You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by dp...@apache.org on 2008/04/24 14:48:17 UTC

svn commit: r651246 - /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java

Author: dpfister
Date: Thu Apr 24 05:48:12 2008
New Revision: 651246

URL: http://svn.apache.org/viewvc?rev=651246&view=rev
Log:
JCR-1104 - JSR 283 support
- shareble nodes (work in progress)
- add consistency check to CachingHierarchyManager

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=651246&r1=651245&r2=651246&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Thu Apr 24 05:48:12 2008
@@ -88,6 +88,11 @@
     private LRUEntry tail;
 
     /**
+     * Flag indicating whether consistency checking is enabled.
+     */
+    private boolean consistencyCheckEnabled;
+
+    /**
      * Create a new instance of this class.
      *
      * @param rootNodeId   root node id
@@ -101,6 +106,16 @@
         upperLimit = DEFAULT_UPPER_LIMIT;
     }
 
+    /**
+     * Enable or disable consistency checks in this instance.
+     *
+     * @param enable <code>true</code> to enable consistency checks;
+     *               <code>false</code> to disable
+     */
+    public void enableConsistencyChecks(boolean enable) {
+        this.consistencyCheckEnabled = enable;
+    }
+
     //-------------------------------------------------< base class overrides >
 
     /**
@@ -305,7 +320,7 @@
                     if (cne == null) {
                         // Item does not exist, remove
                         evict(child, true);
-                        return;
+                        continue;
                     }
 
                     LRUEntry childEntry = (LRUEntry) child.get();
@@ -315,6 +330,7 @@
                     }
                 }
             }
+            checkConsistency();
         }
     }
 
@@ -350,6 +366,7 @@
                 try {
                     Path path = PathFactoryImpl.getInstance().create(getPath(state.getNodeId()), name, index, true);
                     nodeAdded(state, path, id);
+                    checkConsistency();
                 } catch (PathNotFoundException e) {
                     log.warn("Unable to get path of node " + state.getNodeId()
                             + ", event ignored.");
@@ -424,6 +441,7 @@
                     parents[i].setChildren(newChildrenOrder);
                 }
             }
+            checkConsistency();
         }
     }
 
@@ -437,6 +455,7 @@
                 try {
                     Path path = PathFactoryImpl.getInstance().create(getPath(state.getNodeId()), name, index, true);
                     nodeRemoved(state, path, id);
+                    checkConsistency();
                 } catch (PathNotFoundException e) {
                     log.warn("Unable to get path of node " + state.getNodeId()
                             + ", event ignored.");
@@ -539,6 +558,8 @@
                 entry.addElement(element);
             }
             element.set(entry);
+
+            checkConsistency();
         }
     }
 
@@ -605,6 +626,7 @@
                     evict(elements[i], shift);
                 }
             }
+            checkConsistency();
         }
     }
 
@@ -641,36 +663,35 @@
     private void nodeAdded(NodeState state, Path path, NodeId id)
             throws PathNotFoundException, ItemStateException {
 
-        synchronized (cacheMonitor) {
-            PathMap.Element element = null;
+        // assert: synchronized (cacheMonitor)
+        PathMap.Element element = null;
 
-            LRUEntry entry = (LRUEntry) idCache.get(id);
-            if (entry != null) {
-                // child node already cached: this can have the following
-                // reasons:
-                //    1) node was moved, cached path is outdated
-                //    2) node was cloned, cached path is still valid
-                NodeState child = null;
-                if (hasItemState(id)) {
-                    child = (NodeState) getItemState(id);
-                }
-                if (child == null || !child.isShareable()) {
-                    PathMap.Element[] elements = entry.getElements();
-                    element = elements[0];
-                    for (int i = 0; i < elements.length; i++) {
-                        elements[i].remove();
-                    }
-                }
-            }
-            PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
-            if (parent != null) {
-                parent.insert(path.getNameElement());
+        LRUEntry entry = (LRUEntry) idCache.get(id);
+        if (entry != null) {
+            // child node already cached: this can have the following
+            // reasons:
+            //    1) node was moved, cached path is outdated
+            //    2) node was cloned, cached path is still valid
+            NodeState child = null;
+            if (hasItemState(id)) {
+                child = (NodeState) getItemState(id);
             }
-            if (element != null) {
-                // store remembered element at new position
-                pathCache.put(path, element);
+            if (child == null || !child.isShareable()) {
+                PathMap.Element[] elements = entry.getElements();
+                element = elements[0];
+                for (int i = 0; i < elements.length; i++) {
+                    elements[i].remove();
+                }
             }
         }
+        PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
+        if (parent != null) {
+            parent.insert(path.getNameElement());
+        }
+        if (element != null) {
+            // store remembered element at new position
+            pathCache.put(path, element);
+        }
     }
 
     /**
@@ -685,37 +706,36 @@
     private void nodeRemoved(NodeState state, Path path, NodeId id)
             throws PathNotFoundException, ItemStateException {
 
-        synchronized (cacheMonitor) {
-            PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
-            if (parent == null) {
+        // assert: synchronized (cacheMonitor)
+        PathMap.Element parent = pathCache.map(path.getAncestor(1), true);
+        if (parent == null) {
+            return;
+        }
+        PathMap.Element element = parent.getDescendant(PathFactoryImpl.getInstance().create(
+                new Path.Element[] { path.getNameElement() }), true);
+        if (element != null) {
+            // with SNS, this might evict a child that is NOT the one
+            // having <code>id</code>, check first whether item has
+            // the id passed as argument
+            LRUEntry entry = (LRUEntry) element.get();
+            if (entry != null && !entry.getId().equals(id)) {
                 return;
             }
-            PathMap.Element element = parent.getDescendant(PathFactoryImpl.getInstance().create(
-                    new Path.Element[] { path.getNameElement() }), true);
-            if (element != null) {
-                // with SNS, this might evict a child that is NOT the one
-                // having <code>id</code>, check first whether item has
-                // the id passed as argument
-                LRUEntry entry = (LRUEntry) element.get();
-                if (entry != null && !entry.getId().equals(id)) {
-                    return;
-                }
-                // if item is shareable, remove this path only, otherwise
-                // every path this item has been mapped to
-                NodeState child = null;
-                if (hasItemState(id)) {
-                    child = (NodeState) getItemState(id);
-                }
-                if (child == null || !child.isShareable()) {
-                    evictAll(id, true);
-                } else {
-                    evict(element, true);
-                }
+            // if item is shareable, remove this path only, otherwise
+            // every path this item has been mapped to
+            NodeState child = null;
+            if (hasItemState(id)) {
+                child = (NodeState) getItemState(id);
+            }
+            if (child == null || !child.isShareable()) {
+                evictAll(id, true);
             } else {
-                // element itself is not cached, but removal might cause SNS
-                // index shifting
-                parent.remove(path.getNameElement());
+                evict(element, true);
             }
+        } else {
+            // element itself is not cached, but removal might cause SNS
+            // index shifting
+            parent.remove(path.getNameElement());
         }
     }
 
@@ -744,6 +764,63 @@
                     ps.println(line.toString());
                 }
             }, true);
+        }
+    }
+
+    /**
+     * Check consistency.
+     */
+    private void checkConsistency() throws IllegalStateException {
+        // assert: synchronized (cacheMonitor)
+        if (!consistencyCheckEnabled) {
+            return;
+        }
+
+        int elementsInCache = 0;
+
+        Iterator iter = idCache.values().iterator();
+        while (iter.hasNext()) {
+            LRUEntry entry = (LRUEntry) iter.next();
+            elementsInCache += entry.getElements().length;
+        }
+
+        class PathMapElementCounter implements PathMap.ElementVisitor {
+            int count;
+            public void elementVisited(PathMap.Element element) {
+                LRUEntry mappedEntry = (LRUEntry) element.get();
+                LRUEntry cachedEntry = (LRUEntry) idCache.get(mappedEntry.getId());
+                if (cachedEntry == null) {
+                    String msg = "Path element (" + element +
+                        " ) cached in path map, associated id (" +
+                        mappedEntry.getId() + ") isn't.";
+                    throw new IllegalStateException(msg);
+                }
+                if (cachedEntry != mappedEntry) {
+                    String msg = "LRUEntry associated with element (" + element +
+                        " ) in path map is not equal to cached LRUEntry (" +
+                        cachedEntry.getId() + ").";
+                    throw new IllegalStateException(msg);
+                }
+                PathMap.Element[] elements = cachedEntry.getElements();
+                for (int i = 0; i < elements.length; i++) {
+                    if (elements[i] == element) {
+                        count++;
+                        return;
+                    }
+                }
+                String msg = "Element (" + element +
+                    ") cached in path map, but not in associated LRUEntry (" +
+                    cachedEntry.getId() + ").";
+                throw new IllegalStateException(msg);
+            }
+        }
+
+        PathMapElementCounter counter = new PathMapElementCounter();
+        pathCache.traverse(counter, false);
+        if (counter.count != elementsInCache) {
+            String msg = "PathMap element and cached element count don't match (" +
+                counter.count + " != " + elementsInCache + ")";
+            throw new IllegalStateException(msg);
         }
     }