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);
                 }
             }


Reply via email to