summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@cern.ch>2014-05-12 16:55:54 +0200
committerAndrew Branson <andrew.branson@cern.ch>2014-05-12 16:55:54 +0200
commit8fc06d9c794c704eed2ab8707768fc72cc677ded (patch)
treea30d296158c22316fdcb17935c405f9958e7e606
parent5bf7c8dabdfc7eaf26d2748a6a05eebb1023ef83 (diff)
Tweak locks to hopefully avoid deadlocks a bit
-rw-r--r--src/main/java/com/c2kernel/persistency/TransactionManager.java89
1 files changed, 52 insertions, 37 deletions
diff --git a/src/main/java/com/c2kernel/persistency/TransactionManager.java b/src/main/java/com/c2kernel/persistency/TransactionManager.java
index 86e8199..d966eec 100644
--- a/src/main/java/com/c2kernel/persistency/TransactionManager.java
+++ b/src/main/java/com/c2kernel/persistency/TransactionManager.java
@@ -63,16 +63,14 @@ public class TransactionManager {
Integer sysKeyIntObj = new Integer(sysKey);
// check to see if the locker has been modifying this cluster
- synchronized(locks) {
- if (locks.containsKey(sysKeyIntObj) && locks.get(sysKeyIntObj).equals(locker)) {
- ArrayList<TransactionEntry> lockerTransaction = pendingTransactions.get(locker);
- for (TransactionEntry thisEntry : lockerTransaction) {
- if (sysKey == thisEntry.sysKey.intValue() && path.equals(thisEntry.getPath())) {
- if (thisEntry.obj == null)
- throw new ClusterStorageException("ClusterStorageManager.get() - Cluster " + path + " has been deleted in " + sysKey +
- " but not yet committed");
- return thisEntry.obj;
- }
+ if (locks.containsKey(sysKeyIntObj) && locks.get(sysKeyIntObj).equals(locker)) {
+ ArrayList<TransactionEntry> lockerTransaction = pendingTransactions.get(locker);
+ for (TransactionEntry thisEntry : lockerTransaction) {
+ if (sysKey == thisEntry.sysKey.intValue() && path.equals(thisEntry.getPath())) {
+ if (thisEntry.obj == null)
+ throw new ClusterStorageException("ClusterStorageManager.get() - Cluster " + path + " has been deleted in " + sysKey +
+ " but not yet committed");
+ return thisEntry.obj;
}
}
}
@@ -85,6 +83,7 @@ public class TransactionManager {
*/
public void put(int sysKey, C2KLocalObject obj, Object locker) throws ClusterStorageException {
Integer sysKeyIntObj = new Integer(sysKey);
+ Object tempLocker = null;
ArrayList<TransactionEntry> lockerTransaction;
String path = ClusterStorage.getPath(obj);
@@ -99,28 +98,35 @@ public class TransactionManager {
throw new ClusterStorageException("ClusterStorageManager.get() - Access denied: Object " + sysKeyIntObj +
" has been locked for writing by " + thisLocker);
}
- else { // either we are the locker, or there is no locker
- if (locker == null) { // non-locking put/delete
- storage.put(sysKeyIntObj, obj);
- return;
+ else { // no locks for this item
+ if (locker == null) { // lock the item until the non-transactional put is complete :/
+ tempLocker = new Object();
+ locks.put(sysKeyIntObj, tempLocker);
+ lockerTransaction = null;
}
- else {// initialise the transaction
+ else { // initialise the transaction
locks.put(sysKeyIntObj, locker);
lockerTransaction = new ArrayList<TransactionEntry>();
pendingTransactions.put(locker, lockerTransaction);
}
}
-
- // create the new entry in the transaction table
- TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, obj);
- /* equals() in TransactionEntry only compares sysKey and path, so we can use
- * contains() in ArrayList to looks for preexisting entries for this cluster
- * and overwrite them.
- */
- if (lockerTransaction.contains(newEntry))
- lockerTransaction.remove(newEntry);
- lockerTransaction.add(newEntry);
}
+
+ if (tempLocker != null) { // non-locking put/delete
+ storage.put(sysKeyIntObj, obj);
+ locks.remove(sysKeyIntObj);
+ return;
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, obj);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
}
/** Public delete method. Uses the put method, with null as the object value.
@@ -128,6 +134,7 @@ public class TransactionManager {
public void remove(int sysKey, String path, Object locker) throws ClusterStorageException {
Integer sysKeyIntObj = new Integer(sysKey);
ArrayList<TransactionEntry> lockerTransaction;
+ Object tempLocker = null;
synchronized(locks) {
// look to see if this object is already locked
if (locks.containsKey(sysKeyIntObj)) {
@@ -141,8 +148,9 @@ public class TransactionManager {
}
else { // either we are the locker, or there is no locker
if (locker == null) { // non-locking put/delete
- storage.remove(sysKeyIntObj, path);
- return;
+ tempLocker = new Object();
+ locks.put(sysKeyIntObj, tempLocker);
+ lockerTransaction = null;
}
else {// initialise the transaction
locks.put(sysKeyIntObj, locker);
@@ -150,17 +158,24 @@ public class TransactionManager {
pendingTransactions.put(locker, lockerTransaction);
}
}
-
- // create the new entry in the transaction table
- TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, null);
- /* equals() in TransactionEntry only compares sysKey and path, so we can use
- * contains() in ArrayList to looks for preexisting entries for this cluster
- * and overwrite them.
- */
- if (lockerTransaction.contains(newEntry))
- lockerTransaction.remove(newEntry);
- lockerTransaction.add(newEntry);
}
+
+ if (tempLocker != null) {
+ storage.remove(sysKeyIntObj, path);
+ locks.remove(sysKeyIntObj);
+ return;
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(sysKeyIntObj, path, null);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
+
}
/**