You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2004/11/08 18:42:34 UTC

svn commit: rev 56953 - in incubator/jackrabbit/trunk: . src/java/org/apache/jackrabbit/core src/java/org/apache/jackrabbit/core/state xdocs

Author: stefan
Date: Mon Nov  8 09:42:33 2004
New Revision: 56953

Added:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LazyItemIterator.java   (contents, props changed)
Modified:
   incubator/jackrabbit/trunk/ToDo.txt
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java
   incubator/jackrabbit/trunk/xdocs/tasks.xml
Log:
- added lazy-loading item iterator
- optimized Node.has/getNodes(), Node.has/getProperties()

Modified: incubator/jackrabbit/trunk/ToDo.txt
==============================================================================
--- incubator/jackrabbit/trunk/ToDo.txt	(original)
+++ incubator/jackrabbit/trunk/ToDo.txt	Mon Nov  8 09:42:33 2004
@@ -6,9 +6,6 @@
 
 - locking
 - access control (jaas)
-- current persistence model (nodes and properties are stored in separate
-  files) leads to *very* slow performance in a normal filesystem;
-  see next issues for solutions 
 - use jdbc as an alternative to virtual filesystem persistence layer
 - use an alternative journaling store as (transactional) persistence layer 
 - provide clean abstraction for persistence grouping (nodes & properties 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java	Mon Nov  8 09:42:33 2004
@@ -18,17 +18,13 @@
 import org.apache.commons.collections.ReferenceMap;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.util.IteratorHelper;
 import org.apache.log4j.Logger;
 
 import javax.jcr.*;
 import javax.jcr.nodetype.NodeDef;
 import javax.jcr.nodetype.PropertyDef;
 import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
 
 /**
  * There's one <code>ItemManager</code> instance per <code>Session</code>
@@ -237,6 +233,57 @@
      * @throws AccessDeniedException
      * @throws RepositoryException
      */
+    synchronized boolean hasChildNodes(NodeId parentId)
+            throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+        // check privileges
+        if (!session.getAccessManager().isGranted(parentId, AccessManager.READ)) {
+            // clear cache
+            ItemImpl item = retrieveItem(parentId);
+            if (item != null) {
+                evictItem(parentId);
+            }
+            throw new AccessDeniedException("cannot read item " + parentId);
+        }
+
+        ItemState state = null;
+        try {
+            state = itemStateProvider.getItemState(parentId);
+        } catch (NoSuchItemStateException nsise) {
+            String msg = "no such item: " + parentId;
+            log.error(msg);
+            throw new ItemNotFoundException(msg);
+        } catch (ItemStateException ise) {
+            String msg = "failed to retrieve item state of node " + parentId;
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+
+        if (!state.isNode()) {
+            String msg = "can't list child nodes of property " + parentId;
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+        NodeState nodeState = (NodeState) state;
+        Iterator iter = nodeState.getChildNodeEntries().iterator();
+
+        while (iter.hasNext()) {
+            NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
+            NodeId id = new NodeId(entry.getUUID());
+            // check read access
+            if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param parentId
+     * @return
+     * @throws ItemNotFoundException
+     * @throws AccessDeniedException
+     * @throws RepositoryException
+     */
     synchronized NodeIterator getChildNodes(NodeId parentId)
             throws ItemNotFoundException, AccessDeniedException, RepositoryException {
         // check privileges
@@ -249,7 +296,7 @@
             throw new AccessDeniedException("cannot read item " + parentId);
         }
 
-        ArrayList children = new ArrayList();
+        ArrayList childIds = new ArrayList();
 
         ItemState state = null;
         try {
@@ -274,16 +321,66 @@
 
         while (iter.hasNext()) {
             NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) iter.next();
-            try {
-                Item item = getItem(new NodeId(entry.getUUID()));
-                children.add(item);
-            } catch (AccessDeniedException ade) {
-                // ignore
-                continue;
+            NodeId id = new NodeId(entry.getUUID());
+            // check read access
+            if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+                childIds.add(id);
+            }
+        }
+
+        return new LazyItemIterator(this, childIds);
+    }
+
+    /**
+     * @param parentId
+     * @return
+     * @throws ItemNotFoundException
+     * @throws AccessDeniedException
+     * @throws RepositoryException
+     */
+    synchronized boolean hasChildProperties(NodeId parentId)
+            throws ItemNotFoundException, AccessDeniedException, RepositoryException {
+        // check privileges
+        if (!session.getAccessManager().isGranted(parentId, AccessManager.READ)) {
+            ItemImpl item = retrieveItem(parentId);
+            if (item != null) {
+                evictItem(parentId);
             }
+            throw new AccessDeniedException("cannot read item " + parentId);
         }
 
-        return new IteratorHelper(Collections.unmodifiableList(children));
+        ItemState state = null;
+        try {
+            state = itemStateProvider.getItemState(parentId);
+        } catch (NoSuchItemStateException nsise) {
+            String msg = "no such item: " + parentId;
+            log.error(msg);
+            throw new ItemNotFoundException(msg);
+        } catch (ItemStateException ise) {
+            String msg = "failed to retrieve item state of node " + parentId;
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+
+        if (!state.isNode()) {
+            String msg = "can't list child properties of property " + parentId;
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+        NodeState nodeState = (NodeState) state;
+        Iterator iter = nodeState.getPropertyEntries().iterator();
+
+        while (iter.hasNext()) {
+            NodeState.PropertyEntry entry = (NodeState.PropertyEntry) iter.next();
+
+            PropertyId id = new PropertyId(parentId.getUUID(), entry.getName());
+            // check read access
+            if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     /**
@@ -304,7 +401,7 @@
             throw new AccessDeniedException("cannot read item " + parentId);
         }
 
-        ArrayList children = new ArrayList();
+        ArrayList childIds = new ArrayList();
 
         ItemState state = null;
         try {
@@ -329,18 +426,14 @@
 
         while (iter.hasNext()) {
             NodeState.PropertyEntry entry = (NodeState.PropertyEntry) iter.next();
-            try {
-                Item item = getItem(new PropertyId(parentId.getUUID(), entry.getName()));
-                children.add(item);
-            } catch (AccessDeniedException ade) {
-                // ignore
-                continue;
+            PropertyId id = new PropertyId(parentId.getUUID(), entry.getName());
+            // check read access
+            if (session.getAccessManager().isGranted(id, AccessManager.READ)) {
+                childIds.add(id);
             }
         }
 
-        // not need to add virtual properties
-
-        return new IteratorHelper(Collections.unmodifiableList(children));
+        return new LazyItemIterator(this, childIds);
     }
 
     //-------------------------------------------------< item factory methods >

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LazyItemIterator.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/LazyItemIterator.java	Mon Nov  8 09:42:33 2004
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * <code>LazyItemIterator</code> is an id-based iterator that instantiates
+ * the <code>Item</code>s only when they are requested.
+ */
+public class LazyItemIterator implements NodeIterator, PropertyIterator {
+
+    private final ItemManager itemMgr;
+    private final List idList;
+    private int pos;
+
+    /**
+     * Creates a new <code>LazyItemIterator</code> instance.
+     *
+     * @param itemMgr item manager
+     * @param idList  list of item id's
+     */
+    LazyItemIterator(ItemManager itemMgr, List idList) {
+        this.itemMgr = itemMgr;
+        this.idList = new ArrayList(idList);
+        pos = -1;
+    }
+
+    //---------------------------------------------------------< NodeIterator >
+    public Node nextNode() {
+        return (Node) next();
+    }
+
+    //-----------------------------------------------------< PropertyIterator >
+    public Property nextProperty() {
+        return (Property) next();
+    }
+
+    //--------------------------------------------------------< RangeIterator >
+    public long getPos() {
+        return pos + 1;
+    }
+
+    public long getSize() {
+        return idList.size();
+    }
+
+    public void skip(long skipNum) {
+        if (skipNum < 0) {
+            throw new IllegalArgumentException("skipNum must be a positive number");
+        }
+        if (pos + skipNum >= idList.size()) {
+            pos = idList.size() - 1;
+            throw new NoSuchElementException();
+        }
+        pos += skipNum;
+    }
+
+    //-------------------------------------------------------------< Iterator >
+    public boolean hasNext() {
+        return pos < idList.size() - 1;
+    }
+
+    public Object next() {
+        if (pos >= idList.size() - 1) {
+            throw new NoSuchElementException();
+        }
+        while (true) {
+            pos++;
+            try {
+                return itemMgr.getItem((ItemId) idList.get(pos));
+            } catch (AccessDeniedException ade) {
+                // silently ignore and try next
+                continue;
+            } catch (RepositoryException re) {
+                // FIXME: not quite correct
+                throw new NoSuchElementException(re.getMessage());
+            }
+        }
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException("remove");
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java	Mon Nov  8 09:42:33 2004
@@ -17,7 +17,6 @@
 
 import org.apache.jackrabbit.core.nodetype.*;
 import org.apache.jackrabbit.core.state.*;
-import org.apache.jackrabbit.core.util.ChildrenCollector;
 import org.apache.jackrabbit.core.util.ChildrenCollectorFilter;
 import org.apache.jackrabbit.core.util.IteratorHelper;
 import org.apache.jackrabbit.core.util.uuid.UUID;
@@ -1463,10 +1462,7 @@
          * return false if child nodes exist
          * but the session is not granted read-access
          */
-        ArrayList nodes = new ArrayList();
-        // traverse children using a 'collector'
-        accept(new ChildrenCollector(nodes, true, false, 1));
-        return (nodes.size() > 0);
+        return itemMgr.hasChildNodes((NodeId) id);
     }
 
     /**
@@ -1482,10 +1478,7 @@
          * return false if properties exist
          * but the session is not granted read-access
          */
-        ArrayList props = new ArrayList();
-        // traverse children using a 'collector'
-        accept(new ChildrenCollector(props, false, true, 1));
-        return (props.size() > 0);
+        return itemMgr.hasChildProperties((NodeId) id);
     }
 
     /**
@@ -1877,13 +1870,9 @@
         ReferenceManager refMgr = wsp.getReferenceManager();
         synchronized (refMgr) {
             NodeReferences refs = refMgr.get((NodeId) id);
-            Iterator iter = refs.getReferences().iterator();
-            ArrayList list = new ArrayList();
-            while (iter.hasNext()) {
-                PropertyId propId = (PropertyId) iter.next();
-                list.add(itemMgr.getItem(propId));
-            }
-            return new IteratorHelper(list);
+            // refs.getReferences returns a list of PropertyId's
+            List idList = refs.getReferences();
+            return new LazyItemIterator(itemMgr, idList);
         }
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeReferences.java	Mon Nov  8 09:42:33 2004
@@ -71,8 +71,8 @@
     /**
      * @return
      */
-    public Collection getReferences() {
-        return Collections.unmodifiableCollection(references);
+    public List getReferences() {
+        return Collections.unmodifiableList(references);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/xdocs/tasks.xml
==============================================================================
--- incubator/jackrabbit/trunk/xdocs/tasks.xml	(original)
+++ incubator/jackrabbit/trunk/xdocs/tasks.xml	Mon Nov  8 09:42:33 2004
@@ -13,10 +13,6 @@
         	access control (jaas)
         </task>
         <task creator="stefan" assignedto="" startdate="" enddate="" effort="" status="">
-		current persistence model (nodes and properties are stored in separate
-		files) leads to *very* slow performance in a normal filesystem;
-        </task>
-        <task creator="stefan" assignedto="" startdate="" enddate="" effort="" status="">
         	use jdbc as an alternative to virtual filesystem persistence layer
         </task>
         <task creator="stefan" assignedto="" startdate="" enddate="" effort="" status="">