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