Author: mreutegg
Date: Mon Mar 5 10:36:01 2018
New Revision: 1825863
URL: http://svn.apache.org/viewvc?rev=1825863&view=rev
Log:
OAK-7286: DocumentNodeStoreBranch handling of non-recoverable
DocumentStoreExceptions
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ConflictException.java
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Commit.java
Mon Mar 5 10:36:01 2018
@@ -228,7 +228,8 @@ public class Commit {
/**
* Apply the changes to the document store and the cache.
*/
- private void applyInternal() {
+ private void applyInternal()
+ throws ConflictException, DocumentStoreException {
if (!operations.isEmpty()) {
updateParentChildStatus();
updateBinaryStatus();
@@ -236,7 +237,8 @@ public class Commit {
}
}
- private void prepare(RevisionVector baseRevision) {
+ private void prepare(RevisionVector baseRevision)
+ throws ConflictException, DocumentStoreException {
if (!operations.isEmpty()) {
updateParentChildStatus();
updateBinaryStatus();
@@ -262,7 +264,7 @@ public class Commit {
/**
* Apply the changes to the document store.
*/
- void applyToDocumentStore() {
+ void applyToDocumentStore() throws ConflictException,
DocumentStoreException {
applyToDocumentStore(null);
}
@@ -271,11 +273,12 @@ public class Commit {
*
* @param baseBranchRevision the base revision of this commit. Currently
only
* used for branch commits.
+ * @throws ConflictException if a conflict is detected with another commit.
* @throws DocumentStoreException if an error occurs while writing to the
* underlying store.
*/
private void applyToDocumentStore(RevisionVector baseBranchRevision)
- throws DocumentStoreException {
+ throws ConflictException, DocumentStoreException {
// initially set the rollbackFailed flag to true
// the flag will be set to false at the end of the method
// when the commit succeeds
@@ -370,15 +373,13 @@ public class Commit {
String msg = "Conflicting concurrent change. " +
"Update operation failed: " + commitRoot;
NodeDocument commitRootDoc = store.find(NODES,
commitRoot.getId());
- DocumentStoreException dse;
if (commitRootDoc == null) {
- dse = new DocumentStoreException(msg);
+ throw new DocumentStoreException(msg);
} else {
- dse = new ConflictException(msg,
+ throw new ConflictException(msg,
commitRootDoc.getConflictsFor(
Collections.singleton(revision)));
}
- throw dse;
} else {
success = true;
// if we get here the commit was successful and
@@ -409,7 +410,11 @@ public class Commit {
// and throw the original exception
LOG.warn("Rollback failed", ex);
}
- throw DocumentStoreException.convert(e);
+ if (e instanceof ConflictException) {
+ throw e;
+ } else {
+ throw DocumentStoreException.convert(e);
+ }
}
} finally {
if (success) {
@@ -500,12 +505,15 @@ public class Commit {
/**
* Try to create or update the node. If there was a conflict, this method
- * throws an exception, even though the change is still applied.
+ * throws a {@link ConflictException}, even though the change is still
applied.
*
* @param store the store
* @param op the operation
+ * @throws ConflictException if there was a conflict introduced by the
+ * given update operation.
*/
- private void createOrUpdateNode(DocumentStore store, UpdateOp op) {
+ private void createOrUpdateNode(DocumentStore store, UpdateOp op)
+ throws ConflictException, DocumentStoreException {
NodeDocument doc = store.createOrUpdate(NODES, op);
checkConflicts(op, doc);
checkSplitCandidate(doc);
@@ -618,7 +626,8 @@ public class Commit {
}
private void checkConflicts(List<NodeDocument> oldDocs,
- List<UpdateOp> updates) {
+ List<UpdateOp> updates)
+ throws ConflictException {
int i = 0;
List<ConflictException> exceptions = new
ArrayList<ConflictException>();
Set<Revision> revisions = new HashSet<Revision>();
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ConflictException.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ConflictException.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ConflictException.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ConflictException.java
Mon Mar 5 10:36:01 2018
@@ -27,11 +27,11 @@ import java.util.Collections;
import java.util.Set;
/**
- * A document store exception with an optional conflict revision. The
- * DocumentNodeStore implementation will throw this exception when a commit
- * or merge fails with a conflict.
+ * An exception with an optional conflict revision. The DocumentNodeStore
+ * implementation will throw this exception when a commit or merge fails with a
+ * conflict.
*/
-class ConflictException extends DocumentStoreException {
+class ConflictException extends Exception {
private static final long serialVersionUID = 1418838561903727231L;
@@ -85,7 +85,7 @@ class ConflictException extends Document
/**
* List of conflict revisions.
- *
+ *
* @return a list of conflict revisions (may be empty)
*/
@Nonnull
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
Mon Mar 5 10:36:01 2018
@@ -612,7 +612,11 @@ public final class DocumentNodeStore
RevisionVector head = new RevisionVector(commitRev);
DocumentNodeState n = new DocumentNodeState(this, "/", head);
commit.addNode(n);
- commit.applyToDocumentStore();
+ try {
+ commit.applyToDocumentStore();
+ } catch (ConflictException e) {
+ throw new IllegalStateException("Conflict while creating root
document", e);
+ }
unsavedLastRevisions.put("/", commitRev);
sweepRevisions = sweepRevisions.pmax(new
RevisionVector(commitRev));
setRoot(head);
@@ -1686,7 +1690,7 @@ public final class DocumentNodeStore
@Nonnull
RevisionVector merge(@Nonnull RevisionVector branchHead,
@Nonnull CommitInfo info)
- throws CommitFailedException {
+ throws ConflictException, CommitFailedException {
Branch b = getBranches().getBranch(branchHead);
RevisionVector base = branchHead;
if (b != null) {
@@ -1721,7 +1725,7 @@ public final class DocumentNodeStore
NodeDocument root = Utils.getRootDocument(store);
Set<Revision> conflictRevs =
root.getConflictsFor(b.getCommits());
String msg = "Conflicting concurrent change. Update
operation failed: " + op;
- throw new ConflictException(msg,
conflictRevs).asCommitFailedException();
+ throw new ConflictException(msg, conflictRevs);
}
} else {
// no commits in this branch -> do nothing
Modified:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreBranch.java
Mon Mar 5 10:36:01 2018
@@ -256,19 +256,21 @@ class DocumentNodeStoreBranch implements
/**
* Persists the changes between {@code toPersist} and {@code base}
* to the underlying store.
- * <p>
- * While this method does not declare any exceptions to be thrown, an
- * implementation may still throw a runtime exception specific to the
- * concrete implementation of this node store branch.
*
* @param toPersist the state with the changes on top of {@code base}.
* @param base the base state.
* @param info the commit info.
* @return the state with the persisted changes.
+ * @throws ConflictException if changes cannot be persisted because a
+ * conflict occurred. The exception may contain the revisions of
+ * the conflicting operations.
+ * @throws DocumentStoreException if the persist operation failed because
+ * of an exception in the underlying {@link DocumentStore}.
*/
private DocumentNodeState persist(final @Nonnull NodeState toPersist,
final @Nonnull DocumentNodeState base,
- final @Nonnull CommitInfo info) {
+ final @Nonnull CommitInfo info)
+ throws ConflictException, DocumentStoreException {
return persist(new Changes() {
@Override
public void with(Commit c) {
@@ -285,10 +287,16 @@ class DocumentNodeStoreBranch implements
* @param base the base state.
* @param info the commit info.
* @return the result state.
+ * @throws ConflictException if changes cannot be persisted because a
+ * conflict occurred. The exception may contain the revisions of
+ * the conflicting operations.
+ * @throws DocumentStoreException if the persist operation failed because
+ * of an exception in the underlying {@link DocumentStore}.
*/
private DocumentNodeState persist(@Nonnull Changes op,
@Nonnull DocumentNodeState base,
- @Nonnull CommitInfo info) {
+ @Nonnull CommitInfo info)
+ throws ConflictException, DocumentStoreException {
boolean success = false;
Commit c = store.newCommit(base.getRootRevision(), this);
RevisionVector rev;
@@ -334,6 +342,14 @@ class DocumentNodeStoreBranch implements
return BRANCHES.get(Thread.currentThread());
}
+ private static CommitFailedException mergeFailed(Throwable t) {
+ String msg = t.getMessage();
+ if (msg == null) {
+ msg = "Failed to merge changes to the underlying store";
+ }
+ return new CommitFailedException(OAK, 1, msg, t);
+ }
+
/**
* Sub classes of this class represent a state a branch can be in. See the
individual
* sub classes for permissible state transitions.
@@ -519,12 +535,8 @@ class DocumentNodeStoreBranch implements
return newHead;
} catch (ConflictException e) {
throw e.asCommitFailedException();
- } catch(DocumentStoreException e) {
- throw new CommitFailedException(MERGE, 1,
- "Failed to merge changes to the underlying store",
e);
- } catch (Exception e) {
- throw new CommitFailedException(OAK, 1,
- "Failed to merge changes to the underlying store",
e);
+ } catch (Throwable t) {
+ throw mergeFailed(t);
}
} finally {
if (lock != null) {
@@ -623,9 +635,8 @@ class DocumentNodeStoreBranch implements
throw e;
} catch (ConflictException e) {
throw e.asCommitFailedException();
- } catch (Exception e) {
- throw new CommitFailedException(MERGE, 1,
- "Failed to merge changes to the underlying store", e);
+ } catch (Throwable t) {
+ throw mergeFailed(t);
} finally {
if (lock != null) {
lock.unlock();
@@ -636,8 +647,13 @@ class DocumentNodeStoreBranch implements
}
}
- private void persistTransientHead(NodeState newHead) {
- head = DocumentNodeStoreBranch.this.persist(newHead, head,
CommitInfo.EMPTY);
+ private void persistTransientHead(NodeState newHead)
+ throws DocumentStoreException {
+ try {
+ head = DocumentNodeStoreBranch.this.persist(newHead, head,
CommitInfo.EMPTY);
+ } catch (ConflictException e) {
+ throw DocumentStoreException.convert(e);
+ }
numCommits++;
store.getStatsCollector().doneBranchCommit();
}
Modified:
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/CommitTest.java
Mon Mar 5 10:36:01 2018
@@ -67,7 +67,7 @@ public class CommitTest {
try {
c.apply();
ns.done(c, false, CommitInfo.EMPTY);
- } catch (DocumentStoreException e) {
+ } catch (ConflictException e) {
// expected
}
} finally {
@@ -101,7 +101,7 @@ public class CommitTest {
c.apply();
ns.done(c, false, CommitInfo.EMPTY);
fail("commit must fail");
- } catch (DocumentStoreException e) {
+ } catch (ConflictException e) {
// expected
assertTrue("Unexpected exception message: " + e.getMessage(),
e.getMessage().contains("older than base"));
Modified:
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentMK.java
Mon Mar 5 10:36:01 2018
@@ -217,8 +217,8 @@ public class DocumentMK {
commit.apply();
rev = nodeStore.done(commit, isBranch, CommitInfo.EMPTY);
success = true;
- } catch (DocumentStoreException e) {
- throw new DocumentStoreException(e);
+ } catch (Exception e) {
+ throw DocumentStoreException.convert(e);
} finally {
if (!success) {
nodeStore.canceled(commit);
@@ -243,10 +243,8 @@ public class DocumentMK {
}
try {
return nodeStore.merge(revision, CommitInfo.EMPTY).toString();
- } catch (DocumentStoreException e) {
- throw new DocumentStoreException(e);
- } catch (CommitFailedException e) {
- throw new DocumentStoreException(e);
+ } catch (Exception e) {
+ throw DocumentStoreException.convert(e);
}
}
Modified:
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1825863&r1=1825862&r2=1825863&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
(original)
+++
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
Mon Mar 5 10:36:01 2018
@@ -296,7 +296,7 @@ public class DocumentNodeStoreTest {
c.addNode(new DocumentNodeState(store, "/deletedNode", new
RevisionVector(r)));
c.updateProperty("/updateNode", "foo", "baz");
c.apply();
- } catch (DocumentStoreException e) {
+ } catch (Exception e) {
exceptions.add(e);
}
}