You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/11/18 09:03:54 UTC

svn commit: r1036336 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: TransactionContext.java state/DefaultISMLocking.java state/ISMLocking.java

Author: jukka
Date: Thu Nov 18 08:03:53 2010
New Revision: 1036336

URL: http://svn.apache.org/viewvc?rev=1036336&view=rev
Log:
JCR-2753: Deadlock in DefaultISMLocking

Move the thread identifier computations to TransactionContext from where they can be better reused.

Note that it's not necessarily possible to "upgrade" an ISMLocking read lock.

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java?rev=1036336&r1=1036335&r2=1036336&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java Thu Nov 18 08:03:53 2010
@@ -23,6 +23,7 @@ import org.apache.jackrabbit.util.Timer;
 import javax.transaction.xa.XAException;
 import javax.transaction.xa.Xid;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -338,4 +339,36 @@ public class TransactionContext extends 
     public static Xid getCurrentXid() {
         return CURRENT_XID.get();
     }
+
+    /**
+     * Returns the current thread identifier. The identifier is either the
+     * current thread instance or the global transaction identifier when
+     * running under a transaction.
+     *
+     * @return current thread identifier
+     */
+    public static Object getCurrentThreadId() {
+        Xid xid = TransactionContext.getCurrentXid();
+        if (xid != null) {
+            return xid.getGlobalTransactionId();
+        } else {
+            return Thread.currentThread();
+        }
+    }
+
+    /**
+     * Compares the given thread identifiers for equality.
+     *
+     * @see #getCurrentThreadId()
+     */
+    public static boolean isSameThreadId(Object a, Object b) {
+        if (a == b) {
+            return true;
+        } else if (a instanceof byte[] && b instanceof byte[]) {
+            return Arrays.equals((byte[]) a, (byte[]) b);
+        } else {
+            return false;
+        }
+    }
+
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java?rev=1036336&r1=1036335&r2=1036336&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java Thu Nov 18 08:03:53 2010
@@ -16,11 +16,9 @@
  */
 package org.apache.jackrabbit.core.state;
 
-import java.util.Arrays;
+import static org.apache.jackrabbit.core.TransactionContext.getCurrentThreadId;
+import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId;
 
-import javax.transaction.xa.Xid;
-
-import org.apache.jackrabbit.core.TransactionContext;
 import org.apache.jackrabbit.core.id.ItemId;
 
 /**
@@ -87,8 +85,9 @@ public class DefaultISMLocking implement
      */
     public synchronized ReadLock acquireReadLock(ItemId id)
             throws InterruptedException {
+        Object currentId = getCurrentThreadId();
         while (writerId != null
-                ? (writerCount > 0 && !isSameId(writerId, getCurrentId()))
+                ? (writerCount > 0 && !isSameThreadId(writerId, currentId))
                 : writersWaiting > 0) {
             wait();
         }
@@ -116,12 +115,12 @@ public class DefaultISMLocking implement
      */
     public synchronized WriteLock acquireWriteLock(ChangeLog changeLog)
             throws InterruptedException {
-        Object currentId = getCurrentId();
+        Object currentId = getCurrentThreadId();
 
         writersWaiting++;
         try {
             while (writerId != null
-                    ? !isSameId(writerId, currentId) : readerCount > 0) {
+                    ? !isSameThreadId(writerId, currentId) : readerCount > 0) {
                 wait();
             }
         } finally {
@@ -153,33 +152,4 @@ public class DefaultISMLocking implement
         }
     }
 
-    /**
-     * Returns the current thread identifier. The identifier is either the
-     * current thread instance or the global transaction identifier when
-     * running under a transaction.
-     *
-     * @return current thread identifier
-     */
-    private Object getCurrentId() {
-        Xid xid = TransactionContext.getCurrentXid();
-        if (xid != null) {
-            return xid.getGlobalTransactionId();
-        } else {
-            return Thread.currentThread();
-        }
-    }
-
-    /**
-     * Compares the given thread identifiers for equality.
-     */
-    private boolean isSameId(Object a, Object b) {
-        if (a == b) {
-            return true;
-        } else if (a instanceof byte[] && b instanceof byte[]) {
-            return Arrays.equals((byte[]) a, (byte[]) b);
-        } else {
-            return false;
-        }
-    }
-
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java?rev=1036336&r1=1036335&r2=1036336&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java Thu Nov 18 08:03:53 2010
@@ -42,7 +42,9 @@ import org.apache.jackrabbit.core.id.Ite
  * <li>While a write lock is held for a change log <code>C</code>, the holder
  * of the write lock (and any related threads) needs to be able to acquire
  * a read lock even if other writers are waiting for the lock. This behaviour
- * must continue also when the write lock has been downgraded.</li>
+ * must continue also when the write lock has been downgraded. Note that it
+ * is not necessary for a holder of a read lock to be able to upgrade to a
+ * write lock.</li>
  * </ul>
  */
 public interface ISMLocking {