jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r388178 - in /jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core: RepositoryImpl.java XASessionImpl.java XAWorkspace.java state/SharedItemStateManager.java
Date Thu, 23 Mar 2006 14:21:36 GMT
Author: tripod
Date: Thu Mar 23 06:21:11 2006
New Revision: 388178

URL: http://svn.apache.org/viewcvs?rev=388178&view=rev
Log:
[JCR-335] Deadlock caused by versioning operations within transaction

Modified:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=388178&r1=388177&r2=388178&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
Thu Mar 23 06:21:11 2006
@@ -16,14 +16,15 @@
  */
 package org.apache.jackrabbit.core;
 
+import EDU.oswego.cs.dl.util.concurrent.Mutex;
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.config.FileSystemConfig;
 import org.apache.jackrabbit.core.config.LoginModuleConfig;
 import org.apache.jackrabbit.core.config.PersistenceManagerConfig;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.core.config.VersioningConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
-import org.apache.jackrabbit.core.config.FileSystemConfig;
 import org.apache.jackrabbit.core.fs.BasedFileSystem;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -42,8 +43,8 @@
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
@@ -67,16 +68,16 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Properties;
 import java.util.Set;
-import java.util.HashSet;
-import java.nio.channels.FileLock;
-import java.nio.channels.FileChannel;
 
 /**
  * A <code>RepositoryImpl</code> ...
@@ -787,7 +788,7 @@
      * @throws RepositoryException      if another error occurs
      */
     protected final synchronized SessionImpl createSession(AuthContext loginContext,
-                              String workspaceName)
+                                                           String workspaceName)
             throws NoSuchWorkspaceException, AccessDeniedException,
             RepositoryException {
         WorkspaceInfo wspInfo = getWorkspaceInfo(workspaceName);
@@ -817,7 +818,7 @@
      * @throws RepositoryException      if another error occurs
      */
     protected final synchronized SessionImpl createSession(Subject subject,
-                                              String workspaceName)
+                                                           String workspaceName)
             throws NoSuchWorkspaceException, AccessDeniedException,
             RepositoryException {
         WorkspaceInfo wspInfo = getWorkspaceInfo(workspaceName);
@@ -1294,6 +1295,11 @@
         private long idleTimestamp;
 
         /**
+         * mutex for this workspace, used for locking transactions
+         */
+        private final Mutex xaLock = new Mutex();
+
+        /**
          * Creates a new <code>WorkspaceInfo</code> based on the given
          * <code>config</code>.
          *
@@ -1601,6 +1607,31 @@
             initialized = false;
 
             log.info("workspace '" + getName() + "' has been shutdown");
+        }
+
+        /**
+         * Locks this workspace info. This is used (and only should be) by
+         * the {@link XASessionImpl} in order to lock all internal resources
+         * during a commit.
+         *
+         * @throws TransactionException
+         */
+        void lockAcquire() throws TransactionException {
+            try {
+                xaLock.acquire();
+            } catch (InterruptedException e) {
+                throw new TransactionException("Error while acquiering lock", e);
+            }
+
+        }
+
+        /**
+         * Unlocks this workspace info. This is used (and only should be) by
+         * the {@link XASessionImpl} in order to lock all internal resources
+         * during a commit.
+         */
+        void lockRelease() {
+            xaLock.release();
         }
     }
 

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=388178&r1=388177&r2=388178&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
Thu Mar 23 06:21:11 2006
@@ -127,8 +127,16 @@
         XALockManager lockMgr = (XALockManager) getLockManager();
         XAVersionManager versionMgr = (XAVersionManager) getVersionManager();
 
+        /**
+         * Create array that contains all resources that paricipate in this
+         * transactions. Because some resources depend on each other, there is
+         * also a workspace scoped lock resource inserted, that guards the
+         * entire transaction from deadlocks (see JCR-335) 
+         */
         txResources = new InternalXAResource[] {
-            stateMgr, lockMgr, versionMgr
+            ((XAWorkspace) wsp).getXAResourceBegin(),
+            stateMgr, lockMgr, versionMgr,
+            ((XAWorkspace) wsp).getXAResourceEnd()
         };
         stateMgr.setVirtualProvider(versionMgr);
     }

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java?rev=388178&r1=388177&r2=388178&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
Thu Mar 23 06:21:11 2006
@@ -21,6 +21,8 @@
 import org.apache.jackrabbit.core.state.XAItemStateManager;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
 
+import javax.jcr.NoSuchWorkspaceException;
+
 /**
  * Workspace extension that works in an XA environment.
  */
@@ -47,5 +49,80 @@
     protected LocalItemStateManager createItemStateManager(SharedItemStateManager shared)
{
         return new XAItemStateManager(shared, this);
     }
+
+
+    /**
+     * Returns an internal XAResource that is used at the beginning of the
+     * resources chain in {@link XASessionImpl#init()}. This resource will lock
+     * the workspace on <code>prepare</code>.
+     *
+     * @return an internal XAResource
+     */
+    protected InternalXAResource getXAResourceBegin() {
+        return new InternalXAResource() {
+            public void associate(TransactionContext tx) {
+            }
+
+            public void beforeOperation(TransactionContext tx) {
+            }
+
+            public void prepare(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockAcquire();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while preparing for transaction",
e);
+                }
+            }
+
+            public void commit(TransactionContext tx) {
+            }
+
+            public void rollback(TransactionContext tx) {
+            }
+
+            public void afterOperation(TransactionContext tx) {
+            }
+        };
+    }
+
+    /**
+     * Returns an internal XAResource that is used at the end of the
+     * resources chain in {@link XASessionImpl#init()}. This resource will unlock
+     * the workspace on <code>commit</code> or on <code>rollback</code>.
+     *
+     * @return an internal XAResource
+     */
+    protected InternalXAResource getXAResourceEnd() {
+        return new InternalXAResource() {
+            public void associate(TransactionContext tx) {
+            }
+
+            public void beforeOperation(TransactionContext tx) {
+            }
+
+            public void prepare(TransactionContext tx) {
+            }
+
+            public void commit(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockRelease();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while commit transaction", e);
+                }
+            }
+
+            public void rollback(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockRelease();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while rollback transaction", e);
+                }
+            }
+
+            public void afterOperation(TransactionContext tx) {
+            }
+        };
+    }
+
 }
 

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewcvs/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=388178&r1=388177&r2=388178&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Thu Mar 23 06:21:11 2006
@@ -44,8 +44,8 @@
 import java.io.PrintStream;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.Set;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Shared <code>ItemStateManager</code> (SISM). Caches objects returned from
a
@@ -451,14 +451,6 @@
 
             virtualNodeReferences = new List[virtualProviders.length];
 
-            try {
-                events = factory.createEventStateCollection();
-            } catch (RepositoryException e) {
-                String msg = "Unable to create event state collection.";
-                log.error(msg);
-                throw new ItemStateException(msg, e);
-            }
-
             acquireWriteLock();
             holdingWriteLock = true;
 
@@ -477,6 +469,19 @@
                  * Check whether reference targets exist/were not removed
                  */
                 checkReferentialIntegrity(local);
+
+                /**
+                 * prepare the events. this needs to be after the referential
+                 * integrity check, since another transaction could have modified
+                 * the states.
+                 */
+                try {
+                    events = factory.createEventStateCollection();
+                } catch (RepositoryException e) {
+                    String msg = "Unable to create event state collection.";
+                    log.error(msg);
+                    throw new ItemStateException(msg, e);
+                }
 
                 /**
                  * Reconnect all items contained in the change log to their



Mime
View raw message