You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2006/01/14 13:43:31 UTC

svn commit: r369016 - in /incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core: RepositoryImpl.java version/VersionManagerImpl.java

Author: tripod
Date: Sat Jan 14 04:43:27 2006
New Revision: 369016

URL: http://svn.apache.org/viewcvs?rev=369016&view=rev
Log:
- improved extensibility of repository
- fixing potential deadlock in version manager

Modified:
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=369016&r1=369015&r2=369016&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Sat Jan 14 04:43:27 2006
@@ -209,7 +209,8 @@
         }
 
         // init version manager
-        vMgr = createVersionManager(repConfig.getVersioningConfig());
+        vMgr = createVersionManager(repConfig.getVersioningConfig(),
+                delegatingDispatcher);
 
         // init virtual nodetype manager
         virtNTMgr = new VirtualNodeTypeStateManager(getNodeTypeRegistry(),
@@ -242,7 +243,8 @@
      * @return the newly created version manager
      * @throws RepositoryException if an error occurrs
      */
-    protected VersionManager createVersionManager(VersioningConfig vConfig)
+    protected VersionManager createVersionManager(VersioningConfig vConfig,
+                                                  DelegatingObservationDispatcher delegatingDispatcher)
             throws RepositoryException {
         PersistenceManager pm = createPersistenceManager(vConfig.getHomeDir(),
                 vConfig.getFileSystem(),

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=369016&r1=369015&r2=369016&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Sat Jan 14 04:43:27 2006
@@ -104,6 +104,11 @@
     private transient SessionImpl eventSource;
 
     /**
+     * workaround for potential deadlock
+     */
+    private final Object eventSourceLock = new Object();
+
+    /**
      * Creates a bew vesuion manager
      *
      */
@@ -166,16 +171,21 @@
     /**
      * {@inheritDoc}
      * <p/>
-     * This method needs to be synchronized since it sets the event source
-     * to be used when creating the events to be dispatched later on.
+     * This method must not be synchronized since it could cause deadlocks with
+     * item-reading listeners in the observation thread.
      */
-    public synchronized VersionHistory createVersionHistory(Session session,
-                                                            NodeState node)
+    public VersionHistory createVersionHistory(Session session, NodeState node)
             throws RepositoryException {
 
-        eventSource = (SessionImpl) session;
+        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 = createVersionHistory(node);
         if (history == null) {
             throw new VersionException("History already exists for node " + node.getUUID());
         }
@@ -231,34 +241,38 @@
     /**
      * {@inheritDoc}
      * <p/>
-     * This method needs to be synchronized since it sets the event source
-     * to be used when creating the events to be dispatched later on.
+     * This method must not be synchronized since it could cause deadlocks with
+     * item-reading listeners in the observation thread.
      */
-    public synchronized Version checkin(NodeImpl node) throws RepositoryException {
-        eventSource = (SessionImpl) node.getSession();
-
-        String histUUID = node.getProperty(QName.JCR_VERSIONHISTORY).getString();
-        InternalVersion version = checkin(
-                (InternalVersionHistoryImpl) getVersionHistory(histUUID), node);
+    public Version checkin(NodeImpl node) throws RepositoryException {
+        InternalVersion version;
 
-        AbstractVersion v = (AbstractVersion) eventSource.getNodeByUUID(version.getId());
-
-        // 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);
+        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(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 v;
+        return (AbstractVersion) eventSource.getNodeByUUID(version.getId());
     }
 
     /**
      * {@inheritDoc}
      * <p/>
-     * This method needs to be synchronized since it sets the event source
-     * to be used when creating the events to be dispatched later on.
+     * This method must not be synchronized since it could cause deadlocks with
+     * item-reading listeners in the observation thread.
      */
-    public synchronized void removeVersion(VersionHistory history, QName name)
+    public void removeVersion(VersionHistory history, QName name)
             throws VersionException, RepositoryException {
 
         AbstractVersionHistory historyImpl = (AbstractVersionHistory) history;
@@ -266,40 +280,50 @@
             throw new VersionException("Version with name " + name.toString()
                     + " does not exist in this VersionHistory");
         }
-        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);
+        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);
+            }
         }
     }
 
     /**
      * {@inheritDoc}
      * <p/>
-     * This method needs to be synchronized since it sets the event source
-     * to be used when creating the events to be dispatched later on.
+     * This method must not be synchronized since it could cause deadlocks with
+     * item-reading listeners in the observation thread.
      */
-    public synchronized Version setVersionLabel(VersionHistory history,
+    public Version setVersionLabel(VersionHistory history,
                                                 QName version, QName label,
                                                 boolean move)
             throws RepositoryException {
 
         AbstractVersionHistory historyImpl = (AbstractVersionHistory) history;
-        eventSource = (SessionImpl) history.getSession();
-
-        InternalVersionHistoryImpl vh = (InternalVersionHistoryImpl)
-                historyImpl.getInternalVersionHistory();
-        InternalVersion v = setVersionLabel(vh, version, label, move);
+        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);
+        }
         if (v == null) {
             return null;
         } else {