jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r409525 - in /jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core: ./ state/ version/
Date Fri, 26 May 2006 00:48:29 GMT
Author: jukka
Date: Thu May 25 17:48:28 2006
New Revision: 409525

URL: http://svn.apache.org/viewvc?rev=409525&view=rev
Log:
1.0: Merged revisions 388178 and 393004: JCR-335

Modified:
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
    jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
Thu May 25 17:48:28 2006
@@ -15,14 +15,15 @@
  */
 package org.apache.jackrabbit.core;
 
+import EDU.oswego.cs.dl.util.concurrent.Mutex;
 import org.apache.commons.collections.map.ReferenceMap;
 import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.config.FileSystemConfig;
 import org.apache.jackrabbit.core.config.LoginModuleConfig;
 import org.apache.jackrabbit.core.config.PersistenceManagerConfig;
 import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.core.config.VersioningConfig;
 import org.apache.jackrabbit.core.config.WorkspaceConfig;
-import org.apache.jackrabbit.core.config.FileSystemConfig;
 import org.apache.jackrabbit.core.fs.BasedFileSystem;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
@@ -41,8 +42,8 @@
 import org.apache.jackrabbit.core.state.SharedItemStateManager;
 import org.apache.jackrabbit.core.version.VersionManager;
 import org.apache.jackrabbit.core.version.VersionManagerImpl;
-import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.InputSource;
@@ -66,16 +67,16 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Properties;
 import java.util.Set;
-import java.util.HashSet;
-import java.nio.channels.FileLock;
-import java.nio.channels.FileChannel;
 
 /**
  * A <code>RepositoryImpl</code> ...
@@ -785,7 +786,7 @@
      * @throws RepositoryException      if another error occurs
      */
     protected synchronized final SessionImpl createSession(AuthContext loginContext,
-                              String workspaceName)
+                                                           String workspaceName)
             throws NoSuchWorkspaceException, AccessDeniedException,
             RepositoryException {
         WorkspaceInfo wspInfo = getWorkspaceInfo(workspaceName);
@@ -815,7 +816,7 @@
      * @throws RepositoryException      if another error occurs
      */
     protected synchronized final SessionImpl createSession(Subject subject,
-                                              String workspaceName)
+                                                           String workspaceName)
             throws NoSuchWorkspaceException, AccessDeniedException,
             RepositoryException {
         WorkspaceInfo wspInfo = getWorkspaceInfo(workspaceName);
@@ -1291,6 +1292,11 @@
         private long idleTimestamp;
 
         /**
+         * mutex for this workspace, used for locking transactions
+         */
+        private final Mutex xaLock = new Mutex();
+
+        /**
          * Creates a new <code>WorkspaceInfo</code> based on the given
          * <code>config</code>.
          *
@@ -1595,6 +1601,31 @@
             initialized = false;
 
             log.info("workspace '" + getName() + "' has been shutdown");
+        }
+
+        /**
+         * Locks this workspace info. This is used (and only should be) by
+         * the {@link XASessionImpl} in order to lock all internal resources
+         * during a commit.
+         *
+         * @throws TransactionException
+         */
+        void lockAcquire() throws TransactionException {
+            try {
+                xaLock.acquire();
+            } catch (InterruptedException e) {
+                throw new TransactionException("Error while acquiering lock", e);
+            }
+
+        }
+
+        /**
+         * Unlocks this workspace info. This is used (and only should be) by
+         * the {@link XASessionImpl} in order to lock all internal resources
+         * during a commit.
+         */
+        void lockRelease() {
+            xaLock.release();
         }
     }
 

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java
Thu May 25 17:48:28 2006
@@ -126,8 +126,16 @@
         XALockManager lockMgr = (XALockManager) getLockManager();
         XAVersionManager versionMgr = (XAVersionManager) getVersionManager();
 
+        /**
+         * Create array that contains all resources that paricipate in this
+         * transactions. Because some resources depend on each other, there is
+         * also a workspace scoped lock resource inserted, that guards the
+         * entire transaction from deadlocks (see JCR-335) 
+         */
         txResources = new InternalXAResource[] {
-            stateMgr, lockMgr, versionMgr
+            ((XAWorkspace) wsp).getXAResourceBegin(),
+            stateMgr, lockMgr, versionMgr,
+            ((XAWorkspace) wsp).getXAResourceEnd()
         };
         stateMgr.setVirtualProvider(versionMgr);
     }

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/XAWorkspace.java
Thu May 25 17:48:28 2006
@@ -20,6 +20,8 @@
 import org.apache.jackrabbit.core.state.XAItemStateManager;
 import org.apache.jackrabbit.core.state.LocalItemStateManager;
 
+import javax.jcr.NoSuchWorkspaceException;
+
 /**
  * Workspace extension that works in an XA environment.
  */
@@ -46,5 +48,80 @@
     protected LocalItemStateManager createItemStateManager(SharedItemStateManager shared)
{
         return new XAItemStateManager(shared, this);
     }
+
+
+    /**
+     * Returns an internal XAResource that is used at the beginning of the
+     * resources chain in {@link XASessionImpl#init()}. This resource will lock
+     * the workspace on <code>prepare</code>.
+     *
+     * @return an internal XAResource
+     */
+    protected InternalXAResource getXAResourceBegin() {
+        return new InternalXAResource() {
+            public void associate(TransactionContext tx) {
+            }
+
+            public void beforeOperation(TransactionContext tx) {
+            }
+
+            public void prepare(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockAcquire();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while preparing for transaction",
e);
+                }
+            }
+
+            public void commit(TransactionContext tx) {
+            }
+
+            public void rollback(TransactionContext tx) {
+            }
+
+            public void afterOperation(TransactionContext tx) {
+            }
+        };
+    }
+
+    /**
+     * Returns an internal XAResource that is used at the end of the
+     * resources chain in {@link XASessionImpl#init()}. This resource will unlock
+     * the workspace on <code>commit</code> or on <code>rollback</code>.
+     *
+     * @return an internal XAResource
+     */
+    protected InternalXAResource getXAResourceEnd() {
+        return new InternalXAResource() {
+            public void associate(TransactionContext tx) {
+            }
+
+            public void beforeOperation(TransactionContext tx) {
+            }
+
+            public void prepare(TransactionContext tx) {
+            }
+
+            public void commit(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockRelease();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while commit transaction", e);
+                }
+            }
+
+            public void rollback(TransactionContext tx) throws TransactionException {
+                try {
+                    rep.getWorkspaceInfo(wspConfig.getName()).lockRelease();
+                } catch (NoSuchWorkspaceException e) {
+                    throw new TransactionException("Error while rollback transaction", e);
+                }
+            }
+
+            public void afterOperation(TransactionContext tx) {
+            }
+        };
+    }
+
 }
 

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Thu May 25 17:48:28 2006
@@ -43,8 +43,8 @@
 import java.io.PrintStream;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.Set;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Shared <code>ItemStateManager</code> (SISM). Caches objects returned from
a
@@ -450,14 +450,6 @@
 
             virtualNodeReferences = new List[virtualProviders.length];
 
-            try {
-                events = factory.createEventStateCollection();
-            } catch (RepositoryException e) {
-                String msg = "Unable to create event state collection.";
-                log.error(msg);
-                throw new ItemStateException(msg, e);
-            }
-
             acquireWriteLock();
             holdingWriteLock = true;
 
@@ -476,6 +468,19 @@
                  * Check whether reference targets exist/were not removed
                  */
                 checkReferentialIntegrity(local);
+
+                /**
+                 * prepare the events. this needs to be after the referential
+                 * integrity check, since another transaction could have modified
+                 * the states.
+                 */
+                try {
+                    events = factory.createEventStateCollection();
+                } catch (RepositoryException e) {
+                    String msg = "Unable to create event state collection.";
+                    log.error(msg);
+                    throw new ItemStateException(msg, e);
+                }
 
                 /**
                  * Reconnect all items contained in the change log to their

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/AbstractVersionManager.java
Thu May 25 17:48:28 2006
@@ -59,7 +59,11 @@
      * {@inheritDoc}
      */
     public InternalVersion getVersion(NodeId id) throws RepositoryException {
-        return (InternalVersion) getItem(id);
+        InternalVersion v = (InternalVersion) getItem(id);
+        if (v == null) {
+            log.warn("Versioning item not found: " + id);
+        }
+        return v;
     }
 
     /**

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
Thu May 25 17:48:28 2006
@@ -15,50 +15,50 @@
  */
 package org.apache.jackrabbit.core.version;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.jackrabbit.core.observation.EventStateCollection;
+import org.apache.jackrabbit.core.observation.DelegatingObservationDispatcher;
+import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
+import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
+import org.apache.jackrabbit.core.value.InternalValue;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.observation.DelegatingObservationDispatcher;
-import org.apache.jackrabbit.core.observation.EventStateCollection;
-import org.apache.jackrabbit.core.observation.EventStateCollectionFactory;
+import org.apache.jackrabbit.core.state.PersistenceManager;
+import org.apache.jackrabbit.core.state.SharedItemStateManager;
+import org.apache.jackrabbit.core.state.LocalItemStateManager;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.state.ChangeLog;
 import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.LocalItemStateManager;
 import org.apache.jackrabbit.core.state.NodeReferences;
 import org.apache.jackrabbit.core.state.NodeReferencesId;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.state.PersistenceManager;
-import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.state.SharedItemStateManager;
-import org.apache.jackrabbit.core.value.InternalValue;
-import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
-import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.MalformedPathException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import javax.jcr.PropertyType;
-import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.RepositoryException;
+import javax.jcr.PropertyType;
 import javax.jcr.Session;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionException;
+import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.version.VersionHistory;
-import java.util.ArrayList;
+import javax.jcr.version.VersionException;
+import javax.jcr.version.Version;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * This Class implements a VersionManager.
  */
 public class VersionManagerImpl extends AbstractVersionManager
-        implements EventStateCollectionFactory {
+        /*implements EventStateCollectionFactory*/ {
 
     /**
      * the default logger
@@ -104,9 +104,9 @@
     private NodeTypeRegistry ntReg;
 
     /**
-     * the observation manager
+     * the dynamic event state collection factory
      */
-    private DelegatingObservationDispatcher obsMgr;
+    private final DynamicESCFactory escFactory;
 
     /**
      * Map of returned items. this is kept for invalidating
@@ -114,16 +114,6 @@
     private ReferenceMap versionItems = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
 
     /**
-     * Session to be used when creating observation events.
-     */
-    private transient SessionImpl eventSource;
-
-    /**
-     * workaround for potential deadlock
-     */
-    private final Object eventSourceLock = new Object();
-
-    /**
      * Creates a bew vesuion manager
      *
      */
@@ -133,7 +123,7 @@
         try {
             this.pMgr = pMgr;
             this.ntReg = ntReg;
-            this.obsMgr = obsMgr;
+            this.escFactory = new DynamicESCFactory(obsMgr);
 
             // need to store the version storage root directly into the persistence manager
             if (!pMgr.exists(rootId)) {
@@ -156,7 +146,7 @@
             }
             sharedStateMgr =
                     new VersionItemStateManager(pMgr, rootId, ntReg);
-            stateMgr = new LocalItemStateManager(sharedStateMgr, this);
+            stateMgr = new LocalItemStateManager(sharedStateMgr, escFactory);
             NodeState nodeState = (NodeState) stateMgr.getItemState(rootId);
             historyRoot = new NodeStateEx(stateMgr, ntReg, nodeState, QName.JCR_VERSIONSTORAGE);
 
@@ -183,22 +173,28 @@
     }
 
     /**
+     * Returns the event state collection factory.
+     * @return the event state collection factory.
+     */
+    public DynamicESCFactory getEscFactory() {
+        return escFactory;
+    }
+
+    /**
      * {@inheritDoc}
      * <p/>
      * This method must not be synchronized since it could cause deadlocks with
      * item-reading listeners in the observation thread.
      */
-    public VersionHistory createVersionHistory(Session session, NodeState node)
+    public VersionHistory createVersionHistory(Session session, final NodeState node)
             throws RepositoryException {
 
-        InternalVersionHistory history;
-        synchronized (eventSourceLock) {
-            // This needs to be synchronized since it sets the event source
-            // to be used when creating the events to be dispatched later on.
-            eventSource = (SessionImpl) session;
-
-            history = createVersionHistory(node);
-        }
+        InternalVersionHistory history = (InternalVersionHistory)
+                escFactory.doSourced((SessionImpl) session, new SourcedTarget(){
+            public Object run() throws RepositoryException {
+                return createVersionHistory(node);
+            }
+        });
 
         if (history == null) {
             throw new VersionException("History already exists for node " + node.getNodeId());
@@ -257,26 +253,26 @@
      * This method must not be synchronized since it could cause deadlocks with
      * item-reading listeners in the observation thread.
      */
-    public Version checkin(NodeImpl node) throws RepositoryException {
-        InternalVersion version;
-
-        synchronized (eventSourceLock) {
-            // This  needs to be synchronized since it sets the event source
-            // to be used when creating the events to be dispatched later on.
-            eventSource = (SessionImpl) node.getSession();
-
-            String histUUID = node.getProperty(QName.JCR_VERSIONHISTORY).getString();
-            version = checkin((InternalVersionHistoryImpl)
-                    getVersionHistory(NodeId.valueOf(histUUID)), node);
-
-            // invalidate predecessors successor properties
-            InternalVersion[] preds = version.getPredecessors();
-            for (int i = 0; i < preds.length; i++) {
-                PropertyId propId = new PropertyId(preds[i].getId(), QName.JCR_SUCCESSORS);
-                versProvider.onPropertyChanged(propId);
+    public Version checkin(final NodeImpl node) throws RepositoryException {
+        InternalVersion version = (InternalVersion)
+                escFactory.doSourced((SessionImpl) node.getSession(), new SourcedTarget(){
+            public Object run() throws RepositoryException {
+                String histUUID = node.getProperty(QName.JCR_VERSIONHISTORY).getString();
+                InternalVersion version = checkin((InternalVersionHistoryImpl)
+                        getVersionHistory(NodeId.valueOf(histUUID)), node);
+
+                // invalidate predecessors successor properties
+                InternalVersion[] preds = version.getPredecessors();
+                for (int i = 0; i < preds.length; i++) {
+                    PropertyId propId = new PropertyId(preds[i].getId(), QName.JCR_SUCCESSORS);
+                    versProvider.onPropertyChanged(propId);
+                }
+                return version;
             }
-        }
-        return (AbstractVersion) eventSource.getNodeById(version.getId());
+        });
+
+        return (AbstractVersion)
+                ((SessionImpl) node.getSession()).getNodeById(version.getId());
     }
 
     /**
@@ -285,34 +281,32 @@
      * This method must not be synchronized since it could cause deadlocks with
      * item-reading listeners in the observation thread.
      */
-    public void removeVersion(VersionHistory history, QName name)
+    public void removeVersion(VersionHistory history, final QName name)
             throws VersionException, RepositoryException {
 
-        AbstractVersionHistory historyImpl = (AbstractVersionHistory) history;
+        final AbstractVersionHistory historyImpl = (AbstractVersionHistory) history;
         if (!historyImpl.hasNode(name)) {
             throw new VersionException("Version with name " + name.toString()
                     + " does not exist in this VersionHistory");
         }
 
-        synchronized (eventSourceLock) {
-            // This needs to be synchronized since it sets the event source
-            // to be used when creating the events to be dispatched later on.
-            eventSource = (SessionImpl) history.getSession();
-
-            // save away predecessors before removing version
-            AbstractVersion version = (AbstractVersion) historyImpl.getNode(name);
-            InternalVersion preds[] = version.getInternalVersion().getPredecessors();
-
-            InternalVersionHistoryImpl vh = (InternalVersionHistoryImpl)
-                    historyImpl.getInternalVersionHistory();
-            removeVersion(vh, name);
-
-            // invalidate predecessors successor properties
-            for (int i = 0; i < preds.length; i++) {
-                PropertyId propId = new PropertyId(preds[i].getId(), QName.JCR_SUCCESSORS);
-                versProvider.onPropertyChanged(propId);
+        escFactory.doSourced((SessionImpl) history.getSession(), new SourcedTarget(){
+            public Object run() throws RepositoryException {
+                AbstractVersion version = (AbstractVersion) historyImpl.getNode(name);
+                InternalVersion[] preds = version.getInternalVersion().getPredecessors();
+
+                InternalVersionHistoryImpl vh = (InternalVersionHistoryImpl)
+                        historyImpl.getInternalVersionHistory();
+                removeVersion(vh, name);
+
+                // invalidate predecessors successor properties
+                for (int i = 0; i < preds.length; i++) {
+                    PropertyId propId = new PropertyId(preds[i].getId(), QName.JCR_SUCCESSORS);
+                    versProvider.onPropertyChanged(propId);
+                }
+                return null;
             }
-        }
+        });
     }
 
     /**
@@ -321,26 +315,25 @@
      * This method must not be synchronized since it could cause deadlocks with
      * item-reading listeners in the observation thread.
      */
-    public Version setVersionLabel(VersionHistory history,
-                                                QName version, QName label,
-                                                boolean move)
+    public Version setVersionLabel(final VersionHistory history,
+                                   final QName version, final QName label,
+                                   final boolean move)
             throws RepositoryException {
 
-        AbstractVersionHistory historyImpl = (AbstractVersionHistory) history;
-        InternalVersion v;
-        synchronized (eventSourceLock) {
-            // This  needs to be synchronized since it sets the event source
-            // to be used when creating the events to be dispatched later on.
-            eventSource = (SessionImpl) history.getSession();
-
-            InternalVersionHistoryImpl vh = (InternalVersionHistoryImpl)
-                    historyImpl.getInternalVersionHistory();
-            v = setVersionLabel(vh, version, label, move);
-        }
+        InternalVersion v = (InternalVersion)
+                escFactory.doSourced((SessionImpl) history.getSession(), new SourcedTarget(){
+            public Object run() throws RepositoryException {
+                InternalVersionHistoryImpl vh = (InternalVersionHistoryImpl)
+                        ((AbstractVersionHistory) history).getInternalVersionHistory();
+                return setVersionLabel(vh, version, label, move);
+            }
+        });
+
         if (v == null) {
             return null;
         } else {
-            return (Version) eventSource.getNodeByUUID(v.getId().getUUID());
+            return (Version)
+                    ((SessionImpl) history.getSession()).getNodeByUUID(v.getId().getUUID());
         }
     }
 
@@ -448,34 +441,6 @@
         return sharedStateMgr;
     }
 
-    //------------------------------------------< EventStateCollectionFactory >
-
-    /**
-     * {@inheritDoc}
-     * <p/>
-     * This object uses one instance of a <code>LocalItemStateManager</code>
-     * to update data on behalf of many sessions. In order to maintain the
-     * association between update operation and session who actually invoked
-     * the update, an internal event source is used.
-     */
-    public synchronized EventStateCollection createEventStateCollection()
-            throws RepositoryException {
-
-        if (eventSource == null) {
-            throw new RepositoryException("Unknown event source.");
-        }
-        return createEventStateCollection(eventSource);
-    }
-
-    /**
-     * Creates an {@link EventStateCollection} using the given <code>source</code>.
-     * @param source the Session that did the changes.
-     * @return <code>EventStateCollection</code>.
-     */
-    EventStateCollection createEventStateCollection(SessionImpl source) {
-        return obsMgr.createEventStateCollection(source, VERSION_STORAGE_PATH);
-    }
-
     //--------------------------------------------------------< inner classes >
     /**
      * Spezialized SharedItemStateManager that filters out NodeReferences to
@@ -508,5 +473,76 @@
             }
         }
 
+    }
+
+    public static final class DynamicESCFactory implements EventStateCollectionFactory {
+
+        /**
+         * the observation manager
+         */
+        private DelegatingObservationDispatcher obsMgr;
+
+        /**
+         * the current event source
+         */
+        private SessionImpl source;
+
+
+        /**
+         * Creates a new event state collection factory
+         * @param obsMgr
+         */
+        public DynamicESCFactory(DelegatingObservationDispatcher obsMgr) {
+            this.obsMgr = obsMgr;
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p/>
+         * This object uses one instance of a <code>LocalItemStateManager</code>
+         * to update data on behalf of many sessions. In order to maintain the
+         * association between update operation and session who actually invoked
+         * the update, an internal event source is used.
+         */
+        public synchronized EventStateCollection createEventStateCollection()
+                throws RepositoryException {
+            if (source == null) {
+                throw new RepositoryException("Unknown event source.");
+            }
+            return createEventStateCollection(source);
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p/>
+         * This object uses one instance of a <code>LocalItemStateManager</code>
+         * to update data on behalf of many sessions. In order to maintain the
+         * association between update operation and session who actually invoked
+         * the update, an internal event source is used.
+         */
+        public EventStateCollection createEventStateCollection(SessionImpl source) {
+            return obsMgr.createEventStateCollection(source, VERSION_STORAGE_PATH);
+        }
+
+        /**
+         * Executes the given runnable using the given event source.
+         *
+         * @param eventSource
+         * @param runnable
+         * @throws RepositoryException
+         */
+        public synchronized Object doSourced(SessionImpl eventSource, SourcedTarget runnable)
+                throws RepositoryException {
+            this.source = eventSource;
+            try {
+                return runnable.run();
+            } finally {
+                this.source = null;
+            }
+        }
+    }
+
+    private abstract class SourcedTarget {
+        public abstract Object run() throws RepositoryException;
     }
 }

Modified: jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java?rev=409525&r1=409524&r2=409525&view=diff
==============================================================================
--- jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
(original)
+++ jackrabbit/branches/1.0/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java
Thu May 25 17:48:28 2006
@@ -114,7 +114,7 @@
      */
     public EventStateCollection createEventStateCollection()
             throws RepositoryException {
-        return vMgr.createEventStateCollection(session);
+        return vMgr.getEscFactory().createEventStateCollection(session);
     }
 
     //-------------------------------------------------------< VersionManager >



Mime
View raw message