01: /*
02: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
03: */
04: package com.tc.object.tx;
05:
06: import com.tc.object.lockmanager.api.LockID;
07:
08: import java.util.Collection;
09: import java.util.Collections;
10: import java.util.HashMap;
11: import java.util.HashSet;
12: import java.util.Iterator;
13: import java.util.Map;
14: import java.util.Set;
15:
16: public class LockAccounting {
17:
18: private final Map tx2Locks = new HashMap();
19: private final Map lock2Txs = new HashMap();
20:
21: public synchronized Object dump() {
22: return "LockAccounting:\ntx2Locks=" + tx2Locks + "\nlock2Txs="
23: + lock2Txs + "/LockAccounting";
24: }
25:
26: public String toString() {
27: return "LockAccounting[tx2Locks=" + tx2Locks + ", lock2Txs="
28: + lock2Txs + "]";
29: }
30:
31: public synchronized void add(TransactionID txID, Collection lockIDs) {
32: getOrCreateSetFor(txID, tx2Locks).addAll(lockIDs);
33: for (Iterator i = lockIDs.iterator(); i.hasNext();) {
34: LockID lid = (LockID) i.next();
35: getOrCreateSetFor(lid, lock2Txs).add(txID);
36: }
37: }
38:
39: public synchronized Collection getTransactionsFor(LockID lockID) {
40: Collection rv = new HashSet();
41: Collection toAdd = (Collection) lock2Txs.get(lockID);
42: if (toAdd != null) {
43: rv.addAll(toAdd);
44: }
45: return rv;
46: }
47:
48: // This method returns a set of lockIds that has no more transactions to wait for
49: public synchronized Set acknowledge(TransactionID txID) {
50: Set completedLockIDs = null;
51: Set lockIDs = getSetFor(txID, tx2Locks);
52: if (lockIDs != null) {
53: // this may be null if there are phantom acknowledgements caused by server restart.
54: for (Iterator i = lockIDs.iterator(); i.hasNext();) {
55: LockID lid = (LockID) i.next();
56: Set txIDs = getOrCreateSetFor(lid, lock2Txs);
57: if (!txIDs.remove(txID))
58: throw new AssertionError(
59: "No lock=>transaction found for " + lid
60: + ", " + txID);
61: if (txIDs.isEmpty()) {
62: lock2Txs.remove(lid);
63: if (completedLockIDs == null) {
64: completedLockIDs = new HashSet();
65: }
66: completedLockIDs.add(lid);
67: }
68: }
69: }
70: tx2Locks.remove(txID);
71: return (completedLockIDs == null ? Collections.EMPTY_SET
72: : completedLockIDs);
73: }
74:
75: public synchronized boolean isEmpty() {
76: return tx2Locks.isEmpty() && lock2Txs.isEmpty();
77: }
78:
79: private static Set getSetFor(Object key, Map m) {
80: return (Set) m.get(key);
81: }
82:
83: private static Set getOrCreateSetFor(Object key, Map m) {
84: Set rv = getSetFor(key, m);
85: if (rv == null) {
86: rv = new HashSet();
87: m.put(key, rv);
88: }
89: return rv;
90: }
91:
92: }
|