[infinispan-commits] Infinispan SVN: r1848 - in trunk/core/src: main/java/org/infinispan/container and 2 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Tue May 25 11:46:19 EDT 2010
Author: manik.surtani at jboss.com
Date: 2010-05-25 11:46:19 -0400 (Tue, 25 May 2010)
New Revision: 1848
Modified:
trunk/core/src/main/java/org/infinispan/commands/write/PutKeyValueCommand.java
trunk/core/src/main/java/org/infinispan/container/EntryFactory.java
trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java
Log:
[ISPN-455] (Value removed from cache still be visible to putIfAbsent in single transaction scope.)
Modified: trunk/core/src/main/java/org/infinispan/commands/write/PutKeyValueCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/write/PutKeyValueCommand.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/commands/write/PutKeyValueCommand.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -80,7 +80,7 @@
Object o;
MVCCEntry e = (MVCCEntry) ctx.lookupEntry(key);
Object entryValue = e.getValue();
- if (entryValue != null && putIfAbsent) {
+ if (entryValue != null && putIfAbsent && !e.isRemoved()) {
successful = false;
return entryValue;
} else {
@@ -97,6 +97,11 @@
e.setMaxIdle(maxIdleTimeMillis);
} else {
o = e.setValue(value);
+ if (e.isRemoved()) {
+ e.setRemoved(false);
+ e.setValid(true);
+ o = null;
+ }
e.setLifespan(lifespanMillis);
e.setMaxIdle(maxIdleTimeMillis);
}
Modified: trunk/core/src/main/java/org/infinispan/container/EntryFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactory.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactory.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -64,10 +64,11 @@
* @param forceLockIfAbsent forces a lock even if the entry is absent
* @param alreadyLocked if true, this hint prevents the method from acquiring any locks and the existence and ownership of the lock is presumed.
* @param forRemoval if true, this hint informs this method that the lock is being acquired for removal.
+ * @param undeleteIfNeeded if true, if the entry is found in the current scope (perhaps a transaction) and is deleteed, it will be undeleted. If false, it will be considered deleted.
* @return an MVCCEntry instance
* @throws InterruptedException when things go wrong, usually trying to acquire a lock
*/
- MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
+ MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval, boolean undeleteIfNeeded) throws InterruptedException;
/**
* Wraps an entry for writing. This would typically acquire write locks if necessary, and place the wrapped
@@ -79,10 +80,10 @@
* @param forceLockIfAbsent forces a lock even if the entry is absent
* @param alreadyLocked if true, this hint prevents the method from acquiring any locks and the existence and ownership of the lock is presumed.
* @param forRemoval if true, this hint informs this method that the lock is being acquired for removal.
- * @return an MVCCEntry instance
+* @param undeleteIfNeeded if true, if the entry is found in the current scope (perhaps a transaction) and is deleteed, it will be undeleted. If false, it will be considered deleted. * @return an MVCCEntry instance
* @throws InterruptedException when things go wrong, usually trying to acquire a lock
*/
- MVCCEntry wrapEntryForWriting(InvocationContext ctx, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
+ MVCCEntry wrapEntryForWriting(InvocationContext ctx, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval, boolean undeleteIfNeeded) throws InterruptedException;
/**
* Wraps an entry for reading. Usually this is just a raw {@link CacheEntry} but certain combinations of isolation
Modified: trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -79,7 +79,7 @@
CacheEntry cacheEntry;
if (ctx.hasFlag(Flag.FORCE_WRITE_LOCK)) {
if (trace) log.trace("Forcing lock on reading");
- return wrapEntryForWriting(ctx, key, false, false, false, false);
+ return wrapEntryForWriting(ctx, key, false, false, false, false, false);
} else if ((cacheEntry = ctx.lookupEntry(key)) == null) {
if (trace) log.trace("Key {0} is not in context, fetching from container.", key);
// simple implementation. Peek the entry, wrap it, put wrapped entry in the context.
@@ -102,15 +102,15 @@
}
}
- 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);
+ public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval, boolean undeleteIfNeeded) throws InterruptedException {
+ return wrapEntryForWriting(ctx, key, null, createIfAbsent, forceLockIfAbsent, alreadyLocked, forRemoval, undeleteIfNeeded);
}
- public MVCCEntry wrapEntryForWriting(InvocationContext ctx, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
- return wrapEntryForWriting(ctx, entry.getKey(), entry, createIfAbsent, forceLockIfAbsent, alreadyLocked, forRemoval);
+ public MVCCEntry wrapEntryForWriting(InvocationContext ctx, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval, boolean undeleteIfNeeded) throws InterruptedException {
+ return wrapEntryForWriting(ctx, entry.getKey(), entry, createIfAbsent, forceLockIfAbsent, alreadyLocked, forRemoval, undeleteIfNeeded);
}
- private MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
+ private MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval, boolean undeleteIfNeeded) throws InterruptedException {
CacheEntry cacheEntry = ctx.lookupEntry(key);
MVCCEntry mvccEntry = null;
if (createIfAbsent && cacheEntry != null && cacheEntry.isNull()) cacheEntry = null;
@@ -133,7 +133,7 @@
mvccEntry.copyForUpdate(container, writeSkewCheck);
}
- if (cacheEntry.isRemoved() && createIfAbsent) {
+ if (cacheEntry.isRemoved() && createIfAbsent && undeleteIfNeeded) {
if (trace) log.trace("Entry is deleted in current scope. Need to un-delete.");
if (mvccEntry != cacheEntry) mvccEntry = (MVCCEntry) cacheEntry;
mvccEntry.setRemoved(false);
Modified: trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/interceptors/CacheLoaderInterceptor.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -138,7 +138,7 @@
}
// Reuse the lock and create a new entry for loading
- MVCCEntry n = entryFactory.wrapEntryForWriting(ctx, key, true, false, keyLocked, false);
+ MVCCEntry n = entryFactory.wrapEntryForWriting(ctx, key, true, false, keyLocked, false, true);
recordLoadedEntry(ctx, key, n, loaded);
return true;
} else {
Modified: trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -135,7 +135,7 @@
if (trace) log.trace("Caching remotely retrieved entry for key {0} in L1", key);
long lifespan = ice.getLifespan() < 0 ? configuration.getL1Lifespan() : Math.min(ice.getLifespan(), configuration.getL1Lifespan());
PutKeyValueCommand put = cf.buildPutKeyValueCommand(ice.getKey(), ice.getValue(), lifespan, -1);
- entryFactory.wrapEntryForWriting(ctx, key, true, false, ctx.hasLockedKey(key), false);
+ entryFactory.wrapEntryForWriting(ctx, key, true, false, ctx.hasLockedKey(key), false, false);
invokeNextInterceptor(ctx, put);
} else {
if (trace) log.trace("Not caching remotely retrieved entry for key {0} in L1", key);
Modified: trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -143,7 +143,7 @@
//if even one key is unlocked we need to invoke this lock command cluster wide...
shouldInvokeOnCluster = true;
}
- entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false);
+ entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false, false);
}
if (shouldInvokeOnCluster || c.isExplicit())
return invokeNextInterceptor(ctx, c);
@@ -165,7 +165,7 @@
try {
// get a snapshot of all keys in the data container
for (InternalCacheEntry entry : dataContainer.entrySet())
- entryFactory.wrapEntryForWriting(ctx, entry, false, false, false, false);
+ entryFactory.wrapEntryForWriting(ctx, entry, false, false, false, false, false);
return invokeNextInterceptor(ctx, command);
} finally {
doAfterCall(ctx);
@@ -183,7 +183,7 @@
public Object visitInvalidateCommand(InvocationContext ctx, InvalidateCommand command) throws Throwable {
try {
if (command.getKeys() != null) {
- for (Object key : command.getKeys()) entryFactory.wrapEntryForWriting(ctx, key, false, true, false, false);
+ for (Object key : command.getKeys()) entryFactory.wrapEntryForWriting(ctx, key, false, true, false, false, false);
}
return invokeNextInterceptor(ctx, command);
} finally {
@@ -194,7 +194,7 @@
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
try {
- entryFactory.wrapEntryForWriting(ctx, command.getKey(), true, false, false, false);
+ entryFactory.wrapEntryForWriting(ctx, command.getKey(), true, false, false, false, !command.isPutIfAbsent());
return invokeNextInterceptor(ctx, command);
} finally {
doAfterCall(ctx);
@@ -205,7 +205,7 @@
public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
try {
for (Object key : command.getMap().keySet()) {
- entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false);
+ entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false, true);
}
return invokeNextInterceptor(ctx, command);
}
@@ -217,7 +217,7 @@
@Override
public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
try {
- entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, true);
+ entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, true, false);
return invokeNextInterceptor(ctx, command);
}
finally {
@@ -228,7 +228,7 @@
@Override
public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
try {
- entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, false);
+ entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, false, false);
return invokeNextInterceptor(ctx, command);
}
finally {
Modified: trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java 2010-05-25 15:22:17 UTC (rev 1847)
+++ trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java 2010-05-25 15:46:19 UTC (rev 1848)
@@ -467,7 +467,6 @@
assert cache.putIfAbsent(key, new_value) == null;
TestingUtil.getTransactionManager(cache).rollback();
- assert cache.get(key).equals(new_value);
-
+ assert cache.get(key).equals(old_value);
}
}
More information about the infinispan-commits
mailing list