Author: mduerig
Date: Wed Aug 28 14:52:05 2013
New Revision: 1518226

URL: http://svn.apache.org/r1518226
Log:
OAK-959: Deadlock between ChangeDispatcher and SegmentNodeStoreService
Use explicit lock in ChangeDispatcher instead of object monitor. Try to acquire 
lock for getting external changes and do nothing if this fails to avoid dead 
locking with incoming changes.

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java?rev=1518226&r1=1518225&r2=1518226&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
 Wed Aug 28 14:52:05 2013
@@ -24,6 +24,8 @@ import static org.apache.jackrabbit.oak.
 
 import java.util.Queue;
 import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
@@ -52,6 +54,7 @@ import org.apache.jackrabbit.oak.spi.sta
 public class ChangeDispatcher {
     private final NodeStore store;
     private final Set<Listener> listeners = Sets.newHashSet();
+    private final Lock changeLock = new ReentrantLock();
 
     private NodeState previousRoot;
 
@@ -91,10 +94,15 @@ public class ChangeDispatcher {
         return listener;
     }
 
-    private synchronized void contentChanged(@Nonnull NodeState before, 
@Nonnull NodeState after,
+    private void contentChanged(@Nonnull NodeState before, @Nonnull NodeState 
after,
             ContentSession contentSession) {
-        externalChange(checkNotNull(before));
-        internalChange(checkNotNull(after), contentSession);
+        changeLock.lock();
+        try {
+            externalChange(checkNotNull(before));
+            internalChange(checkNotNull(after), contentSession);
+        } finally {
+            changeLock.unlock();
+        }
     }
 
     private void externalChange(NodeState root) {
@@ -109,8 +117,14 @@ public class ChangeDispatcher {
         previousRoot = root;
     }
 
-    private synchronized void externalChange() {
-        externalChange(store.getRoot());
+    private void externalChange() {
+        if (changeLock.tryLock()) {
+            try {
+                externalChange(store.getRoot());
+            } finally {
+                changeLock.unlock();
+            }
+        }
     }
 
     private void register(Listener listener) {


Reply via email to