Author: reschke
Date: Mon Sep 10 12:46:55 2018
New Revision: 1840462

URL: http://svn.apache.org/viewvc?rev=1840462&view=rev
Log:
OAK-7709: DocumentNodeStore dispose aborts when store was disposed due to 
LeaseUpdate error

Modified:
    
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.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/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=1840462&r1=1840461&r2=1840462&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 Sep 10 12:46:55 2018
@@ -719,19 +719,28 @@ public final class DocumentNodeStore
                 backgroundUpdateThread,
                 backgroundSweepThread);
 
+        DocumentStoreException ex = null;
+
         // create a tombstone commit revision after isDisposed is set to true.
         // commits created earlier than this revision will be able to finish
         // and we'll get a headOfQueue() callback when they are done
         // after this call there are no more pending trunk commits and
         // the commit queue is empty and stays empty
-        Revision tombstone = commitQueue.createRevision();
-        commitQueue.done(tombstone, new CommitQueue.Callback() {
-            @Override
-            public void headOfQueue(@NotNull Revision revision) {
-                setRoot(getHeadRevision().update(revision));
-                unsavedLastRevisions.put(ROOT_PATH, revision);
+        if (!readOnlyMode) {
+            try {
+                Revision tombstone = commitQueue.createRevision();
+                commitQueue.done(tombstone, new CommitQueue.Callback() {
+                    @Override
+                    public void headOfQueue(@NotNull Revision revision) {
+                        setRoot(getHeadRevision().update(revision));
+                        unsavedLastRevisions.put(ROOT_PATH, revision);
+                    }
+                });
+            } catch (DocumentStoreException e) {
+                LOG.error("dispose: a DocumentStoreException happened during 
dispose's attempt to commit a tombstone: " + e, e);
+                ex = e;
             }
-        });
+        }
 
         try {
             bundlingConfigHandler.close();
@@ -739,7 +748,6 @@ public final class DocumentNodeStore
             LOG.warn("Error closing bundlingConfigHandler", 
bundlingConfigHandler, e);
         }
 
-        DocumentStoreException ex = null;
         // do a final round of background operations after
         // the background thread stopped
         if (!readOnlyMode) {

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=1840462&r1=1840461&r2=1840462&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 Sep 10 12:46:55 2018
@@ -762,6 +762,41 @@ public class DocumentNodeStoreTest {
         
assertTrue(store2.getRoot().getChildNode("test").getChildNode("node").exists());
     }
 
+    // verify that the dispose method does a best effort in releasing 
resources (see OAK-7709)
+    @Test
+    public void disposeAfterLeaseFailure() throws Exception {
+        try {
+            final AtomicBoolean documentStoreDisposeWasReached = new 
AtomicBoolean(false);
+            Clock clock = new Clock.Virtual();
+            clock.waitUntil(System.currentTimeMillis());
+
+            MemoryDocumentStore docStore = new MemoryDocumentStore() {
+                @Override
+                public void dispose() {
+                    documentStoreDisposeWasReached.set(true);
+                }
+            };
+
+            DocumentNodeStore store1 = 
builderProvider.newBuilder().setDocumentStore(docStore).setAsyncDelay(0).clock(clock)
+                    .setClusterId(1).getNodeStore();
+
+            ClusterNodeInfo.setClock(clock);
+            // wait until lease expires
+            clock.waitUntil(clock.getTime() + 
store1.getClusterInfo().getLeaseTime() + 1000);
+
+            assertFalse(documentStoreDisposeWasReached.get());
+            try {
+                store1.dispose();
+                fail("expected lease failure exception; test setup may be 
incorrect");
+            } catch (DocumentStoreException expected) {
+                // due to lease update failure
+            }
+            assertTrue("The DocumentStore instance's dispose() method was not 
called", documentStoreDisposeWasReached.get());
+        } finally {
+            ClusterNodeInfo.resetClockToDefault();
+        }
+    }
+
     // OAK-2336
     @Test
     public void readBranchCommit() throws Exception {


Reply via email to