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