[infinispan-commits] Infinispan SVN: r1141 - in trunk/core/src: main/java/org/infinispan/container/entries and 1 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Nov 11 14:29:25 EST 2009
Author: manik.surtani at jboss.com
Date: 2009-11-11 14:29:25 -0500 (Wed, 11 Nov 2009)
New Revision: 1141
Modified:
trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
trunk/core/src/main/java/org/infinispan/container/entries/RepeatableReadEntry.java
trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/WriteSkewTest.java
Log:
[ISPN-259] (Concurrent puts fail with writeSkew) - Fixed incorrect write skew check routine in RepeatableReadEntry
Modified: trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2009-11-11 19:21:00 UTC (rev 1140)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2009-11-11 19:29:25 UTC (rev 1141)
@@ -87,20 +87,20 @@
// do not bother wrapping though if this is not in a tx. repeatable read etc are all meaningless unless there is a tx.
if (useRepeatableRead && ctx.isInTxScope()) {
MVCCEntry mvccEntry = cacheEntry == null ?
- createWrappedEntry(key, null, false, false, -1) :
- createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
- if (mvccEntry != null) ctx.putLookedUpEntry(key, mvccEntry);
- return mvccEntry;
+ createWrappedEntry(key, null, false, false, -1) :
+ createWrappedEntry(key, cacheEntry.getValue(), false, false, cacheEntry.getLifespan());
+ if (mvccEntry != null) ctx.putLookedUpEntry(key, mvccEntry);
+ return mvccEntry;
}
// if not in transaction and repeatable read, or simply read committed (regardless of whether in TX or not), do not wrap
if (cacheEntry != null) ctx.putLookedUpEntry(key, cacheEntry);
- return cacheEntry;
+ return cacheEntry;
} else {
if (trace) log.trace("Key is already in context");
return cacheEntry;
}
}
-
+
public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
return wrapEntryForWriting(ctx, key, null, createIfAbsent, forceLockIfAbsent, alreadyLocked, forRemoval);
}
@@ -203,12 +203,20 @@
if (!ctx.hasLockedKey(key) && !shouldSkipLocking) {
if (lockManager.lockAndRecord(key, ctx)) {
// successfully locked!
+ if (trace) log.trace("Successfully acquired lock!");
return true;
} else {
Object owner = lockManager.getOwner(key);
throw new TimeoutException("Unable to acquire lock after [" + Util.prettyPrintTime(getLockAcquisitionTimeout(ctx)) + "] on key [" + key + "] for requestor [" +
ctx.getLockOwner() + "]! Lock held by [" + owner + "]");
}
+ } else {
+ if (trace) {
+ if (shouldSkipLocking)
+ log.trace("SKIP_LOCKING flag used!");
+ else
+ log.trace("Already own lock for entry");
+ }
}
return false;
Modified: trunk/core/src/main/java/org/infinispan/container/entries/RepeatableReadEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/RepeatableReadEntry.java 2009-11-11 19:21:00 UTC (rev 1140)
+++ trunk/core/src/main/java/org/infinispan/container/entries/RepeatableReadEntry.java 2009-11-11 19:29:25 UTC (rev 1141)
@@ -47,16 +47,18 @@
setChanged();
if (writeSkewCheck) {
- // check for write skew.
- Object actualValue = container.get(key);
+ // check for write skew.
+ InternalCacheEntry ice = container.get(key);
+ Object actualValue = ice == null ? null : ice.getValue();
+ // Note that this identity-check is intentional. We don't *want* to call actualValue.equals() since that defeats the purpose.
+ // the implicit "versioning" we have in R_R creates a new wrapper "value" instance for every update.
if (actualValue != null && actualValue != value) {
String errormsg = new StringBuilder().append("Detected write skew on key [").append(getKey()).append("]. Another process has changed the entry since we last read it!").toString();
if (log.isWarnEnabled()) log.warn(errormsg + ". Unable to copy entry for update.");
throw new CacheException(errormsg);
}
}
-
// make a backup copy
oldValue = value;
}
Modified: trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/WriteSkewTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/WriteSkewTest.java 2009-11-11 19:21:00 UTC (rev 1140)
+++ trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/WriteSkewTest.java 2009-11-11 19:29:25 UTC (rev 1141)
@@ -1,6 +1,7 @@
package org.infinispan.api.mvcc.repeatable_read;
import org.infinispan.Cache;
+import org.infinispan.CacheException;
import org.infinispan.api.mvcc.LockAssert;
import org.infinispan.config.Configuration;
import org.infinispan.context.InvocationContextContainer;
@@ -32,7 +33,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
- at Test(groups = {"functional", "mvcc"}, testName = "api.mvcc.repeatable_read.WriteSkewTest")
+ at Test(groups = "functional", testName = "api.mvcc.repeatable_read.WriteSkewTest")
public class WriteSkewTest extends AbstractInfinispanTest {
private static final Log log = LogFactory.getLog(WriteSkewTest.class);
protected TransactionManager tm;
@@ -201,6 +202,12 @@
assert "v3".equals(cache.get("k")) : "W2 should have overwritten W1's work!";
assertNoLocks();
+ } else {
+ Collection<Exception> combined = new HashSet<Exception>(w1exceptions);
+ combined.addAll(w2exceptions);
+ assert !combined.isEmpty();
+ assert combined.size() == 1;
+ assert combined.iterator().next() instanceof CacheException;
}
}
More information about the infinispan-commits
mailing list