You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by un...@apache.org on 2012/09/27 14:22:42 UTC

svn commit: r1390963 - in /jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: journal/ lock/ util/ version/

Author: unico
Date: Thu Sep 27 12:22:41 2012
New Revision: 1390963

URL: http://svn.apache.org/viewvc?rev=1390963&view=rev
Log:
JCR-3392 Backport: Combine the XA aware (Reentrant) LockImpls to prevent duplicate code

Added:
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java
      - copied unchanged from r1363218, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java
      - copied unchanged from r1363218, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java
Removed:
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/JournalLock.java
Modified:
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
    jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java?rev=1390963&r1=1390962&r2=1390963&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java Thu Sep 27 12:22:41 2012
@@ -21,6 +21,7 @@ import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.jackrabbit.core.util.XAReentrantWriterPreferenceReadWriteLock;
 import org.apache.jackrabbit.core.version.InternalVersionManagerImpl;
 import org.apache.jackrabbit.core.version.VersioningLock;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
@@ -29,8 +30,6 @@ import org.apache.jackrabbit.spi.commons
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
-
 /**
  * Base journal implementation.
  */
@@ -70,7 +69,7 @@ public abstract class AbstractJournal im
      * Journal lock, allowing multiple readers (synchronizing their contents)
      * but only one writer (appending a new entry).
      */
-    private final ReadWriteLock rwLock = new JournalLock();
+    private final XAReentrantWriterPreferenceReadWriteLock rwLock = new XAReentrantWriterPreferenceReadWriteLock();
 
     /**
      * The path of the local revision file on disk. Configurable through the repository.xml.

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=1390963&r1=1390962&r2=1390963&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Thu Sep 27 12:22:41 2012
@@ -16,16 +16,32 @@
  */
 package org.apache.jackrabbit.core.lock;
 
-import EDU.oswego.cs.dl.util.concurrent.ReentrantLock;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.lock.Lock;
+import javax.jcr.lock.LockException;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+
 import org.apache.commons.collections.map.LinkedMap;
 import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.core.id.ItemId;
-import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.SessionListener;
-import org.apache.jackrabbit.core.TransactionContext;
 import org.apache.jackrabbit.core.WorkspaceImpl;
 import org.apache.jackrabbit.core.cluster.ClusterOperation;
 import org.apache.jackrabbit.core.cluster.LockEventChannel;
@@ -33,43 +49,24 @@ import org.apache.jackrabbit.core.cluste
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.id.ItemId;
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.observation.EventImpl;
 import org.apache.jackrabbit.core.observation.SynchronousEventListener;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.PropertyState;
 import org.apache.jackrabbit.core.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.core.util.XAReentrantLock;
 import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.PathMap;
-import javax.jcr.Workspace;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.lock.Lock;
-import javax.jcr.lock.LockException;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.transaction.xa.Xid;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
 /**
  * Provides the functionality needed for locking and unlocking nodes.
  */
@@ -92,68 +89,11 @@ public class LockManagerImpl
     private final PathMap<LockInfo> lockMap = new PathMap<LockInfo>();
 
     /**
-     * Thread aware lock to path map.
+     * XA/Thread aware lock to path map.
      */
-    private final ReentrantLock lockMapLock = new ReentrantLock();
+    private final XAReentrantLock lockMapLock = new XAReentrantLock();
     
     /**
-     * Xid aware lock to path map.
-     */
-    private final ReentrantLock xidlockMapLock = new ReentrantLock(){
-
-    	/**
-    	 * The actice Xid of this {@link ReentrantLock}
-    	 */
-        private Xid activeXid;
-
-        /**
-         * Check if the given Xid comes from the same globalTX
-         * @param otherXid
-         * @return true if same globalTX otherwise false
-         */
-        boolean isSameGlobalTx(Xid otherXid) {
-    	    return (activeXid == otherXid) || Arrays.equals(activeXid.getGlobalTransactionId(), otherXid.getGlobalTransactionId());
-    	}
-        
-        /**
-         * {@inheritDoc}
-         */
-        public void acquire() throws InterruptedException {
-        	if (Thread.interrupted()) throw new InterruptedException();
-        	Xid currentXid = TransactionContext.getCurrentXid();
-            synchronized(this) {
-            	if (currentXid == activeXid || (activeXid != null && isSameGlobalTx(currentXid))) { 
-                ++holds_;
-            	} else {
-            		try {  
-            			while (activeXid != null) 
-            				wait(); 
-            			activeXid = currentXid;
-            			holds_ = 1;
-            		} catch (InterruptedException ex) {
-            			notify();
-            			throw ex;
-            		}
-            	}
-            }
-        }
-        
-        /**
-         * {@inheritDoc}
-         */
-        public synchronized void release()  {
-        	Xid currentXid = TransactionContext.getCurrentXid();
-            if (activeXid != null && !isSameGlobalTx(currentXid))
-                throw new Error("Illegal Lock usage"); 
-
-              if (--holds_ == 0) {
-                activeXid = null;
-                notify(); 
-              }
-        }
-    };
-
-    /**
      * The periodically invoked lock timeout handler.
      */
     private final ScheduledFuture<?> timeoutHandler;
@@ -226,26 +166,31 @@ public class LockManagerImpl
      *      JSR 283: Locking
      */
     private class TimeoutHandler implements Runnable {
+        private final TimeoutHandlerVisitor visitor = new TimeoutHandlerVisitor();
+
         public void run() {
-            lockMap.traverse(new PathMap.ElementVisitor<LockInfo>() {
-                public void elementVisited(PathMap.Element<LockInfo> element) {
-                    LockInfo info = element.get();
-                    if (info != null && info.isLive() && info.isExpired()) {
-                        NodeId id = info.getId();
-                        SessionImpl holder = info.getLockHolder();
-                        if (holder == null) {
-                            info.setLockHolder(sysSession);
-                            holder = sysSession;
-                        }
-                        try {
-                            // FIXME: This session access is not thread-safe!
-                            unlock(holder.getNodeById(id));
-                        } catch (RepositoryException e) {
-                            log.warn("Unable to expire the lock " + id, e);
-                        }
-                    }
+            lockMap.traverse(visitor, false);
+        }
+    }
+
+    private class TimeoutHandlerVisitor implements
+            PathMap.ElementVisitor<LockInfo> {
+        public void elementVisited(PathMap.Element<LockInfo> element) {
+            LockInfo info = element.get();
+            if (info != null && info.isLive() && info.isExpired()) {
+                NodeId id = info.getId();
+                SessionImpl holder = info.getLockHolder();
+                if (holder == null) {
+                    info.setLockHolder(sysSession);
+                    holder = sysSession;
+                }
+                try {
+                    // FIXME: This session access is not thread-safe!
+                    unlock(holder.getNodeById(id));
+                } catch (RepositoryException e) {
+                    log.warn("Unable to expire the lock " + id, e);
                 }
-            }, false);
+            }
         }
     }
 
@@ -787,10 +732,8 @@ public class LockManagerImpl
             PathMap.Element<LockInfo> element = lockMap.map(path, true);
             if (element != null) {
                 LockInfo info = element.get();
-                if (info != null) {
-                    if (info.isLockHolder(session)) {
-                        // nothing to do
-                    } else if (info.getLockHolder() == null) {
+                if (info != null && !info.isLockHolder(session)) {
+                    if (info.getLockHolder() == null) {
                         info.setLockHolder(session);
                         if (info instanceof InternalLockInfo) {
                             session.addListener((InternalLockInfo) info);
@@ -828,9 +771,7 @@ public class LockManagerImpl
                 if (info != null) {
                     if (info.isLockHolder(session)) {
                         info.setLockHolder(null);
-                    } else if (info.getLockHolder() == null) {
-                        // nothing to do
-                    } else {
+                    } else if (info.getLockHolder() != null) {
                         String msg = "Cannot remove lock token: lock held by other session.";
                         log.warn(msg);
                         info.throwLockException(msg, session);
@@ -848,7 +789,7 @@ public class LockManagerImpl
 
     /**
      * Return the path of an item given its id. This method will lookup the
-     * item inside the systme session.
+     * item inside the system session.
      */
     private Path getPath(SessionImpl session, ItemId id) throws RepositoryException {
         return session.getHierarchyManager().getPath(id);
@@ -860,11 +801,7 @@ public class LockManagerImpl
     private void acquire() {
         for (;;) {
             try {
-            	if (TransactionContext.getCurrentXid() == null) {
-            		lockMapLock.acquire();
-            	} else {
-            		xidlockMapLock.acquire();
-            	}
+           		lockMapLock.acquire();
                 break;
             } catch (InterruptedException e) {
                 // ignore
@@ -876,11 +813,7 @@ public class LockManagerImpl
      * Release lock on the lock map.
      */
     private void release() {
-    	if (TransactionContext.getCurrentXid() == null) {
-    		lockMapLock.release();
-    	} else {
-    		xidlockMapLock.release();
-    	}
+   		lockMapLock.release();
     }
 
     /**
@@ -1030,7 +963,7 @@ public class LockManagerImpl
     /**
      * Internal event class that holds old and new paths for moved nodes
      */
-    private class HierarchyEvent {
+    private static class HierarchyEvent {
 
         /**
          * ID recorded in event

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java?rev=1390963&r1=1390962&r2=1390963&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java Thu Sep 27 12:22:41 2012
@@ -16,10 +16,9 @@
  */
 package org.apache.jackrabbit.core.version;
 
-import static org.apache.jackrabbit.core.TransactionContext.getCurrentThreadId;
-import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId;
+import org.apache.jackrabbit.core.util.XAReentrantWriterPreferenceReadWriteLock;
+
 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
-import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock;
 import EDU.oswego.cs.dl.util.concurrent.Sync;
 
 /**
@@ -33,7 +32,7 @@ public class VersioningLock {
     /**
      * The internal read-write lock.
      */
-    private final ReadWriteLock rwLock = new XAAwareRWLock();
+    private final XAReentrantWriterPreferenceReadWriteLock rwLock = new XAReentrantWriterPreferenceReadWriteLock();
 
     public ReadLock acquireReadLock() throws InterruptedException {
     	return new ReadLock(rwLock.readLock());
@@ -79,110 +78,4 @@ public class VersioningLock {
         }
 
     }
-
-    /**
-     * XA concerning ReentrantWriterPreferenceReadWriteLock
-     */
-    private static final class XAAwareRWLock
-            extends ReentrantWriterPreferenceReadWriteLock {
-
-    	private Object activeWriter;
-
-        /**
-         * {@inheritDoc}
-         */
-        protected boolean allowReader() {
-            Object currentId = getCurrentThreadId();
-            return (activeWriter == null && waitingWriters_ == 0) || isSameThreadId(activeWriter, currentId);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        protected synchronized boolean startWrite() {
-        	Object currentId = getCurrentThreadId();
-            if (activeWriter != null && isSameThreadId(activeWriter, currentId)) { // already held; re-acquire
-            	++writeHolds_;
-                return true;
-            } else if (writeHolds_ == 0) {
-            	if (activeReaders_ == 0 || (readers_.size() == 1 && readers_.get(currentId) != null)) {
-            		activeWriter = currentId;
-            		writeHolds_ = 1;
-            		return true;
-            	} else {
-            		return false;
-            	}
-            } else {
-            	return false;
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        protected synchronized Signaller endWrite() {
-            --writeHolds_;
-            if (writeHolds_ > 0) {  // still being held
-            	return null;
-            } else {
-            	activeWriter = null;
-                if (waitingReaders_ > 0 && allowReader()) {
-                    return readerLock_;
-                } else if (waitingWriters_ > 0) {
-                    return writerLock_;
-                } else {
-                    return null;
-                }
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-    	@SuppressWarnings("unchecked")
-    	protected synchronized boolean startRead() {
-    		Object currentId = getCurrentThreadId();
-    	    Object c = readers_.get(currentId);
-    	    if (c != null) { // already held -- just increment hold count
-    	    	readers_.put(currentId, new Integer(((Integer)(c)).intValue()+1));
-    	    	++activeReaders_;
-    	    	return true;
-    	    } else if (allowReader()) {
-    	    	readers_.put(currentId, IONE);
-    	    	++activeReaders_;
-    	    	return true;
-    	    } else {
-    	    	return false;
-    	    }
-    	}
-
-        /**
-         * {@inheritDoc}
-         */
-    	@SuppressWarnings("unchecked")
-    	protected synchronized Signaller endRead() {
-    		Object currentId = getCurrentThreadId();
-    	    Object c = readers_.get(currentId);
-    	    if (c == null) {
-    	    	throw new IllegalStateException();
-    	    }
-    	    --activeReaders_;
-    	    if (c != IONE) { // more than one hold; decrement count
-    	    	int h = ((Integer)(c)).intValue()-1;
-    	    	Integer ih = (h == 1)? IONE : new Integer(h);
-    	    	readers_.put(currentId, ih);
-    	    	return null;
-    	    } else {
-    	    	readers_.remove(currentId);
-    	    
-    	    	if (writeHolds_ > 0) { // a write lock is still held
-    	    		return null;
-    	    	} else if (activeReaders_ == 0 && waitingWriters_ > 0) {
-    	    		return writerLock_;
-    	    	} else  {
-    	    		return null;
-    	    	}
-    	    }
-    	}
-    }
 }
\ No newline at end of file