You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2013/06/06 15:18:19 UTC

svn commit: r1490270 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java

Author: thomasm
Date: Thu Jun  6 13:18:18 2013
New Revision: 1490270

URL: http://svn.apache.org/r1490270
Log:
OAK-858 NodeBuilder.getChildNodeCount - don't rely on child count from the MK being exact, and reduce memory usage if there are many child nodes

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeState.java

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=1490270&r1=1490269&r2=1490270&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 Thu Jun  6 13:18:18 2013
@@ -75,7 +75,7 @@ public final class KernelNodeState exten
     /**
      * Maximum number of child nodes kept in memory.
      */
-    static final int MAX_CHILD_NODE_NAMES = 1000;
+    static final int MAX_CHILD_NODE_NAMES = 100;
 
     /**
      * Dummy cache instance for static {@link #NULL} kernel node state.
@@ -305,18 +305,87 @@ public final class KernelNodeState exten
     @Override
     public Iterable<? extends ChildNodeEntry> getChildNodeEntries() {
         init();
-        Iterable<ChildNodeEntry> iterable = iterable(childNames);
-        if (childNodeCount > childNames.size()) {
-            List<Iterable<ChildNodeEntry>> iterables = Lists.newArrayList();
-            iterables.add(iterable);
-            long offset = childNames.size();
-            while (offset < childNodeCount) {
-                iterables.add(getChildNodeEntries(offset, MAX_CHILD_NODE_NAMES));
-                offset += MAX_CHILD_NODE_NAMES;
-            }
-            iterable = Iterables.concat(iterables);
+        if (childNodeCount <= childNames.size()) {
+            return iterable(childNames);
         }
-        return iterable;
+        List<Iterable<ChildNodeEntry>> iterables = Lists.newArrayList();
+        iterables.add(iterable(childNames));
+        iterables.add(getChildNodeEntries(childNames.size()));
+        return Iterables.concat(iterables);
+    }
+
+    private Iterable<ChildNodeEntry> getChildNodeEntries(final long offset) {
+        return new Iterable<ChildNodeEntry>() {
+            @Override
+            public Iterator<ChildNodeEntry> iterator() {
+                return new Iterator<ChildNodeEntry>() {
+                    private long currentOffset = offset;
+                    private Iterator<ChildNodeEntry> current;
+
+                    {
+                        fetchEntries();
+                    }
+
+                    private void fetchEntries() {
+                        List<ChildNodeEntry> entries = Lists
+                                .newArrayListWithCapacity(MAX_CHILD_NODE_NAMES);
+                        String json = kernel.getNodes(path, revision, 0,
+                                currentOffset, MAX_CHILD_NODE_NAMES, null);
+                        JsopReader reader = new JsopTokenizer(json);
+                        reader.read('{');
+                        do {
+                            String name = StringCache.get(reader.readString());
+                            reader.read(':');
+                            if (reader.matches('{')) {
+                                reader.read('}');
+                                entries.add(new KernelChildNodeEntry(name));
+                            } else if (reader.matches('[')) {
+                                while (reader.read() != ']') {
+                                    // skip
+                                }
+                            } else {
+                                reader.read();
+                            }
+                        } while (reader.matches(','));
+                        reader.read('}');
+                        reader.read(JsopReader.END);
+                        if (entries.isEmpty()) {
+                            current = null;
+                        } else {
+                            currentOffset += entries.size();
+                            current = entries.iterator();
+                        }
+                    }
+
+                    @Override
+                    public boolean hasNext() {
+                        while (true) {
+                            if (current == null) {
+                                return false;
+                            } else if (current.hasNext()) {
+                                return true;
+                            }
+                            fetchEntries();
+                        }
+                    }
+
+                    @Override
+                    public ChildNodeEntry next() {
+                        if (!hasNext()) {
+                            throw new IllegalStateException(
+                                    "Reading past the end");
+                        }
+                        return current.next();
+                    }
+
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    
+                };
+            }
+        };
     }
 
     @Override
@@ -539,38 +608,6 @@ public final class KernelNodeState exten
         }
     }
 
-    private Iterable<ChildNodeEntry> getChildNodeEntries(
-            final long offset, final int count) {
-        return new Iterable<ChildNodeEntry>() {
-            @Override
-            public Iterator<ChildNodeEntry> iterator() {
-                List<ChildNodeEntry> entries =
-                        Lists.newArrayListWithCapacity(count);
-                String json = kernel.getNodes(
-                        path, revision, 0, offset, count, null);
-                JsopReader reader = new JsopTokenizer(json);
-                reader.read('{');
-                do {
-                    String name = StringCache.get(reader.readString());
-                    reader.read(':');
-                    if (reader.matches('{')) {
-                        reader.read('}');
-                        entries.add(new KernelChildNodeEntry(name));
-                    } else if (reader.matches('[')) {
-                        while (reader.read() != ']') {
-                            // skip
-                        }
-                    } else {
-                        reader.read();
-                    }
-                } while (reader.matches(','));
-                reader.read('}');
-                reader.read(JsopReader.END);
-                return entries.iterator();
-            }
-        };
-    }
-
     private String getChildPath(String name) {
         if ("/".equals(path)) {
             return '/' + name;