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/10/11 15:34:11 UTC
svn commit: r1181777 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/persistence/check/
main/java/org/apache/jackrabbit/core/persistence/pool/
test/java/org/apache/jackrabbit/core/
test/java/org/apache/jackrabbit/core/p...
Author: reschke
Date: Tue Oct 11 13:34:10 2011
New Revision: 1181777
URL: http://svn.apache.org/viewvc?rev=1181777&view=rev
Log:
JCR-3069: add new ConsistencyChecker interface, implement it in BundleDbPersistenceManager, use it in ConcurrentImportTest, extend AutoFixCorruptNode to check it (work-in-progress)
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyChecker.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReport.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReportImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItem.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItemImpl.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyChecker.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyChecker.java?rev=1181777&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyChecker.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyChecker.java Tue Oct 11 13:34:10 2011
@@ -0,0 +1,49 @@
+/*
+ * 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.check;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Optional interface for Persistence Managers. Allows running consistency
+ * checks similar to the base one (see @link
+ * {@link PersistenceManager#checkConsistency(String[], boolean, boolean)) but
+ * providing a result that can be acted upon.
+ * <p>
+ * <em>Beware: this interface is designed for unit tests only.</em>
+ */
+public interface ConsistencyChecker {
+
+ /**
+ * Perform a consistency check of the data. An example are non-existent
+ * nodes referenced in a child node entry. The existence of this feature and
+ * the scope of the implementation can vary in different PersistenceManager
+ * implementations.
+ *
+ * @param uuids
+ * list of UUIDs of nodes to be checked. if null, all nodes will
+ * be checked
+ * @param recursive
+ * if true, the tree(s) below the given node(s) will be traversed
+ * and checked as well
+ * @param fix
+ * if true, any problems found that can be repaired will be
+ * repaired. if false, no data will be modified, instead all
+ * inconsistencies will only get logged
+ */
+ ConsistencyReport check(String[] uuids, boolean recursive, boolean fix) throws RepositoryException;
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReport.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReport.java?rev=1181777&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReport.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReport.java Tue Oct 11 13:34:10 2011
@@ -0,0 +1,40 @@
+/*
+ * 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.check;
+
+import java.util.Set;
+
+/**
+ * Returned as result of a {@link ConsistencyChecker} run.
+ */
+public interface ConsistencyReport {
+
+ /**
+ * @return number of nodes that were checked
+ */
+ public int getNodeCount();
+
+ /**
+ * @return elapsed time in ms
+ */
+ public long getElapsedTimeMs();
+
+ /**
+ * @return generated messages
+ */
+ public Set<ReportItem> getItems();
+}
\ No newline at end of file
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReportImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReportImpl.java?rev=1181777&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReportImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ConsistencyReportImpl.java Tue Oct 11 13:34:10 2011
@@ -0,0 +1,51 @@
+/*
+ * 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.check;
+
+import java.util.Set;
+
+public class ConsistencyReportImpl implements ConsistencyReport {
+
+ private final int nodeCount;
+ private final long elapsedTimeMs;
+ private final Set<ReportItem> reports;
+
+ public ConsistencyReportImpl(int nodeCount, long elapsedTimeMs,
+ Set<ReportItem> reports) {
+ this.nodeCount = nodeCount;
+ this.elapsedTimeMs = elapsedTimeMs;
+ this.reports = reports;
+ }
+
+ public int getNodeCount() {
+ return nodeCount;
+ }
+
+ public long getElapsedTimeMs() {
+ return elapsedTimeMs;
+ }
+
+ public Set<ReportItem> getItems() {
+ return reports;
+ }
+
+ @Override
+ public String toString() {
+ return "elapsedTimeMs " + elapsedTimeMs + ", nodeCount " + nodeCount
+ + ", reports: " + reports;
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItem.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItem.java?rev=1181777&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItem.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItem.java Tue Oct 11 13:34:10 2011
@@ -0,0 +1,33 @@
+/*
+ * 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.check;
+
+/**
+ * An item reported inside a {@link ConsistencyChecker.Report}.
+ */
+public interface ReportItem {
+
+ /**
+ * @return node id to which the message applies
+ */
+ public String getNodeId();
+
+ /**
+ * @return message
+ */
+ public String getMessage();
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItemImpl.java?rev=1181777&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItemImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/check/ReportItemImpl.java Tue Oct 11 13:34:10 2011
@@ -0,0 +1,41 @@
+/*
+ * 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.check;
+
+public class ReportItemImpl implements ReportItem {
+
+ private final String nodeId;
+ private final String message;
+
+ public ReportItemImpl(String nodeId, String message) {
+ this.nodeId = nodeId;
+ this.message = message;
+ }
+
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return nodeId + " -- " + message;
+ }
+}
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=1181777&r1=1181776&r2=1181777&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 Oct 11 13:34:10 2011
@@ -27,9 +27,11 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import javax.jcr.RepositoryException;
import javax.sql.DataSource;
@@ -42,6 +44,11 @@ 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;
@@ -85,7 +92,7 @@ import org.slf4j.LoggerFactory;
* </ul>
*/
public class BundleDbPersistenceManager
- extends AbstractBundlePersistenceManager implements DatabaseAware {
+ extends AbstractBundlePersistenceManager implements DatabaseAware, ConsistencyChecker {
/** the default logger */
private static Logger log = LoggerFactory.getLogger(BundleDbPersistenceManager.class);
@@ -700,6 +707,12 @@ 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.
@@ -711,7 +724,8 @@ public class BundleDbPersistenceManager
* {@linkplain NodePropBundle bundles} here
*/
protected void checkBundleConsistency(NodeId id, NodePropBundle bundle,
- boolean fix, Collection<NodePropBundle> modifications) {
+ boolean fix, Collection<NodePropBundle> modifications,
+ Set<ReportItem> reports) {
//log.info(name + ": checking bundle '" + id + "'");
// skip all system nodes except root node
@@ -732,20 +746,25 @@ public class BundleDbPersistenceManager
try {
// analyze child node bundles
NodePropBundle child = loadBundle(entry.getId());
+ String message = null;
if (child == null) {
- log.error(
- "NodeState '" + id + "' references inexistent child"
- + " '" + entry.getName() + "' with id "
- + "'" + entry.getId() + "'");
+ 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) {
- log.error("ChildNode has invalid parent uuid: <null>");
+ message = "ChildNode has invalid parent uuid: <null>";
+ log.error(message);
} else if (!cp.equals(id)) {
- log.error("ChildNode has invalid parent uuid: '" + cp + "' (instead of '" + id + "')");
+ message = "ChildNode has invalid parent uuid: '" + 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)
}
@@ -764,7 +783,9 @@ public class BundleDbPersistenceManager
// skip root nodes (that point to itself)
if (parentId != null && !id.toString().endsWith("babecafebabe")) {
if (loadBundle(parentId) == null) {
- log.error("NodeState '" + id + "' references inexistent parent uuid '" + parentId + "'");
+ String message = "NodeState '" + id + "' references inexistent parent uuid '" + parentId + "'";
+ log.error(message);
+ addMessage(reports, id, message);
}
NodePropBundle parentBundle = loadBundle(parentId);
Iterator<NodePropBundle.ChildNodeEntry> childNodeIter = parentBundle.getChildNodeEntries().iterator();
@@ -776,29 +797,54 @@ public class BundleDbPersistenceManager
break;
}
}
- if (!found) {
- log.error("NodeState '" + id + "' is not referenced by its parent node '" + parentId + "'");
- 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);
- }
+ 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) {
log.error("Error reading node '" + parentId + "' (parent of '" + id + "'): " + e);
}
}
+ 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) {
- // get all node bundles in the database with a single sql statement,
+ // get all node bundles in the database with a single SQL statement,
// which is (probably) faster than loading each bundle and traversing the tree
ResultSet rs = null;
try {
@@ -806,8 +852,9 @@ public class BundleDbPersistenceManager
rs = conHelper.exec(sql, new Object[0], false, 0);
try {
if (!rs.next()) {
- log.error("Could not retrieve total number of bundles. empty result set.");
- return;
+ String message = "Could not retrieve total number of bundles. empty result set.";
+ log.error(message);
+ throw new RepositoryException(message);
}
total = rs.getInt(1);
} finally {
@@ -838,7 +885,7 @@ public class BundleDbPersistenceManager
}
// parse and check bundle
NodePropBundle bundle = readBundle(id, bRs, 1);
- checkBundleConsistency(id, bundle, fix, modifications);
+ checkBundleConsistency(id, bundle, fix, modifications, reports);
} catch (SQLException e) {
log.error("Unable to parse bundle " + id, e);
} finally {
@@ -887,7 +934,7 @@ public class BundleDbPersistenceManager
continue;
}
- checkBundleConsistency(id, bundle, fix, modifications);
+ checkBundleConsistency(id, bundle, fix, modifications, reports);
if (recursive) {
for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
@@ -923,6 +970,8 @@ public class BundleDbPersistenceManager
}
log.info(name + ": checked " + count + "/" + total + " bundles.");
+
+ return total;
}
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java?rev=1181777&r1=1181776&r2=1181777&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentImportTest.java Tue Oct 11 13:34:10 2011
@@ -27,7 +27,9 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.test.NotExecutableException;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
@@ -51,9 +53,14 @@ public class ConcurrentImportTest extend
* performed by the threads.
*/
private static final int NUM_NODES = 10;
-
+
public void testConcurrentImport() throws RepositoryException {
- concurrentImport(new String[]{JcrConstants.MIX_REFERENCEABLE}, false);
+ try {
+ concurrentImport(new String[]{JcrConstants.MIX_REFERENCEABLE}, false);
+ }
+ finally {
+ checkConsistency();
+ }
}
public void testConcurrentImportSynced() throws RepositoryException {
@@ -206,4 +213,12 @@ public class ConcurrentImportTest extend
}
-}
\ No newline at end of file
+ private void checkConsistency() throws RepositoryException {
+ try {
+ ConsistencyReport rep = TestHelper.checkConsistency(testRootNode.getSession());
+ assertEquals("Found broken nodes in repository: " + rep, 0, rep.getItems().size());
+ } catch (NotExecutableException ex) {
+ // ignore
+ }
+ }
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java?rev=1181777&r1=1181776&r2=1181777&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestHelper.java Tue Oct 11 13:34:10 2011
@@ -16,7 +16,14 @@
*/
package org.apache.jackrabbit.core;
+import javax.jcr.Repository;
import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+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.test.NotExecutableException;
/**
* <code>TestHelper</code> provides test utility methods.
@@ -35,4 +42,31 @@ public class TestHelper {
throws RepositoryException {
repo.getWorkspaceInfo(name).dispose();
}
+
+ /**
+ * Runs a consistency check on the workspace used by the specified session.
+ *
+ * @param session the Session accessing the workspace to be checked
+ * @throws RepositoryException if an error occurs while getting the
+ * workspace with the given name.
+ * @throws NotExecutableException if the {@link PersistenceManager} does
+ * not implement {@link ConsistencyChecker}, or if the associated
+ * {@link Repository} is not a {@link RepositoryImpl}.
+ */
+ public static ConsistencyReport checkConsistency(Session session)
+ throws NotExecutableException, RepositoryException {
+ Repository r = session.getRepository();
+ if (!(r instanceof RepositoryImpl)) {
+ throw new NotExecutableException();
+ } else {
+ RepositoryImpl ri = (RepositoryImpl) r;
+ PersistenceManager pm = ri.getWorkspaceInfo(
+ session.getWorkspace().getName()).getPersistenceManager();
+ if (!(pm instanceof ConsistencyChecker)) {
+ throw new NotExecutableException();
+ } else {
+ return ((ConsistencyChecker) pm).check(null, true, false);
+ }
+ }
+ }
}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java?rev=1181777&r1=1181776&r2=1181777&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/AutoFixCorruptNode.java Tue Oct 11 13:34:10 2011
@@ -21,15 +21,20 @@ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.UUID;
+
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
+
import junit.framework.TestCase;
+
import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.core.TestHelper;
import org.apache.jackrabbit.core.TransientRepository;
+import org.apache.jackrabbit.core.persistence.check.ConsistencyReport;
/**
* Tests that a corrupt node is automatically fixed.
@@ -46,6 +51,51 @@ public class AutoFixCorruptNode extends
setUp();
}
+ /**
+ * Unit test for <a
+ * href="https://issues.apache.org/jira/browse/JCR-3069">JCR-3069</a>
+ */
+ public void testAutoFixWithConsistencyCheck() throws Exception {
+
+ // new repository
+ TransientRepository rep = new TransientRepository(new File(TEST_DIR));
+ Session s = openSession(rep, false);
+ Node root = s.getRootNode();
+
+ // add nodes /test and /test/missing
+ Node test = root.addNode("test");
+ Node missing = test.addNode("missing");
+ missing.addMixin("mix:referenceable");
+ UUID id = UUID.fromString(missing.getIdentifier());
+ s.save();
+ s.logout();
+
+ // remove the bundle for /test/missing directly in the database
+ Connection conn = DriverManager.getConnection("jdbc:derby:" + TEST_DIR
+ + "/workspaces/default/db");
+ PreparedStatement prep = conn
+ .prepareStatement("delete from DEFAULT_BUNDLE where NODE_ID_HI=? and NODE_ID_LO=?");
+ prep.setLong(1, id.getMostSignificantBits());
+ prep.setLong(2, id.getLeastSignificantBits());
+ prep.executeUpdate();
+ conn.close();
+
+ s = openSession(rep, false);
+ try {
+ ConsistencyReport r = TestHelper.checkConsistency(s);
+ assertNotNull(r);
+ assertNotNull(r.getItems());
+ assertEquals(1, r.getItems().size());
+ assertEquals(test.getIdentifier(), r.getItems().iterator().next()
+ .getNodeId());
+ } finally {
+ s.logout();
+ rep.shutdown();
+ FileUtils.deleteDirectory(new File("repository"));
+ }
+
+ }
+
public void testAutoFix() throws Exception {
// new repository
@@ -62,10 +112,10 @@ public class AutoFixCorruptNode extends
s.logout();
// remove the bundle for /test/missing directly in the database
- Connection conn = DriverManager.getConnection(
- "jdbc:derby:"+TEST_DIR+"/workspaces/default/db");
- PreparedStatement prep = conn.prepareStatement(
- "delete from DEFAULT_BUNDLE where NODE_ID_HI=? and NODE_ID_LO=?");
+ Connection conn = DriverManager.getConnection("jdbc:derby:" + TEST_DIR
+ + "/workspaces/default/db");
+ PreparedStatement prep = conn
+ .prepareStatement("delete from DEFAULT_BUNDLE where NODE_ID_HI=? and NODE_ID_LO=?");
prep.setLong(1, id.getMostSignificantBits());
prep.setLong(2, id.getLeastSignificantBits());
prep.executeUpdate();
@@ -108,10 +158,13 @@ public class AutoFixCorruptNode extends
}
- private Session openSession(Repository rep, boolean autoFix) throws RepositoryException {
- SimpleCredentials cred = new SimpleCredentials("admin", "admin".toCharArray());
+ private Session openSession(Repository rep, boolean autoFix)
+ throws RepositoryException {
+ SimpleCredentials cred = new SimpleCredentials("admin",
+ "admin".toCharArray());
if (autoFix) {
- cred.setAttribute("org.apache.jackrabbit.autoFixCorruptions", "true");
+ cred.setAttribute("org.apache.jackrabbit.autoFixCorruptions",
+ "true");
}
return rep.login(cred);
}