001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.gtx;
006:
007: import com.tc.net.groups.NodeID;
008: import com.tc.object.tx.ServerTransactionID;
009:
010: import java.util.ArrayList;
011: import java.util.Collection;
012: import java.util.Collections;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Map;
017: import java.util.Set;
018: import java.util.TreeMap;
019: import java.util.Map.Entry;
020:
021: public class ServerTransactionIDBookKeeper {
022:
023: private final static TreeMap EMPTY_TREEMAP = new TreeMap();
024:
025: private final HashMap nodes = new HashMap();
026:
027: public synchronized GlobalTransactionDescriptor add(
028: ServerTransactionID sid, GlobalTransactionDescriptor gtx) {
029: TreeMap tids = getOrCreateTreeMap(sid.getSourceID());
030: return (GlobalTransactionDescriptor) tids.put(sid
031: .getClientTransactionID(), gtx);
032: }
033:
034: private TreeMap getOrCreateTreeMap(NodeID nodeID) {
035: TreeMap tm = (TreeMap) nodes.get(nodeID);
036: if (tm == null) {
037: tm = new TreeMap();
038: nodes.put(nodeID, tm);
039: }
040: return tm;
041: }
042:
043: private TreeMap getTreeMap(NodeID nodeID) {
044: TreeMap tm = (TreeMap) nodes.get(nodeID);
045: return (tm == null ? EMPTY_TREEMAP : tm);
046: }
047:
048: public synchronized GlobalTransactionDescriptor get(
049: ServerTransactionID sid) {
050: TreeMap tids = getTreeMap(sid.getSourceID());
051: return (GlobalTransactionDescriptor) tids.get(sid
052: .getClientTransactionID());
053: }
054:
055: public synchronized GlobalTransactionDescriptor remove(
056: ServerTransactionID sid) {
057: TreeMap tids = getTreeMap(sid.getSourceID());
058: return (GlobalTransactionDescriptor) tids.remove(sid
059: .getClientTransactionID());
060: }
061:
062: public synchronized Collection removeAll(NodeID nid) {
063: TreeMap tm = (TreeMap) nodes.remove(nid);
064: if (tm != null) {
065: return tm.values();
066: } else {
067: return Collections.EMPTY_LIST;
068: }
069: }
070:
071: public synchronized Collection removeAllExcept(Set cids) {
072: List removed = new ArrayList();
073: for (Iterator i = nodes.entrySet().iterator(); i.hasNext();) {
074: Map.Entry e = (Entry) i.next();
075: if (!cids.contains(e.getKey())) {
076: TreeMap tm = (TreeMap) e.getValue();
077: removed.addAll(tm.values());
078: i.remove();
079: }
080: }
081: return removed;
082: }
083:
084: public synchronized Collection clearCommitedSidsBelowLowWaterMark(
085: ServerTransactionID sid) {
086: List removed = new ArrayList();
087: TreeMap tids = getTreeMap(sid.getSourceID());
088: Map toRemove = tids.headMap(sid.getClientTransactionID());
089: for (Iterator i = toRemove.values().iterator(); i.hasNext();) {
090: GlobalTransactionDescriptor gd = (GlobalTransactionDescriptor) i
091: .next();
092: // We are only removing the transactions that are already committed to disk. Transactions could be reordered in
093: // the passive, so we need this check.
094: if (gd.complete()) {
095: i.remove();
096: removed.add(gd);
097: }
098: }
099: return removed;
100: }
101:
102: }
|