jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r202365 - in /incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: HierarchyManager.java HierarchyManagerImpl.java state/SessionItemStateManager.java
Date Wed, 29 Jun 2005 13:01:29 GMT
Author: stefan
Date: Wed Jun 29 06:01:28 2005
New Revision: 202365

URL: http://svn.apache.org/viewcvs?rev=202365&view=rev
Log:
optimized performance of Item.save() if a large number of items 
were removed

Modified:
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
    incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java?rev=202365&r1=202364&r2=202365&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManager.java Wed
Jun 29 06:01:28 2005
@@ -67,6 +67,24 @@
     int getDepth(ItemId id) throws ItemNotFoundException, RepositoryException;
 
     /**
+     * Returns the depth of the specified descendant relative to the given
+     * ancestor. If <code>ancestorId</code> and <code>descendantId</code>
+     * denote the same item 0 is returned. If <code>ancestorId</code> does not
+     * denote an ancestor -1 is returned.
+     *
+     * @param ancestorId ancestor id
+     * @param descendantId descendant id
+     * @return the relative depth; -1 if <code>ancestorId</code> does not
+     *         denote an ancestor of the item denoted by <code>descendantId</code>
+     *         (or itself).
+     * @throws ItemNotFoundException if either of the specified id's does not
+     *                               denote an existing item.
+     * @throws RepositoryException   if another error occurs
+     */
+    int getRelativeDepth(NodeId ancestorId, ItemId descendantId)
+            throws ItemNotFoundException, RepositoryException;
+
+    /**
      * Determines whether the node with the specified <code>nodeId</code>
      * is an ancestor of the item denoted by the given <code>itemId</code>.
      * This is equivalent to

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java?rev=202365&r1=202364&r2=202365&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/HierarchyManagerImpl.java
Wed Jun 29 06:01:28 2005
@@ -93,10 +93,15 @@
 
     //---------------------------------------------------------< overridables >
     /**
-     * @param id
-     * @return
-     * @throws NoSuchItemStateException
-     * @throws ItemStateException
+     * Return an item state, given its item id.
+     * <p/>
+     * Low-level hook provided for specialized derived classes.
+     *
+     * @param id item id
+     * @return item state
+     * @throws NoSuchItemStateException if the item does not exist
+     * @throws ItemStateException       if an error occurs
+     * @see ZombieHierarchyManager#getItemState(ItemId)
      */
     protected ItemState getItemState(ItemId id)
             throws NoSuchItemStateException, ItemStateException {
@@ -104,26 +109,44 @@
     }
 
     /**
-     * @param id
-     * @return
+     * Determines whether an item state for a given item id exists.
+     * <p/>
+     * Low-level hook provided for specialized derived classes.
+     *
+     * @param id item id
+     * @return <code>true</code> if an item state exists, otherwise
+     *         <code>false</code>
+     * @see ZombieHierarchyManager#hasItemState(ItemId)
      */
     protected boolean hasItemState(ItemId id) {
         return provider.hasItemState(id);
     }
 
     /**
+     * Returns the <code>parentUUID</code> of the given item.
+     * <p/>
+     * Low-level hook provided for specialized derived classes.
      *
-     * @param state
-     * @return
+     * @param state item state
+     * @return <code>parentUUID</code> of the given item
+     * @see ZombieHierarchyManager#getParentUUID(ItemState)
      */
     protected String getParentUUID(ItemState state) {
         return state.getParentUUID();
     }
 
     /**
+     * Returns the <code>ChildNodeEntry</code> of <code>parent</code>
with the
+     * specified <code>uuid</code> or <code>null</code> if there's
no such entry.
+     * <p/>
+     * Low-level hook provided for specialized derived classes.
      *
-     * @param parent
-     * @return
+     * @param parent node state
+     * @param uuid   uuid of child node entry
+     * @return the <code>ChildNodeEntry</code> of <code>parent</code>
with
+     *         the specified <code>uuid</code> or <code>null</code>
if there's
+     *         no such entry.
+     * @see ZombieHierarchyManager#getChildNodeEntry(NodeState, String)
      */
     protected NodeState.ChildNodeEntry getChildNodeEntry(NodeState parent,
                                                          String uuid) {
@@ -131,11 +154,19 @@
     }
 
     /**
+     * Returns the <code>ChildNodeEntry</code> of <code>parent</code>
with the
+     * specified <code>name</code> and <code>index</code> or <code>null</code>
+     * if there's no such entry.
+     * <p/>
+     * Low-level hook provided for specialized derived classes.
      *
-     * @param parent
-     * @param name
-     * @param index
-     * @return
+     * @param parent node state
+     * @param name   name of child node entry
+     * @param index  name of child node entry
+     * @return the <code>ChildNodeEntry</code> of <code>parent</code>
with
+     *         the specified <code>name</code> and <code>index</code>
or
+     *         <code>null</code> if there's no such entry.
+     * @see ZombieHierarchyManager#getChildNodeEntry(NodeState, QName, int)
      */
     protected NodeState.ChildNodeEntry getChildNodeEntry(NodeState parent,
                                                          QName name,
@@ -149,8 +180,9 @@
      * response to cache.
      *
      * @param path full path of item to resolve
-     * @param id   item id
+     * @param id   intermediate item id
      * @param next next path element index to resolve
+     * @return the id of the item denoted by <code>path</code>
      */
     protected ItemId resolvePath(Path path, ItemId id, int next)
             throws RepositoryException {
@@ -176,6 +208,7 @@
      * @param path  full path of item to resolve
      * @param state intermediate state
      * @param next  next path element index to resolve
+     * @return the id of the item denoted by <code>path</code>
      */
     protected ItemId resolvePath(Path path, ItemState state, int next)
             throws PathNotFoundException, ItemStateException {
@@ -373,13 +406,20 @@
      */
     public int getDepth(ItemId id)
             throws ItemNotFoundException, RepositoryException {
+        // shortcut
+        if (id.equals(rootNodeId)) {
+            return 0;
+        }
         try {
             ItemState state = getItemState(id);
             String parentUUID = getParentUUID(state);
-            if (parentUUID != null) {
-                return getDepth(new NodeId(parentUUID)) + 1;
+            int depth = 0;
+            while (parentUUID != null) {
+                depth++;
+                state = getItemState(new NodeId(parentUUID));
+                parentUUID = getParentUUID(state);
             }
-            return 0;
+            return depth;
         } catch (NoSuchItemStateException nsise) {
             String msg = "failed to determine depth of " + id;
             log.debug(msg);
@@ -394,17 +434,58 @@
     /**
      * {@inheritDoc}
      */
+    public int getRelativeDepth(NodeId ancestorId, ItemId descendantId)
+            throws ItemNotFoundException, RepositoryException {
+        if (ancestorId.equals(descendantId)) {
+            return 0;
+        }
+        int depth = 1;
+        try {
+            ItemState state = getItemState(descendantId);
+            String parentUUID = getParentUUID(state);
+            while (parentUUID != null) {
+                if (parentUUID.equals(ancestorId.getUUID())) {
+                    return depth;
+                }
+                depth++;
+                state = getItemState(new NodeId(parentUUID));
+                parentUUID = getParentUUID(state);
+            }
+            // not an ancestor
+            return -1;
+        } catch (NoSuchItemStateException nsise) {
+            String msg = "failed to determine depth of " + descendantId
+                    + " relative to " + ancestorId;
+            log.debug(msg);
+            throw new ItemNotFoundException(msg, nsise);
+        } catch (ItemStateException ise) {
+            String msg = "failed to determine depth of " + descendantId
+                    + " relative to " + ancestorId;
+            log.debug(msg);
+            throw new RepositoryException(msg, ise);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public boolean isAncestor(NodeId nodeId, ItemId itemId)
             throws ItemNotFoundException, RepositoryException {
+        if (nodeId.equals(itemId)) {
+            // can't be ancestor of self
+            return false;
+        }
         try {
             ItemState state = getItemState(itemId);
             String parentUUID = getParentUUID(state);
-            if (parentUUID != null) {
+            while (parentUUID != null) {
                 if (parentUUID.equals(nodeId.getUUID())) {
                     return true;
                 }
-                return isAncestor(nodeId, new NodeId(parentUUID));
+                state = getItemState(new NodeId(parentUUID));
+                parentUUID = getParentUUID(state);
             }
+            // not an ancestor
             return false;
         } catch (NoSuchItemStateException nsise) {
             String msg = "failed to determine degree of relationship of "

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=202365&r1=202364&r2=202365&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
Wed Jun 29 06:01:28 2005
@@ -26,6 +26,7 @@
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.ZombieHierarchyManager;
 import org.apache.log4j.Logger;
+import org.apache.commons.collections.iterators.IteratorChain;
 
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.ItemNotFoundException;
@@ -35,6 +36,8 @@
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.TreeMap;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * <code>SessionItemStateManager</code> ...
@@ -412,11 +415,11 @@
         if (!transientStateMgr.hasAnyItemStatesInAttic()) {
             return Collections.EMPTY_LIST.iterator();
         }
-
-        // collection of descendant transient states in attic:
+/*
+        // build ordered collection of descendant transient states in attic:
         // the path serves as key and sort criteria
 
-        // we have to use a special attic-aware hierarchy manager
+        // use a special attic-aware hierarchy manager
         ZombieHierarchyManager zombieHierMgr =
                 new ZombieHierarchyManager(hierMgr.getRootNodeId().getUUID(),
                         this,
@@ -444,18 +447,60 @@
         } catch (RepositoryException re) {
             log.warn("inconsistent hierarchy state", re);
         }
-/*
-        TreeMap descendants = new TreeMap();
-        Iterator iter = transientStateMgr.getEntriesInAttic();
-        while (iter.hasNext()) {
-            ItemState state = (ItemState) iter.next();
-            int depth = getAncestorCount(state, parentId.getUUID());
-            if (depth >= 0) {
-                descendants.put(new ItemStateKey(state, depth), state);
+        return descendants.values().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.getRootNodeId().getUUID(),
+                        this,
+                        transientStateMgr.getAttic(),
+                        hierMgr.getNamespaceResolver());
+
+        // 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 {
+            Iterator iter = transientStateMgr.getEntriesInAttic();
+            while (iter.hasNext()) {
+                ItemState state = (ItemState) iter.next();
+                // determine relative depth: > 0 means it's a descendant
+                int depth = zombieHierMgr.getRelativeDepth(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);
+                }
+
+                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);
         }
-*/
-        return descendants.values().iterator();
+        // 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 resultIter;
+
     }
 
     //------< methods for creating & discarding transient ItemState instances >



Mime
View raw message