Author: j16sdiz
Date: 2008-07-13 13:27:03 +0000 (Sun, 13 Jul 2008)
New Revision: 21131
Modified:
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
Log:
verify condition on unlock
Modified:
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
===================================================================
---
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
2008-07-13 13:26:42 UTC (rev 21130)
+++
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/LockManager.java
2008-07-13 13:27:03 UTC (rev 21131)
@@ -35,16 +35,17 @@
* 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) {
+ Condition lockEntry(long offset) {
if (logDEBUG)
Logger.debug(this, "try locking " + offset, new
Exception());
+ Condition condition;
try {
entryLock.lock();
try {
do {
if (shutdown)
- return false;
+ return null;
Condition lockCond =
lockMap.get(offset);
if (lockCond != null)
@@ -52,31 +53,32 @@
else
break;
} while (true);
- lockMap.put(offset, entryLock.newCondition());
+ condition = entryLock.newCondition();
+ lockMap.put(offset, condition);
} finally {
entryLock.unlock();
}
} catch (InterruptedException e) {
Logger.error(this, "lock interrupted", e);
- return false;
+ return null;
}
if (logDEBUG)
Logger.debug(this, "locked " + offset, new Exception());
- return true;
+ return condition;
}
/**
* Unlock the entry
*/
- void unlockEntry(long offset) {
+ void unlockEntry(long offset, Condition condition) {
if (logDEBUG)
Logger.debug(this, "unlocking " + offset, new
Exception("debug"));
entryLock.lock();
try {
Condition cond = lockMap.remove(offset);
- assert cond != null;
+ assert cond != condition;
cond.signal();
} finally {
entryLock.unlock();
Modified:
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
===================================================================
---
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
2008-07-13 13:26:42 UTC (rev 21130)
+++
branches/saltedhashstore/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
2008-07-13 13:27:03 UTC (rev 21131)
@@ -14,9 +14,10 @@
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import java.util.Random;
-import java.util.Set;
import java.util.SortedSet;
+import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -151,8 +152,8 @@
configLock.readLock().lock();
try {
- boolean locked = lockPlainKey(routingKey, true);
- if (!locked) {
+ Map<Long, Condition> lockMap = lockPlainKey(routingKey,
true);
+ if (lockMap == null) {
if (logDEBUG)
Logger.debug(this, "cannot lock key: "
+ HexUtil.bytesToHex(routingKey) + ", shutting down?");
return null;
@@ -179,7 +180,7 @@
return null;
}
} finally {
- unlockPlainKey(routingKey, true);
+ unlockPlainKey(routingKey, true, lockMap);
}
} finally {
configLock.readLock().unlock();
@@ -238,8 +239,8 @@
configLock.readLock().lock();
try {
- boolean locked = lockPlainKey(routingKey, false);
- if (!locked) {
+ Map<Long, Condition> lockMap = lockPlainKey(routingKey,
false);
+ if (lockMap == null) {
if (logDEBUG)
Logger.debug(this, "cannot lock key: "
+ HexUtil.bytesToHex(routingKey) + ", shutting down?");
return;
@@ -305,7 +306,7 @@
if (oldEntry.generation != generation)
keyCount.incrementAndGet();
} finally {
- unlockPlainKey(routingKey, false);
+ unlockPlainKey(routingKey, false, lockMap);
}
} finally {
configLock.readLock().unlock();
@@ -1133,13 +1134,12 @@
* otherwise (e.g. can't acquire locks, node shutting
down)
*/
private boolean batchProcessEntries(long offset, int length,
BatchProcessor processor) {
- boolean[] locked = new boolean[length];
+ Condition[] locked = new Condition[length];
try {
// acquire all locks in the region, will unlock
in the finally block
for (int i = 0; i < length; i++) {
- if (lockManager.lockEntry(offset + i))
- locked[i] = true;
- else
+ locked[i] =
lockManager.lockEntry(offset + i);
+ if (locked[i] == null)
return false;
}
@@ -1215,8 +1215,8 @@
} finally {
// unlock
for (int i = 0; i < length; i++)
- if (locked[i])
- lockManager.unlockEntry(offset
+ i);
+ if (locked[i] != null)
+ lockManager.unlockEntry(offset
+ i, locked[i]);
}
}
@@ -1227,7 +1227,8 @@
* @return <code>true</code> if the entry have put back
successfully.
*/
private boolean resolveOldEntry(Entry entry) {
- if (!lockDigestedKey(entry.getDigestedRoutingKey(),
false))
+ Map<Long, Condition> lockMap =
lockDigestedKey(entry.getDigestedRoutingKey(), false);
+ if (lockMap == null)
return false;
try {
entry.storeSize = storeSize;
@@ -1261,7 +1262,7 @@
}
return false;
} finally {
-
unlockDigestedKey(entry.getDigestedRoutingKey(), false);
+
unlockDigestedKey(entry.getDigestedRoutingKey(), false, lockMap);
}
}
}
@@ -1304,12 +1305,12 @@
* @param plainKey
* @return <code>true</code> if all the offsets are locked.
*/
- private boolean lockPlainKey(byte[] plainKey, boolean usePrevStoreSize)
{
+ private Map<Long, Condition> lockPlainKey(byte[] plainKey, boolean
usePrevStoreSize) {
return lockDigestedKey(cipherManager.getDigestedKey(plainKey),
usePrevStoreSize);
}
- private void unlockPlainKey(byte[] plainKey, boolean usePrevStoreSize) {
- unlockDigestedKey(cipherManager.getDigestedKey(plainKey),
usePrevStoreSize);
+ private void unlockPlainKey(byte[] plainKey, boolean usePrevStoreSize,
Map<Long, Condition> lockMap) {
+ unlockDigestedKey(cipherManager.getDigestedKey(plainKey),
usePrevStoreSize, lockMap);
}
/**
@@ -1319,7 +1320,7 @@
* @param digestedKey
* @return <code>true</code> if all the offsets are locked.
*/
- private boolean lockDigestedKey(byte[] digestedKey, boolean
usePrevStoreSize) {
+ private Map<Long, Condition> lockDigestedKey(byte[] digestedKey,
boolean usePrevStoreSize) {
// use a set to prevent duplicated offsets,
// a sorted set to prevent deadlocks
SortedSet<Long> offsets = new TreeSet<Long>();
@@ -1332,25 +1333,25 @@
offsets.add(offset);
}
- Set<Long> locked = new TreeSet<Long>();
+ Map<Long, Condition> locked = new TreeMap<Long, Condition>();
for (long offset : offsets) {
- boolean status = lockManager.lockEntry(offset);
- if (!status)
+ Condition condition = lockManager.lockEntry(offset);
+ if (condition == null)
break;
- locked.add(offset);
+ locked.put(offset, condition);
}
if (locked.size() == offsets.size()) {
- return true;
+ return locked;
} else {
// failed, remove the locks
- for (long offset : locked)
- lockManager.unlockEntry(offset);
- return false;
+ for (Map.Entry<Long, Condition> e : locked.entrySet())
+ lockManager.unlockEntry(e.getKey(),
e.getValue());
+ return null;
}
}
- private void unlockDigestedKey(byte[] digestedKey, boolean
usePrevStoreSize) {
+ private void unlockDigestedKey(byte[] digestedKey, boolean
usePrevStoreSize, Map<Long, Condition> lockMap) {
// use a set to prevent duplicated offsets
SortedSet<Long> offsets = new TreeSet<Long>();
long[] offsetArray = getOffsetFromDigestedKey(digestedKey,
storeSize);
@@ -1363,7 +1364,8 @@
}
for (long offset : offsets) {
- lockManager.unlockEntry(offset);
+ lockManager.unlockEntry(offset, lockMap.get(offset));
+ lockMap.remove(offset);
}
}