You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2011/12/29 17:39:16 UTC

svn commit: r1225586 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/ main/java/org/apache/jackrabbit/configuration/ main/java/org/apache/jackrabbit/state/ test/java/org/apache/jackrabbit/

Author: mduerig
Date: Thu Dec 29 16:39:15 2011
New Revision: 1225586

URL: http://svn.apache.org/viewvc?rev=1225586&view=rev
Log:
Microkernel based prototype of JCR implementation (WIP)
- add configurable node state cache

Added:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/CacheFactory.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCache.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCacheImpl.java
Modified:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfiguration.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfigurationImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/RepositoryTest.java

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/CacheFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/CacheFactory.java?rev=1225586&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/CacheFactory.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/CacheFactory.java Thu Dec 29 16:39:15 2011
@@ -0,0 +1,8 @@
+package org.apache.jackrabbit;
+
+import org.apache.jackrabbit.configuration.RepositoryConfiguration;
+import org.apache.jackrabbit.state.NodeStateCache;
+
+public interface CacheFactory {
+    NodeStateCache create(RepositoryConfiguration configuration);
+}

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/GlobalContext.java Thu Dec 29 16:39:15 2011
@@ -19,13 +19,14 @@
 
 package org.apache.jackrabbit;
 
+import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.configuration.RepositoryConfiguration;
+import org.apache.jackrabbit.mk.MicroKernelFactory;
+import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.security.Authenticator;
 import org.apache.jackrabbit.security.AuthenticatorImpl;
+import org.apache.jackrabbit.state.NodeStateCacheImpl;
 import org.apache.jackrabbit.utils.Unchecked;
-import org.apache.jackrabbit.commons.SimpleValueFactory;
-import org.apache.jackrabbit.mk.MicroKernelFactory;
-import org.apache.jackrabbit.mk.api.MicroKernel;
 
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
@@ -48,6 +49,7 @@ public class GlobalContext {
         put(Repository.class, RepositoryImpl.create(this));
         put(Authenticator.class, AuthenticatorImpl.INSTANCE);
         put(SessionFactory.class, SessionImpl.FACTORY);
+        put(CacheFactory.class, NodeStateCacheImpl.FACTORY);
     }
 
     public <T> T getInstance(Class<T> forClass) {

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionContext.java Thu Dec 29 16:39:15 2011
@@ -21,6 +21,7 @@ package org.apache.jackrabbit;
 
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.security.CredentialsInfo;
+import org.apache.jackrabbit.state.NodeStateCache;
 import org.apache.jackrabbit.state.TransientSpace;
 
 import javax.jcr.Session;
@@ -35,4 +36,5 @@ public interface SessionContext<T extend
     String getRevision();
     ValueFactory getValueFactory();
     TransientSpace getTransientSpace();
+    NodeStateCache getNodeStateCache();
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/SessionImpl.java Thu Dec 29 16:39:15 2011
@@ -19,10 +19,12 @@
 
 package org.apache.jackrabbit;
 
+import org.apache.jackrabbit.configuration.RepositoryConfiguration;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.security.Authenticator;
 import org.apache.jackrabbit.security.CredentialsInfo;
 import org.apache.jackrabbit.state.NodeState;
+import org.apache.jackrabbit.state.NodeStateCache;
 import org.apache.jackrabbit.state.TransientSpace;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -53,6 +55,7 @@ public class SessionImpl implements Sess
     private final String workspaceName;
     private final MicroKernel microKernel;
     private final TransientSpace transientSpace;
+    private final NodeStateCache nodeStateCache;
 
     private String revision;
     private boolean live = true;
@@ -99,6 +102,11 @@ public class SessionImpl implements Sess
         public TransientSpace getTransientSpace() {
             return transientSpace;
         }
+
+        @Override
+        public NodeStateCache getNodeStateCache() {
+            return nodeStateCache;
+        }
     };
 
     public static final SessionFactory FACTORY = new SessionFactory() {
@@ -138,6 +146,8 @@ public class SessionImpl implements Sess
         this.revision = revision;
         microKernel = globalContext.getInstance(MicroKernel.class);
         transientSpace = new TransientSpace(workspaceName, microKernel, revision);
+        nodeStateCache = globalContext.getInstance(CacheFactory.class)
+            .create(globalContext.getInstance(RepositoryConfiguration.class));
     }
 
     //------------------------------------------< Session >--- 
@@ -266,12 +276,14 @@ public class SessionImpl implements Sess
     public void save() throws RepositoryException {
         checkLive();
         revision = transientSpace.save();
+        nodeStateCache.clear();
     }
 
     @Override
     public void refresh(boolean keepChanges) throws RepositoryException {
         checkLive();
         revision = transientSpace.refresh(keepChanges);
+        nodeStateCache.clear();
     }
 
     @Override
@@ -426,6 +438,7 @@ public class SessionImpl implements Sess
 
     //------------------------------------------< private >---
 
+    // todo: we need to checkLive from ops on nodes and properties too.
     private void checkLive() throws RepositoryException {
         if (!isLive()) {
             throw new RepositoryException("Session has already been closed");

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfiguration.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfiguration.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfiguration.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfiguration.java Thu Dec 29 16:39:15 2011
@@ -24,7 +24,9 @@ import java.util.Map;
 
 public interface RepositoryConfiguration {
     String MICROKERNEL_URL = RepositoryConfiguration.class.getName() + ".microkernel-url";
+    String NODE_STATE_CACHE_SIZE = RepositoryConfiguration.class.getName() + ".node-state-cache-size";
 
     Map<String, String> getParameterMap();
     String getMicrokernelUrl() throws RepositoryException;
+    int getNodeStateCacheSize();
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfigurationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfigurationImpl.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfigurationImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/configuration/RepositoryConfigurationImpl.java Thu Dec 29 16:39:15 2011
@@ -27,28 +27,44 @@ import static java.text.MessageFormat.fo
 
 public class RepositoryConfigurationImpl implements RepositoryConfiguration {
     private final Map<String, String> parameters;
+    private final String microkernelUrl;
+    private final int nodeStateCacheSize;
 
-    private RepositoryConfigurationImpl(Map<String, String> parameters) {
+    private RepositoryConfigurationImpl(Map<String, String> parameters) throws RepositoryException {
         this.parameters = Collections.unmodifiableMap(parameters);
+
+        microkernelUrl = getParameterMap().get(MICROKERNEL_URL);
+        if (microkernelUrl == null) {
+            throw new RepositoryException(format("Missing configuration value for {0}", MICROKERNEL_URL));
+        }
+
+        String size = getParameterMap().get(NODE_STATE_CACHE_SIZE);
+        try {
+            nodeStateCacheSize = size == null ? 0 : Integer.parseInt(size);
+        }
+        catch (NumberFormatException e) {
+            throw new RepositoryException(format("Invalid configuration value {0} for {1}",
+                    size, NODE_STATE_CACHE_SIZE), e);
+        }
+
     }
 
-    public static RepositoryConfiguration create(Map<String, String> parameters) {
+    public static RepositoryConfiguration create(Map<String, String> parameters) throws RepositoryException {
         return new RepositoryConfigurationImpl(parameters);
     }
 
     @Override
-    public Map<String, String> getParameterMap() {
+    public final Map<String, String> getParameterMap() {
         return parameters;
     }
 
     @Override
     public String getMicrokernelUrl() throws RepositoryException {
-        String microkernelUrl = getParameterMap().get(RepositoryConfiguration.MICROKERNEL_URL);
-        if (microkernelUrl == null) {
-            throw new RepositoryException(
-                    format("Missing configuration value for {0}", RepositoryConfiguration.MICROKERNEL_URL));
-        }
-
         return microkernelUrl;
     }
+
+    @Override
+    public int getNodeStateCacheSize() {
+        return nodeStateCacheSize;
+    }
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeState.java Thu Dec 29 16:39:15 2011
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.json.JsonVa
 import org.apache.jackrabbit.json.JsonValue.JsonObject;
 import org.apache.jackrabbit.json.JsonValue.Type;
 import org.apache.jackrabbit.json.UnescapingJsonTokenizer;
+import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.spi.commons.iterator.Iterators;
 import org.apache.jackrabbit.spi.commons.iterator.Predicate;
 import org.apache.jackrabbit.spi.commons.iterator.Transformer;
@@ -72,17 +73,19 @@ public class NodeState {
 
     public NodeState addNode(String name) throws ItemExistsException {
         NodeDelta child = nodeDelta.addNode(name);
-        return new NodeState(sessionContext, child);
+        return getNodeState(sessionContext, child);
     }
 
     public void remove() throws ItemNotFoundException {
         nodeDelta.remove();
+        nodeStateCache().remove(getPath());
     }
 
     public void move(String name, Path destination) throws ItemExistsException, PathNotFoundException,
             ItemNotFoundException {
 
         nodeDelta.moveNode(name, destination);
+        nodeStateCache().remove(getPath().concat(name));
     }
 
     public void setProperty(String name, JsonValue value) {
@@ -107,7 +110,7 @@ public class NodeState {
             new Transformer<NodeDelta, NodeState>() {
                 @Override
                 public NodeState transform(NodeDelta delta) {
-                    return new NodeState(sessionContext, nodeDelta);
+                    return getNodeState(sessionContext, nodeDelta);
                 }
         });
 
@@ -157,15 +160,44 @@ public class NodeState {
 
     public static NodeState getNodeState(Context sessionContext, Path path) {
         NodeDelta delta = sessionContext.getTransientSpace().getNode(path);
-        return delta == null ? null : new NodeState(sessionContext, delta);
+        return delta == null ? null : getNodeState(sessionContext, delta);
     }
 
     public static boolean hasNodeState(Context sessionContext, Path path) {
         return getNodeState(sessionContext, path) != null;
     }
 
+    @Override
+    public String toString() {
+        return getPath().toString();
+    }
+
     //------------------------------------------< private >---
 
+    private NodeStateCache nodeStateCache() {
+        return sessionContext.getNodeStateCache();
+    }
+    
+    private MicroKernel getMicrokernel() {
+        return sessionContext.getMicrokernel();
+    }
+    
+    private String getBaseRevision() {
+        return sessionContext.getRevision();
+    }
+    
+    private static NodeState getNodeState(Context sessionContext, NodeDelta nodeDelta) {
+        NodeStateCache cache = sessionContext.getNodeStateCache();
+        Path path = nodeDelta.getPath();
+
+        NodeState nodeState = cache.get(path);
+        if (nodeState == null) {
+            nodeState = new NodeState(sessionContext, nodeDelta);
+            cache.put(path, nodeState);
+        }
+        return nodeState;
+    }
+
     private static final Predicate<Entry<String, JsonValue>> IS_NODE = new Predicate<Entry<String, JsonValue>>() {
         @Override
         public boolean evaluate(Entry<String, JsonValue> entry) {
@@ -185,7 +217,7 @@ public class NodeState {
         return Iterators.transformIterator(nodeEntries, new Transformer<Entry<String, JsonValue>, NodeState>() {
             @Override
             public NodeState transform(Entry<String, JsonValue> entry) {
-                return new NodeState(sessionContext, nodeDelta.getNode(entry.getKey()));
+                return getNodeState(sessionContext, nodeDelta.getNode(entry.getKey()));
             }
         });
     }
@@ -225,14 +257,14 @@ public class NodeState {
 
     private synchronized JsonObject getJsonObject() {
         Path path = nodeDelta.getPersistentPath();
-        String baseRevision = sessionContext.getRevision();
+        String baseRevision = getBaseRevision();
         if (jsonObject == null || !revision.equals(baseRevision)) {
             revision =  baseRevision;
             if (path == null) {
                 jsonObject = JsonObject.EMPTY;
             }
             else {
-                String json = sessionContext.getMicrokernel().getNodes(nodeDelta.getPersistentPath().toMkPath(), revision);
+                String json = getMicrokernel().getNodes(nodeDelta.getPersistentPath().toMkPath(), revision);
                 jsonObject = FullJsonParser.parseObject(new UnescapingJsonTokenizer(json));
             }
         }

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCache.java?rev=1225586&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCache.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCache.java Thu Dec 29 16:39:15 2011
@@ -0,0 +1,10 @@
+package org.apache.jackrabbit.state;
+
+import org.apache.jackrabbit.Path;
+
+public interface NodeStateCache {
+    NodeState get(Path path);
+    void put(Path path, NodeState nodeState);
+    void remove(Path path);
+    void clear();
+}

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCacheImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCacheImpl.java?rev=1225586&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCacheImpl.java (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/state/NodeStateCacheImpl.java Thu Dec 29 16:39:15 2011
@@ -0,0 +1,61 @@
+package org.apache.jackrabbit.state;
+
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.jackrabbit.CacheFactory;
+import org.apache.jackrabbit.Path;
+import org.apache.jackrabbit.configuration.RepositoryConfiguration;
+import org.apache.jackrabbit.utils.Unchecked;
+
+import java.util.Map;
+
+public class NodeStateCacheImpl implements NodeStateCache {
+    public static final CacheFactory FACTORY = new CacheFactory() {
+        @Override
+        public NodeStateCache create(RepositoryConfiguration configuration) {
+            int size = configuration.getNodeStateCacheSize();
+            return size > 0 ? new NodeStateCacheImpl(size) : NO_CACHE;
+        }
+    };
+
+    private static final NodeStateCache NO_CACHE = new NodeStateCache() {
+        @Override
+        public NodeState get(Path path) {
+            return null;
+        }
+
+        @Override
+        public void put(Path path, NodeState nodeState) { }
+
+        @Override
+        public void remove(Path path) { }
+
+        @Override
+        public void clear() { }
+    };
+
+    private final Map<Path, NodeState> cache;
+
+    public NodeStateCacheImpl(int size) {
+        cache = Unchecked.cast(new LRUMap(size));
+    }
+
+    @Override
+    public NodeState get(Path path) {
+        return cache.get(path);
+    }
+
+    @Override
+    public void put(Path path, NodeState nodeState) {
+        cache.put(path, nodeState);
+    }
+
+    @Override
+    public void remove(Path path) {
+        cache.remove(path);
+    }
+
+    @Override
+    public void clear() {
+        cache.clear();
+    }
+}

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/RepositoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/RepositoryTest.java?rev=1225586&r1=1225585&r2=1225586&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/RepositoryTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/RepositoryTest.java Thu Dec 29 16:39:15 2011
@@ -59,7 +59,7 @@ import java.io.InputStream;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -80,6 +80,7 @@ import static org.junit.Assert.assertTru
 import static org.junit.Assert.fail;
 
 public class RepositoryTest {
+    private static final String NODE_STATE_CACHE_SIZE = "65536";
     private static final String URL = "fs:target/repository-test/repository";
     // private static final String URL = "mem:";
 
@@ -1692,8 +1693,10 @@ public class RepositoryTest {
             Iterator<RepositoryFactory> factories = ServiceRegistry.lookupProviders(RepositoryFactory.class);
             while (repository == null && factories.hasNext()) {
                 RepositoryFactory factory = factories.next();
-                repository = factory.getRepository(Collections.singletonMap(
-                        RepositoryConfiguration.MICROKERNEL_URL, URL));
+                repository = factory.getRepository(new HashMap<String, String>() {{
+                    put(RepositoryConfiguration.MICROKERNEL_URL, URL);
+                    put(RepositoryConfiguration.NODE_STATE_CACHE_SIZE, NODE_STATE_CACHE_SIZE);
+                }}); 
             }
         }