diff src/org/dancres/blitz/txnlock/LockCache.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/dancres/blitz/txnlock/LockCache.java	Sat Mar 21 11:00:06 2009 +0000
@@ -0,0 +1,90 @@
+package org.dancres.blitz.txnlock;
+
+import java.util.HashMap;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import org.dancres.blitz.oid.OID;
+
+class LockCache {
+    private HashMap theLocks = new HashMap();
+
+    private ReferenceQueue theDeadLocks = new ReferenceQueue();
+
+    LockCache() {
+    }
+
+    TxnLock getOrInsert(OID aOID) {
+        cleanQueue();
+        
+        synchronized(this) {
+            TxnLock myLock = get(aOID);
+            
+            if (myLock == null) {
+                myLock = new TxnLock();
+                put(aOID, myLock);
+            }
+            
+            return myLock;
+        }
+    }
+    
+    TxnLock get(OID aOID) {
+        cleanQueue();
+
+        synchronized(this) {
+            LockHolder myHolder = (LockHolder) theLocks.get(aOID);
+            
+            return (myHolder == null) ? null : (TxnLock) myHolder.get();
+        }
+    }
+
+    void put(OID aOID, TxnLock aLock) {
+        cleanQueue();
+
+        synchronized(this) {
+            LockHolder myHolder = new LockHolder(aOID, aLock, theDeadLocks);
+            
+            theLocks.put(aOID, myHolder);
+        }
+    }
+
+    private void cleanQueue() {
+        LockHolder myRef;
+        
+        while ((myRef = (LockHolder) theDeadLocks.poll()) != null) {
+            synchronized(this) {
+                LockHolder myOther = (LockHolder) theLocks.remove(myRef.getOID());
+                
+                /*
+                   Check that the reference we're releasing is the same as the
+                   one we currently have in the table.  Otherwise:
+
+                   It could be that get(OID) was called above and the holder was
+                   recovered but it's reference had been cleared resulting in
+                   allocation of a new lock BEFORE we've processed the reference
+                   from the queue.  Thus we allocate the new lock, the old
+                   reference (from get(OID)) is enqueued and we then delete the
+                   new lock - oops!
+                 */
+                if ((myOther != null) &&(! myOther.equals(myRef))) {
+                    theLocks.put(myOther.getOID(), myOther);
+                }
+            }
+        }
+    }
+
+    private class LockHolder extends WeakReference {
+        private OID theOID;
+
+        LockHolder(OID aOID, TxnLock aLock, ReferenceQueue aQueue) {
+            super(aLock, aQueue);
+            theOID = aOID;
+        }
+
+        OID getOID() {
+            return theOID;
+        }
+    }
+}