You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ck...@apache.org on 2009/09/28 12:30:36 UTC
svn commit: r819491 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
test/java/org/apache/jackrabbit/core/UserTransactionImpl.java
test/java/org/apache/jackrabbit/core/XATest.java
Author: ckoell
Date: Mon Sep 28 10:30:36 2009
New Revision: 819491
URL: http://svn.apache.org/viewvc?rev=819491&view=rev
Log:
JCR-769 Unable to login with two different Credentials to same workspace in one Transaction
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/UserTransactionImpl.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java?rev=819491&r1=819490&r2=819491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/DefaultISMLocking.java Mon Sep 28 10:30:36 2009
@@ -16,10 +16,14 @@
*/
package org.apache.jackrabbit.core.state;
+import java.util.Arrays;
+
import javax.transaction.xa.Xid;
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;
@@ -32,6 +36,11 @@
public class DefaultISMLocking implements ISMLocking {
/**
+ * Logger instance
+ */
+ private static final Logger log = LoggerFactory.getLogger(DefaultISMLocking.class);
+
+ /**
* The internal read-write lock.
*/
private final RWLock rwLock = new RWLock();
@@ -60,7 +69,6 @@
* {@inheritDoc}
*/
public void release() {
- rwLock.setActiveXid(null);
rwLock.writeLock().release();
}
@@ -109,8 +117,36 @@
* @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;
}
-
+
+ /**
+ * {@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;
+ }
+ }
+ }
}
}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/UserTransactionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/UserTransactionImpl.java?rev=819491&r1=819490&r2=819491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/UserTransactionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/UserTransactionImpl.java Mon Sep 28 10:30:36 2009
@@ -16,6 +16,10 @@
*/
package org.apache.jackrabbit.core;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import javax.transaction.xa.XAException;
@@ -41,14 +45,9 @@
private static byte counter = 0;
/**
- * XAResource
- */
- private final XAResource xares;
-
- /**
- * Xid
+ * The XAResources map
*/
- private Xid xid;
+ private Map xaResources = new HashMap();
/**
* Status
@@ -75,7 +74,8 @@
*/
public UserTransactionImpl(Session session, boolean distributedThreadAccess) {
if (session instanceof XASession) {
- xares = ((XASession) session).getXAResource();
+ counter++;
+ xaResources.put(((XASession) session).getXAResource(), new XidImpl(counter));
this.distributedThreadAccess = distributedThreadAccess;
} else {
throw new IllegalArgumentException("Session not of type XASession");
@@ -83,6 +83,14 @@
}
/**
+ * Enlists the given Session to this UserTransaction
+ * @param session
+ */
+ public void enlistXAResource(Session session) {
+ xaResources.put(session, new XidImpl(counter));
+ }
+
+ /**
* @see javax.transaction.UserTransaction#begin
*/
public void begin() throws NotSupportedException, SystemException {
@@ -91,8 +99,11 @@
}
try {
- xid = new XidImpl(counter++);
- xares.start(xid, XAResource.TMNOFLAGS);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.start(xid, XAResource.TMNOFLAGS);
+ }
status = Status.STATUS_ACTIVE;
} catch (XAException e) {
@@ -114,10 +125,18 @@
}
try {
- xares.end(xid, XAResource.TMSUCCESS);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.end(xid, XAResource.TMSUCCESS);
+ }
status = Status.STATUS_PREPARING;
- xares.prepare(xid);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.prepare(xid);
+ }
status = Status.STATUS_PREPARED;
status = Status.STATUS_COMMITTING;
@@ -125,7 +144,11 @@
Thread distributedThread = new Thread() {
public void run() {
try {
- xares.commit(xid, false);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.commit(xid, false);
+ }
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
@@ -138,7 +161,11 @@
"Commit from different thread but same XID must not block");
}
} else {
- xares.commit(xid, false);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.commit(xid, false);
+ }
}
status = Status.STATUS_COMMITTED;
@@ -182,10 +209,18 @@
}
try {
- xares.end(xid, XAResource.TMFAIL);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.end(xid, XAResource.TMFAIL);
+ }
status = Status.STATUS_ROLLING_BACK;
- xares.rollback(xid);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ XAResource resource = (XAResource) it.next();
+ XidImpl xid = (XidImpl) xaResources.get(resource);
+ resource.rollback(xid);
+ }
status = Status.STATUS_ROLLEDBACK;
} catch (XAException e) {
@@ -211,7 +246,9 @@
*/
public void setTransactionTimeout(int seconds) throws SystemException {
try {
- xares.setTransactionTimeout(seconds);
+ for (Iterator it = xaResources.keySet().iterator(); it.hasNext(); ) {
+ ((XAResource) it.next()).setTransactionTimeout(seconds);
+ }
} catch (XAException e) {
SystemException se = new SystemException(
"Unable to set the TransactionTiomeout: XA_ERR=" + e.errorCode);
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java?rev=819491&r1=819490&r2=819491&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/XATest.java Mon Sep 28 10:30:36 2009
@@ -1643,6 +1643,99 @@
fail("Committed node not visible in this session");
}
}
+
+ /**
+ * Tests two different Sessions in one Transaction
+ * (see JCR-769)
+ */
+ public void testTwoSessionsInOneTransaction() throws Exception {
+ Session otherSuperuser = getHelper().getSuperuserSession();
+
+ // get user transaction object
+ UserTransactionImpl utx = new UserTransactionImpl(superuser, true);
+ utx.enlistXAResource(otherSuperuser);
+
+ // start transaction
+ utx.begin();
+
+ Node rootNode = superuser.getRootNode();
+ // add node and save
+ Node n = rootNode.addNode(nodeName1, testNodeType);
+ n.addMixin(mixReferenceable);
+ rootNode.save();
+
+ // assertion: node exists in this session
+ try {
+ superuser.getNodeByUUID(n.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("New node not visible after save()");
+ }
+
+ // assertion: node does exist in other session
+ try {
+ otherSuperuser.getNodeByUUID(n.getUUID());
+ fail("Uncommitted node visible for other session");
+ } catch (ItemNotFoundException e) {
+ /* expected */
+ }
+
+ // add node with other session and save
+ rootNode = otherSuperuser.getRootNode();
+ Node n1 = rootNode.addNode(nodeName2, testNodeType);
+ n1.addMixin(mixReferenceable);
+ rootNode.save();
+
+ // assertion: node exists in this session
+ try {
+ otherSuperuser.getNodeByUUID(n1.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("New node not visible after save()");
+ }
+
+ // assertion: node does exist in other session
+ try {
+ superuser.getNodeByUUID(n1.getUUID());
+ fail("Uncommitted node visible for other session");
+ } catch (ItemNotFoundException e) {
+ /* expected */
+ }
+
+
+ // commit
+ utx.commit();
+
+ // assertion: node exists in this session
+ try {
+ superuser.getNodeByUUID(n.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("Committed node not visible in this session");
+ }
+
+ // assertion: node also exists in other session
+ try {
+ otherSuperuser.getNodeByUUID(n.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("Committed node not visible in the other session");
+ }
+
+ // assertion: node1 exists in this session
+ try {
+ superuser.getNodeByUUID(n1.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("Committed node not visible in this session");
+ }
+
+ // assertion: node1 also exists in other session
+ try {
+ otherSuperuser.getNodeByUUID(n1.getUUID());
+ } catch (ItemNotFoundException e) {
+ fail("Committed node not visible in this session");
+ }
+
+ // logout
+ superuser.logout();
+ otherSuperuser.logout();
+ }
/**
* Test setting the same property multiple times. Exposes an issue where