You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2008/03/03 10:17:38 UTC
svn commit: r632996 - in /jackrabbit/branches/1.3/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/
main/java/org/apache/jackrabbit/core/persistence/
main/java/org/apache/jackrabbit/core/persistence/bundle/
main/java/org/apache/jackrabbit/core...
Author: jukka
Date: Mon Mar 3 01:17:36 2008
New Revision: 632996
URL: http://svn.apache.org/viewvc?rev=632996&view=rev
Log:
JCR-1428: Add API for selective bundle consistency check (Jackrabbit-specific)
- 1.3: Patches by Alexander Klimetschek
Modified:
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
jackrabbit/branches/1.3/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/TestAll.java
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Mon Mar 3 01:17:36 2008
@@ -1163,6 +1163,78 @@
return new SharedItemStateManager(persistMgr, rootNodeId, ntReg, true, cacheFactory);
}
+ /**
+ * Checks the consistency of the given nodes in the given workspace or the
+ * versioning subtree. Use <code>jcr:system</code> as workspace name for
+ * checking the versioning tree. The <code>recursive</code> flag indicates
+ * whether the tree below the given nodes shall be traversed and checked as
+ * well.
+ *
+ * <p>
+ * Note: This must be called right after Jackrabbit startup before the
+ * workspace in question (or the system tree) was accessed, ie. a session
+ * was opened. Otherwise Jackrabbit will be in an inconsistent state and
+ * various errors will happen. Be also sure to have logging enabled before
+ * this method is called to catch all messages of the check.
+ *
+ * <p>
+ * To use this method, you will have to subclass {@link RepositoryImpl},
+ * make it public and use an instance of the subclass as the repository.
+ *
+ * <h4>Consistency check details:</h4>
+ * <p>
+ * The check is currently restricted to {@link PersistenceManager}s, more
+ * specifically the {@link BundleDbPersistenceManager}s. They will check
+ * for parent-child relationships of nodes, where either parent or child
+ * nodes no longer exist. In the case of missing child nodes, these will be
+ * repaired by removing them. Any other problems will be logged with ERROR
+ * log level for further analysis. When bundles are fixed, ie.
+ * <code>fix==true</code>, set INFO logging on the specific persistence
+ * manager, to see which bundles get repaired:
+ *
+ * <pre>
+ * log4j.logger.org.apache.jackrabbit.core.persistence.bundle.BundleDbPersistenceManager=INFO, stdout
+ * </pre>
+ *
+ * When more details for all checked node bundles shall be displayed, enable
+ * INFO logging for the BundleBinding:
+ *
+ * <pre>
+ * log4j.logger.org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding=INFO, stdout
+ * </pre>
+ *
+ * @param workspaceName
+ * name of the workspace to be checked. Use
+ * <code>jcr:system</code> to check the versioning subtree.
+ * @param uuids
+ * list of UUIDs of nodes to be checked. if null, all nodes in
+ * the workspace will be checked (and the recursive flag will be
+ * ignored)
+ * @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
+ *
+ * @throws NoSuchWorkspaceException
+ * if the workspace does not exist
+ * @throws IllegalStateException
+ * if this repository has been shut down
+ * @throws RepositoryException
+ * if the persistence manager could not be initialized
+ */
+ protected void checkConsistency(String workspaceName, String[] uuids, boolean recursive, boolean fix) throws IllegalStateException, NoSuchWorkspaceException, RepositoryException {
+ if ("jcr:system".equals(workspaceName)) {
+ PersistenceManager pm = vMgr.getPersistenceManager();
+ pm.checkConsistency(uuids, recursive, fix);
+ } else {
+ PersistenceManager pm = getWorkspaceInfo(workspaceName).getPersistenceManager();
+ pm.checkConsistency(uuids, recursive, fix);
+ }
+ }
+
//-----------------------------------------------------------< Repository >
/**
* {@inheritDoc}
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/AbstractPersistenceManager.java Mon Mar 3 01:17:36 2008
@@ -96,6 +96,14 @@
}
}
}
+
+ /**
+ * This implementation does nothing.
+ *
+ * {@inheritDoc}
+ */
+ public void checkConsistency(String[] uuids, boolean recursive, boolean fix) {
+ }
/**
* Store a node state. Subclass responsibility.
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceManager.java Mon Mar 3 01:17:36 2008
@@ -180,4 +180,23 @@
*/
void store(ChangeLog changeLog) throws ItemStateException;
+ /**
+ * 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
+ */
+ void checkConsistency(String[] uuids, boolean recursive, boolean fix);
+
}
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Mon Mar 3 01:17:36 2008
@@ -701,4 +701,12 @@
bundles.put(bundle);
}
}
+
+ /**
+ * This implementation does nothing.
+ *
+ * {@inheritDoc}
+ */
+ public void checkConsistency(String[] uuids, boolean recursive, boolean fix) {
+ }
}
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Mon Mar 3 01:17:36 2008
@@ -16,32 +16,6 @@
*/
package org.apache.jackrabbit.core.persistence.bundle;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.jackrabbit.util.Text;
-import org.apache.jackrabbit.core.state.ChangeLog;
-import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.NoSuchItemStateException;
-import org.apache.jackrabbit.core.state.NodeReferencesId;
-import org.apache.jackrabbit.core.state.NodeReferences;
-import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
-import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager;
-import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
-import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
-import org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding;
-import org.apache.jackrabbit.core.persistence.bundle.util.ErrorHandling;
-import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
-import org.apache.jackrabbit.core.persistence.util.Serializer;
-import org.apache.jackrabbit.core.persistence.util.BLOBStore;
-import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
-import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
-import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.uuid.UUID;
-
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -66,6 +40,32 @@
import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
+import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager;
+import org.apache.jackrabbit.core.persistence.PMContext;
+import org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding;
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager;
+import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.ErrorHandling;
+import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
+import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
+import org.apache.jackrabbit.core.persistence.util.BLOBStore;
+import org.apache.jackrabbit.core.persistence.util.FileSystemBLOBStore;
+import org.apache.jackrabbit.core.persistence.util.Serializer;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.uuid.UUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* This is a generic persistence manager that stores the {@link NodePropBundle}s
* in a database.
@@ -562,7 +562,8 @@
initialized = true;
if (consistencyCheck) {
- checkConsistency();
+ // check all bundles
+ checkConsistency(null, true, consistencyFix);
}
}
@@ -651,105 +652,209 @@
throws Exception {
return new DbBlobStore();
}
+
+ /**
+ * 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 true, 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 modifications) {
+ //log.info(name + ": checking bundle '" + id + "'");
+
+ // look at the node's children
+ Collection missingChildren = new ArrayList();
+ Iterator iter = bundle.getChildNodeEntries().iterator();
+ while (iter.hasNext()) {
+ NodePropBundle.ChildNodeEntry entry = (NodePropBundle.ChildNodeEntry) iter.next();
+
+ // skip check for system nodes (root, system root, version storage, nodetypes)
+ if (entry.getId().toString().endsWith("babecafebabe")) {
+ continue;
+ }
+ if (id.toString().endsWith("babecafebabe")) {
+ continue;
+ }
+
+ try {
+ // analyze child node bundles
+ NodePropBundle child = loadBundle(entry.getId(), true);
+ if (child == null) {
+ log.error("NodeState '" + id + "' references inexistent child '" + entry.getName() + "' with id '" + entry.getId() + "'");
+ missingChildren.add(entry);
+ } else {
+ NodeId cp = child.getParentId();
+ if (cp == null) {
+ log.error("ChildNode has invalid parent uuid: <null>");
+ } else if (!cp.equals(id)) {
+ log.error("ChildNode has invalid parent uuid: '" + cp + "' (instead of '" + id + "')");
+ }
+ }
+ } catch (ItemStateException e) {
+ // problem already logged (loadBundle called with logDetailedErrors=true)
+ }
+ }
+ // remove child node entry (if fixing is enabled)
+ if (fix && !missingChildren.isEmpty()) {
+ Iterator iterator = missingChildren.iterator();
+ while (iterator.hasNext()) {
+ bundle.getChildNodeEntries().remove(iterator.next());
+ }
+ 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")) {
+ if (!existsBundle(parentId)) {
+ log.error("NodeState '" + id + "' references inexistent parent uuid '" + parentId + "'");
+ }
+ }
+ } catch (ItemStateException e) {
+ log.error("Error reading node '" + parentId + "' (parent of '" + id + "'): " + e);
+ }
+ }
/**
- * Performs a consistency check.
+ * {@inheritDoc}
*/
- private void checkConsistency() {
+ public void checkConsistency(String[] uuids, boolean recursive, boolean fix) {
+
+ log.info("{}: checking workspace consistency...", name);
+
int count = 0;
int total = 0;
- log.info("{}: checking workspace consistency...", name);
-
Collection modifications = new ArrayList();
- ResultSet rs = null;
- DataInputStream din = null;
- try {
- String sql;
- if (getStorageModel() == SM_BINARY_KEYS) {
- sql = "select NODE_ID, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
- } else {
- sql = "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
- }
- Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
- rs = stmt.getResultSet();
- while (rs.next()) {
- NodeId id;
- Blob blob;
+
+ if (uuids == null) {
+ // 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;
+ DataInputStream din = null;
+ try {
+ String sql;
if (getStorageModel() == SM_BINARY_KEYS) {
- id = new NodeId(new UUID(rs.getBytes(1)));
- blob = rs.getBlob(2);
+ sql = "select NODE_ID, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
} else {
- id = new NodeId(new UUID(rs.getLong(1), rs.getLong(2)));
- blob = rs.getBlob(3);
+ sql = "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
}
- din = new DataInputStream(blob.getBinaryStream());
- try {
- NodePropBundle bundle = binding.readBundle(din, id);
- Collection missingChildren = new ArrayList();
- Iterator iter = bundle.getChildNodeEntries().iterator();
- while (iter.hasNext()) {
- NodePropBundle.ChildNodeEntry entry = (NodePropBundle.ChildNodeEntry) iter.next();
- if (entry.getId().toString().endsWith("babecafebabe")) {
- continue;
- }
- if (id.toString().endsWith("babecafebabe")) {
- continue;
- }
- try {
- NodePropBundle child = loadBundle(entry.getId());
- if (child == null) {
- log.error("NodeState " + id.getUUID() + " references unexistent child " + entry.getName() + " with id " + entry.getId().getUUID());
- missingChildren.add(entry);
- } else {
- NodeId cp = child.getParentId();
- if (cp == null) {
- log.error("ChildNode has invalid parent uuid: null");
- } else if (!cp.equals(id)) {
- log.error("ChildNode has invalid parent uuid: " + cp + " (instead of " + id.getUUID() + ")");
- }
- }
- } catch (ItemStateException e) {
- log.error("Error while loading child node: " + e);
- }
+ Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
+ rs = stmt.getResultSet();
+
+ // iterate over all nodebundles in the db
+ while (rs.next()) {
+ NodeId id;
+ Blob blob;
+ if (getStorageModel() == SM_BINARY_KEYS) {
+ id = new NodeId(new UUID(rs.getBytes(1)));
+ blob = rs.getBlob(2);
+ } else {
+ id = new NodeId(new UUID(rs.getLong(1), rs.getLong(2)));
+ blob = rs.getBlob(3);
}
- if (consistencyFix && !missingChildren.isEmpty()) {
- Iterator iterator = missingChildren.iterator();
- while (iterator.hasNext()) {
- bundle.getChildNodeEntries().remove(iterator.next());
+ din = new DataInputStream(blob.getBinaryStream());
+ try {
+ // parse and check bundle
+
+ // check bundle will log any problems itself
+ if (binding.checkBundle(din)) {
+ // reset stream for readBundle()
+ din = new DataInputStream(blob.getBinaryStream());
+
+ NodePropBundle bundle = binding.readBundle(din, id);
+
+ checkBundleConsistency(id, bundle, fix, modifications);
+ } else {
+ log.error("invalid bundle '" + id + "', see previous BundleBinding error log entry");
}
- modifications.add(bundle);
+
+ } catch (Exception e) {
+ log.error("Error in bundle " + id + ": " + e);
}
-
- NodeId parentId = bundle.getParentId();
- if (parentId != null) {
- if (!exists(parentId)) {
- log.error("NodeState " + id + " references unexistent parent id " + parentId);
- }
+ count++;
+ if (count % 1000 == 0) {
+ log.info(name + ": checked " + count + " bundles...");
}
- } catch (IOException e) {
- log.error("Error in bundle " + id + ": " + e);
- din = new DataInputStream(blob.getBinaryStream());
- binding.checkBundle(din);
}
- count++;
- if (count % 1000 == 0) {
- log.info(name + ": checked " + count + "/" + total + " bundles...");
+ } catch (Exception e) {
+ log.error("Error loading bundle", e);
+ } finally {
+ closeStream(din);
+ closeResultSet(rs);
+ 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 uuidList = new ArrayList(recursive ? uuids.length*3 : uuids.length);
+ // convert uuid string array to list of UUID objects
+ for (int i=0; i < uuids.length; i++) {
+ try {
+ uuidList.add(new UUID(uuids[i]));
+ } catch (IllegalArgumentException e) {
+ log.error("Invalid uuid for consistency check, skipping: '" + uuids[i] + "': " + e);
}
}
- } catch (Exception e) {
- log.error("Error in bundle", e);
- } finally {
- closeStream(din);
- closeResultSet(rs);
+
+ // iterate over UUIDs (including ones that are newly added inside the loop!)
+ for (int i=0; i < uuidList.size(); i++) {
+ final UUID uuid = (UUID) uuidList.get(i);
+ try {
+ // load the node from the database
+ NodeId id = new NodeId(uuid);
+ NodePropBundle bundle = loadBundle(id, true);
+
+ if (bundle == null) {
+ log.error("No bundle found for uuid '" + uuid + "'");
+ continue;
+ }
+
+ checkBundleConsistency(id, bundle, fix, modifications);
+
+ if (recursive) {
+ Iterator iter = bundle.getChildNodeEntries().iterator();
+ while (iter.hasNext()) {
+ NodePropBundle.ChildNodeEntry entry = (NodePropBundle.ChildNodeEntry) iter.next();
+ uuidList.add(entry.getId().getUUID());
+ }
+ }
+
+ count++;
+ if (count % 1000 == 0) {
+ log.info(name + ": checked " + count + "/" + uuidList.size() + " bundles...");
+ }
+ } catch (ItemStateException e) {
+ // problem already logged (loadBundle called with logDetailedErrors=true)
+ }
+ }
+
+ total = uuidList.size();
}
-
- if (consistencyFix && !modifications.isEmpty()) {
+
+ // repair collected broken bundles
+ if (fix && !modifications.isEmpty()) {
log.info(name + ": Fixing " + modifications.size() + " inconsistent bundle(s)...");
Iterator iterator = modifications.iterator();
while (iterator.hasNext()) {
NodePropBundle bundle = (NodePropBundle) iterator.next();
try {
- log.info(name + ": Fixing bundle " + bundle.getId());
+ log.info(name + ": Fixing bundle '" + bundle.getId() + "'");
bundle.markOld(); // use UPDATE instead of INSERT
storeBundle(bundle);
} catch (ItemStateException e) {
@@ -760,8 +865,7 @@
log.info(name + ": checked " + count + "/" + total + " bundles.");
}
-
-
+
/**
* Makes sure that <code>schemaObjectPrefix</code> does only consist of
* characters that are allowed in names on the target database. Illegal
@@ -887,8 +991,25 @@
*/
protected synchronized NodePropBundle loadBundle(NodeId id)
throws ItemStateException {
+ return loadBundle(id, false);
+ }
+
+ /**
+ * Loads a bundle from the underlying system and optionally performs
+ * a check on the bundle first.
+ *
+ * @param id the node id of the bundle
+ * @param checkBeforeLoading check the bundle before loading it and log
+ * detailed informations about it (slower)
+ * @return the loaded bundle or <code>null</code> if the bundle does not
+ * exist.
+ * @throws ItemStateException if an error while loading occurs.
+ */
+ protected synchronized NodePropBundle loadBundle(NodeId id, boolean checkBeforeLoading)
+ throws ItemStateException {
ResultSet rs = null;
InputStream in = null;
+ byte[] bytes = null;
try {
Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
rs = stmt.getResultSet();
@@ -898,13 +1019,24 @@
Blob b = rs.getBlob(1);
// JCR-1039: pre-fetch/buffer blob data
long length = b.length();
- byte[] bytes = new byte[(int) length];
+ bytes = new byte[(int) length];
in = b.getBinaryStream();
int read, pos = 0;
while ((read = in.read(bytes, pos, bytes.length - pos)) > 0) {
pos += read;
}
DataInputStream din = new DataInputStream(new ByteArrayInputStream(bytes));
+
+ if (checkBeforeLoading) {
+ if (binding.checkBundle(din)) {
+ // reset stream for readBundle()
+ din = new DataInputStream(new ByteArrayInputStream(bytes));
+ } else {
+ // gets wrapped as proper ItemStateException below
+ throw new Exception("invalid bundle, see previous BundleBinding error log entry");
+ }
+ }
+
NodePropBundle bundle = binding.readBundle(din, id);
bundle.setSize(length);
return bundle;
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Mon Mar 3 01:17:36 2008
@@ -196,6 +196,14 @@
public DynamicESCFactory getEscFactory() {
return escFactory;
}
+
+ /**
+ * Returns the persistence manager used by the version manager.
+ * @return the persistence manager used by the version manager
+ */
+ public PersistenceManager getPersistenceManager() {
+ return pMgr;
+ }
/**
* {@inheritDoc}
Modified: jackrabbit/branches/1.3/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/TestAll.java?rev=632996&r1=632995&r2=632996&view=diff
==============================================================================
--- jackrabbit/branches/1.3/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/TestAll.java (original)
+++ jackrabbit/branches/1.3/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/persistence/TestAll.java Mon Mar 3 01:17:36 2008
@@ -36,6 +36,7 @@
public static Test suite() {
TestSuite suite = new TestSuite("Persistence tests");
+ suite.addTestSuite(ConsistencyCheckTest.class);
suite.addTestSuite(DatabaseConnectionFailureTest.class);
return suite;