### Eclipse Workspace Patch 1.0 #P jackrabbit-core Index: src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java (revision 1360013) +++ src/main/java/org/apache/jackrabbit/core/version/VersioningLock.java (working copy) @@ -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 @@ /** * 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 @@ } } - - /** - * 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 Index: src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (revision 1337147) +++ src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (working copy) @@ -22,7 +22,6 @@ 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; @@ -37,14 +36,12 @@ import javax.jcr.lock.LockException; import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; -import javax.transaction.xa.Xid; import org.apache.commons.collections.map.LinkedMap; import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.core.NodeImpl; 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; @@ -61,6 +58,7 @@ 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; @@ -69,8 +67,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import EDU.oswego.cs.dl.util.concurrent.ReentrantLock; - /** * Provides the functionality needed for locking and unlocking nodes. */ @@ -93,74 +89,11 @@ private final PathMap lockMap = new PathMap(); /** - * 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 active 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} - */ - @Override - 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} - */ - @Override - 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; @@ -868,11 +801,7 @@ private void acquire() { for (;;) { try { - if (TransactionContext.getCurrentXid() == null) { - lockMapLock.acquire(); - } else { - xidlockMapLock.acquire(); - } + lockMapLock.acquire(); break; } catch (InterruptedException e) { // ignore @@ -884,11 +813,7 @@ * Release lock on the lock map. */ private void release() { - if (TransactionContext.getCurrentXid() == null) { - lockMapLock.release(); - } else { - xidlockMapLock.release(); - } + lockMapLock.release(); } /** Index: src/main/java/org/apache/jackrabbit/core/journal/JournalLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/journal/JournalLock.java (revision 1354499) +++ src/main/java/org/apache/jackrabbit/core/journal/JournalLock.java (working copy) @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.jackrabbit.core.journal; - -import static org.apache.jackrabbit.core.TransactionContext.getCurrentThreadId; -import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId; -import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock; - -/** - * A reentrant read-write lock used by the Journal for synchronization. - * Unlike a normal reentrant lock, this one allows the lock - * to be re-entered not just by a thread that's already holding the lock but - * by any thread within the same transaction. - */ -public class JournalLock 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 Index: src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java (working copy) @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.util; + +import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId; +import org.apache.jackrabbit.core.TransactionContext; +import EDU.oswego.cs.dl.util.concurrent.ReentrantLock; + +/** + * A reentrant lock for synchronization. + * Unlike a normal reentrant lock, this one allows the lock + * to be re-entered not just by a thread that's already holding the lock but + * by any thread within the same transaction. + */ +public class XAReentrantLock extends ReentrantLock { + + /** + * The active lock holder of this {@link ReentrantLock} + */ + private Object activeId; + + /** + * {@inheritDoc} + */ + @Override + public void acquire() throws InterruptedException { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + Object currentId = TransactionContext.getCurrentThreadId(); + synchronized(this) { + if (currentId == activeId || (activeId != null && isSameThreadId(activeId, currentId))) { + ++holds_; + } else { + try { + while (activeId != null) { + wait(); + } + activeId = currentId; + holds_ = 1; + } catch (InterruptedException ex) { + notify(); + throw ex; + } + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public synchronized void release() { + Object currentId = TransactionContext.getCurrentThreadId(); + if (activeId != null && !isSameThreadId(activeId, currentId)) { + throw new Error("Illegal Lock usage"); + } + + if (--holds_ == 0) { + activeId = null; + notify(); + } + } +} Index: src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java (working copy) Property changes on: src/main/java/org/apache/jackrabbit/core/util/XAReentrantLock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java (revision 1354499) +++ src/main/java/org/apache/jackrabbit/core/journal/AbstractJournal.java (working copy) @@ -21,6 +21,7 @@ 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.slf4j.Logger; import org.slf4j.LoggerFactory; -import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock; - /** * Base journal implementation. */ @@ -70,7 +69,7 @@ * 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. Index: src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java (working copy) @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.util; + +import static org.apache.jackrabbit.core.TransactionContext.getCurrentThreadId; +import static org.apache.jackrabbit.core.TransactionContext.isSameThreadId; +import EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock; + +/** + * A reentrant read-write lock for synchronization. + * Unlike a normal reentrant lock, this one allows the lock + * to be re-entered not just by a thread that's already holding the lock but + * by any thread within the same transaction. + */ +public class XAReentrantWriterPreferenceReadWriteLock 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; + } + } + } + +} Index: src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java (working copy) Property changes on: src/main/java/org/apache/jackrabbit/core/util/XAReentrantWriterPreferenceReadWriteLock.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property