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/24 14:59:16 UTC

svn commit: r1038604 - in /jackrabbit/branches/2.0: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/ jackrabbi...

Author: jukka
Date: Wed Nov 24 13:59:16 2010
New Revision: 1038604

URL: http://svn.apache.org/viewvc?rev=1038604&view=rev
Log:
2.0: Merged revision 1038594 (JCR-2573)

Added:
    jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/DefaultISMLockingDeadlockTest.java
      - copied unchanged from r1038594, jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/DefaultISMLockingDeadlockTest.java
Modified:
    jackrabbit/branches/2.0/   (props changed)
    jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
    jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
    jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java
    jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
    jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java
    jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/TestAll.java

Propchange: jackrabbit/branches/2.0/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Nov 24 13:59:16 2010
@@ -1,6 +1,6 @@
 /jackrabbit/branches/1.5:794012,794100,794102
-/jackrabbit/branches/2.1:955309,955314,982266,982277,982505,998310,1025933,1025957,1025962,1025964,1025981,1025985,1025990,1025995,1025999,1026002
+/jackrabbit/branches/2.1:955309,955314,982266,982277,982505,998310,1025933,1025957,1025962,1025964,1025981,1025985,1025990,1025995,1025999,1026002,1038594
 /jackrabbit/sandbox/JCR-1456:774917-886178
 /jackrabbit/sandbox/JCR-2170:812417-816332
 /jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:891595,891629,892253,892263,894150-894151,896408,896513,896532,896857,896870,896876,896908,896940,896942-896943,896969,896977,897071,897836,897842,897858,897935,897983,897992-897993,897996,898002,898042,898267,898325,898540,898677,898699,898701,898715,898872,899102,899181,899391,899393-899394,899583,899594,899643,900305,900310,900314,900453,900702,900736,900762-900763,900767,900782,901095,901122,901139,901144,901170,901176,901191,901193,901196,901216,901228,901285,902058,902062,926324,928888,936668,955222,955229,955307,955852,965539,996810,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470,1003542,1003773,1004182,1004184,1004223-1004224,1004652,1005057,1005112
+/jackrabbit/trunk:891595,891629,892253,892263,894150-894151,896408,896513,896532,896857,896870,896876,896908,896940,896942-896943,896969,896977,897071,897836,897842,897858,897935,897983,897992-897993,897996,898002,898042,898267,898325,898540,898677,898699,898701,898715,898872,899102,899181,899391,899393-899394,899583,899594,899643,900305,900310,900314,900453,900702,900736,900762-900763,900767,900782,901095,901122,901139,901144,901170,901176,901191,901193,901196,901216,901228,901285,902058,902062,926324,928888,936668,955222,955229,955307,955852,965539,995411-995412,996810,999298-999299,999965,1000947,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470,1003542,1003773,1004182,1004184,1004223-1004224,1004652,1005057,1005112,1036336-1036337

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransactionContext.java Wed Nov 24 13:59:16 2010
@@ -352,4 +352,36 @@ public class TransactionContext extends 
         Xid currentXid = CURRENT_XID.get();
         return fallback ? true : (currentXid == null || xid == null) ? fallback : Arrays.equals(xid.getGlobalTransactionId(), currentXid.getGlobalTransactionId());
     }
+
+    /**
+     * 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/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java Wed Nov 24 13:59:16 2010
@@ -16,137 +16,143 @@
  */
 package org.apache.jackrabbit.core.state;
 
-import java.util.Arrays;
-
-import javax.transaction.xa.Xid;
+import static org.apache.jackrabbit.core.TransactionContext.getCurrentThreadId;
+import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId;
 
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.TransactionContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
-import EDU.oswego.cs.dl.util.concurrent.Sync;
-
 /**
- * <code>DefaultISMLocking</code> implements the default locking strategy using
- * coarse grained locking on an ItemStateManager wide read-write lock. E.g.
- * while a write lock is held, no read lock can be acquired.
+ * Default item state locking strategy. The default strategy is simply to use
+ * a single coarse-grained read-write lock over the entire workspace.
  */
 public class DefaultISMLocking implements ISMLocking {
 
     /**
-     * Logger instance
+     * The read lock instance used by readers to release the acquired lock.
      */
-    private static final Logger log = LoggerFactory.getLogger(DefaultISMLocking.class);
+    private final ReadLock readLock = new ReadLock() {
+        public void release() {
+            releaseReadLock();
+        }
+    };
 
     /**
-     * The internal read-write lock.
+     * The write lock instance used by writers to release or downgrade the
+     * acquired lock.
      */
-    private final RWLock rwLock = new RWLock();
+    private final WriteLock writeLock = new WriteLock() {
+        public void release() {
+            releaseWriteLock(false);
+        }
+        public ReadLock downgrade() {
+            releaseWriteLock(true);
+            return readLock;
+        }
+    };
 
     /**
-     * {@inheritDoc}
+     * Number of writer threads waiting. While greater than zero, no new
+     * (unrelated) readers are allowed to proceed.
      */
-    public ReadLock acquireReadLock(ItemId id)
-            throws InterruptedException {
-        return new ReadLockImpl(rwLock.readLock());
-    }
+    private int writersWaiting = 0;
 
     /**
-     * {@inheritDoc}
+     * The thread identifier of the current writer, or <code>null</code> if
+     * no write is in progress. A thread with the same identifier (i.e. the
+     * same thread or another thread in the same transaction) can re-acquire
+     * read or write locks without limitation, while all other readers and
+     * writers remain blocked. Note that a downgraded write lock still retains
+     * the writer thread identifier, which allows related threads to reacquire
+     * read or write locks even when there are concurrent writers waiting.
      */
-    public WriteLock acquireWriteLock(ChangeLog changeLog)
-            throws InterruptedException {
-        return new WriteLock() {
+    private Object writerId = null;
 
-            {
-                rwLock.writeLock().acquire();
-                rwLock.setActiveXid(TransactionContext.getCurrentXid());
-            }
+    /**
+     * Number of acquired write locks. All the concurrent write locks are
+     * guaranteed to share the same thread identifier (see {@link #writerId}).
+     */
+    private int writerCount = 0;
 
-            /**
-             * {@inheritDoc}
-             */
-            public void release() {
-                rwLock.writeLock().release();
-            }
+    /**
+     * Number of acquired read locks.
+     */
+    private int readerCount = 0;
 
-            /**
-             * {@inheritDoc}
-             */
-            public ReadLock downgrade() throws InterruptedException {
-                ReadLock rLock = new ReadLockImpl(rwLock.readLock());
-                release();
-                return rLock;
-            }
-        };
+    /**
+     * Increments the reader count and returns the acquired read lock once
+     * there are no more writers or the current writer shares the thread id
+     * with this reader.
+     */
+    public synchronized ReadLock acquireReadLock(ItemId id)
+            throws InterruptedException {
+        Object currentId = getCurrentThreadId();
+        while (writerId != null
+                ? (writerCount > 0 && !isSameThreadId(writerId, currentId))
+                : writersWaiting > 0) {
+            wait();
+        }
+
+        readerCount++;
+        return readLock;
     }
 
-    private static final class ReadLockImpl implements ReadLock {
+    /**
+     * Decrements the reader count and notifies all pending threads if the
+     * lock is now available. Used by the {@link #readLock} instance.
+     */
+    private synchronized void releaseReadLock() {
+        readerCount--;
+        if (readerCount == 0 && writerCount == 0) {
+            writerId = null;
+            notifyAll();
+        }
+    }
 
-        private final Sync readLock;
+    /**
+     * Increments the writer count, sets the writer identifier and returns
+     * the acquired read lock once there are no other active readers or
+     * writers or the current writer shares the thread id with this writer.
+     */
+    public synchronized WriteLock acquireWriteLock(ChangeLog changeLog)
+            throws InterruptedException {
+        Object currentId = getCurrentThreadId();
 
-        private ReadLockImpl(Sync readLock) throws InterruptedException {
-            this.readLock = readLock;
-            this.readLock.acquire();
+        writersWaiting++;
+        try {
+            while (writerId != null
+                    ? !isSameThreadId(writerId, currentId) : readerCount > 0) {
+                wait();
+            }
+        } finally {
+            writersWaiting--;
         }
 
-        /**
-         * {@inheritDoc}
-         */
-        public void release() {
-            readLock.release();
+        if (writerCount++ == 0) {
+            writerId = currentId;
         }
+        return writeLock;
     }
 
-    private static final class RWLock extends ReentrantWriterPreferenceReadWriteLock {
-
-        private Xid activeXid;
-
-        /**
-         * Allow reader when there is no active writer, or current thread owns
-         * the write lock (reentrant).
-         */
-        protected boolean allowReader() {
-            return TransactionContext.isCurrentXid(activeXid, (activeWriter_ == null || activeWriter_ == Thread.currentThread()));
-        }
-
-        /**
-         * Sets the active Xid
-         * @param xid
-         */
-        synchronized void setActiveXid(Xid xid) {
-            if (activeXid != null && xid != null) {
-                boolean sameGTI = Arrays.equals(activeXid.getGlobalTransactionId(), xid.getGlobalTransactionId());
-                if (!sameGTI) {
-                    log.warn("Unable to set the ActiveXid while a other one is associated with a different GloalTransactionId with this RWLock.");
-                    return;
-                }
-            }
-            activeXid = xid;
+    /**
+     * Decrements the writer count (and possibly clears the writer identifier)
+     * and notifies all pending threads if the lock is now available. If the
+     * downgrade argument is true, then the reader count is incremented before
+     * notifying any pending threads. Used by the {@link #writeLock} instance.
+     */
+    private synchronized void releaseWriteLock(boolean downgrade) {
+        writerCount--;
+        if (downgrade) {
+            readerCount++;
         }
-
-        /**
-         * {@inheritDoc}
-         * 
-         * If there are no more writeHolds the activeXid will be set to null
-         */
-        protected synchronized Signaller endWrite() {
-            --writeHolds_;
-            if (writeHolds_ > 0) {  // still being held
-                return null;
-            } else {
-                activeXid = null;
-                activeWriter_ = null;
-                if (waitingReaders_ > 0 && allowReader()) {
-                    return readerLock_;
-                } else if (waitingWriters_ > 0) {
-                    return writerLock_;
-                } else {
-                    return null;
-                }
+        if (writerCount == 0) {
+            if (readerCount == 0) {
+                writerId = null;
             }
+            notifyAll();
         }
     }
+
 }

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ISMLocking.java Wed Nov 24 13:59:16 2010
@@ -39,6 +39,12 @@ import org.apache.jackrabbit.core.id.Ite
  * is free to block requests entirely for additional write lock while a write
  * lock is active. It is not a requirement to support concurrent write locks.
  * </li>
+ * <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. 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 {
@@ -81,10 +87,8 @@ public interface ISMLocking {
          * used to further release the read lock.
          *
          * @return the read lock downgraded from this write lock.
-         * @throws InterruptedException if the current thread is interrupted
-         *                              while downgrading the write lock.
          */
-        ReadLock downgrade() throws InterruptedException;
+        ReadLock downgrade();
 
     }
 

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Wed Nov 24 13:59:16 2010
@@ -790,9 +790,6 @@ public class SharedItemStateManager
                     String path = events.getSession().getUserID() + "@" + events.getCommonPath();
                     eventChannel.updateCommitted(this, path);
                 }
-
-            } catch (InterruptedException e) {
-                throw new ItemStateException("Interrupted while downgrading to read lock");
             } finally {
                 if (writeLock != null) {
                     // exception occurred before downgrading lock
@@ -1515,9 +1512,6 @@ public class SharedItemStateManager
                 holdingWriteLock = false;
                 events.dispatch();
             }
-        } catch (InterruptedException e) {
-            String msg = "Unable to downgrade to read lock.";
-            log.error(msg);
         } finally {
             if (holdingWriteLock) {
                 if (wLock != null) {

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/InternalVersionManagerImpl.java Wed Nov 24 13:59:16 2010
@@ -29,7 +29,6 @@ import javax.jcr.version.VersionExceptio
 
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.core.RepositoryImpl;
 import org.apache.jackrabbit.core.cluster.UpdateEventChannel;
 import org.apache.jackrabbit.core.cluster.UpdateEventListener;
 import org.apache.jackrabbit.core.fs.FileSystem;
@@ -58,9 +57,9 @@ import org.apache.jackrabbit.core.value.
 import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
+import org.apache.jackrabbit.spi.PathFactory;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.PathBuilder;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -80,38 +79,13 @@ public class InternalVersionManagerImpl 
      */
     private static final Path SYSTEM_PATH;
 
-    /**
-     * The path to the version storage: /jcr:system/jcr:versionStorage
-     */
-    private static final Path HISTORIES_PATH;
-
-    /**
-     * The path to the version storage: /jcr:system/jcr:versionStorage/jcr:activities
-     */
-    private static final Path ACTIVITIES_PATH;
-
     static {
         try {
-            PathBuilder builder = new PathBuilder();
-            builder.addRoot();
-            builder.addLast(NameConstants.JCR_SYSTEM);
-            SYSTEM_PATH = builder.getPath();
-
-            builder = new PathBuilder();
-            builder.addRoot();
-            builder.addLast(NameConstants.JCR_SYSTEM);
-            builder.addLast(NameConstants.JCR_VERSIONSTORAGE);
-            HISTORIES_PATH = builder.getPath();
-
-            builder = new PathBuilder();
-            builder.addRoot();
-            builder.addLast(NameConstants.JCR_SYSTEM);
-            builder.addLast(NameConstants.JCR_ACTIVITIES);
-            ACTIVITIES_PATH = builder.getPath();
-
-        } catch (MalformedPathException e) {
-            // will not happen. path is always valid
-            throw new InternalError("Cannot initialize path");
+            PathFactory factory = PathFactoryImpl.getInstance();
+            SYSTEM_PATH = factory.create(
+                    factory.getRootPath(), NameConstants.JCR_SYSTEM, true);
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
         }
     }
 
@@ -185,28 +159,6 @@ public class InternalVersionManagerImpl 
             this.fs = fs;
             this.escFactory = new DynamicESCFactory(obsMgr);
 
-            // need to recreate the jcr:system node in this pm, too. so that
-            // it can act as parent for the histories and activities.
-            if (false && !pMgr.exists(systemId)) {
-                NodeState root = pMgr.createNew(systemId);
-                root.setParentId(RepositoryImpl.ROOT_NODE_ID);
-                root.setNodeTypeName(NameConstants.REP_SYSTEM);
-                PropertyState pt = pMgr.createNew(new PropertyId(systemId, NameConstants.JCR_PRIMARYTYPE));
-                pt.setMultiValued(false);
-                pt.setType(PropertyType.NAME);
-                pt.setValues(new InternalValue[]{InternalValue.create(NameConstants.REP_SYSTEM)});
-                root.addPropertyName(pt.getName());
-
-                // add version storage and activities as child node entries
-                root.addChildNodeEntry(NameConstants.JCR_VERSIONSTORAGE, historiesId);
-                root.addChildNodeEntry(NameConstants.JCR_ACTIVITIES, activitiesId);
-
-                ChangeLog cl = new ChangeLog();
-                cl.added(root);
-                cl.added(pt);
-                pMgr.store(cl);
-            }
-
             // need to store the version storage root directly into the persistence manager
             if (!pMgr.exists(historiesId)) {
                 NodeState root = pMgr.createNew(historiesId);
@@ -701,13 +653,13 @@ public class InternalVersionManagerImpl 
         /**
          * the observation manager
          */
-        private DelegatingObservationDispatcher obsMgr;
+        private final DelegatingObservationDispatcher obsMgr;
 
         /**
-         * the current event source
+         * The event source of the current thread.
          */
-        private SessionImpl source;
-
+        private final ThreadLocal<SessionImpl> source =
+            new ThreadLocal<SessionImpl>();
 
         /**
          * Creates a new event state collection factory
@@ -725,12 +677,14 @@ public class InternalVersionManagerImpl 
          * association between update operation and session who actually invoked
          * the update, an internal event source is used.
          */
-        public synchronized EventStateCollection createEventStateCollection()
+        public EventStateCollection createEventStateCollection()
                 throws RepositoryException {
-            if (source == null) {
+            SessionImpl session = source.get();
+            if (session != null) {
+                return createEventStateCollection(session);
+            } else {
                 throw new RepositoryException("Unknown event source.");
             }
-            return createEventStateCollection(source);
         }
 
         /**
@@ -753,15 +707,16 @@ public class InternalVersionManagerImpl 
          * @return the return value of the executed runnable
          * @throws RepositoryException if an error occurs
          */
-        public synchronized Object doSourced(SessionImpl eventSource, SourcedTarget runnable)
+        public Object doSourced(SessionImpl eventSource, SourcedTarget runnable)
                 throws RepositoryException {
-            this.source = eventSource;
+            source.set(eventSource);
             try {
                 return runnable.run();
             } finally {
-                this.source = null;
+                source.remove();
             }
         }
+
     }
 
     private abstract class SourcedTarget {

Modified: jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/TestAll.java?rev=1038604&r1=1038603&r2=1038604&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/TestAll.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/state/TestAll.java Wed Nov 24 13:59:16 2010
@@ -37,6 +37,7 @@ public class TestAll extends TestCase {
 
         suite.addTestSuite(ChangeLogTest.class);
         suite.addTestSuite(DefaultISMLockingTest.class);
+        suite.addTestSuite(DefaultISMLockingDeadlockTest.class);
         suite.addTestSuite(FineGrainedISMLockingTest.class);
         suite.addTestSuite(NameSetTest.class);