jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dpfis...@apache.org
Subject svn commit: r741652 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java test/java/org/apache/jackrabbit/core/XATest.java
Date Fri, 06 Feb 2009 17:53:32 GMT
Author: dpfister
Date: Fri Feb  6 17:53:32 2009
New Revision: 741652

URL: http://svn.apache.org/viewvc?rev=741652&view=rev
Log:
JCR-1554 - StaleItemStateException with distributed transactions

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.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/XAItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java?rev=741652&r1=741651&r2=741652&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/XAItemStateManager.java
Fri Feb  6 17:53:32 2009
@@ -27,6 +27,8 @@
 import org.apache.jackrabbit.uuid.UUID;
 import org.apache.commons.collections.iterators.FilterIterator;
 import org.apache.commons.collections.Predicate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.PropertyType;
@@ -44,6 +46,11 @@
 public class XAItemStateManager extends LocalItemStateManager implements InternalXAResource
{
 
     /**
+     * The logger instance.
+     */
+    private static Logger log = LoggerFactory.getLogger(XAItemStateManager.class);
+
+    /**
      * Default change log attribute name.
      */
     private static final String DEFAULT_ATTRIBUTE_NAME = "ChangeLog";
@@ -559,4 +566,30 @@
             references.modified(refs);
         }
     }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Check whether the shared state modified is contained in our transactional
+     * log: in that case, update its state as well, as it might get reused
+     * in a subsequent transaction (see JCR-1554).
+     */
+    public void stateModified(ItemState modified) {
+        ChangeLog changeLog = (ChangeLog) commitLogs.get(Thread.currentThread());
+        if (changeLog != null) {
+            ItemState local;
+            if (modified.getContainer() != this) {
+                // shared state was modified
+                try {
+                    local = changeLog.get(modified.getId());
+                    if (local != null && local.isConnected()) {
+                        local.pull();
+                    }
+                } catch (NoSuchItemStateException e) {
+                    log.warn("Modified state marked for deletion: " + modified.getId());
+                }
+            }
+        }
+        super.stateModified(modified);
+    }
 }

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=741652&r1=741651&r2=741652&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
Fri Feb  6 17:53:32 2009
@@ -1468,7 +1468,7 @@
         // assert: version label known in other session
         nOther.getVersionHistory().getVersionByLabel(versionLabel);
     }
-    
+
     /**
      * Tests two different Threads for prepare and commit in a Transaction
      */
@@ -1501,4 +1501,104 @@
             fail("Committed node not visible in this session");
         }
     }
+
+    /**
+     * Test setting the same property multiple times. Exposes an issue where
+     * the same property instance got reused in subsequent transactions
+     * (see JCR-1554).
+     *
+     * @throws Exception if an error occurs
+     */
+    public void testSetProperty() throws Exception {
+        final String testNodePath = testPath + "/" + Math.random();
+
+        Session session = helper.getSuperuserSession();
+
+        // Add node
+        doTransactional(new Operation() {
+            public void invoke(Session session) throws Exception {
+                session.getRootNode().addNode(testNodePath);
+                session.save();
+            }
+        }, session);
+
+        for (int i = 1; i <= 3; i++) {
+            // Set property "name" to value "value"
+            doTransactional(new Operation() {
+                public void invoke(Session session) throws Exception {
+                    Node n = (Node) session.getItem("/" + testNodePath);
+                    n.setProperty("name", "value");
+                    session.save();
+                }
+            }, session);
+        }
+    }
+
+    /**
+     * Test deleting a subnode after creation. Exposes an issue where
+     * the same node instance got reused in subsequent transactions
+     * (see JCR-1554).
+     *
+     * @throws Exception if an error occurs
+     */
+    public void testDeleteNode() throws Exception {
+        final String testNodePath = testPath + "/" + Math.random();
+
+        Session session = helper.getSuperuserSession();
+
+        for (int i = 1; i <= 3; i++) {
+            // Add parent node
+            doTransactional(new Operation() {
+                public void invoke(Session session) throws Exception {
+                    session.getRootNode().addNode(testNodePath);
+                    session.save();
+                }
+            }, session);
+
+            // Add child node
+            doTransactional(new Operation() {
+                public void invoke(Session session) throws Exception {
+                    session.getRootNode().addNode(testNodePath + "/subnode");
+                    session.save();
+                }
+            }, session);
+
+            // Remove parent node
+            doTransactional(new Operation() {
+                public void invoke(Session session) throws Exception {
+                    session.getRootNode().getNode(testNodePath).remove();
+                    session.save();
+                }
+            }, session);
+        }
+    }
+
+    /**
+     * Operation to invoke on a session scope.
+     */
+    interface Operation {
+
+        /**
+         * Invoke the operation.
+         * @param session session to use inside operation
+         * @throws Exception if an error occurs
+         */
+        void invoke(Session session) throws Exception;
+    }
+
+    /**
+     * Wrap a session-scoped operation with a transaction.
+     *
+     * @param op operation to invoke
+     * @param session session to use for the transaction
+     * @throws Exception if an error occurs
+     */
+    private void doTransactional(Operation op, Session session) throws Exception {
+        UserTransaction utx = new UserTransactionImpl(session);
+        utx.begin();
+
+        op.invoke(session);
+
+        utx.commit();
+    }
 }



Mime
View raw message