jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r957189 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core: ItemImpl.java ItemManager.java ItemSaveOperation.java NodeImpl.java state/SessionItemStateManager.java
Date Wed, 23 Jun 2010 13:27:51 GMT
Author: jukka
Date: Wed Jun 23 13:27:50 2010
New Revision: 957189

URL: http://svn.apache.org/viewvc?rev=957189&view=rev
Log:
JCR-890: concurrent read-only access to a session

Streamline the new ItemSaveOperation and related classes.

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java?rev=957189&r1=957188&r2=957189&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemImpl.java
Wed Jun 23 13:27:50 2010
@@ -17,7 +17,6 @@
 package org.apache.jackrabbit.core;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 
 import javax.jcr.AccessDeniedException;
 import javax.jcr.InvalidItemStateException;
@@ -351,11 +350,10 @@ public abstract class ItemImpl implement
 
         // list of transient items that should be discarded
         ArrayList<ItemState> list = new ArrayList<ItemState>();
-        ItemState transientState;
 
         // check status of this item's state
         if (isTransient()) {
-            transientState = getItemState();
+            ItemState transientState = getItemState();
             switch (transientState.getStatus()) {
                 case ItemState.STATUS_STALE_MODIFIED:
                 case ItemState.STATUS_STALE_DESTROYED:
@@ -387,9 +385,8 @@ public abstract class ItemImpl implement
 
         if (isNode()) {
             // build list of 'new', 'modified' or 'stale' descendants
-            Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStates((NodeId)
id);
-            while (iter.hasNext()) {
-                transientState = iter.next();
+            for (ItemState transientState
+                    : stateMgr.getDescendantTransientItemStates((NodeId) id)) {
                 switch (transientState.getStatus()) {
                     case ItemState.STATUS_STALE_MODIFIED:
                     case ItemState.STATUS_STALE_DESTROYED:
@@ -418,12 +415,10 @@ public abstract class ItemImpl implement
         if (isNode()) {
             // discard all transient descendants in the attic (i.e. those marked
             // as 'removed'); this will resurrect the removed items
-            Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStatesInAttic((NodeId)
id);
-            while (iter.hasNext()) {
-                transientState = iter.next();
+            for (ItemState state : stateMgr.getDescendantTransientItemStatesInAttic((NodeId)
id)) {
                 // dispose the transient state; this will indirectly (through
                 // stateDiscarded listener method) resurrect the wrapping Item instances
-                stateMgr.disposeTransientItemStateInAttic(transientState);
+                stateMgr.disposeTransientItemStateInAttic(state);
             }
         }
     }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java?rev=957189&r1=957188&r2=957189&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemManager.java
Wed Jun 23 13:27:50 2010
@@ -32,7 +32,6 @@ import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.ConstraintViolationException;
 
 import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java?rev=957189&r1=957188&r2=957189&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ItemSaveOperation.java
Wed Jun 23 13:27:50 2010
@@ -18,10 +18,10 @@ package org.apache.jackrabbit.core;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.ConcurrentModificationException;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
@@ -223,15 +223,11 @@ class ItemSaveOperation extends SessionO
         try {
             stateMgr.edit();
         } catch (IllegalStateException e) {
-            String msg = "Unable to start edit operation";
-            log.debug(msg);
-            throw new RepositoryException(msg, e);
+            throw new RepositoryException("Unable to start edit operation", e);
         }
 
         boolean succeeded = false;
-
         try {
-
             // process transient items marked as 'removed'
             removeTransientItems(stateMgr, removed);
 
@@ -309,13 +305,11 @@ class ItemSaveOperation extends SessionO
             throws InvalidItemStateException, RepositoryException {
         // list of transient states that should be persisted
         ArrayList<ItemState> dirty = new ArrayList<ItemState>();
-        ItemState transientState;
 
         if (isNode) {
             // build list of 'new' or 'modified' descendants
-            Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStates((NodeId)
state.getId());
-            while (iter.hasNext()) {
-                transientState = iter.next();
+            for (ItemState transientState
+                    : stateMgr.getDescendantTransientItemStates(state.getId())) {
                 // fail-fast test: check status of transient state
                 switch (transientState.getStatus()) {
                     case ItemState.STATUS_NEW:
@@ -397,30 +391,29 @@ class ItemSaveOperation extends SessionO
     private Collection<ItemState> getRemovedStates(
             SessionItemStateManager stateMgr)
             throws InvalidItemStateException, RepositoryException {
-        ArrayList<ItemState> removed = new ArrayList<ItemState>();
-        ItemState transientState;
-
         if (isNode) {
-            Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStatesInAttic((NodeId)
state.getId());
-            while (iter.hasNext()) {
-                transientState = iter.next();
+            ArrayList<ItemState> removed = new ArrayList<ItemState>();
+            for (ItemState transientState
+                    : stateMgr.getDescendantTransientItemStatesInAttic(state.getId())) {
                 // check if stale
-                if (transientState.getStatus() == ItemState.STATUS_STALE_MODIFIED) {
-                    String msg = transientState.getId()
-                            + ": the item cannot be removed because it has been modified
externally.";
-                    log.debug(msg);
-                    throw new InvalidItemStateException(msg);
-                }
-                if (transientState.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
-                    String msg = transientState.getId()
-                            + ": the item cannot be removed because it has already been deleted
externally.";
-                    log.debug(msg);
-                    throw new InvalidItemStateException(msg);
+                switch (transientState.getStatus()) {
+                case ItemState.STATUS_STALE_MODIFIED:
+                    throw new InvalidItemStateException(
+                            "Item can't be removed because it has been"
+                            + " modified externally: "
+                            + transientState.getId());
+                case ItemState.STATUS_STALE_DESTROYED:
+                    throw new InvalidItemStateException(
+                            "Item can't be removed because it has already"
+                            + " been deleted externally: "
+                            + transientState.getId());
                 }
                 removed.add(transientState);
             }
+            return removed;
+        } else {
+            return Collections.emptyList();
         }
-        return removed;
     }
 
     /**
@@ -776,10 +769,8 @@ class ItemSaveOperation extends SessionO
     }
 
     /**
-     * Initializes the version history of all new nodes of node type
+     * Initialises the version history of all new nodes of node type
      * <code>mix:versionable</code>.
-     * <p/>
-     * Called by {@link #save()}.
      *
      * @param states
      * @return true if this call generated new transient state; otherwise false

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=957189&r1=957188&r2=957189&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
Wed Jun 23 13:27:50 2010
@@ -304,8 +304,7 @@ public class NodeImpl extends ItemImpl i
         if (isTransient()) {
             return true;
         }
-        Iterator<ItemState> iter = stateMgr.getDescendantTransientItemStates((NodeId)
id);
-        return iter.hasNext();
+        return !stateMgr.getDescendantTransientItemStates((NodeId) id).isEmpty();
     }
 
     protected synchronized ItemState getOrCreateTransientItemState()

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=957189&r1=957188&r2=957189&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
Wed Jun 23 13:27:50 2010
@@ -20,16 +20,16 @@ import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.LinkedList;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.ReferentialIntegrityException;
 import javax.jcr.RepositoryException;
 
-import org.apache.commons.collections.iterators.IteratorChain;
 import org.apache.jackrabbit.core.CachingHierarchyManager;
 import org.apache.jackrabbit.core.HierarchyManager;
 import org.apache.jackrabbit.core.ZombieHierarchyManager;
@@ -367,175 +367,99 @@ public class SessionItemStateManager
     }
 
     /**
-     * Returns an iterator over those transient item state instances that are
-     * direct or indirect descendants of the item state with the given
-     * <code>parentId</code>. The transient item state instance with the given
-     * <code>parentId</code> itself (if there is such) will not be included.
-     * <p/>
+     * Returns a collection of those transient item state instances that are
+     * direct or indirect descendants of the item state with the given parent.
+     * The transient item state instance with the given identifier itself
+     * (if there is such) will not be included.
+     * <p>
      * The instances are returned in depth-first tree traversal order.
      *
-     * @param parentId the id of the common parent of the transient item state
-     *                 instances to be returned.
-     * @return an iterator over descendant transient item state instances
+     * @param id identifier of the common parent of the transient item state
+     *           instances to be returned
+     * @return collection of descendant transient item state instances
      * @throws InvalidItemStateException if any descendant item state has been
      *                                   deleted externally
      * @throws RepositoryException       if another error occurs
      */
-    public Iterator<ItemState> getDescendantTransientItemStates(NodeId parentId)
+    public Collection<ItemState> getDescendantTransientItemStates(ItemId id)
             throws InvalidItemStateException, RepositoryException {
-        if (transientStore.isEmpty()) {
-            List<ItemState> empty = Collections.emptyList();
-            return empty.iterator();
-        }
-
-        // build ordered collection of descendant transient states
-        // sorted by decreasing relative depth
-
-        // use an array of lists to group the descendants by relative depth;
-        // the depth is used as array index
-        List[] la = new List[10];
         try {
-            HierarchyManager atticAware = getAtticAwareHierarchyMgr();
-            for (ItemState state : transientStore.values()) {
-                // determine relative depth: > 0 means it's a descendant
-                int depth;
-                try {
-                    depth = atticAware.getShareRelativeDepth(parentId, state.getId());
-                } catch (ItemNotFoundException infe) {
-                    /**
-                     * one of the parents of the specified item has been
-                     * removed externally; as we don't know its path,
-                     * we can't determine if it is a descendant;
-                     * InvalidItemStateException should only be thrown if
-                     * a descendant is affected;
-                     * => throw InvalidItemStateException for now
-                     * todo FIXME
-                     */
-                    // unable to determine relative depth, assume that the item
-                    // (or any of its ancestors) has been removed externally
-                    String msg = state.getId()
-                            + ": the item seems to have been removed externally.";
-                    log.debug(msg);
-                    throw new InvalidItemStateException(msg);
-                }
-
-                if (depth < 1) {
-                    // not a descendant
-                    continue;
-                }
-
-                // ensure capacity
-                if (depth > la.length) {
-                    List[] old = la;
-                    la = new List[depth + 10];
-                    System.arraycopy(old, 0, la, 0, old.length);
-                }
-
-                List list = la[depth - 1];
-                if (list == null) {
-                    list = new ArrayList();
-                    la[depth - 1] = list;
-                }
-                list.add(state);
-            }
-        } catch (RepositoryException re) {
-            log.warn("inconsistent hierarchy state", re);
-        }
-        // create an iterator over the collected descendants
-        // in decreasing depth order
-        IteratorChain resultIter = new IteratorChain();
-        for (int i = la.length - 1; i >= 0; i--) {
-            List list = la[i];
-            if (list != null) {
-                resultIter.addIterator(list.iterator());
-            }
+            return getDescendantItemStates(
+                    id, transientStore, getAtticAwareHierarchyMgr());
+        } catch (ItemNotFoundException e) {
+            // one of the parents of the specified item has been
+            // removed externally; as we don't know its path,
+            // we can't determine if it is a descendant;
+            // InvalidItemStateException should only be thrown if
+            // a descendant is affected;
+            // => throw InvalidItemStateException for now (FIXME)
+            // unable to determine relative depth, assume that the item
+            // (or any of its ancestors) has been removed externally
+            throw new InvalidItemStateException(
+                    "Item seems to have been removed externally", e);
         }
-        /**
-         * if the resulting iterator chain is empty return
-         * EMPTY_LIST.iterator() instead because older versions
-         * of IteratorChain (pre Commons Collections 3.1)
-         * would throw UnsupportedOperationException in this
-         * situation
-         */
-        if (resultIter.getIterators().isEmpty()) {
-            List<ItemState> empty = Collections.emptyList();
-            return empty.iterator();
-        }
-        return resultIter;
     }
 
     /**
      * Same as <code>{@link #getDescendantTransientItemStates(NodeId)}</code>
      * except that item state instances in the attic are returned.
      *
-     * @param parentId the id of the common parent of the transient item state
-     *                 instances to be returned.
-     * @return an iterator over descendant transient item state instances in the attic
-     */
-    public Iterator<ItemState> getDescendantTransientItemStatesInAttic(NodeId parentId)
{
-        if (atticStore.isEmpty()) {
-            List<ItemState> empty = Collections.emptyList();
-            return empty.iterator();
-        }
-
-        // build ordered collection of descendant transient states in attic
-        // sorted by decreasing relative depth
-
-        // use a special attic-aware hierarchy manager
-        ZombieHierarchyManager zombieHierMgr =
-            new ZombieHierarchyManager(hierMgr, this, getAttic());
-
-        // use an array of lists to group the descendants by relative depth;
-        // the depth is used as array index
-        List[] la = new List[10];
-        try {
-            for (ItemState state : atticStore.values()) {
-                // determine relative depth: > 0 means it's a descendant
-                //int depth = zombieHierMgr.getRelativeDepth(parentId, state.getId());
-                int depth = zombieHierMgr.getShareRelativeDepth(parentId, state.getId());
-                if (depth < 1) {
-                    // not a descendant
-                    continue;
-                }
-
-                // ensure capacity
-                if (depth > la.length) {
-                    List[] old = la;
-                    la = new List[depth + 10];
-                    System.arraycopy(old, 0, la, 0, old.length);
-                }
+     * @param id identifier of the common parent of the transient item state
+     *           instances to be returned
+     * @return collection of descendant transient item state instances
+     *         in the attic
+     */
+    public Iterable<ItemState> getDescendantTransientItemStatesInAttic(
+            ItemId id) throws RepositoryException {
+        return getDescendantItemStates(
+                id, atticStore,
+                new ZombieHierarchyManager(hierMgr, this, getAttic()));
+    }
 
-                List list = la[depth - 1];
-                if (list == null) {
-                    list = new ArrayList();
-                    la[depth - 1] = list;
+    /**
+     * Utility method used by the
+     * {@link #getDescendantTransientItemStates(ItemId)} and
+     * {@link #getDescendantTransientItemStatesInAttic(ItemId)} methods
+     * to collect descendant item states from the given item state store.
+     *
+     * @param id identifier of the parent item
+     * @param store item state store
+     * @param hierarchyManager hierarchy manager associated with the store
+     * @return descendants of the identified item
+     * @throws RepositoryException if the descendants could not be accessed
+     */
+    private List<ItemState> getDescendantItemStates(
+            ItemId id, ItemStateStore store, HierarchyManager hierarchyManager)
+            throws RepositoryException {
+        if (id.denotesNode() && !store.isEmpty()) {
+            // Group the descendants by reverse relative depth
+            SortedMap<Integer, Collection<ItemState>> statesByReverseDepth =
+                new TreeMap<Integer, Collection<ItemState>>();
+            for (ItemState state : store.values()) {
+                // determine relative depth: > 0 means it's a descendant
+                int depth = hierarchyManager.getShareRelativeDepth(
+                        (NodeId) id, state.getId());
+                if (depth > 0) {
+                    Collection<ItemState> statesAtDepth =
+                        statesByReverseDepth.get(-depth);
+                    if (statesAtDepth == null) {
+                        statesAtDepth = new ArrayList<ItemState>();
+                        statesByReverseDepth.put(-depth, statesAtDepth);
+                    }
+                    statesAtDepth.add(state);
                 }
-                list.add(state);
             }
-        } catch (RepositoryException re) {
-            log.warn("inconsistent hierarchy state", re);
-        }
-        // create an iterator over the collected descendants
-        // in decreasing depth order
-        IteratorChain resultIter = new IteratorChain();
-        for (int i = la.length - 1; i >= 0; i--) {
-            List list = la[i];
-            if (list != null) {
-                resultIter.addIterator(list.iterator());
+
+            // Collect the descendants in decreasing depth order
+            List<ItemState> descendants = new ArrayList<ItemState>();
+            for (Collection<ItemState> statesAtDepth
+                    : statesByReverseDepth.values()) {
+                descendants.addAll(statesAtDepth);
             }
+            return descendants;
+        } else {
+            return Collections.emptyList();
         }
-        /**
-         * if the resulting iterator chain is empty return
-         * EMPTY_LIST.iterator() instead because older versions
-         * of IteratorChain (pre Commons Collections 3.1)
-         * would throw UnsupportedOperationException in this
-         * situation
-         */
-        if (resultIter.getIterators().isEmpty()) {
-            List<ItemState> empty = Collections.emptyList();
-            return empty.iterator();
-        }
-        return resultIter;
     }
 
     /**



Mime
View raw message