You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2011/12/20 19:49:46 UTC

svn commit: r1221428 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence: ./ bundle/ mem/ pool/

Author: reschke
Date: Tue Dec 20 18:49:46 2011
New Revision: 1221428

URL: http://svn.apache.org/viewvc?rev=1221428&view=rev
Log:
JCR-3185: refactor consistency checks in BundleDBPersistenceManager into a standalone class that could be re-used for other PMs

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/IterablePersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemBundlePersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/IterablePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/IterablePersistenceManager.java?rev=1221428&r1=1221427&r2=1221428&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/IterablePersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/IterablePersistenceManager.java Tue Dec 20 18:49:46 2011
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core.persistence;
 
+import java.util.List;
+
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.state.ItemStateException;
 
@@ -37,11 +39,11 @@ public interface IterablePersistenceMana
      *
      * @param after the lower limit, or null for no limit.
      * @param maxCount the maximum number of node ids to return, or 0 for no limit.
-     * @return an iterator of all bundles.
+     * @return a list of all bundles.
      * @throws ItemStateException if an error while loading occurs.
      * @throws RepositoryException if a repository exception occurs
      */
-    Iterable<NodeId> getAllNodeIds(NodeId after, int maxCount)
+    List<NodeId> getAllNodeIds(NodeId after, int maxCount)
             throws ItemStateException, RepositoryException;
 
 }

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=1221428&r1=1221427&r2=1221428&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Tue Dec 20 18:49:46 2011
@@ -26,6 +26,7 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
 import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
 
 import org.apache.jackrabbit.api.stats.RepositoryStatistics;
 import org.apache.jackrabbit.core.cache.Cache;
@@ -40,6 +41,8 @@ import org.apache.jackrabbit.core.persis
 import org.apache.jackrabbit.core.persistence.IterablePersistenceManager;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.PersistenceManager;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyChecker;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
 import org.apache.jackrabbit.core.persistence.util.BLOBStore;
 import org.apache.jackrabbit.core.persistence.util.FileBasedIndex;
 import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
@@ -87,7 +90,7 @@ import org.slf4j.LoggerFactory;
  * </ul>
  */
 public abstract class AbstractBundlePersistenceManager implements
-    PersistenceManager, CachingPersistenceManager, IterablePersistenceManager, CacheAccessListener {
+    PersistenceManager, CachingPersistenceManager, IterablePersistenceManager, CacheAccessListener, ConsistencyChecker {
 
     /** the default logger */
     private static Logger log = LoggerFactory.getLogger(AbstractBundlePersistenceManager.class);
@@ -777,11 +780,23 @@ public abstract class AbstractBundlePers
     }
 
     /**
-     * This implementation does nothing.
-     *
      * {@inheritDoc}
      */
     public void checkConsistency(String[] uuids, boolean recursive, boolean fix) {
+        try {
+            ConsistencyCheckerImpl cs = new ConsistencyCheckerImpl(this);
+            cs.check(uuids, recursive, fix);
+        } catch (RepositoryException ex) {
+            log.error("While running consistency check.", ex);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ConsistencyReport check(String[] uuids, boolean recursive, boolean fix) throws RepositoryException {
+        ConsistencyCheckerImpl cs = new ConsistencyCheckerImpl(this);
+        return cs.check(uuids, recursive, fix);
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java?rev=1221428&r1=1221427&r2=1221428&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java Tue Dec 20 18:49:46 2011
@@ -42,6 +42,7 @@ import java.io.OutputStream;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * This is a generic persistence manager that stores the {@link NodePropBundle}s
@@ -482,7 +483,7 @@ public class BundleFsPersistenceManager 
     /**
      * {@inheritDoc}
      */
-    public Iterable<NodeId> getAllNodeIds(NodeId bigger, int maxCount)
+    public List<NodeId> getAllNodeIds(NodeId bigger, int maxCount)
             throws ItemStateException {
         ArrayList<NodeId> list = new ArrayList<NodeId>();
         try {

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java?rev=1221428&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java Tue Dec 20 18:49:46 2011
@@ -0,0 +1,282 @@
+/*
+ * 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.core.persistence.bundle;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.id.NodeId;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyChecker;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyReportImpl;
+import org.apache.jackrabbit.core.persistence.check.ReportItem;
+import org.apache.jackrabbit.core.persistence.check.ReportItemImpl;
+import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConsistencyCheckerImpl implements ConsistencyChecker {
+
+    /** the default logger */
+    private static Logger log = LoggerFactory.getLogger(ConsistencyCheckerImpl.class);
+
+    private AbstractBundlePersistenceManager pm;
+    
+    public ConsistencyCheckerImpl(AbstractBundlePersistenceManager pm) {
+        this.pm = pm;
+    }
+
+    public ConsistencyReport check(String[] uuids, boolean recursive, boolean fix) throws RepositoryException {
+        Set<ReportItem> reports = new HashSet<ReportItem>();
+
+        long tstart = System.currentTimeMillis();
+        int total = internalCheckConsistency(uuids, recursive, fix, reports);
+        long elapsed = System.currentTimeMillis() - tstart;
+
+        return new ConsistencyReportImpl(total, elapsed, reports);
+    }
+    
+    private int internalCheckConsistency(String[] uuids, boolean recursive, boolean fix, Set<ReportItem> reports) throws RepositoryException {
+        int count = 0;
+        int total = 0;
+        Collection<NodePropBundle> modifications = new ArrayList<NodePropBundle>();        
+
+        if (uuids == null) {
+            try {
+                List<NodeId> allIds = pm.getAllNodeIds(null, 0);
+                total = allIds.size();
+                
+                for (NodeId id : allIds) {
+                    try {
+                        // parse and check bundle
+                        NodePropBundle bundle = pm.loadBundle(id);
+                        if (bundle == null) {
+                            log.error("No bundle found for id '" + id + "'");
+                        } else {
+                            checkBundleConsistency(id, bundle, fix, modifications, reports);
+
+                            count++;
+                            if (count % 1000 == 0) {
+                                log.info(pm + ": checked " + count + "/" + (total == -1 ? "?" : total) + " bundles...");
+                            }
+                        }
+                    } catch (ItemStateException e) {
+                        // problem already logged (loadBundle called with
+                        // logDetailedErrors=true)
+                    }
+
+                }
+            } catch (ItemStateException ex) {
+                throw new RepositoryException("getting nodeIds", ex);
+            } finally {
+                total = count;
+            }
+        } else {
+            // check only given uuids, handle recursive flag
+
+            // 1) convert uuid array to modifiable list
+            // 2) for each uuid do
+            //     a) load node bundle
+            //     b) check bundle, store any bundle-to-be-modified in collection
+            //     c) if recursive, add child uuids to list of uuids
+
+            List<NodeId> idList = new ArrayList<NodeId>(uuids.length);
+            // convert uuid string array to list of UUID objects
+            for (int i = 0; i < uuids.length; i++) {
+                try {
+                    idList.add(new NodeId(uuids[i]));
+                } catch (IllegalArgumentException e) {
+                    log.error("Invalid id for consistency check, skipping: '" + uuids[i] + "': " + e);
+                }
+            }
+            
+            // iterate over UUIDs (including ones that are newly added inside the loop!)
+            for (int i = 0; i < idList.size(); i++) {
+                NodeId id = idList.get(i);
+                try {
+                    // load the node from the database
+                    NodePropBundle bundle = pm.loadBundle(id);
+
+                    if (bundle == null) {
+                        log.error("No bundle found for id '" + id + "'");
+                    }
+                    else {
+                        checkBundleConsistency(id, bundle, fix, modifications, reports);
+
+                        if (recursive) {
+                            for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
+                                idList.add(entry.getId());
+                            }
+                        }
+
+                        count++;
+                        if (count % 1000 == 0) {
+                            log.info(pm + ": checked " + count + "/" + idList.size() + " bundles...");
+                        }
+                    }
+                } catch (ItemStateException e) {
+                    // problem already logged (loadBundle called with logDetailedErrors=true)
+                }
+            }
+
+            total = idList.size();
+        }
+
+        // repair collected broken bundles
+        if (fix && !modifications.isEmpty()) {
+            log.info(pm + ": Fixing " + modifications.size() + " inconsistent bundle(s)...");
+            for (NodePropBundle bundle : modifications) {
+                try {
+                    log.info(pm + ": Fixing bundle '" + bundle.getId() + "'");
+                    bundle.markOld(); // use UPDATE instead of INSERT
+                    pm.storeBundle(bundle);
+                    pm.evictBundle(bundle.getId());
+                } catch (ItemStateException e) {
+                    log.error(pm + ": Error storing fixed bundle: " + e);
+                }
+            }
+        }
+
+        log.info(pm + ": checked " + count + "/" + total + " bundles.");
+
+        return total;
+    }
+
+    /**
+     * Checks a single bundle for inconsistencies, ie. inexistent child nodes
+     * and inexistent parents.
+     *
+     * @param id node id for the bundle to check
+     * @param bundle the bundle to check
+     * @param fix if <code>true</code>, repair things that can be repaired
+     * @param modifications if <code>fix == true</code>, collect the repaired
+     * {@linkplain NodePropBundle bundles} here
+     */
+    private void checkBundleConsistency(NodeId id, NodePropBundle bundle,
+                                          boolean fix, Collection<NodePropBundle> modifications,
+                                          Set<ReportItem> reports) {
+        //log.info(name + ": checking bundle '" + id + "'");
+
+        // skip all system nodes except root node
+        if (id.toString().endsWith("babecafebabe")
+                && !id.toString().equals("cafebabe-cafe-babe-cafe-babecafebabe")) {
+            return;
+        }
+
+        // look at the node's children
+        Collection<NodePropBundle.ChildNodeEntry> missingChildren = new ArrayList<NodePropBundle.ChildNodeEntry>();
+        for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
+
+            // skip check for system nodes (root, system root, version storage, node types)
+            if (entry.getId().toString().endsWith("babecafebabe")) {
+                continue;
+            }
+
+            try {
+                // analyze child node bundles
+                NodePropBundle child = pm.loadBundle(entry.getId());
+                String message = null;
+                if (child == null) {
+                    message = "NodeState '" + id + "' references inexistent child" + " '"
+                            + entry.getName() + "' with id " + "'" + entry.getId() + "'";
+                    log.error(message);
+                    missingChildren.add(entry);
+                } else {
+                    NodeId cp = child.getParentId();
+                    if (cp == null) {
+                        message = "ChildNode has invalid parent id: <null>";
+                        log.error(message);
+                    } else if (!cp.equals(id)) {
+                        message = "ChildNode has invalid parent id: '" + cp + "' (instead of '" + id + "')";
+                        log.error(message);
+                    }
+                }
+                if (message != null) {
+                    addMessage(reports, id, message);
+                }
+            } catch (ItemStateException e) {
+                // problem already logged (loadBundle called with logDetailedErrors=true)
+                addMessage(reports, id, e.getMessage());
+            }
+        }
+        // remove child node entry (if fixing is enabled)
+        if (fix && !missingChildren.isEmpty()) {
+            for (NodePropBundle.ChildNodeEntry entry : missingChildren) {
+                bundle.getChildNodeEntries().remove(entry);
+            }
+            modifications.add(bundle);
+        }
+
+        // check parent reference
+        NodeId parentId = bundle.getParentId();
+        try {
+            // skip root nodes (that point to itself)
+            if (parentId != null && !id.toString().endsWith("babecafebabe")) {
+                NodePropBundle parentBundle = pm.loadBundle(parentId);
+                
+                if (parentBundle == null) {
+                    String message = "NodeState '" + id + "' references inexistent parent id '" + parentId + "'";
+                    log.error(message);
+                    addMessage(reports, id, message);
+                }
+                else {
+                    boolean found = false;
+
+                    for (NodePropBundle.ChildNodeEntry entry : parentBundle.getChildNodeEntries()) {
+                        if (entry.getId().equals(id)){
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if (!found) {
+                        String message = "NodeState '" + id + "' is not referenced by its parent node '" + parentId + "'";
+                        log.error(message);
+                        addMessage(reports, id, message);
+
+                        int l = (int) System.currentTimeMillis();
+                        int r = new Random().nextInt();
+                        int n = l + r;
+                        String nodeName = Integer.toHexString(n);
+                        parentBundle.addChildNodeEntry(NameFactoryImpl
+                                .getInstance().create("{}" + nodeName), id);
+                        log.info("NodeState '" + id + "' adds itself to its parent node '" + parentId + "' with a new name '" + nodeName + "'");
+                        modifications.add(parentBundle);
+                    }
+                }
+            }
+        } catch (ItemStateException e) {
+            String message = "Error reading node '" + parentId + "' (parent of '" + id + "'): " + e;
+            log.error(message);
+            addMessage(reports, id, message);
+        }
+    }
+
+    private void addMessage(Set<ReportItem> reports, NodeId id, String message) {
+        if (reports != null) {
+            reports.add(new ReportItemImpl(id.toString(), message));
+        }
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemBundlePersistenceManager.java?rev=1221428&r1=1221427&r2=1221428&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemBundlePersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/mem/InMemBundlePersistenceManager.java Tue Dec 20 18:49:46 2011
@@ -25,7 +25,9 @@ import java.io.DataOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.jcr.RepositoryException;
@@ -489,9 +491,11 @@ public class InMemBundlePersistenceManag
     /**
      * {@inheritDoc}
      */
-    public Iterable<NodeId> getAllNodeIds(NodeId after, int maxCount) throws ItemStateException, RepositoryException {
+    public List<NodeId> getAllNodeIds(NodeId after, int maxCount) throws ItemStateException, RepositoryException {
         // ignore after and count parameters.
-        return bundleStore.keySet();
+        List<NodeId> result = new ArrayList<NodeId>();
+        result.addAll(bundleStore.keySet());
+        return result;
     }
 
     /**

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1221428&r1=1221427&r2=1221428&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Tue Dec 20 18:49:46 2011
@@ -26,11 +26,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Random;
-import java.util.Set;
 
 import javax.jcr.RepositoryException;
 import javax.sql.DataSource;
@@ -43,11 +39,6 @@ import org.apache.jackrabbit.core.id.Nod
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.persistence.PMContext;
 import org.apache.jackrabbit.core.persistence.bundle.AbstractBundlePersistenceManager;
-import org.apache.jackrabbit.core.persistence.check.ConsistencyChecker;
-import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
-import org.apache.jackrabbit.core.persistence.check.ConsistencyReportImpl;
-import org.apache.jackrabbit.core.persistence.check.ReportItem;
-import org.apache.jackrabbit.core.persistence.check.ReportItemImpl;
 import org.apache.jackrabbit.core.persistence.util.BLOBStore;
 import org.apache.jackrabbit.core.persistence.util.BundleBinding;
 import org.apache.jackrabbit.core.persistence.util.ErrorHandling;
@@ -65,7 +56,6 @@ import org.apache.jackrabbit.core.util.d
 import org.apache.jackrabbit.core.util.db.DatabaseAware;
 import org.apache.jackrabbit.core.util.db.DbUtility;
 import org.apache.jackrabbit.core.util.db.StreamWrapper;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -91,7 +81,7 @@ import org.slf4j.LoggerFactory;
  * </ul>
  */
 public class BundleDbPersistenceManager
-        extends AbstractBundlePersistenceManager implements DatabaseAware, ConsistencyChecker {
+        extends AbstractBundlePersistenceManager implements DatabaseAware {
 
     /** the default logger */
     private static Logger log = LoggerFactory.getLogger(BundleDbPersistenceManager.class);
@@ -706,250 +696,6 @@ public class BundleDbPersistenceManager
         return new DbBlobStore();
     }
 
-    private void addMessage(Set<ReportItem> reports, NodeId id, String message) {
-        if (reports != null) {
-            reports.add(new ReportItemImpl(id.toString(), message));
-        }
-    }
-
-    /**
-     * Checks a single bundle for inconsistencies, ie. inexistent child nodes
-     * and inexistent parents.
-     *
-     * @param id node id for the bundle to check
-     * @param bundle the bundle to check
-     * @param fix if <code>true</code>, repair things that can be repaired
-     * @param modifications if <code>fix == true</code>, collect the repaired
-     * {@linkplain NodePropBundle bundles} here
-     */
-    protected void checkBundleConsistency(NodeId id, NodePropBundle bundle,
-                                          boolean fix, Collection<NodePropBundle> modifications,
-                                          Set<ReportItem> reports) {
-        //log.info(name + ": checking bundle '" + id + "'");
-
-        // skip all system nodes except root node
-        if (id.toString().endsWith("babecafebabe")
-                && !id.toString().equals("cafebabe-cafe-babe-cafe-babecafebabe")) {
-            return;
-        }
-
-        // look at the node's children
-        Collection<NodePropBundle.ChildNodeEntry> missingChildren = new ArrayList<NodePropBundle.ChildNodeEntry>();
-        for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
-
-            // skip check for system nodes (root, system root, version storage, node types)
-            if (entry.getId().toString().endsWith("babecafebabe")) {
-                continue;
-            }
-
-            try {
-                // analyze child node bundles
-                NodePropBundle child = loadBundle(entry.getId());
-                String message = null;
-                if (child == null) {
-                    message = "NodeState '" + id + "' references inexistent child" + " '"
-                            + entry.getName() + "' with id " + "'" + entry.getId() + "'";
-                    log.error(message);
-                    missingChildren.add(entry);
-                } else {
-                    NodeId cp = child.getParentId();
-                    if (cp == null) {
-                        message = "ChildNode has invalid parent id: <null>";
-                        log.error(message);
-                    } else if (!cp.equals(id)) {
-                        message = "ChildNode has invalid parent id: '" + cp + "' (instead of '" + id + "')";
-                        log.error(message);
-                    }
-                }
-                if (message != null) {
-                    addMessage(reports, id, message);
-                }
-            } catch (ItemStateException e) {
-                // problem already logged (loadBundle called with logDetailedErrors=true)
-                addMessage(reports, id, e.getMessage());
-            }
-        }
-        // remove child node entry (if fixing is enabled)
-        if (fix && !missingChildren.isEmpty()) {
-            for (NodePropBundle.ChildNodeEntry entry : missingChildren) {
-                bundle.getChildNodeEntries().remove(entry);
-            }
-            modifications.add(bundle);
-        }
-
-        // check parent reference
-        NodeId parentId = bundle.getParentId();
-        try {
-            // skip root nodes (that point to itself)
-            if (parentId != null && !id.toString().endsWith("babecafebabe")) {
-                NodePropBundle parentBundle = loadBundle(parentId);
-                
-                if (parentBundle == null) {
-                    String message = "NodeState '" + id + "' references inexistent parent id '" + parentId + "'";
-                    log.error(message);
-                    addMessage(reports, id, message);
-                }
-                else {
-                    boolean found = false;
-
-                    for (NodePropBundle.ChildNodeEntry entry : parentBundle.getChildNodeEntries()) {
-                        if (entry.getId().equals(id)){
-                            found = true;
-                            break;
-                        }
-                    }
-
-                    if (!found) {
-                        String message = "NodeState '" + id + "' is not referenced by its parent node '" + parentId + "'";
-                        log.error(message);
-                        addMessage(reports, id, message);
-
-                        int l = (int) System.currentTimeMillis();
-                        int r = new Random().nextInt();
-                        int n = l + r;
-                        String nodeName = Integer.toHexString(n);
-                        parentBundle.addChildNodeEntry(NameFactoryImpl
-                                .getInstance().create("{}" + nodeName), id);
-                        log.info("NodeState '" + id + "' adds itself to its parent node '" + parentId + "' with a new name '" + nodeName + "'");
-                        modifications.add(parentBundle);
-                    }
-                }
-            }
-        } catch (ItemStateException e) {
-            String message = "Error reading node '" + parentId + "' (parent of '" + id + "'): " + e;
-            log.error(message);
-            addMessage(reports, id, message);
-        }
-    }
-
-    public ConsistencyReport check(String[] uuids, boolean recursive,
-            boolean fix) throws RepositoryException {
-
-        Set<ReportItem> reports = new HashSet<ReportItem>();
-
-        long tstart = System.currentTimeMillis();
-        int total = internalCheckConsistency(uuids, recursive, fix, reports);
-        long elapsed = System.currentTimeMillis() - tstart;
-
-        return new ConsistencyReportImpl(total, elapsed, reports);
-    }
-
-    public void checkConsistency(String[] uuids, boolean recursive, boolean fix) {
-        try {
-            internalCheckConsistency(uuids, recursive, fix, null);
-        }
-        catch (RepositoryException ex) {
-            log.error("While running consistency check.", ex);
-        }
-    }
-    
-    private int internalCheckConsistency(String[] uuids, boolean recursive, boolean fix, Set<ReportItem> reports) throws RepositoryException {
-        int count = 0;
-        int total = 0;
-        Collection<NodePropBundle> modifications = new ArrayList<NodePropBundle>();        
-
-        if (uuids == null) {
-            total = getNumberOfNodeIds();
-            
-            try {
-                Iterable<NodeId> allIds = getAllNodeIds(null, 0);
-
-                for (NodeId id : allIds) {
-                    try {
-                        // parse and check bundle
-                        NodePropBundle bundle = loadBundle(id);
-                        if (bundle == null) {
-                            log.error("No bundle found for id '" + id + "'");
-                        } else {
-                            checkBundleConsistency(id, bundle, fix, modifications, reports);
-
-                            count++;
-                            if (count % 1000 == 0) {
-                                log.info(name + ": checked " + count + "/" + total + " bundles...");
-                            }
-                        }
-                    } catch (ItemStateException e) {
-                        // problem already logged (loadBundle called with
-                        // logDetailedErrors=true)
-                    }
-
-                }
-            } catch (ItemStateException ex) {
-                throw new RepositoryException("getting nodeIds", ex);
-            } finally {
-                total = count;
-            }
-        } else {
-            // check only given uuids, handle recursive flag
-
-            // 1) convert uuid array to modifiable list
-            // 2) for each uuid do
-            //     a) load node bundle
-            //     b) check bundle, store any bundle-to-be-modified in collection
-            //     c) if recursive, add child uuids to list of uuids
-
-            List<NodeId> idList = new ArrayList<NodeId>(uuids.length);
-            // convert uuid string array to list of UUID objects
-            for (int i = 0; i < uuids.length; i++) {
-                try {
-                    idList.add(new NodeId(uuids[i]));
-                } catch (IllegalArgumentException e) {
-                    log.error("Invalid id for consistency check, skipping: '" + uuids[i] + "': " + e);
-                }
-            }
-            
-            // iterate over UUIDs (including ones that are newly added inside the loop!)
-            for (int i = 0; i < idList.size(); i++) {
-                NodeId id = idList.get(i);
-                try {
-                    // load the node from the database
-                    NodePropBundle bundle = loadBundle(id);
-
-                    if (bundle == null) {
-                        log.error("No bundle found for id '" + id + "'");
-                    }
-                    else {
-                        checkBundleConsistency(id, bundle, fix, modifications, reports);
-
-                        if (recursive) {
-                            for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
-                                idList.add(entry.getId());
-                            }
-                        }
-
-                        count++;
-                        if (count % 1000 == 0) {
-                            log.info(name + ": checked " + count + "/" + idList.size() + " bundles...");
-                        }
-                    }
-                } catch (ItemStateException e) {
-                    // problem already logged (loadBundle called with logDetailedErrors=true)
-                }
-            }
-
-            total = idList.size();
-        }
-
-        // repair collected broken bundles
-        if (fix && !modifications.isEmpty()) {
-            log.info(name + ": Fixing " + modifications.size() + " inconsistent bundle(s)...");
-            for (NodePropBundle bundle : modifications) {
-                try {
-                    log.info(name + ": Fixing bundle '" + bundle.getId() + "'");
-                    bundle.markOld(); // use UPDATE instead of INSERT
-                    storeBundle(bundle);
-                    evictBundle(bundle.getId());
-                } catch (ItemStateException e) {
-                    log.error(name + ": Error storing fixed bundle: " + e);
-                }
-            }
-        }
-
-        log.info(name + ": checked " + count + "/" + total + " bundles.");
-
-        return total;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -1020,29 +766,10 @@ public class BundleDbPersistenceManager
         return params.toArray();
     }
 
-    private synchronized int getNumberOfNodeIds() throws RepositoryException {
-        ResultSet rs = null;
-        try {
-            String sql = "select count(*) from " + schemaObjectPrefix + "BUNDLE";
-            rs = conHelper.exec(sql, new Object[0], false, 0);
-
-            if (!rs.next()) {
-                String message = "Could not retrieve total number of bundles: empty result set.";
-                log.error(message);
-                throw new RepositoryException(message);
-            }
-            return rs.getInt(1);
-        } catch (SQLException ex) {
-            throw new RepositoryException("Could not retrieve total number of bundles", ex);
-        } finally {
-            DbUtility.close(rs);
-        }
-    }
-
     /**
      * {@inheritDoc}
      */
-    public synchronized Iterable<NodeId> getAllNodeIds(NodeId bigger, int maxCount)
+    public synchronized List<NodeId> getAllNodeIds(NodeId bigger, int maxCount)
             throws ItemStateException, RepositoryException {
         ResultSet rs = null;
         try {