You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2011/02/01 16:03:27 UTC

svn commit: r1066059 - /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java

Author: jukka
Date: Tue Feb  1 15:03:26 2011
New Revision: 1066059

URL: http://svn.apache.org/viewvc?rev=1066059&view=rev
Log:
JCR-2855: Writers blocked forever when waiting on update operations

Automatically clear a downgraded activeWriterId when the last reader lock is released.

Also add generics.

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java?rev=1066059&r1=1066058&r2=1066059&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/FineGrainedISMLocking.java Tue Feb  1 15:03:26 2011
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
@@ -65,17 +66,23 @@ public class FineGrainedISMLocking imple
     private final LockMap readLockMap = new LockMap();
 
     /**
+     * Number of current readers.
+     */
+    private final AtomicInteger readerCount = new AtomicInteger(0);
+
+    /**
      * List of waiting readers that are blocked because they conflict with
      * the current writer.
      */
-    private List waitingReaders = Collections.synchronizedList(new LinkedList());
+    private List<Sync> waitingReaders =
+        Collections.synchronizedList(new LinkedList<Sync>());
 
     /**
      * List of waiting writers that are blocked because there is already a
      * current writer or one of the current reads conflicts with the change log
      * of the blocked writer.
      */
-    private List waitingWriters = new LinkedList();
+    private List<Sync> waitingWriters = new LinkedList<Sync>();
 
     /**
      * {@inheritDoc}
@@ -84,6 +91,7 @@ public class FineGrainedISMLocking imple
             throws InterruptedException {
         if (isSameThreadId(activeWriterId, getCurrentThreadId())) {
             // we hold the write lock
+            readerCount.incrementAndGet();
             readLockMap.addLock(id);
             return new ReadLockImpl(id);
         }
@@ -98,6 +106,7 @@ public class FineGrainedISMLocking imple
             try {
                 if (activeWriter == null
                         || !hasDependency(activeWriter.changes, id)) {
+                    readerCount.incrementAndGet();
                     readLockMap.addLock(id);
                     return new ReadLockImpl(id);
                 } else {
@@ -176,6 +185,7 @@ public class FineGrainedISMLocking imple
         }
 
         public ReadLock downgrade() {
+            readerCount.incrementAndGet();
             readLockMap.addLock(null);
             Sync exclusive = writerStateRWLock.writeLock();
             for (;;) {
@@ -226,6 +236,9 @@ public class FineGrainedISMLocking imple
             }
             try {
                 readLockMap.removeLock(id);
+                if (readerCount.decrementAndGet() == 0 && activeWriter == null) {
+                    activeWriterId = null;
+                }
                 if (!isSameThreadId(activeWriterId, getCurrentThreadId())) {
                     // only notify waiting writers if we do *not* hold a write
                     // lock at the same time. that would be a waste of cpu time.
@@ -256,9 +269,9 @@ public class FineGrainedISMLocking imple
      * only one thread calls this method at a time.
      */
     private void notifyWaitingReaders() {
-        Iterator it = waitingReaders.iterator();
+        Iterator<Sync> it = waitingReaders.iterator();
         while (it.hasNext()) {
-            ((Sync) it.next()).release();
+            it.next().release();
             it.remove();
         }
     }
@@ -271,9 +284,9 @@ public class FineGrainedISMLocking imple
             if (waitingWriters.isEmpty()) {
                 return;
             }
-            Iterator it = waitingWriters.iterator();
+            Iterator<Sync> it = waitingWriters.iterator();
             while (it.hasNext()) {
-                ((Sync) it.next()).release();
+                it.next().release();
                 it.remove();
             }
         }
@@ -284,7 +297,8 @@ public class FineGrainedISMLocking imple
         /**
          * 16 slots
          */
-        private final Map[] slots = new Map[0x10];
+        @SuppressWarnings("unchecked")
+        private final Map<ItemId, Integer>[] slots = new Map[0x10];
 
         /**
          * Flag that indicates if the entire map is locked.
@@ -293,7 +307,7 @@ public class FineGrainedISMLocking imple
 
         public LockMap() {
             for (int i = 0; i < slots.length; i++) {
-                slots[i] = new HashMap();
+                slots[i] = new HashMap<ItemId, Integer>();
             }
         }
 
@@ -312,7 +326,7 @@ public class FineGrainedISMLocking imple
                 global = true;
                 return;
             }
-            Map locks = slots[slotIndex(id)];
+            Map<ItemId, Integer> locks = slots[slotIndex(id)];
             synchronized (locks) {
                 Integer i = (Integer) locks.get(id);
                 if (i == null) {
@@ -339,7 +353,7 @@ public class FineGrainedISMLocking imple
                 global = false;
                 return;
             }
-            Map locks = slots[slotIndex(id)];
+            Map<ItemId, Integer> locks = slots[slotIndex(id)];
             synchronized (locks) {
                 Integer i = (Integer) locks.get(id);
                 if (i != null) {
@@ -370,14 +384,10 @@ public class FineGrainedISMLocking imple
                 return true;
             }
             for (int i = 0; i < slots.length; i++) {
-                Map locks = slots[i];
-                if (!locks.isEmpty()) {
-                    Iterator it = locks.keySet().iterator();
-                    while (it.hasNext()) {
-                        ItemId id = (ItemId) it.next();
-                        if (FineGrainedISMLocking.hasDependency(changes, id)) {
-                            return true;
-                        }
+                Map<ItemId, Integer> locks = slots[i];
+                for (ItemId id : locks.keySet()) {
+                    if (FineGrainedISMLocking.hasDependency(changes, id)) {
+                        return true;
                     }
                 }
             }