jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From un...@apache.org
Subject svn commit: r1448555 - /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java
Date Thu, 21 Feb 2013 08:59:51 GMT
Author: unico
Date: Thu Feb 21 08:59:50 2013
New Revision: 1448555

URL: http://svn.apache.org/r1448555
Log:
JCR-3525 code cleanup and java doc comments; remove the option of checking in batches instead
of all at once: this broke during a previous refactoring and is not a user friendly option
since it is very slow

Modified:
    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/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=1448555&r1=1448554&r2=1448555&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/ConsistencyCheckerImpl.java
Thu Feb 21 08:59:50 2013
@@ -44,6 +44,7 @@ import org.apache.jackrabbit.core.state.
 import org.apache.jackrabbit.core.state.ItemState;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.NameFactory;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
@@ -52,7 +53,6 @@ import org.slf4j.LoggerFactory;
 
 public class ConsistencyCheckerImpl {
 
-    /** the default logger */
     private static Logger log = LoggerFactory.getLogger(ConsistencyCheckerImpl.class);
 
     /**
@@ -61,24 +61,16 @@ public class ConsistencyCheckerImpl {
     private static final int NODESATONCE = Integer.getInteger("org.apache.jackrabbit.checker.nodesatonce",
1024 * 8);
 
     /**
-     * Whether to load all node infos before checking or to check nodes as they are loaded.
-     * The former is magnitudes faster but requires more memory.
-     */
-    private static final boolean CHECKAFTERLOADING = Boolean.getBoolean("org.apache.jackrabbit.checker.checkafterloading");
-
-    /**
      * Attribute name used to store the size of the update.
      */
     private static final String ATTRIBUTE_UPDATE_SIZE = "updateSize";
 
-    private static final NameFactory NF = NameFactoryImpl.getInstance();
-
     private final AbstractBundlePersistenceManager pm;
     private final ConsistencyCheckListener listener;
     private NodeId lostNFoundId;
     private UpdateEventChannel eventChannel = new DummyUpdateEventChannel();
     private Map<NodeId, NodePropBundle> bundles;
-    private final List<ConsistencyCheckerError> errors = new ArrayList<ConsistencyCheckerError>();
+    private List<ConsistencyCheckerError> errors;
     private int nodeCount;
     private long elapsedTime;
 
@@ -102,6 +94,7 @@ public class ConsistencyCheckerImpl {
      * @throws RepositoryException
      */
     public void check(String[] uuids, boolean recursive) throws RepositoryException {
+        errors = new ArrayList<ConsistencyCheckerError>();
         long tstart = System.currentTimeMillis();
         nodeCount = internalCheckConsistency(uuids, recursive);
         elapsedTime = System.currentTimeMillis() - tstart;
@@ -112,7 +105,7 @@ public class ConsistencyCheckerImpl {
      * Removes all false positives from the report.
      */
     public void doubleCheckErrors() {
-        if (!errors.isEmpty()) {
+        if (hasErrors()) {
             final Iterator<ConsistencyCheckerError> errorIterator = errors.iterator();
             while (errorIterator.hasNext()) {
                 final ConsistencyCheckerError error = errorIterator.next();
@@ -133,8 +126,10 @@ public class ConsistencyCheckerImpl {
      */
     public ConsistencyReport getReport() {
         final Set<ReportItem> reportItems = new HashSet<ReportItem>();
-        for (ConsistencyCheckerError error : errors) {
-            reportItems.add(error.getReportItem());
+        if (hasErrors()) {
+            for (ConsistencyCheckerError error : errors) {
+                reportItems.add(error.getReportItem());
+            }
         }
         return new ConsistencyReportImpl(nodeCount, elapsedTime, reportItems);
     }
@@ -168,7 +163,6 @@ public class ConsistencyCheckerImpl {
                 if (changes.hasUpdates()) {
                     eventChannel.updatePrepared(update);
                     for (NodePropBundle bundle : bundles.values()) {
-                        bundle.setModCount((short) (bundle.getModCount()+1));
                         storeBundle(bundle);
                     }
                     update.setAttribute(ATTRIBUTE_UPDATE_SIZE, changes.getUpdateSize());
@@ -186,10 +180,16 @@ public class ConsistencyCheckerImpl {
         }
     }
 
+    private boolean hasErrors() {
+        return errors != null && !errors.isEmpty();
+    }
+
     private boolean hasRepairableErrors() {
-        for (ConsistencyCheckerError error : errors) {
-            if (error.isRepairable()) {
-                return true;
+        if (hasErrors()) {
+            for (ConsistencyCheckerError error : errors) {
+                if (error.isRepairable()) {
+                    return true;
+                }
             }
         }
         return false;
@@ -220,6 +220,7 @@ public class ConsistencyCheckerImpl {
         int count = 0;
 
         if (uuids == null) {
+            // check all nodes
             try {
                 Map<NodeId, NodeInfo> batch = pm.getAllNodeInfos(null, NODESATONCE);
                 Map<NodeId, NodeInfo> allInfos = batch;
@@ -228,48 +229,33 @@ public class ConsistencyCheckerImpl {
                     NodeId lastId = null;
 
                     for (Map.Entry<NodeId, NodeInfo> entry : batch.entrySet()) {
-                        NodeId id = entry.getKey();
-                        lastId = id;
+                        lastId = entry.getKey();
 
                         count++;
                         if (count % 1000 == 0) {
                             log.info(pm + ": loaded " + count + " infos...");
                         }
 
-                        if (!CHECKAFTERLOADING) {
-                            // check immediately
-                            NodeInfo nodeInfo = entry.getValue();
-                            checkBundleConsistency(id, nodeInfo, batch);
-                        }
                     }
 
                     batch = pm.getAllNodeInfos(lastId, NODESATONCE);
 
-                    if (CHECKAFTERLOADING) {
-                        allInfos.putAll(batch);
-                    }
+                    allInfos.putAll(batch);
                 }
 
-                if (CHECKAFTERLOADING) {
-                    // check info
-                    for (Map.Entry<NodeId, NodeInfo> entry : allInfos.entrySet()) {
-                        checkBundleConsistency(entry.getKey(), entry.getValue(), allInfos);
-                    }
+                for (Map.Entry<NodeId, NodeInfo> entry : allInfos.entrySet()) {
+                    checkBundleConsistency(entry.getKey(), entry.getValue(), allInfos);
                 }
-            } catch (ItemStateException ex) {
-                throw new RepositoryException("getting nodeIds", ex);
+
+            } catch (ItemStateException e) {
+                throw new RepositoryException("Error loading nodes", e);
+            } finally {
+                NodeInfo.clearPool();
             }
         } 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 (final String uuid : uuids) {
                 try {
                     idList.add(new NodeId(uuid));
@@ -278,14 +264,10 @@ public class ConsistencyCheckerImpl {
                 }
             }
 
-            // 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);
-
+                    final NodePropBundle bundle = pm.loadBundle(id);
                     if (bundle == null) {
                         if (!isVirtualNode(id)) {
                             error(id.toString(), "No bundle found for id '" + id + "'");
@@ -301,22 +283,17 @@ public class ConsistencyCheckerImpl {
 
                         count++;
                         if (count % 1000 == 0 && listener == null) {
-                            log.info(pm + ": checked " + count + "/"
-                                    + idList.size() + " bundles...");
+                            log.info(pm + ": checked " + count + "/" + idList.size() + "
bundles...");
                         }
                     }
-                } catch (ItemStateException e) {
-                    // problem already logged (loadBundle called with
-                    // logDetailedErrors=true)
+                } catch (ItemStateException ignored) {
+                    // problem already logged
                 }
             }
         }
 
         log.info(pm + ": checked " + count + " bundles.");
 
-        // clear the NodeId pool
-        NodeInfo.clearPool();
-
         return count;
     }
 
@@ -324,77 +301,72 @@ public class ConsistencyCheckerImpl {
      * Checks a single bundle for inconsistencies, ie. inexistent child nodes, inexistent
parents, and other
      * structural inconsistencies.
      *
-     * @param id node id for the bundle to check
+     * @param nodeId node id for the bundle to check
      * @param nodeInfo the node info for the node to check
      * @param infos all the {@link NodeInfo}s loaded in the current batch
      */
-    private void checkBundleConsistency(NodeId id, NodeInfo nodeInfo, Map<NodeId, NodeInfo>
infos) {
+    private void checkBundleConsistency(NodeId nodeId, NodeInfo nodeInfo, Map<NodeId,
NodeInfo> infos) {
 
         // skip all virtual nodes
-        if (isVirtualNode(id)) {
+        if (!isRoot(nodeId) && isVirtualNode(nodeId)) {
             return;
         }
 
         if (listener != null) {
-            listener.startCheck(id.toString());
+            listener.startCheck(nodeId.toString());
         }
 
         // check the children
         for (final NodeId childNodeId : nodeInfo.getChildren()) {
 
-            // skip check for system nodes (root, system root, version storage, node types)
-            if (childNodeId.toString().endsWith("babecafebabe")) {
+            if (isVirtualNode(childNodeId)) {
                 continue;
             }
 
             NodeInfo childNodeInfo = infos.get(childNodeId);
 
             if (childNodeInfo == null) {
-                addError(new MissingChild(id, childNodeId));
+                addError(new MissingChild(nodeId, childNodeId));
             } else {
-                if (!id.equals(childNodeInfo.getParentId())) {
-                    addError(new DisconnectedChild(id, childNodeId, childNodeInfo.getParentId()));
+                if (!nodeId.equals(childNodeInfo.getParentId())) {
+                    addError(new DisconnectedChild(nodeId, childNodeId, childNodeInfo.getParentId()));
                 }
             }
         }
 
         // check the parent
         NodeId parentId = nodeInfo.getParentId();
-        // skip root nodes (that point to itself)
-        if (parentId != null && !id.toString().endsWith("babecafebabe")) {
+        // skip root nodes
+        if (parentId != null && !isRoot(nodeId)) {
             NodeInfo parentInfo = infos.get(parentId);
 
             if (parentInfo == null) {
-                addError(new OrphanedNode(id, parentId));
+                addError(new OrphanedNode(nodeId, parentId));
             } else {
                 // if the parent exists, does it have a child node entry for us?
                 boolean found = false;
 
                 for (NodeId childNodeId : parentInfo.getChildren()) {
-                    if (childNodeId.equals(id)){
+                    if (childNodeId.equals(nodeId)){
                         found = true;
                         break;
                     }
                 }
 
                 if (!found) {
-                    addError(new AbandonedNode(id, parentId));
+                    addError(new AbandonedNode(nodeId, parentId));
                 }
 
             }
         }
     }
 
-    /**
-     * @return whether the id is for a virtual node (not needing checking)
-     */
-    protected boolean isVirtualNode(NodeId id) {
-        String s = id.toString();
-        return !isRoot(s) && s.endsWith("babecafebabe");
+    protected boolean isVirtualNode(NodeId nodeId) {
+        return nodeId.toString().endsWith("babecafebabe");
     }
 
-    private boolean isRoot(String id) {
-        return "cafebabe-cafe-babe-cafe-babecafebabe".equals(id);
+    private boolean isRoot(NodeId nodeId) {
+        return "cafebabe-cafe-babe-cafe-babecafebabe".equals(nodeId.toString());
     }
 
     private void addError(ConsistencyCheckerError error) {
@@ -432,7 +404,8 @@ public class ConsistencyCheckerImpl {
 
     private void storeBundle(NodePropBundle bundle) {
         try {
-            bundle.markOld(); // use UPDATE instead of INSERT
+            bundle.markOld();
+            bundle.setModCount((short) (bundle.getModCount()+1));
             pm.storeBundle(bundle);
             pm.evictBundle(bundle.getId());
         } catch (ItemStateException e) {
@@ -451,6 +424,12 @@ public class ConsistencyCheckerImpl {
         bundles.put(bundle.getId(), bundle);
     }
 
+    /**
+     * A missing child is when the node referred to by a child node entry
+     * does not exist.
+     *
+     * This type of error is repaired by removing the corrupted child node entry.
+     */
     private class MissingChild extends ConsistencyCheckerError {
 
         private final NodeId childNodeId;
@@ -501,6 +480,12 @@ public class ConsistencyCheckerImpl {
         }
     }
 
+    /**
+     * A disconnected child is when a child node entry refers to a node
+     * that exists, but that node actually has a different parent.
+     *
+     * This type of error is repaired by removing the corrupted child node entry.
+     */
     private class DisconnectedChild extends ConsistencyCheckerError {
 
         private final NodeId childNodeId;
@@ -553,6 +538,12 @@ public class ConsistencyCheckerImpl {
         }
     }
 
+    /**
+     * An orphaned node is a node whose parent does not exist.
+     *
+     * This type of error is repaired by reattaching the orphan to
+     * a special purpose 'lost and found' node.
+     */
     private class OrphanedNode extends ConsistencyCheckerError {
 
         private final NodeId parentNodeId;
@@ -579,7 +570,8 @@ public class ConsistencyCheckerImpl {
                 final NodePropBundle lfBundle = getBundle(lostNFoundId);
 
                 final String nodeName = nodeId + "-" + System.currentTimeMillis();
-                lfBundle.addChildNodeEntry(NF.create("", nodeName), nodeId);
+                final NameFactory nameFactory = NameFactoryImpl.getInstance();
+                lfBundle.addChildNodeEntry(nameFactory.create("", nodeName), nodeId);
                 bundle.setParentId(lostNFoundId);
 
                 saveBundle(bundle);
@@ -605,6 +597,14 @@ public class ConsistencyCheckerImpl {
         }
     }
 
+    /**
+     * An abandoned node is a node that points to an existing node
+     * as its parent, but that parent node does not have a corresponding
+     * child node entry for the child.
+     *
+     * This type of error is repaired by adding the missing child node entry
+     * to the parent.
+     */
     private class AbandonedNode extends ConsistencyCheckerError {
 
         private final NodeId nodeId;
@@ -630,18 +630,17 @@ public class ConsistencyCheckerImpl {
         void doRepair(final ChangeLog changes) throws ItemStateException {
             final NodePropBundle parentBundle = getBundle(parentNodeId);
 
-            final String nodeName = createNodeName();
-            parentBundle.addChildNodeEntry(NF.create("{}" + nodeName), nodeId);
+            parentBundle.addChildNodeEntry(createNodeName(), nodeId);
 
             saveBundle(parentBundle);
             changes.modified(new NodeState(parentNodeId, null, null, ItemState.STATUS_EXISTING,
false));
         }
 
-        private String createNodeName() {
-            int l = (int) System.currentTimeMillis();
-            int r = new Random().nextInt();
-            int n = l + r;
-            return Integer.toHexString(n);
+        private Name createNodeName() {
+            int n = (int) System.currentTimeMillis() + new Random().nextInt();
+            final String localName = Integer.toHexString(n);
+            final NameFactory nameFactory = NameFactoryImpl.getInstance();
+            return nameFactory.create("{}" + localName);
         }
 
         @Override



Mime
View raw message