Author: mreutegg
Date: Tue Nov  3 15:53:36 2015
New Revision: 1712313

URL: http://svn.apache.org/viewvc?rev=1712313&view=rev
Log:
OAK-3579: BackgroundLeaseUpdate not scheduled when asyncDelay=0

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1712313&r1=1712312&r2=1712313&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
 Tue Nov  3 15:53:36 2015
@@ -68,6 +68,8 @@ import javax.management.NotCompliantMBea
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
 import com.google.common.cache.Cache;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
@@ -2561,18 +2563,35 @@ public final class DocumentNodeStore
     static abstract class NodeStoreTask implements Runnable {
         final WeakReference<DocumentNodeStore> ref;
         private final AtomicBoolean isDisposed;
-        private int delay;
+        private final Supplier<Integer> delaySupplier;
 
-        NodeStoreTask(DocumentNodeStore nodeStore, AtomicBoolean isDisposed) {
-            ref = new WeakReference<DocumentNodeStore>(nodeStore);
-            delay = nodeStore.getAsyncDelay();
+        NodeStoreTask(final DocumentNodeStore nodeStore,
+                      final AtomicBoolean isDisposed,
+                      Supplier<Integer> delay) {
+            this.ref = new WeakReference<DocumentNodeStore>(nodeStore);
             this.isDisposed = isDisposed;
+            if (delay == null) {
+                delay = new Supplier<Integer>() {
+                    @Override
+                    public Integer get() {
+                        DocumentNodeStore ns = ref.get();
+                        return ns != null ? ns.getAsyncDelay() : 0;
+                    }
+                };
+            }
+            this.delaySupplier = delay;
+        }
+
+        NodeStoreTask(final DocumentNodeStore nodeStore,
+                      final AtomicBoolean isDisposed) {
+            this(nodeStore, isDisposed, null);
         }
 
         protected abstract void execute(@Nonnull DocumentNodeStore nodeStore);
 
         @Override
         public void run() {
+            int delay = delaySupplier.get();
             while (delay != 0 && !isDisposed.get()) {
                 synchronized (isDisposed) {
                     try {
@@ -2588,7 +2607,7 @@ public final class DocumentNodeStore
                     } catch (Throwable t) {
                         LOG.warn("Background operation failed: " + 
t.toString(), t);
                     }
-                    delay = nodeStore.getAsyncDelay();
+                    delay = delaySupplier.get();
                 } else {
                     // node store not in use anymore
                     break;
@@ -2633,7 +2652,7 @@ public final class DocumentNodeStore
 
         BackgroundLeaseUpdate(DocumentNodeStore nodeStore,
                               AtomicBoolean isDisposed) {
-            super(nodeStore, isDisposed);
+            super(nodeStore, isDisposed, Suppliers.ofInstance(1000));
         }
 
         @Override

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java?rev=1712313&r1=1712312&r2=1712313&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStoreTest.java
 Tue Nov  3 15:53:36 2015
@@ -27,11 +27,15 @@ import static org.apache.jackrabbit.oak.
 import static 
org.apache.jackrabbit.oak.plugins.document.NodeDocument.getModifiedInSecs;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -40,6 +44,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
@@ -1621,6 +1626,47 @@ public class DocumentNodeStoreTest {
 
     }
 
+    // OAK-3579
+    @Test
+    public void backgroundLeaseUpdateThread() throws Exception {
+        int clusterId = -1;
+        Random random = new Random();
+        // pick a random clusterId between 1000 and 2000
+        // and make sure it is not in use (give up after 10 tries)
+        for (int i = 0; i < 10; i++) {
+            int id = random.nextInt(1000) + 1000;
+            if (!backgroundLeaseUpdateThreadRunning(id)) {
+                clusterId = id;
+                break;
+            }
+        }
+        assertNotEquals(-1, clusterId);
+        DocumentNodeStore ns = builderProvider.newBuilder().setAsyncDelay(0)
+                .setClusterId(clusterId).getNodeStore();
+        for (int i = 0; i < 10; i++) {
+            if (!backgroundLeaseUpdateThreadRunning(clusterId)) {
+                Thread.sleep(100);
+            }
+        }
+        assertTrue(backgroundLeaseUpdateThreadRunning(clusterId));
+        // access DocumentNodeStore to make sure it is not
+        // garbage collected prematurely
+        assertEquals(clusterId, ns.getClusterId());
+    }
+
+    private static boolean backgroundLeaseUpdateThreadRunning(int clusterId) {
+        String threadName = "DocumentNodeStore lease update thread (" + 
clusterId + ")";
+        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+        for (ThreadInfo ti : 
threadBean.getThreadInfo(threadBean.getAllThreadIds())) {
+            if (ti != null) {
+                if (threadName.equals(ti.getThreadName())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * Utility class that eases creating single cluster id merge conflicts. 
The two methods:
      * <ul>


Reply via email to