Author: j16sdiz
Date: 2008-07-04 13:53:05 +0000 (Fri, 04 Jul 2008)
New Revision: 20988

Added:
   
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
Modified:
   
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
Log:
factor out LockManager

Added: 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
===================================================================
--- 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java  
                            (rev 0)
+++ 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java  
    2008-07-04 13:53:05 UTC (rev 20988)
@@ -0,0 +1,101 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.store.saltedhash;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import freenet.support.Logger;
+
+/**
+ * Lock Manager
+ * 
+ * Handle locking/unlocking of individual offsets.
+ * 
+ * @author sdiz
+ */
+public class LockManager {
+       private static boolean logDEBUG;
+       private volatile boolean shutdown;
+       private Lock entryLock = new ReentrantLock();
+       private Map<Long, Condition> lockMap = new HashMap<Long, Condition>();
+
+       LockManager() {
+               logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+       }
+
+       /**
+        * Lock the entry
+        * 
+        * This lock is <strong>not</strong> re-entrance. No threads except 
Cleaner should hold more
+        * then one lock at a time (or deadlock may occur).
+        */
+       boolean lockEntry(long offset) {
+               if (logDEBUG)
+                       Logger.debug(this, "try locking " + offset, new 
Exception());
+
+               try {
+                       entryLock.lock();
+                       try {
+                               do {
+                                       if (shutdown)
+                                               return false;
+
+                                       Condition lockCond = 
lockMap.get(offset);
+                                       if (lockCond != null)
+                                               lockCond.await(10, 
TimeUnit.SECONDS); // 10s for checking shutdown
+                                       else
+                                               break;
+                               } while (true);
+                               lockMap.put(offset, entryLock.newCondition());
+                       } finally {
+                               entryLock.unlock();
+                       }
+               } catch (InterruptedException e) {
+                       Logger.error(this, "lock interrupted", e);
+                       return false;
+               }
+
+               if (logDEBUG)
+                       Logger.debug(this, "locked " + offset, new Exception());
+               return true;
+       }
+
+       /**
+        * Unlock the entry
+        */
+       void unlockEntry(long offset) {
+               if (logDEBUG)
+                       Logger.debug(this, "unlocking " + offset, new 
Exception("debug"));
+
+               entryLock.lock();
+               try {
+                       Condition cond = lockMap.remove(offset);
+                       assert cond != null;
+                       cond.signal();
+               } finally {
+                       entryLock.unlock();
+               }
+       }
+
+       /**
+        * Shutdown and wait for all entries unlocked
+        */
+       void shutdown() {
+               shutdown = true;
+               entryLock.lock();
+               try {
+                       while (!lockMap.isEmpty()) {
+                               Condition cond = 
lockMap.values().iterator().next();
+                               cond.awaitUninterruptibly();
+                       }
+               } finally {
+                       entryLock.unlock();
+               }
+       }
+}

Modified: 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
===================================================================
--- 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
   2008-07-04 13:52:40 UTC (rev 20987)
+++ 
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
   2008-07-04 13:53:05 UTC (rev 20988)
@@ -12,7 +12,6 @@
 import java.security.MessageDigest;
 import java.text.DecimalFormat;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -68,7 +67,6 @@
        private static final boolean checkBloom = true;
        private BloomFilter bloomFilter;

-       private static final boolean logLOCK = false;
        private static boolean logMINOR;
        private static boolean logDEBUG;

@@ -112,6 +110,8 @@
                entryPaddingLength = 0x200L - (length % 0x200L);
                entryTotalLength = length + entryPaddingLength;

+               lockManager = new LockManager();
+               
                // Create a directory it not exist
                this.baseDir.mkdirs();

@@ -1118,7 +1118,7 @@
                        try {
                                // acquire all locks in the region, will unlock 
in the finally block
                                for (int i = 0; i < length; i++) {
-                                       if (lockEntry(offset + i))
+                                       if (lockManager.lockEntry(offset + i))
                                                locked[i] = true;
                                        else
                                                return false;
@@ -1199,7 +1199,7 @@
                                // unlock
                                for (int i = 0; i < length; i++)
                                        if (locked[i])
-                                               unlockEntry(offset + i);
+                                               lockManager.unlockEntry(offset 
+ i);
                        }
                }

@@ -1343,66 +1343,11 @@
        }

        // ------------- Locking
-       private boolean shutdown = false;
+       volatile boolean shutdown = false;
+       private LockManager lockManager;
        private ReadWriteLock configLock = new ReentrantReadWriteLock(); 
-       private Lock entryLock = new ReentrantLock();
-       private Map<Long, Condition> lockMap = new HashMap<Long, Condition> ();

        /**
-        * Lock the entry
-        * 
-        * This lock is <strong>not</strong> re-entrance. No threads except 
Cleaner should hold more
-        * then one lock at a time (or deadlock may occur).
-        */
-       private boolean lockEntry(long offset) {
-               if (logDEBUG && logLOCK)
-                       Logger.debug(this, "try locking " + offset, new 
Exception());
-
-               try {
-                       entryLock.lock();
-                       try {
-                               do {
-                                       if (shutdown)
-                                               return false;
-
-                                       Condition lockCond = 
lockMap.get(offset);
-                                       if (lockCond != null)
-                                               lockCond.await(10, 
TimeUnit.SECONDS); // 10s for checking shutdown
-                                       else
-                                               break;
-                               } while (true);
-                               lockMap.put(offset, entryLock.newCondition());
-                       } finally {
-                               entryLock.unlock();
-                       }
-               } catch (InterruptedException e) {
-                       Logger.error(this, "lock interrupted", e);
-                       return false;
-               }
-
-               if (logDEBUG && logLOCK)
-                       Logger.debug(this, "locked " + offset, new Exception());
-               return true;
-       }
-
-       /**
-        * Unlock the entry
-        */
-       private void unlockEntry(long offset) {
-               if (logDEBUG && logLOCK)
-                       Logger.debug(this, "unlocking " + offset, new 
Exception("debug"));
-
-               entryLock.lock();
-               try {
-                       Condition cond = lockMap.remove(offset);
-                       assert cond != null;
-                       cond.signal();
-               } finally {
-                       entryLock.unlock();
-               }
-       }
-
-       /**
         * Lock all possible offsets of a key. This method would release the 
locks if any locking
         * operation failed.
         * 
@@ -1439,7 +1384,7 @@

                Set<Long> locked = new TreeSet<Long>();
                for (long offset : offsets) {
-                       boolean status = lockEntry(offset);
+                       boolean status = lockManager.lockEntry(offset);
                        if (!status)
                                break;
                        locked.add(offset);
@@ -1450,7 +1395,7 @@
                } else {
                        // failed, remove the locks
                        for (long offset : locked)
-                               unlockEntry(offset);
+                               lockManager.unlockEntry(offset);
                        return false;
                }
        }
@@ -1468,13 +1413,14 @@
                }

                for (long offset : offsets) {
-                       unlockEntry(offset);
+                       lockManager.unlockEntry(offset);
                }
        }

        public class ShutdownDB implements Runnable {
                public void run() {
                        shutdown = true;
+                       lockManager.shutdown();

                        synchronized (cleanerLock) {
                                cleanerLock.notifyAll();
@@ -1544,7 +1490,7 @@
         * @param storeSize
         * @return
         */
-       public long[] getOffsetFromPlainKey(byte[] plainKey, long storeSize) {
+       private long[] getOffsetFromPlainKey(byte[] plainKey, long storeSize) {
                return 
getOffsetFromDigestedKey(getDigestedRoutingKey(plainKey), storeSize);
        }

@@ -1555,7 +1501,7 @@
         * @param storeSize
         * @return
         */
-       public long[] getOffsetFromDigestedKey(byte[] digestedKey, long 
storeSize) {
+       private long[] getOffsetFromDigestedKey(byte[] digestedKey, long 
storeSize) {
                long keyValue = Fields.bytesToLong(digestedKey);
                long[] offsets = new long[OPTION_MAX_PROBE];



Reply via email to