[infinispan-commits] Infinispan SVN: r1045 - in trunk/core/src: main/java/org/infinispan/context/impl and 8 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Oct 28 06:17:13 EDT 2009
Author: mircea.markus
Date: 2009-10-28 06:17:13 -0400 (Wed, 28 Oct 2009)
New Revision: 1045
Added:
trunk/core/src/test/java/org/infinispan/api/ForceWriteLockTest.java
Modified:
trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java
trunk/core/src/main/java/org/infinispan/container/entries/MortalCacheEntry.java
trunk/core/src/main/java/org/infinispan/container/entries/TransientCacheEntry.java
trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java
trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java
trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/RepeatableReadLockTest.java
trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java
trunk/core/src/test/java/org/infinispan/loaders/decorators/AsyncTest.java
trunk/core/src/test/java/org/infinispan/stress/PutIfAbsentStressTest.java
trunk/core/src/test/java/org/infinispan/test/AbstractCacheTest.java
trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
Log:
[ISPN-236]-(cache.putIfAbsent() is not atomic) - fixed by placing locking interceptor before repl interceptor
Modified: trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -1,12 +1,12 @@
package org.infinispan.container.entries;
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-
/**
* A cache entry that is immortal/cannot expire
*
@@ -122,4 +122,11 @@
return new ImmortalCacheEntry(k, v);
}
}
+
+ @Override
+ public String toString() {
+ return "ImmortalCacheEntry{" +
+ "cacheValue=" + cacheValue +
+ "} " + super.toString();
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/container/entries/MortalCacheEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/MortalCacheEntry.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/container/entries/MortalCacheEntry.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -1,13 +1,13 @@
package org.infinispan.container.entries;
+import org.infinispan.io.UnsignedNumeric;
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import org.infinispan.io.UnsignedNumeric;
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-
/**
* A cache entry that is mortal. I.e., has a lifespan.
*
@@ -137,4 +137,11 @@
return new MortalCacheEntry(k, v, lifespan, created);
}
}
+
+ @Override
+ public String toString() {
+ return "MortalCacheEntry{" +
+ "cacheValue=" + cacheValue +
+ "} " + super.toString();
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/container/entries/TransientCacheEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/TransientCacheEntry.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/container/entries/TransientCacheEntry.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -1,13 +1,13 @@
package org.infinispan.container.entries;
+import org.infinispan.io.UnsignedNumeric;
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import org.infinispan.io.UnsignedNumeric;
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-
/**
* A cache entry that is transient, i.e., it can be considered expired afer a period of not being used.
*
@@ -139,4 +139,11 @@
return new TransientCacheEntry(k, v, maxIdle, lastUsed);
}
}
+
+ @Override
+ public String toString() {
+ return "TransientCacheEntry{" +
+ "cacheValue=" + cacheValue +
+ "} " + super.toString();
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -116,7 +116,11 @@
public boolean hasLockedKey(Object key) {
CacheEntry e = lookupEntry(key);
- return e != null && e.isChanged();
+ if (e == null) {
+ return getLookedUpEntries().containsKey(key); // this will chk if the key is present
+ } else {
+ return e.isChanged();
+ }
}
public boolean hasLockedEntries() {
@@ -124,7 +128,6 @@
boolean result = false;
for (CacheEntry e : lookedUpEntries.values()) {
if (e.isChanged()) {
- System.out.println("Entry is locked = " + e);
result = true;
}
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -71,4 +71,9 @@
public void clearLookedUpEntries() {
xaAdapter.clearLookedUpEntries();
}
+
+ @Override
+ public boolean hasLockedKey(Object key) {
+ return xaAdapter != null && super.hasLockedKey(key);
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -82,7 +82,7 @@
interceptorChain.appendIntereceptor(createInterceptor(DistTxInterceptor.class));
else
interceptorChain.appendIntereceptor(createInterceptor(TxInterceptor.class));
-
+
if(configuration.isUseEagerLocking())
interceptorChain.appendIntereceptor(createInterceptor(ImplicitEagerLockingInterceptor.class));
@@ -95,23 +95,6 @@
interceptorChain.appendIntereceptor(createInterceptor(DeadlockDetectingInterceptor.class));
}
- switch (configuration.getCacheMode()) {
- case REPL_SYNC:
- case REPL_ASYNC:
- interceptorChain.appendIntereceptor(createInterceptor(ReplicationInterceptor.class));
- break;
- case INVALIDATION_SYNC:
- case INVALIDATION_ASYNC:
- interceptorChain.appendIntereceptor(createInterceptor(InvalidationInterceptor.class));
- break;
- case DIST_SYNC:
- case DIST_ASYNC:
- interceptorChain.appendIntereceptor(createInterceptor(DistributionInterceptor.class));
- break;
- case LOCAL:
- //Nothing...
- }
-
if (configuration.isUsingCacheLoaders()) {
if (configuration.getCacheLoaderManagerConfig().isPassivation()) {
interceptorChain.appendIntereceptor(createInterceptor(ActivationInterceptor.class));
@@ -130,11 +113,30 @@
}
}
+
if (configuration.getCacheMode().isDistributed())
interceptorChain.appendIntereceptor(createInterceptor(DistLockingInterceptor.class));
else
interceptorChain.appendIntereceptor(createInterceptor(LockingInterceptor.class));
+ switch (configuration.getCacheMode()) {
+ case REPL_SYNC:
+ case REPL_ASYNC:
+ interceptorChain.appendIntereceptor(createInterceptor(ReplicationInterceptor.class));
+ break;
+ case INVALIDATION_SYNC:
+ case INVALIDATION_ASYNC:
+ interceptorChain.appendIntereceptor(createInterceptor(InvalidationInterceptor.class));
+ break;
+ case DIST_SYNC:
+ case DIST_ASYNC:
+ interceptorChain.appendIntereceptor(createInterceptor(DistributionInterceptor.class));
+ break;
+ case LOCAL:
+ //Nothing...
+ }
+
+
CommandInterceptor callInterceptor = createInterceptor(CallInterceptor.class);
interceptorChain.appendIntereceptor(callInterceptor);
if (log.isTraceEnabled()) log.trace("Finished building default interceptor chain.");
Modified: trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -15,6 +15,7 @@
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.commands.write.WriteCommand;
import org.infinispan.container.DataContainer;
+import org.infinispan.container.EntryFactory;
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
@@ -48,6 +49,7 @@
CommandsFactory cf;
DataContainer dataContainer;
boolean isL1CacheEnabled, needReliableReturnValues;
+ EntryFactory entryFactory;
static final RecipientGenerator CLEAR_COMMAND_GENERATOR = new RecipientGenerator() {
@@ -63,10 +65,11 @@
};
@Inject
- public void injectDependencies(DistributionManager distributionManager, CommandsFactory cf, DataContainer dataContainer) {
+ public void injectDependencies(DistributionManager distributionManager, CommandsFactory cf, DataContainer dataContainer, EntryFactory entryFactory) {
this.dm = distributionManager;
this.cf = cf;
this.dataContainer = dataContainer;
+ this.entryFactory = entryFactory;
}
@Start
@@ -114,6 +117,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);
invokeNextInterceptor(ctx, put);
} else {
if (trace) log.trace("Not caching remotely retrieved entry for key {0} in L1", key);
@@ -306,7 +310,7 @@
private boolean isSingleOwnerAndLocal(RecipientGenerator recipientGenerator) {
return configuration.getNumOwners() == 1 && recipientGenerator.generateRecipients().get(0).equals(rpcManager.getTransport().getAddress());
}
-
+
interface KeyGenerator {
Object[] getKeys();
}
Added: trunk/core/src/test/java/org/infinispan/api/ForceWriteLockTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/ForceWriteLockTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/api/ForceWriteLockTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -0,0 +1,45 @@
+package org.infinispan.api;
+
+import org.infinispan.AdvancedCache;
+import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.ReadCommittedEntry;
+import org.infinispan.context.Flag;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.test.SingleCacheManagerTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ */
+ at Test(groups = "functional", testName = "api.ForceWriteLockTest")
+public class ForceWriteLockTest extends SingleCacheManagerTest {
+ private TransactionManager tm;
+ private AdvancedCache advancedCache;
+
+ protected CacheManager createCacheManager() throws Exception {
+ CacheManager cacheManager = TestCacheManagerFactory.createLocalCacheManager(true);
+ advancedCache = cacheManager.getCache().getAdvancedCache();
+ tm = TestingUtil.getTransactionManager(advancedCache);
+ return cacheManager;
+ }
+
+ public void testWriteLockIsAcquired() throws Exception {
+ advancedCache.put("k","v");
+ assertNotLocked(advancedCache,"k");
+ tm.begin();
+ advancedCache.get("k", Flag.FORCE_WRITE_LOCK);
+
+ InvocationContext ic = advancedCache.getInvocationContextContainer().getInvocationContext();
+ CacheEntry cacheEntry = ic.getLookedUpEntries().get("k");
+ assert (cacheEntry instanceof ReadCommittedEntry && cacheEntry.isChanged());
+
+ assertLocked(advancedCache,"k");
+ tm.commit();
+ assertNotLocked(advancedCache,"k");
+ }
+}
Modified: trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/RepeatableReadLockTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/RepeatableReadLockTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/api/mvcc/repeatable_read/RepeatableReadLockTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -110,7 +110,7 @@
tm.resume(tx);
cache.remove("a");
tx.commit();
- assert cache.get("a") == null;
+ assert cache.get("a") == null : "expected null but received " + cache.get("a");
}
public void testLocksOnPutKeyVal() throws Exception {
@@ -126,6 +126,8 @@
tm.begin();
assert cache.get("k").equals("v");
+
+
assertNotLocked("k");
tm.commit();
Modified: trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -201,7 +201,13 @@
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
+ asserLocked(c1, false, k1, k2);
+ asserLocked(c2, false, k1, k2);
+ asserLocked(c3, false, k1, k2);
+ asserLocked(c4, false, k1, k2);
+
+ log.info("***** Here it starts!");
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
Object ret = c4.remove(k1);
@@ -212,20 +218,39 @@
assert !c4.containsKey(k1);
assert !c4.containsKey(k2);
tm4.rollback();
+ log.info("----- Here it ends!");
+ asserLocked(c1, false, k1, k2);
+ asserLocked(c2, false, k1, k2);
+ asserLocked(c3, false, k1, k2);
+ asserLocked(c4, false, k1 );
+ asserLocked(c4, false, k2 );
+
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
+ asserLocked(c1, false, k1, k2);
+ asserLocked(c2, false, k1, k2);
+ asserLocked(c3, false, k1, k2);
+ asserLocked(c4, false, k1, k2);
+
+
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
+ asserLocked(c1, false, k1, k2);
+ asserLocked(c2, false, k1, k2);
+ asserLocked(c3, false, k1, k2);
+ asserLocked(c4, false, k1, k2);
+
checkOwnership(k1, k2, "value1", "value2");
}
+
public void testConditionalRemoveFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
Modified: trunk/core/src/test/java/org/infinispan/loaders/decorators/AsyncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/decorators/AsyncTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/loaders/decorators/AsyncTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -68,7 +68,6 @@
String value = "testMultiplePutsOnSameKey-v-";
doTestSameKeyPut(number, key, value);
doTestSameKeyRemove(key);
-
}
public void testRestrictionOnAddingToAsyncQueue() throws Exception {
@@ -121,15 +120,20 @@
}
private void doTestSameKeyPut(int number, String key, String value) throws Exception {
- for (int i = 0; i < number; i++) store.store(InternalEntryFactory.create(key, value + i));
-
+ for (int i = 0; i < number; i++)
+ store.store(InternalEntryFactory.create(key, value + i));
+
InternalCacheEntry entry;
- do {
+ boolean success = false;
+ for (int i = 0; i < 120; i++) {
TestingUtil.sleepRandom(1000);
entry = store.load(key);
- } while (!entry.getValue().equals(value + (number-1)));
+ success = entry.getValue().equals(value + (number-1));
+ if (success) break;
+ }
+ assert success;
}
-
+
private void doTestRemove(int number, String key) throws Exception {
for (int i = 0; i < number; i++) store.remove(key + i);
@@ -156,9 +160,9 @@
do {
TestingUtil.sleepRandom(1000);
entry = store.load(key);
- } while (entry != null);
+ } while (entry != null);
}
-
+
private void doTestClear(int number, String key) throws Exception {
store.clear();
TestingUtil.sleepRandom(1000);
Modified: trunk/core/src/test/java/org/infinispan/stress/PutIfAbsentStressTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/stress/PutIfAbsentStressTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/stress/PutIfAbsentStressTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -47,7 +47,7 @@
* @see java.util.concurrent.ConcurrentMap#putIfAbsent(Object, Object)
* @author Sanne Grinovero
*/
- at Test(groups = "stress", testName = "atomic.PutIfAbsentStressTest")
+ at Test(groups = "stress", testName = "stress.PutIfAbsentStressTest")
public class PutIfAbsentStressTest {
private static final int NODES_NUM = 5;
@@ -123,7 +123,7 @@
} finally {
for (CacheManager cm : cacheManagers) {
try {
- TestingUtil.clearContent(cm);
+ TestingUtil.killCacheManagers(cm);
} catch (Exception e) {
// try cleaning up the other cacheManagers too
}
Modified: trunk/core/src/test/java/org/infinispan/test/AbstractCacheTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/AbstractCacheTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/test/AbstractCacheTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -6,6 +6,7 @@
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
+import org.infinispan.util.concurrent.locks.LockManager;
import java.util.Set;
@@ -61,4 +62,14 @@
protected boolean xor(boolean b1, boolean b2) {
return (b1 || b2) && !(b1 && b2);
}
+
+ protected void assertNotLocked(Cache cache, Object key) {
+ LockManager lockManager = TestingUtil.extractLockManager(cache);
+ assert !lockManager.isLocked(key) : "expected key '" + key + "' not to be locked, and it is by: " + lockManager.getOwner(key);
+ }
+
+ protected void assertLocked(Cache cache, Object key) {
+ LockManager lockManager = TestingUtil.extractLockManager(cache);
+ assert lockManager.isLocked(key) : "expected key '" + key + "' to be locked, but it is not";
+ }
}
Modified: trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java 2009-10-27 19:35:38 UTC (rev 1044)
+++ trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java 2009-10-28 10:17:13 UTC (rev 1045)
@@ -4,7 +4,6 @@
import org.infinispan.config.Configuration;
import org.infinispan.manager.CacheManager;
import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.util.concurrent.locks.LockManager;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
@@ -173,15 +172,4 @@
* {@link #addClusterEnabledCacheManager()}
*/
protected abstract void createCacheManagers() throws Throwable;
-
-
- protected void assertNotLocked(Cache cache, Object key) {
- LockManager lockManager = TestingUtil.extractLockManager(cache);
- assert !lockManager.isLocked(key) : "expected key '" + key + "' not to be locked, and it is by: " + lockManager.getOwner(key);
- }
-
- protected void assertLocked(Cache cache, Object key) {
- LockManager lockManager = TestingUtil.extractLockManager(cache);
- assert lockManager.isLocked(key) : "expected key '" + key + "' to be locked, but it is not";
- }
}
More information about the infinispan-commits
mailing list