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/22 07:54:34 UTC

svn commit: r1173953 - in /jackrabbit/sandbox/microkernel/src: main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java test/java/org/apache/jackrabbit/mk/MultiMkTestBase.java

Author: thomasm
Date: Thu Sep 22 05:54:34 2011
New Revision: 1173953

URL: http://svn.apache.org/viewvc?rev=1173953&view=rev
Log:
Store nodes in a database.

Added:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java
Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MultiMkTestBase.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=1173953&r1=1173952&r2=1173953&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 Thu Sep 22 05:54:34 2011
@@ -74,6 +74,7 @@ public class MemoryKernelImpl implements
     private NodeMap nodeMap;
     private String lastJournalRevRange, lastJournal;
     private Server server;
+    private boolean disposed;
 
     private MemoryKernelImpl(String name) {
         if (DEBUG) {
@@ -93,6 +94,7 @@ public class MemoryKernelImpl implements
             } catch (IOException e) {
                 throw ExceptionFactory.convert(e);
             }
+            nodeMap = new NodeMapInDb(dir);
         } else {
             ds = new MemoryBlobStore();
         }
@@ -573,12 +575,15 @@ public class MemoryKernelImpl implements
         if (DEBUG) {
             log("dispose");
         }
-        gate.commit("end");
-        nodeMap.close();
-        INSTANCES.remove(name);
-        if (server != null) {
-            server.stop();
-            server = null;
+        if (!disposed) {
+            disposed = true;
+            gate.commit("end");
+            nodeMap.close();
+            INSTANCES.remove(name);
+            if (server != null) {
+                server.stop();
+                server = null;
+            }
         }
     }
 

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java?rev=1173953&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeMapInDb.java Thu Sep 22 05:54:34 2011
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.mk.mem;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+import org.apache.jackrabbit.mk.fs.FilePath;
+import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.mem.NodeImpl.ChildVisitor;
+import org.apache.jackrabbit.mk.util.Cache;
+import org.apache.jackrabbit.mk.util.ExceptionFactory;
+import org.apache.jackrabbit.mk.util.SimpleLRUCache;
+
+/**
+ * A node map that stores data in a database.
+ */
+public class NodeMapInDb extends NodeMap implements Cache.Backend<Long, NodeImpl> {
+
+    final HashMap<Long, NodeImpl> temp = new HashMap<Long, NodeImpl>();
+    private Connection conn;
+    private final String url;
+    private final TreeMap<String, String> properties = new TreeMap<String, String>();
+    private final Cache<Long, NodeImpl> cache = Cache.newInstance(this, 10 * 1024 * 1024);
+    private final Map<NodeImpl, NodeImpl> reuse = SimpleLRUCache.newInstance(10000);
+    private final HashMap<Long, Long> pos = new HashMap<Long, Long>();
+    private final PreparedStatement select, insert, merge;
+    private long nextId;
+    private NodeImpl root = new NodeImpl(this, 0);
+
+    NodeMapInDb(String dir) {
+        try {
+            url = "jdbc:h2:" + FilePath.get(dir).resolve("nodes").toRealPath().toString() + System.getProperty("mk.db", "");
+            Class.forName("org.h2.Driver");
+            conn = DriverManager.getConnection(url);
+            Statement stat = conn.createStatement();
+            stat.execute("create table if not exists nodes(id bigint primary key, data varchar)");
+            stat.execute("create table if not exists roots(key bigint primary key, value bigint) as select 0, 0");
+            ResultSet rs = stat.executeQuery("select max(id) from nodes");
+            rs.next();
+            nextId = rs.getLong(1) + 1;
+            rs = stat.executeQuery("select max(value) from roots");
+            rs.next();
+            root.setId(rs.getLong(1));
+            select = conn.prepareStatement("select * from nodes where id = ?");
+            insert = conn.prepareStatement("insert into nodes sorted select ?, ?");
+            merge = conn.prepareStatement("update roots set value = ?");
+        } catch (Exception e) {
+            throw ExceptionFactory.convert(e);
+        }
+    }
+
+    public synchronized long addNode(NodeImpl node) {
+        long x = node.getId();
+        if (x == 0) {
+            x = -temp.size() - 1;
+            node.setId(x);
+            temp.put(x, node);
+        }
+        return x;
+    }
+
+    public NodeImpl getNode(long x) {
+        return x < 0 ? temp.get(x) : cache.get(x);
+    }
+
+    public NodeImpl load(Long key) {
+        try {
+            select.setLong(1, key);
+            ResultSet rs = select.executeQuery();
+            if (!rs.next()) {
+                throw ExceptionFactory.get("Node not found: " + key);
+            }
+            return NodeImpl.fromString(this, rs.getString(2));
+        } catch (Exception e) {
+            throw ExceptionFactory.convert(e);
+        }
+    }
+
+    public synchronized long commit(NodeImpl newRoot) {
+        addNode(newRoot);
+        try {
+            final ArrayList<Long> list = new ArrayList<Long>();
+            newRoot.visit(new ChildVisitor() {
+                public void accept(long childId) {
+                    if (childId < 0) {
+                        temp.get(childId).visit(this);
+                        list.add(childId);
+                    }
+                }
+            });
+            list.add(newRoot.getId());
+            for (Long id : list) {
+                NodeImpl n = temp.get(id);
+                NodeImpl r = reuse.get(n);
+                long newId;
+                if (r != null) {
+                    newId = r.getId();
+                    pos.put(id, newId);
+                } else {
+                    newId = nextId++;
+                    n.setId(newId);
+                    pos.put(id, newId);
+                    insert.setLong(1, newId);
+                    insert.setString(2, n.asString());
+                    insert.execute();
+                    cache.put(n.getId(), n);
+                    reuse.put(n, n);
+                }
+            }
+            merge.setLong(1, newRoot.getId());
+            merge.execute();
+            temp.clear();
+            pos.clear();
+        } catch (Exception e) {
+            throw ExceptionFactory.convert(e);
+        }
+        root = newRoot;
+        return root.getId();
+    }
+
+    public long getId(long id) {
+        return (id > 0 || !pos.containsKey(id)) ? id : pos.get(id);
+    }
+
+    public long getRootId() {
+        return root.getId();
+    }
+
+    public NodeImpl getInfo(String path) {
+        NodeImpl n = new NodeImpl(this, 0);
+        n.setProperty("url", JsopBuilder.encode(url));
+        for (Entry<String, String> e : properties.entrySet()) {
+            n.setProperty("property." + e.getKey(), e.getValue());
+        }
+        n.setProperty("cache.size", "" + cache.size());
+        n.setProperty("cache.memoryUsed", "" + cache.getMemoryUsed());
+        n.setProperty("cache.memoryMax", "" + cache.getMemoryMax());
+        n.setProperty("nextId", "" + nextId);
+        n.setProperty("root", "" + root.getId());
+        return n;
+    }
+
+    public synchronized void close() {
+        try {
+            conn.close();
+        } catch (SQLException e) {
+            throw ExceptionFactory.convert(e);
+        }
+    }
+
+}

Modified: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MultiMkTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MultiMkTestBase.java?rev=1173953&r1=1173952&r2=1173953&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MultiMkTestBase.java (original)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MultiMkTestBase.java Thu Sep 22 05:54:34 2011
@@ -51,7 +51,7 @@ public class MultiMkTestBase {
     }
 
     protected void reconnect() {
-        if (!url.startsWith("mem:")) {
+        if (!url.equals("mem:")) {
             mk.dispose();
             mk = MicroKernelFactory.getInstance(url);
         }