jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1510896 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/ oak-core/src/main/java/org/apache/jac...
Date Tue, 06 Aug 2013 10:23:12 GMT
Author: thomasm
Date: Tue Aug  6 10:23:11 2013
New Revision: 1510896

URL: http://svn.apache.org/r1510896
Log:
OAK-858 NodeBuilder.getChildNodeCount performance and scalability

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MutableNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableTreeTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootFuzzIT.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenTreeTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TreeTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/AbstractPermissionHookTest.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Tree.java Tue
Aug  6 10:23:11 2013
@@ -75,7 +75,7 @@ import javax.annotation.Nullable;
  * <p>
  * The <em>iterability</em> of a tree is a related to existence. A node
  * state is <em>iterable</em> if it is included in the return values of the
- * {@link #getChildrenCount()} and {@link #getChildren()} methods. An iterable
+ * {@link #getChildrenCount(long)} and {@link #getChildren()} methods. An iterable
  * node is guaranteed to exist, though not all existing nodes are necessarily
  * iterable.
  * <p>
@@ -211,14 +211,20 @@ public interface Tree {
      *         exists and is accessible for the current content session.
      */
     boolean hasChild(@Nonnull String name);
-
+    
     /**
      * Determine the number of children of this {@code Tree} instance taking
      * access restrictions into account.
-     *
-     * @return The number of accessible children.
-     */
-    long getChildrenCount();
+     * <p>
+     * If an implementation does know the exact value, it returns it (even if
+     * the value is higher than max). If the implementation does not know the
+     * exact value, and the child node count is higher than max, it may return
+     * Long.MAX_VALUE. The cost of the operation is at most O(max).
+     * 
+     * @param max the maximum value
+     * @return the number of accessible children.
+     */    
+    long getChildrenCount(long max);
 
     /**
      * All accessible children of this {@code Tree} instance. The returned

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractTree.java
Tue Aug  6 10:23:11 2013
@@ -225,8 +225,15 @@ public abstract class AbstractTree imple
     }
 
     @Override
-    public long getChildrenCount() {
-        long count = nodeBuilder.getChildNodeCount();
+    public long getChildrenCount(long max) {
+        if (max + INTERNAL_NODE_NAMES.length < 0) {
+            // avoid overflow (if max is near Long.MAX_VALUE)
+            max = Long.MAX_VALUE;
+        } else {
+            // fetch a few more
+            max += INTERNAL_NODE_NAMES.length;
+        }
+        long count = nodeBuilder.getChildNodeCount(max);
         for (String name : INTERNAL_NODE_NAMES) {
             if (nodeBuilder.hasChildNode(name)) {
                 count--;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableTree.java
Tue Aug  6 10:23:11 2013
@@ -179,9 +179,9 @@ public class MutableTree extends Abstrac
     }
 
     @Override
-    public long getChildrenCount() {
+    public long getChildrenCount(long max) {
         enter();
-        return super.getChildrenCount();
+        return super.getChildrenCount(max);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeBuilder.java
Tue Aug  6 10:23:11 2013
@@ -293,9 +293,9 @@ class SecureNodeBuilder implements NodeB
     }
 
     @Override
-    public synchronized long getChildNodeCount() {
+    public synchronized long getChildNodeCount(long max) {
         if (getSecurityContext().canReadAll()) {
-            return builder.getChildNodeCount();
+            return builder.getChildNodeCount(max);
         } else {
             return size(getChildNodeNames());
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SecureNodeState.java
Tue Aug  6 10:23:11 2013
@@ -125,13 +125,18 @@ class SecureNodeState extends AbstractNo
     }
 
     @Override
-    public synchronized long getChildNodeCount() {
+    public synchronized long getChildNodeCount(long max) {
         if (childNodeCount == -1) {
+            long count;
             if (context.canReadAll()) {
-                childNodeCount = state.getChildNodeCount();
+                count = state.getChildNodeCount(max);
             } else {
-                childNodeCount = super.getChildNodeCount();
+                count = super.getChildNodeCount(max);
             }
+            if (count == Long.MAX_VALUE) {
+                return count;
+            }
+            childNodeCount = count;
         }
         return childNodeCount;
     }
@@ -214,7 +219,7 @@ class SecureNodeState extends AbstractNo
             NodeState child = input.getNodeState();
             SecurityContext childContext = context.getChildContext(name, child);
             SecureNodeState secureChild = new SecureNodeState(child, childContext);
-            if (child.getChildNodeCount() == 0
+            if (child.getChildNodeCount(1) == 0
                     && secureChild.context.canReadThisNode()
                     && secureChild.context.canReadAllProperties()) {
                 // Since this is an accessible leaf node whose all properties

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java
Tue Aug  6 10:23:11 2013
@@ -120,6 +120,8 @@ public final class KernelNodeState exten
 
     private long childNodeCount = -1;
 
+    private long childNodeCountMin;
+
     private String hash;
 
     private String id;
@@ -255,10 +257,35 @@ public final class KernelNodeState exten
         init();
         return properties.values();
     }
-
+    
     @Override
-    public long getChildNodeCount() {
+    public long getChildNodeCount(long max) {
         init();
+        if (childNodeCount == Long.MAX_VALUE) {
+            if (childNodeCountMin > max) {
+                // getChildNodeCount(max) was already called,
+                // and we know the value is higher than max
+                return childNodeCountMin;
+            }
+            // count the entries
+            Iterator<?> iterator = getChildNodeEntries().iterator();
+            long n = 0;
+            while (n <= max) {
+                if (!iterator.hasNext()) {
+                    // we know the exact number now
+                    childNodeCount = n;
+                    return n;
+                }
+                iterator.next();
+                n++;
+            }
+            // remember we have at least this number of entries
+            childNodeCountMin = n;
+            if (n == max) {
+                // we didn't count all entries
+                return max;
+            }
+        }
         return childNodeCount;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/MergingNodeStateDiff.java
Tue Aug  6 10:23:11 2013
@@ -121,7 +121,7 @@ public final class MergingNodeStateDiff 
 
         NodeBuilder conflictMarker = getConflictMarker(conflictName);
         if (conflictMarker != null) {
-            assert conflictMarker.getChildNodeCount() == 0;
+            assert conflictMarker.getChildNodeCount(1) == 0;
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
Tue Aug  6 10:23:11 2013
@@ -98,7 +98,7 @@ public class ContentMirrorStoreStrategy 
 
             // Prune all index nodes that are no longer needed
             for (NodeBuilder node : builders) {
-                if (node.getBoolean("match") || node.getChildNodeCount() > 0) {
+                if (node.getBoolean("match") || node.getChildNodeCount(1) > 0) {
                     return;
                 } else if (node.exists()) {
                     node.remove();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/EmptyNodeState.java
Tue Aug  6 10:23:11 2013
@@ -96,7 +96,7 @@ public final class EmptyNodeState implem
     }
 
     @Override
-    public long getChildNodeCount() {
+    public long getChildNodeCount(long max) {
         return 0;
     }
 
@@ -182,7 +182,7 @@ public final class EmptyNodeState implem
         } else if (object instanceof NodeState) {
             NodeState that = (NodeState) object;
             return that.getPropertyCount() == 0
-                    && that.getChildNodeCount() == 0;
+                    && that.getChildNodeCount(1) == 0;
         } else {
             return false;
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilder.java
Tue Aug  6 10:23:11 2013
@@ -231,8 +231,8 @@ public class MemoryNodeBuilder implement
     }
 
     @Override
-    public long getChildNodeCount() {
-        return head().getCurrentNodeState().getChildNodeCount();
+    public long getChildNodeCount(long max) {
+        return head().getCurrentNodeState().getChildNodeCount(max);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeState.java
Tue Aug  6 10:23:11 2013
@@ -101,7 +101,7 @@ class MemoryNodeState extends AbstractNo
     }
 
     @Override
-    public long getChildNodeCount() {
+    public long getChildNodeCount(long max) {
         return nodes.size();
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
Tue Aug  6 10:23:11 2013
@@ -173,20 +173,34 @@ public class ModifiedNodeState extends A
     }
 
     static long getChildNodeCount(
-            NodeState base, Map<String, ? extends NodeState> nodes) {
-        long count = 0;
-        if (base.exists()) {
-            count = base.getChildNodeCount();
-            for (Entry<String, ? extends NodeState> entry
-                    : nodes.entrySet()) {
-                if (base.hasChildNode(entry.getKey())) {
-                    count--;
-                }
-                if (entry.getValue().exists()) {
-                    count++;
-                }
+            NodeState base, Map<String, ? extends NodeState> nodes, long max) {
+        if (!base.exists()) {
+            return 0;
+        }
+        long deleted = 0, added = 0;
+        for (Entry<String, ? extends NodeState> entry
+                : nodes.entrySet()) {
+            if (!base.hasChildNode(entry.getKey())) {
+                added++;
+            }
+            if (!entry.getValue().exists()) {
+                deleted++;
             }
         }
+        // if we deleted 100 entries, then we need to 
+        // be sure there are 100 more entries than max
+        if (max + deleted < 0) {
+            // avoid overflow
+            max = Long.MAX_VALUE;
+        } else {
+            max += deleted;
+        }
+        long count = base.getChildNodeCount(max);
+        if (count + added - deleted < 0) {
+            count = Long.MAX_VALUE;
+        } else {
+            count = count + added - deleted;
+        }
         return count;
     }
 
@@ -292,8 +306,8 @@ public class ModifiedNodeState extends A
     }
 
     @Override
-    public long getChildNodeCount() {
-        return getChildNodeCount(base, nodes);
+    public long getChildNodeCount(long max) {
+        return getChildNodeCount(base, nodes, max);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MutableNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MutableNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MutableNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MutableNodeState.java
Tue Aug  6 10:23:11 2013
@@ -234,9 +234,9 @@ class MutableNodeState extends AbstractN
     }
 
     @Override
-    public long getChildNodeCount() {
+    public long getChildNodeCount(long max) {
         assert base != null;
-        return ModifiedNodeState.getChildNodeCount(base, nodes);
+        return ModifiedNodeState.getChildNodeCount(base, nodes, max);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeState.java
Tue Aug  6 10:23:11 2013
@@ -97,7 +97,7 @@ public class SegmentNodeState extends Ab
     }
 
     @Override
-    public long getChildNodeCount() {
+    public long getChildNodeCount(long max) {
         return getTemplate().getChildNodeCount(store, recordId);
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
Tue Aug  6 10:23:11 2013
@@ -661,8 +661,8 @@ public class SegmentWriter {
             MapRecord base;
             final Map<String, RecordId> childNodes = Maps.newHashMap();
             if (before != null
-                    && before.getChildNodeCount() > 1
-                    && after.getChildNodeCount() > 1) {
+                    && before.getChildNodeCount(2) > 1
+                    && after.getChildNodeCount(2) > 1) {
                 base = before.getChildNodeMap();
                 after.compareAgainstBaseState(before, new DefaultNodeStateDiff() {
                     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Template.java
Tue Aug  6 10:23:11 2013
@@ -111,7 +111,7 @@ public class Template {
                 templates.toArray(new PropertyTemplate[templates.size()]);
         Arrays.sort(properties);
 
-        long count = state.getChildNodeCount();
+        long count = state.getChildNodeCount(2);
         if (count == 0) {
             childName = ZERO_CHILD_NODES;
         } else if (count == 1) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractChildNodeEntry.java
Tue Aug  6 10:23:11 2013
@@ -33,7 +33,7 @@ public abstract class AbstractChildNodeE
     public String toString() {
         String name = getName();
         NodeState state = getNodeState();
-        if (state.getChildNodeCount() == 0) {
+        if (state.getChildNodeCount(1) == 0) {
             return name + " : " + state;
         } else {
             return name + " = { ... }";

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/AbstractNodeState.java
Tue Aug  6 10:23:11 2013
@@ -124,8 +124,17 @@ public abstract class AbstractNodeState 
     }
 
     @Override
-    public long getChildNodeCount() {
-        return count(getChildNodeEntries());
+    public long getChildNodeCount(long max) {
+        long n = 0;
+        Iterator<?> iterator = getChildNodeEntries().iterator();
+        while (iterator.hasNext()) {
+            iterator.next();
+            n++;
+            if (n >= max) {
+                return Long.MAX_VALUE;
+            }
+        }
+        return n;
     }
 
     @Override
@@ -231,10 +240,25 @@ public abstract class AbstractNodeState 
             return false;
         }
 
-        if (getPropertyCount() != other.getPropertyCount()
-                || getChildNodeCount() != other.getChildNodeCount()) {
+        if (getPropertyCount() != other.getPropertyCount()) {
             return false;
         }
+        // if one of the objects has few entries,
+        // then compare the number of entries with the other one
+        long max = 20;
+        long c1 = getChildNodeCount(max);
+        long c2 = other.getChildNodeCount(max);
+        if (c1 <= max || c2 <= max) {
+            // one has less than max entries
+            if (c1 != c2) {
+                return false;
+            }
+        } else if (c1 != Long.MAX_VALUE && c2 != Long.MAX_VALUE) {
+            // we know the exact number for both
+            if (c1 != c2) {
+                return false;
+            }
+        }
 
         for (PropertyState property : getProperties()) {
             if (!property.equals(other.getProperty(property.getName()))) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeBuilder.java
Tue Aug  6 10:23:11 2013
@@ -131,10 +131,16 @@ public interface NodeBuilder {
 
     /**
      * Returns the current number of child nodes.
-     *
+     * <p>
+     * If an implementation does know the exact value, it returns it (even if
+     * the value is higher than max). If the implementation does not know the
+     * exact value, and the child node count is higher than max, it may return
+     * Long.MAX_VALUE. The cost of the operation is at most O(max).
+     * 
+     * @param max the maximum value
      * @return number of child nodes
      */
-    long getChildNodeCount();
+    long getChildNodeCount(long max);
 
     /**
      * Returns the names of current child nodes.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeState.java
Tue Aug  6 10:23:11 2013
@@ -89,7 +89,7 @@ import com.google.common.base.Predicate;
  * <p>
  * The <em>iterability</em> of a node is a related concept to the
  * above-mentioned existence. A node state is <em>iterable</em> if it
- * is included in the return values of the {@link #getChildNodeCount()},
+ * is included in the return values of the {@link #getChildNodeCount(long)},
  * {@link #getChildNodeNames()} and {@link #getChildNodeEntries()} methods.
  * An iterable node is guaranteed to exist, though not all existing nodes
  * are necessarily iterable.
@@ -289,10 +289,16 @@ public interface NodeState {
 
     /**
      * Returns the number of <em>iterable</em> child nodes of this node.
-     *
+     * <p>
+     * If an implementation knows the exact value, it returns it (even if
+     * the value is higher than max). If the implementation does not know the
+     * exact value, and the child node count is higher than max, it may return
+     * Long.MAX_VALUE. The cost of the operation is at most O(max).
+     * 
+     * @param max the maximum number of entries to traverse
      * @return number of iterable child nodes
      */
-    long getChildNodeCount();
+    long getChildNodeCount(long max);
 
     /**
      * Returns the names of all <em>iterable</em> child nodes.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ReadOnlyBuilder.java
Tue Aug  6 10:23:11 2013
@@ -73,8 +73,8 @@ public class ReadOnlyBuilder implements 
     }
 
     @Override
-    public long getChildNodeCount() {
-        return state.getChildNodeCount();
+    public long getChildNodeCount(long max) {
+        return state.getChildNodeCount(max);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableTreeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableTreeTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableTreeTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/MutableTreeTest.java
Tue Aug  6 10:23:11 2013
@@ -111,7 +111,7 @@ public class MutableTreeTest extends Oak
         }
         assertTrue(expectedPaths.isEmpty());
 
-        assertEquals(3, tree.getChildrenCount());
+        assertEquals(3, tree.getChildrenCount(4));
     }
 
     @Test
@@ -226,16 +226,16 @@ public class MutableTreeTest extends Oak
     public void getChildrenCount() {
         Tree tree = root.getTree("/");
 
-        assertEquals(3, tree.getChildrenCount());
+        assertEquals(3, tree.getChildrenCount(4));
 
         tree.getChild("x").remove();
-        assertEquals(2, tree.getChildrenCount());
+        assertEquals(2, tree.getChildrenCount(3));
 
         tree.addChild("a");
-        assertEquals(3, tree.getChildrenCount());
+        assertEquals(3, tree.getChildrenCount(3));
 
         tree.addChild("x");
-        assertEquals(4, tree.getChildrenCount());
+        assertEquals(4, tree.getChildrenCount(5));
     }
 
     @Test

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootFuzzIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootFuzzIT.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootFuzzIT.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootFuzzIT.java
Tue Aug  6 10:23:11 2013
@@ -396,7 +396,7 @@ public class RootFuzzIT {
     private String chooseNode(String parentPath) {
         Tree state = root1.getTree(parentPath);
 
-        int k = random.nextInt((int) (state.getChildrenCount() + 1));
+        int k = random.nextInt((int) (state.getChildrenCount(Long.MAX_VALUE) + 1));
         int c = 0;
         for (Tree child : state.getChildren()) {
             if (c++ == k) {
@@ -428,7 +428,7 @@ public class RootFuzzIT {
                 tree1.getPath() + "!=" + tree2.getPath()
                 + " (seed " + SEED + ')';
         assertEquals(message, tree1.getPath(), tree2.getPath());
-        assertEquals(message, tree1.getChildrenCount(), tree2.getChildrenCount());
+        assertEquals(message, tree1.getChildrenCount(Long.MAX_VALUE), tree2.getChildrenCount(Long.MAX_VALUE));
         assertEquals(message, tree1.getPropertyCount(), tree2.getPropertyCount());
 
         for (PropertyState property1 : tree1.getProperties()) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/core/RootTest.java
Tue Aug  6 10:23:11 2013
@@ -440,7 +440,7 @@ public class RootTest extends OakBaseTes
     }
 
     private static void checkEqual(Tree tree1, Tree tree2) {
-        assertEquals(tree1.getChildrenCount(), tree2.getChildrenCount());
+        assertEquals(tree1.getChildrenCount(Long.MAX_VALUE), tree2.getChildrenCount(Long.MAX_VALUE));
         assertEquals(tree1.getPropertyCount(), tree2.getPropertyCount());
 
         for (PropertyState property1 : tree1.getProperties()) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
Tue Aug  6 10:23:11 2013
@@ -102,7 +102,7 @@ public class KernelNodeStateTest {
 
     @Test
     public void testGetChildNodeCount() {
-        assertEquals(3, state.getChildNodeCount());
+        assertEquals(3, state.getChildNodeCount(4));
     }
 
     @Test

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
Tue Aug  6 10:23:11 2013
@@ -63,7 +63,7 @@ public class LargeKernelNodeStateTest {
 
     @Test
     public void testGetChildNodeCount() {
-        assertEquals(N + 1, state.getChildNodeCount());
+        assertEquals(N + 1, state.getChildNodeCount(N + 2));
     }
 
     @Test

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategyTest.java
Tue Aug  6 10:23:11 2013
@@ -97,7 +97,7 @@ public class ContentMirrorStoreStrategyT
 
         // remove the root key when the index is empty
         store.update(index, "", KEY, EMPTY);
-        Assert.assertEquals(0, index.getChildNodeCount());
+        Assert.assertEquals(0, index.getChildNodeCount(1));
     }
 
     private static void checkPath(NodeBuilder node, String key, String path,

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeBuilderTest.java
Tue Aug  6 10:23:11 2013
@@ -120,7 +120,7 @@ public class MemoryNodeBuilderTest {
             }
 
             root.child(name);
-            assertEquals(0, child.getChildNodeCount()); // reconnect!
+            assertEquals(0, child.getChildNodeCount(1)); // reconnect!
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/AccessControlManagerImplTest.java
Tue Aug  6 10:23:11 2013
@@ -1220,7 +1220,7 @@ public class AccessControlManagerImplTes
         assertTrue(tree.hasChild(REP_POLICY));
         Tree policyTree = tree.getChild(REP_POLICY);
         assertEquals(NT_REP_ACL, TreeUtil.getPrimaryTypeName(policyTree));
-        assertEquals(2, policyTree.getChildrenCount());
+        assertEquals(2, policyTree.getChildrenCount(3));
 
         Iterator<Tree> children = policyTree.getChildren().iterator();
         Tree ace = children.next();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenTreeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenTreeTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenTreeTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/HiddenTreeTest.java
Tue Aug  6 10:23:11 2013
@@ -95,6 +95,6 @@ public class HiddenTreeTest extends Abst
 
     @Test
     public void testGetHiddenChildrenCount() {
-        assertEquals(0, parent.getChildrenCount());
+        assertEquals(0, parent.getChildrenCount(1));
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TreeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TreeTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TreeTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/TreeTest.java
Tue Aug  6 10:23:11 2013
@@ -93,19 +93,19 @@ public class TreeTest extends AbstractOa
 
     @Test
 	public void testGetChildrenCount() throws Exception {
-        long cntRoot = root.getTree("/").getChildrenCount();
-        long cntA = root.getTree("/a").getChildrenCount();
+        long cntRoot = root.getTree("/").getChildrenCount(Long.MAX_VALUE);
+        long cntA = root.getTree("/a").getChildrenCount(Long.MAX_VALUE);
 
         // 'testUser' may only see 'regular' child nodes -> count must be adjusted.
-        assertEquals(cntRoot-1, testRoot.getTree("/").getChildrenCount());
-        assertEquals(cntA - 1, testRoot.getTree("/a").getChildrenCount());
+        assertEquals(cntRoot-1, testRoot.getTree("/").getChildrenCount(Long.MAX_VALUE));
+        assertEquals(cntA - 1, testRoot.getTree("/a").getChildrenCount(Long.MAX_VALUE));
 
         // for the following nodes the cnt must not differ
         List<String> paths = ImmutableList.of("/a/b", "/a/b/c");
         for (String path : paths) {
             assertEquals(
-                    root.getTree(path).getChildrenCount(),
-                    testRoot.getTree(path).getChildrenCount());
+                    root.getTree(path).getChildrenCount(Long.MAX_VALUE),
+                    testRoot.getTree(path).getChildrenCount(Long.MAX_VALUE));
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/AbstractPermissionHookTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/AbstractPermissionHookTest.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/AbstractPermissionHookTest.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/AbstractPermissionHookTest.java
Tue Aug  6 10:23:11 2013
@@ -128,7 +128,7 @@ public abstract class AbstractPermission
     }
 
     protected long cntEntries(Tree parent) {
-        long cnt = parent.getChildrenCount();
+        long cnt = parent.getChildrenCount(Long.MAX_VALUE);
         for (Tree child : parent.getChildren()) {
             cnt += cntEntries(child);
         }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
Tue Aug  6 10:23:11 2013
@@ -98,6 +98,12 @@ import static org.apache.jackrabbit.oak.
 public class NodeImpl<T extends NodeDelegate> extends ItemImpl<T> implements
Node, JackrabbitNode {
 
     /**
+     * The maximum returned value for {@link NodeIterator#getSize()}. If there
+     * are more nodes, the method returns -1.
+     */
+    private static final long NODE_ITERATOR_MAX_SIZE = Long.MAX_VALUE;
+
+    /**
      * logger instance
      */
     private static final Logger log = LoggerFactory.getLogger(NodeImpl.class);
@@ -498,12 +504,15 @@ public class NodeImpl<T extends NodeDele
             public NodeIterator perform() throws RepositoryException {
                 Iterator<NodeDelegate> children = node.getChildren();
                 return new NodeIteratorAdapter(nodeIterator(children)) {
-                    private long size = -1;
+                    private long size = -2;
                     @Override
                     public long getSize() {
-                        if (size == -1) {
+                        if (size == -2) {
                             try {
-                                size = node.getChildCount(); // TODO: perform()
+                                size = node.getChildCount(NODE_ITERATOR_MAX_SIZE); // TODO:
perform()
+                                if (size == Long.MAX_VALUE) {
+                                    size = -1;
+                                }
                             } catch (InvalidItemStateException e) {
                                 throw new IllegalStateException(
                                         "This iterator is no longer valid", e);

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1510896&r1=1510895&r2=1510896&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
Tue Aug  6 10:23:11 2013
@@ -305,12 +305,18 @@ public class NodeDelegate extends ItemDe
 
     /**
      * Get the number of child nodes
-     *
+     * <p>
+     * If an implementation does know the exact value, it returns it (even if
+     * the value is higher than max). If the implementation does not know the
+     * exact value, and the child node count is higher than max, it may return
+     * Long.MAX_VALUE. The cost of the operation is at most O(max).
+     * 
+     * @param max the maximum value
      * @return number of child nodes of the node
      */
-    public long getChildCount() throws InvalidItemStateException {
+    public long getChildCount(long max) throws InvalidItemStateException {
         // TODO: Exclude "invisible" internal child nodes (OAK-182)
-        return getTree().getChildrenCount();
+        return getTree().getChildrenCount(max);
     }
 
     /**



Mime
View raw message