You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2011/09/05 17:15:30 UTC

svn commit: r1165326 - in /jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem: MemoryKernelImpl.java NodeImpl.java NodeList.java NodeListLarge.java NodeListOld.java NodeListSmall.java NodeMap.java Revision.java

Author: thomasm
Date: Mon Sep  5 15:15:30 2011
New Revision: 1165326

URL: http://svn.apache.org/viewvc?rev=1165326&view=rev
Log:
Trying to support large child node lists (WIP) and other changes.

Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListOld.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java Mon Sep  5 15:15:30 2011
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.mk.json.Jso
 import org.apache.jackrabbit.mk.util.CommitGate;
 import org.apache.jackrabbit.mk.util.NonDescendingClock;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.mk.util.SmallLRUCache;
 
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -57,14 +58,17 @@ Node structure:
  */
 public class MemoryKernelImpl implements MicroKernel {
 
+    private static final boolean DEBUG = false;
     private static final int MAX_REVISIONS_PER_NODE = 100;
     private static final HashMap<String, MemoryKernelImpl> INSTANCES = new HashMap<String, MemoryKernelImpl>();
 
-    private AbstractBlobStore ds;
+    private final AbstractBlobStore ds;
+    private final NonDescendingClock clock = new NonDescendingClock(System.currentTimeMillis());
+    private final CommitGate gate = new CommitGate();
+    private final SmallLRUCache<Long, Revision> revisionCache = SmallLRUCache.newInstance(1000);
     private long headRevId;
     private NodeMap nodeMap;
-    private NonDescendingClock clock = new NonDescendingClock(System.currentTimeMillis());
-    private final CommitGate gate = new CommitGate();
+    private String lastJournalRevRange, lastJournal;
 
     private MemoryKernelImpl(String name) {
         nodeMap = new NodeMap();
@@ -96,6 +100,8 @@ public class MemoryKernelImpl implements
         ds.clear();
         nodeMap.clear();
         NodeImpl head = new NodeImpl(nodeMap, 0);
+        Revision revNode = new Revision(0, 0, "", "");
+        head = revNode.store(head, new NodeImpl(nodeMap, 0));
         head.addChildNode("data", new NodeImpl(nodeMap, 0));
         NodeImpl root = new NodeImpl(nodeMap, 0);
         root.addChildNode("head", head);
@@ -112,7 +118,11 @@ public class MemoryKernelImpl implements
         // TODO property type as comment versus as special property
         // TODO metadata in storage (version)
         // TODO optional read / write version in json 'api' (as comments?)
-        long oldRevision = headRevId++;
+        if (DEBUG) {
+            System.out.println("commit " + jsonDiff);
+        }
+        long oldRevision = headRevId;
+        long rev = headRevId + 1;
         NodeImpl root = nodeMap.getNode(nodeMap.getRootId());
         NodeImpl head = root.getNode("head");
         NodeImpl oldHead = head;
@@ -131,17 +141,17 @@ public class MemoryKernelImpl implements
                 path = t.readString();
                 w.appendTag("+ ").key(PathUtils.concat(rootPath, path));
                 t.read(':');
-                int todoSupportAddProperty;
+                // TODO support adding a property?
                 t.read('{');
-                NodeImpl n = NodeImpl.parse(nodeMap, t, headRevId);
-                data = data.cloneAndAddChildNode(PathUtils.concat(fromRoot, path), false, null, n, headRevId);
+                NodeImpl n = NodeImpl.parse(nodeMap, t, rev);
+                data = data.cloneAndAddChildNode(PathUtils.concat(fromRoot, path), false, null, n, rev);
                 n.append(w, -1, 0, -1, false);
                 w.newline();
                 break;
             case '-':
                 path = t.readString();
                 w.appendTag("- ").value(PathUtils.concat(rootPath, path));
-                data = data.cloneAndRemoveChildNode(PathUtils.concat(fromRoot, path), headRevId);
+                data = data.cloneAndRemoveChildNode(PathUtils.concat(fromRoot, path), rev);
                 w.newline();
                 break;
             case '^':
@@ -163,7 +173,7 @@ public class MemoryKernelImpl implements
                     }
                     w.encodedValue(value);
                 }
-                data = data.cloneAndSetProperty(PathUtils.concat(fromRoot, path), value, headRevId);
+                data = data.cloneAndSetProperty(PathUtils.concat(fromRoot, path), value, rev);
                 w.newline();
                 break;
             case '>':
@@ -235,29 +245,31 @@ public class MemoryKernelImpl implements
                 }
                 NodeImpl node = data.getNode(from);
                 if (!inPlaceRename) {
-                    data = data.cloneAndRemoveChildNode(from, headRevId);
+                    data = data.cloneAndRemoveChildNode(from, rev);
                 }
-                data = data.cloneAndAddChildNode(to, before, position, node, headRevId);
+                data = data.cloneAndAddChildNode(to, before, position, node, rev);
                 if (inPlaceRename) {
-                    data = data.cloneAndRemoveChildNode(from, headRevId);
+                    data = data.cloneAndRemoveChildNode(from, rev);
                 }
                 break;
             default:
                 throw new AssertionError("token: " + (char) t.getTokenType());
             }
         }
-        head = head.setChild("data", data, headRevId);
-        Revision rev = new Revision(headRevId, clock.time(), w.toString(), message);
-        head = rev.store(head, new NodeImpl(nodeMap, headRevId));
-        root = root.setChild("head", head, headRevId);
+        head = head.setChild("data", data, rev);
+        Revision revNode = new Revision(rev, clock.time(), w.toString(), message);
+        revisionCache.put(rev, revNode);
+        head = revNode.store(head, new NodeImpl(nodeMap, rev));
+        root = root.setChild("head", head, rev);
         NodeImpl old = root.getNode("old");
         if (old.getChildNodeCount() > MAX_REVISIONS_PER_NODE) {
-            NodeImpl newOld = new NodeImpl(nodeMap, headRevId);
-            old = newOld.setChild("old", old, headRevId);
+            NodeImpl newOld = new NodeImpl(nodeMap, rev);
+            old = newOld.setChild("old", old, rev);
         }
-        old = old.setChild(Revision.formatId(oldRevision), oldHead, headRevId);
-        root = root.setChild("old", old, headRevId);
+        old = old.setChild(Revision.formatId(oldRevision), oldHead, rev);
+        root = root.setChild("old", old, rev);
         nodeMap.commit(root);
+        headRevId = rev;
         String headRev = getHeadRevision();
         gate.commit(headRev);
         return headRev;
@@ -272,16 +284,21 @@ public class MemoryKernelImpl implements
     }
 
     public String getRevisions(long since, int maxEntries) {
+        if (DEBUG) {
+            System.out.println("getRevisions " + since);
+        }
         NodeImpl node = getRoot();
         ArrayList<Revision> revisions = new ArrayList<Revision>();
-        Revision r = new Revision(node.getNode("head"));
+        Revision r = Revision.get(revisionCache, node.getNode("head"));
         if (since < r.getTime()) {
             revisions.add(r);
             while (node.exists("old")) {
                 node = node.getNode("old");
                 for (Iterator<String> it = node.getChildNodeNames(); it.hasNext();) {
-                    r = new Revision(node.getNode(it.next()));
-                    revisions.add(r);
+                    r = Revision.get(revisionCache, node.getNode(it.next()));
+                    if (r != null) {
+                        revisions.add(r);
+                    }
                 }
                 if (since >= r.getTime()) {
                     break;
@@ -303,19 +320,28 @@ public class MemoryKernelImpl implements
     }
 
     public String getJournal(String fromRevisionId, String toRevisionId) {
+        if (DEBUG) {
+            System.out.println("getJournal " + fromRevisionId + " " + toRevisionId);
+        }
+    	String revRange = fromRevisionId + "-" + toRevisionId;
+    	synchronized (this) {
+    	    if (revRange.equals(lastJournalRevRange)) {
+    	        return lastJournal;
+    	    }
+    	}
         long fromRevId = Revision.parseId(fromRevisionId);
         long toRevId = Revision.parseId(toRevisionId);
         NodeImpl node = getRoot();
         ArrayList<Revision> revisions = new ArrayList<Revision>();
-        Revision r = new Revision(node.getNode("head"));
+        Revision r = Revision.get(revisionCache, node.getNode("head"));
         if (r.getId() >= fromRevId) {
             revisions.add(r);
         }
         while (r.getId() > fromRevId && node.exists("old")) {
             node = node.getNode("old");
             for (Iterator<String> it = node.getChildNodeNames(); it.hasNext();) {
-                r = new Revision(node.getNode(it.next()));
-                if (r.getId() >= fromRevId && r.getId() <= toRevId) {
+                r = Revision.get(revisionCache, node.getNode(it.next()));
+                if (r != null && r.getId() >= fromRevId && r.getId() <= toRevId) {
                     revisions.add(r);
                 }
             }
@@ -327,7 +353,11 @@ public class MemoryKernelImpl implements
                 rev.appendJournal(buff);
             }
         }
-        return buff.endArray().toString();
+        synchronized (this) {
+            lastJournalRevRange = revRange;
+            lastJournal = buff.endArray().toString();
+        }
+        return lastJournal;
     }
 
     public String getNodes(String path, String revisionId) {
@@ -335,6 +365,9 @@ public class MemoryKernelImpl implements
     }
 
     public String getNodes(String path, String revisionId, int depth, long offset, int count) {
+        if (DEBUG) {
+            System.out.println("getNodes " + path + " " + revisionId + " " + depth + " " + offset + " " + count);
+        }
         if (!PathUtils.isAbsolute(path)) {
             throw new IllegalArgumentException("Not an absolute path: " + path);
         }
@@ -353,6 +386,9 @@ public class MemoryKernelImpl implements
         if (revId == headRevId) {
             node = node.getNode("head");
         } else {
+            if (DEBUG) {
+                System.out.println("getRevision " + revisionId);
+            }
             while (true) {
                 if (!node.exists("old")) {
                     throw new RuntimeException("Revision not found: " + revisionId);
@@ -368,6 +404,10 @@ public class MemoryKernelImpl implements
     }
 
     public boolean nodeExists(String path, String revisionId) {
+        if (DEBUG) {
+            System.out.println("nodeExists " + path + " " + revisionId);
+        }
+
         // TODO possibly use a bloom filter
         if (!PathUtils.isAbsolute(path)) {
             throw new IllegalArgumentException("Not an absolute path: " + path);
@@ -376,6 +416,9 @@ public class MemoryKernelImpl implements
     }
 
     public long getLength(String blobId) {
+        if (DEBUG) {
+            System.out.println("getLength " + blobId);
+        }
         try {
             return ds.getBlobLength(blobId);
         } catch (Exception e) {
@@ -384,6 +427,9 @@ public class MemoryKernelImpl implements
     }
 
     public int read(String blobId, long pos, byte[] buff, int off, int length) {
+        if (DEBUG) {
+            System.out.println("read " + blobId);
+        }
         try {
             return ds.readBlob(blobId, pos, buff, off, length);
         } catch (Exception e) {
@@ -392,6 +438,9 @@ public class MemoryKernelImpl implements
     }
 
     public String write(InputStream in) {
+        if (DEBUG) {
+            System.out.println("write " + in);
+        }
         try {
             return ds.writeBlob(in);
         } catch (Exception e) {
@@ -400,6 +449,9 @@ public class MemoryKernelImpl implements
     }
 
     public void dispose() {
+        if (DEBUG) {
+            System.out.println("dispose");
+        }
         gate.commit("end");
         nodeMap.close();
     }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java Mon Sep  5 15:15:30 2011
@@ -80,6 +80,9 @@ public class NodeImpl {
             return childNodes.containsKey(path);
         }
         String child = path.substring(0, index);
+        if (!childNodes.containsKey(child)) {
+            return false;
+        }
         NodeImpl n = getChildNode(child);
         if (n == null) {
             return false;
@@ -258,9 +261,7 @@ public class NodeImpl {
         if (childNodes == null) {
             throw new RuntimeException("Node not found: " + name);
         }
-        if (childNodes.remove(name) == null) {
-            throw new RuntimeException("Node not found: " + name);
-        }
+        childNodes.remove(name);
         if (childNodes.size() == 0) {
             childNodes = null;
         }
@@ -341,7 +342,7 @@ public class NodeImpl {
 
     public String asString() {
         JsopBuilder json = new JsopBuilder();
-        json.setLineLength(80);
+        json.setLineLength(120);
         json.encodedValue(map.formatId(id)).appendTag("=");
         json.object();
         if (properties != null && properties.size() > 0) {
@@ -375,7 +376,7 @@ public class NodeImpl {
                 String key = t.readString();
                 t.read(':');
                 String value = t.readRawValue();
-                if (value.length() > 0 && value.charAt(0) >= 'a') {
+                if (map.isId(value)) {
                     if (node.childNodes == null) {
                         node.childNodes = new NodeListSmall();
                     }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java Mon Sep  5 15:15:30 2011
@@ -9,15 +9,15 @@ interface NodeList {
 
     boolean containsKey(String name);
 
-    Long get(String name);
+    long get(String name);
 
-    void add(String name, Long x);
+    void add(String name, long x);
 
-    void setId(String name, Long x);
+    void setId(String name, long x);
 
     Iterator<String> getNames(long offset);
 
-    Long remove(String name);
+    long remove(String name);
 
     NodeList createClone(NodeMap map);
 

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java Mon Sep  5 15:15:30 2011
@@ -55,8 +55,15 @@ public class NodeListLarge implements No
         return false;
     }
 
-    public void setId(String name, Long x) {
-        int todoKeepOrder;
+    public void setId(String name, long x) {
+        for (Child c : children) {
+            if (c.possiblyContains(name)) {
+                if (getList(c).containsKey(name)) {
+//                    getList(c).get
+                }
+            }
+        }
+        throw new RuntimeException("Node node found: " + name);
     }
 
     NodeList getList(Child c) {
@@ -64,7 +71,7 @@ public class NodeListLarge implements No
         return n.getNodeList();
     }
 
-    public Long get(String name) {
+    public long get(String name) {
         for (Child c : children) {
             if (c.possiblyContains(name)) {
                 NodeList child = getList(c);
@@ -73,7 +80,7 @@ public class NodeListLarge implements No
                 }
             }
         }
-        return null;
+        throw new RuntimeException("Node node found: " + name);
     }
 
     public Iterator<String> getNames(long offset) {
@@ -124,14 +131,14 @@ public class NodeListLarge implements No
         return it;
     }
 
-    public void add(String name, Long x) {
+    public void add(String name, long x) {
         Child c = children.get(children.size() - 1);
         NodeList child = getList(c);
         child.add(name, x);
         size++;
     }
 
-    public Long remove(String name) {
+    public long remove(String name) {
         for (Child c : children) {
             if (c.possiblyContains(name)) {
                 NodeList child = getList(c);
@@ -145,7 +152,7 @@ public class NodeListLarge implements No
                 }
             }
         }
-        return null;
+        throw new RuntimeException("Node node found: " + name);
     }
 
     public long size() {

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java Mon Sep  5 15:15:30 2011
@@ -17,102 +17,146 @@
 package org.apache.jackrabbit.mk.mem;
 
 import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
-import org.apache.jackrabbit.mk.json.JsopTokenizer;
 import org.apache.jackrabbit.mk.mem.NodeImpl.ChildVisitor;
+import org.apache.jackrabbit.mk.util.StringUtils;
 
 public class NodeListSmall implements NodeList {
 
-    private LinkedHashMap<String, Long> list;
-
-    private NodeListSmall(LinkedHashMap<String, Long> list) {
-        this.list = list;
-    }
-
-    public NodeListSmall() {
-        this(new LinkedHashMap<String, Long>());
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+    private static final long[] EMPTY_LONG_ARRAY = new long[0];
+    private static final int[] EMPTY_INTEGER_ARRAY = new int[0];
+
+    int size;
+    String[] names;
+    long[] children;
+    private int[] sort;
+    private int last;
+
+    NodeListSmall() {
+        this(EMPTY_STRING_ARRAY, EMPTY_LONG_ARRAY, EMPTY_INTEGER_ARRAY, 0);
+    }
+
+    private NodeListSmall(String[] names, long[] children, int[] sort, int size) {
+        this.names = names;
+        this.children = children;
+        this.sort = sort;
+        this.size = size;
     }
 
     public long size() {
-        return list.size();
+        return size;
     }
 
     public boolean containsKey(String name) {
-        return list.containsKey(name);
-    }
-
-    public Long get(String name) {
-        return list.get(name);
+        return find(name) >= 0;
     }
 
-    public void add(String name, Long x) {
-        Long old = list.put(name, x);
-        if (old != null) {
+    private int find(String name) {
+        if (last < size && names[sort[last]].equals(name)) {
+            return last;
+        }
+        int min = 0, max = size - 1;
+        while (min <= max) {
+            int test = (min + max) >>> 1;
+            int compare = names[sort[test]].compareTo(name);
+            if (compare == 0) {
+                last = test;
+                return test;
+            }
+            if (compare > 0) {
+                max = test - 1;
+            } else if (compare < 0) {
+                min = test + 1;
+            }
+        }
+        // not found: return negative insertion point
+        return -(min + 1);
+    }
+
+    public long get(String name) {
+        int index = find(name);
+        if (index < 0) {
+            throw new RuntimeException("Node node found: " + name);
+        }
+        return children[sort[index]];
+    }
+
+    public void add(String name, long x) {
+        int index = find(name);
+        if (index >= 0) {
             throw new RuntimeException("Node already exists: " + name);
         }
-    }
-
-    public void setId(String name, Long x) {
-        int todoKeepOrder;
-        list.put(name, x);
-    }
-
-    public Iterator<String> getNames(long offset) {
-        Iterator<String> it = list.keySet().iterator();
-        while (offset > 0 && it.hasNext()) {
-            offset--;
-            it.next();
-        }
-        return it;
-    }
-
-    public Long remove(String name) {
-        Long old = list.remove(name);
-        if (old == null) {
+        index = -index - 1;
+        names = StringUtils.arrayInsert(names, size, name);
+        children = StringUtils.arrayInsert(children, size, x);
+        sort = StringUtils.arrayInsert(sort, index, size);
+        size++;
+    }
+
+    public void setId(String name, long x) {
+        int index = find(name);
+        if (index < 0) {
+            throw new RuntimeException("Node node found: " + name);
+        }
+        children[sort[index]] = x;
+    }
+
+    public Iterator<String> getNames(final long offset) {
+        return  new Iterator<String>() {
+            int pos = (int) offset;
+            public boolean hasNext() {
+                return pos < size;
+            }
+            public String next() {
+                return names[pos++];
+            }
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    public long remove(String name) {
+        int index = find(name);
+        if (index < 0) {
             throw new RuntimeException("Node not found: " + name);
         }
-        return old;
-    }
-
-    public static NodeListSmall fromString(String s) {
-        NodeListSmall x = new NodeListSmall();
-        JsopTokenizer t = new JsopTokenizer(s);
-        if (!t.matches('{')) {
-            return null;
-        }
-        if (!t.matches('}')) {
-            do {
-                String n = t.readString();
-                t.read(':');
-                long id = Long.parseLong(t.readString());
-                x.list.put(n, id);
-            } while (t.matches(','));
-            t.read('}');
+        int s = sort[index];
+        long result = children[s];
+        names = StringUtils.arrayRemove(names, s);
+        children = StringUtils.arrayRemove(children, s);
+        sort = StringUtils.arrayRemove(sort, index);
+        if (s != size - 1) {
+            for (int i = 0; i < sort.length; i++) {
+                if (sort[i] >= s) {
+                    sort[i]--;
+                }
+            }
         }
-        return x;
+        size--;
+        return result;
     }
 
     public String toString() {
         JsopBuilder json = new JsopBuilder();
         json.object();
-        for (Entry<String, Long> e : list.entrySet()) {
-            json.key(e.getKey()).value(e.getValue());
+        for (int i = 0; i < size; i++) {
+            json.key(names[i]).value(children[i]);
         }
         json.endObject();
         return json.toString();
     }
 
     public NodeList createClone(NodeMap map) {
-        if (list.size() > map.getMaxMemoryChildren()) {
-            return new NodeListLarge(map, list);
-        }
-        return new NodeListSmall(new LinkedHashMap<String, Long>(list));
+//        if (size > map.getMaxMemoryChildren()) {
+//            return new NodeListLarge(map, list);
+//        }
+        return new NodeListSmall(names, children, sort, size);
     }
 
     public void visit(ChildVisitor v) {
-        for (Long c : list.values()) {
+        for (long c : children) {
             v.accept(c);
         }
     }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMap.java Mon Sep  5 15:15:30 2011
@@ -16,11 +16,7 @@
  */
 package org.apache.jackrabbit.mk.mem;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.HashMap;
-import org.apache.jackrabbit.mk.util.IOUtils;
 
 public class NodeMap {
 
@@ -66,15 +62,6 @@ public class NodeMap {
         return id;
     }
 
-    public void writeId(OutputStream out, long x) throws IOException {
-        IOUtils.writeVarInt(out, (int) (x >>> 32));
-        IOUtils.writeInt(out, (int) x);
-    }
-
-    public long readId(InputStream in) throws IOException {
-        return (IOUtils.readVarInt(in) << 32) | IOUtils.readInt(in);
-    }
-
     public long commit(NodeImpl root) {
         return rootId = addNode(root);
     }
@@ -91,4 +78,8 @@ public class NodeMap {
         return Long.parseLong(id.substring(1));
     }
 
+    public boolean isId(String value) {
+        return value.startsWith("n");
+    }
+
 }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java?rev=1165326&r1=1165325&r2=1165326&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java Mon Sep  5 15:15:30 2011
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.mk.mem;
 
 import org.apache.jackrabbit.mk.json.JsopBuilder;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.util.SmallLRUCache;
 
 /**
  * A revision, including pointer to the root node of that revision.
@@ -30,22 +31,31 @@ public class Revision implements Compara
     private String diff;
     private String msg;
 
-    Revision(NodeImpl node) {
-        this.node = node;
-        if (node.hasProperty("rev")) {
-            String r = node.getProperty("rev");
-            id = parseId(r.substring(1, r.length() - 1));
-            time = Long.parseLong(node.getProperty("time"));
-        } else {
-            id = time = 0;
-        }
-    }
-
     public Revision(long id, long time, String diff, String msg) {
         this.id = id;
         this.time = time;
         this.diff = diff;
-        this.msg = msg;
+        this.msg = msg == null ? "" : msg;
+    }
+
+    private Revision(NodeImpl node, long id) {
+        this.node = node;
+        this.id = id;
+        time = Long.parseLong(node.getProperty("time"));
+    }
+
+    static Revision get(SmallLRUCache<Long, Revision>cache, NodeImpl node) {
+        String rev = node.getProperty("rev");
+        if (rev == null) {
+            return null;
+        }
+        long id = parseId(JsopTokenizer.decodeQuoted(rev));
+        Revision r = cache.get(id);
+        if (r == null) {
+            r = new Revision(node, id);
+            cache.put(id, r);
+        }
+        return r;
     }
 
     public long getId() {
@@ -101,7 +111,7 @@ public class Revision implements Compara
 
     NodeImpl store(NodeImpl head, NodeImpl commit) {
         head = head.cloneAndSetProperty("rev", JsopBuilder.encode(formatId(id)), id);
-        head = head.cloneAndSetProperty("time", "" + time, id);
+        head = head.cloneAndSetProperty("time", Long.toString(time), id);
         commit.setProperty("diff", JsopBuilder.encode(diff));
         if (msg != null) {
             commit.setProperty("msg", JsopBuilder.encode(msg));