[infinispan-commits] Infinispan SVN: r998 - in trunk/core/src: main/java/org/infinispan/interceptors and 4 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Fri Oct 23 13:28:09 EDT 2009
Author: galder.zamarreno at jboss.com
Date: 2009-10-23 13:28:08 -0400 (Fri, 23 Oct 2009)
New Revision: 998
Added:
trunk/core/src/test/java/org/infinispan/api/lru/
trunk/core/src/test/java/org/infinispan/api/lru/read_committed/
trunk/core/src/test/java/org/infinispan/api/lru/read_committed/CacheAPIMVCCTest.java
Modified:
trunk/core/src/main/java/org/infinispan/container/DataContainer.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/container/FIFODataContainer.java
trunk/core/src/main/java/org/infinispan/container/SimpleDataContainer.java
trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java
trunk/core/src/test/java/org/infinispan/container/SimpleDataContainerTest.java
Log:
[ISPN-235] (LRUDataContainer keySet() looping fails when inside there's a get call) Cache size is now correct after a clear. Fixed by looping through the entry set rather than the key set. Also added a peek() method to data container to allow cache retrieval without changing the order when iterating through the key set.
Modified: trunk/core/src/main/java/org/infinispan/container/DataContainer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/DataContainer.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/container/DataContainer.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -44,6 +44,21 @@
* @return entry, if it exists and has not expired, or null if not
*/
InternalCacheEntry get(Object k);
+
+ /**
+ * Retrieves a cache entry in the same way as {@link #get(Object)}}
+ * except that it does not update or reorder any of the internal constructs.
+ * I.e., expiration does not happen, and in the case of the LRU container,
+ * the entry is not moved to the end of the chain.
+ *
+ * This method should be used instead of {@link #get(Object)}} when called
+ * while iterating through the data container using methods like {@link #keySet()}
+ * to avoid changing the underlying collection's order.
+ *
+ * @param k key under which entry is stored
+ * @return entry, if it exists, or null if not
+ */
+ InternalCacheEntry peek(Object k);
/**
* Puts an entry in the cache along with a lifespan and a maxIdle time
@@ -80,7 +95,11 @@
void clear();
/**
- * @return a set of keys contained in the container
+ * Returns a set of keys in the container. When iterating through the container using this method,
+ * clients should never call {@link #get()} method but instead {@link #peek()}, in order to avoid
+ * changing the order of the underlying collection as a side of effect of iterating through it.
+ *
+ * @return a set of keys
*/
Set<Object> keySet();
Modified: trunk/core/src/main/java/org/infinispan/container/EntryFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactory.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactory.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -22,6 +22,7 @@
package org.infinispan.container;
import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.MVCCEntry;
import org.infinispan.context.InvocationContext;
import org.infinispan.util.concurrent.TimeoutException;
@@ -30,6 +31,7 @@
* // TODO: MANIK: Document this
*
* @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @author Galder Zamarreño
* @since 4.0
*/
public interface EntryFactory {
@@ -50,6 +52,8 @@
boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException;
MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
+
+ MVCCEntry wrapEntryForWriting(InvocationContext ctx, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException;
CacheEntry wrapEntryForReading(InvocationContext ctx, Object key) throws InterruptedException;
}
Modified: trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/container/EntryFactoryImpl.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -23,6 +23,7 @@
import org.infinispan.config.Configuration;
import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.container.entries.MVCCEntry;
import org.infinispan.container.entries.NullMarkerEntry;
import org.infinispan.container.entries.NullMarkerEntryForRemoval;
@@ -99,8 +100,16 @@
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);
+ }
- public final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
+ 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);
+ }
+
+ private final MVCCEntry wrapEntryForWriting(InvocationContext ctx, Object key, InternalCacheEntry entry, boolean createIfAbsent, boolean forceLockIfAbsent, boolean alreadyLocked, boolean forRemoval) throws InterruptedException {
CacheEntry cacheEntry = ctx.lookupEntry(key);
MVCCEntry mvccEntry = null;
if (createIfAbsent && cacheEntry != null && cacheEntry.isNull()) cacheEntry = null;
@@ -137,8 +146,8 @@
if (!alreadyLocked) {
lockAcquired = acquireLock(ctx, key);
}
- // else, fetch from dataContainer.
- cacheEntry = container.get(key);
+ // else, fetch from dataContainer or used passed entry.
+ cacheEntry = entry != null ? entry : container.get(key);
if (cacheEntry != null) {
if (trace) log.trace("Retrieved from container.");
// exists in cache! Just acquire lock if needed, and wrap.
Modified: trunk/core/src/main/java/org/infinispan/container/FIFODataContainer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/FIFODataContainer.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/container/FIFODataContainer.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -727,6 +727,18 @@
return ice;
}
+ public InternalCacheEntry peek(Object k) {
+ int h = hash(k.hashCode());
+ Segment s = segmentFor(h);
+ LinkedEntry le = s.get(k, h);
+ InternalCacheEntry ice = null;
+ if (le != null) {
+ ice = le.e;
+ if (isMarkedForRemoval(le)) unlink(le);
+ }
+ return ice;
+ }
+
public void put(Object k, Object v, long lifespan, long maxIdle) {
// do a normal put first.
int h = hash(k.hashCode());
Modified: trunk/core/src/main/java/org/infinispan/container/SimpleDataContainer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/SimpleDataContainer.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/container/SimpleDataContainer.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -39,13 +39,7 @@
mortalEntries = new ConcurrentHashMap<Object, InternalCacheEntry>(64, 0.75f, concurrencyLevel);
}
- /**
- * Like a get, but doesn't check for expired entries
- *
- * @param key key to retrieve
- * @return an entry or null
- */
- private InternalCacheEntry peek(Object key) {
+ public InternalCacheEntry peek(Object key) {
InternalCacheEntry e = immortalEntries.get(key);
if (e == null) e = mortalEntries.get(key);
return e;
Modified: trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -36,6 +36,7 @@
import org.infinispan.container.DataContainer;
import org.infinispan.container.EntryFactory;
import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
@@ -163,8 +164,8 @@
public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
try {
// get a snapshot of all keys in the data container
- for (Object key : dataContainer.keySet())
- entryFactory.wrapEntryForWriting(ctx, key, false, false, false, false);
+ for (InternalCacheEntry entry : dataContainer.entrySet())
+ entryFactory.wrapEntryForWriting(ctx, entry, false, false, false, false);
return invokeNextInterceptor(ctx, command);
} finally {
doAfterCall(ctx);
Modified: trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/test/java/org/infinispan/api/CacheAPITest.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -32,6 +32,7 @@
// start a single cache instance
Configuration c = getDefaultStandaloneConfig(true);
c.setIsolationLevel(getIsolationLevel());
+ c = addEviction(c);
CacheManager cm = TestCacheManagerFactory.createLocalCacheManager();
cm.defineConfiguration("test", c);
cache = cm.getCache("test");
@@ -39,6 +40,10 @@
}
protected abstract IsolationLevel getIsolationLevel();
+
+ protected Configuration addEviction(Configuration cfg) {
+ return cfg; // No eviction by default
+ }
/**
* Tests that the configuration contains the values expected, as well as immutability of certain elements
@@ -439,4 +444,13 @@
}
}
+ public void testSizeAfterClear() {
+ for (int i = 0; i < 10; i++) {
+ cache.put(i, "value" + i);
+ }
+
+ cache.clear();
+
+ assert 0 == cache.size();
+ }
}
Added: trunk/core/src/test/java/org/infinispan/api/lru/read_committed/CacheAPIMVCCTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/lru/read_committed/CacheAPIMVCCTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/api/lru/read_committed/CacheAPIMVCCTest.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -0,0 +1,23 @@
+package org.infinispan.api.lru.read_committed;
+
+import org.infinispan.api.CacheAPITest;
+import org.infinispan.config.Configuration;
+import org.infinispan.eviction.EvictionStrategy;
+import org.infinispan.util.concurrent.IsolationLevel;
+import org.testng.annotations.Test;
+
+ at Test(groups = "functional", testName = "api.mvcc.read_committed.CacheAPIMVCCTest")
+public class CacheAPIMVCCTest extends CacheAPITest {
+ @Override
+ protected IsolationLevel getIsolationLevel() {
+ return IsolationLevel.READ_COMMITTED;
+ }
+
+ @Override
+ protected Configuration addEviction(Configuration cfg) {
+ cfg.setEvictionStrategy(EvictionStrategy.LRU);
+ cfg.setEvictionWakeUpInterval(60000);
+ cfg.setEvictionMaxEntries(1000);
+ return cfg;
+ }
+}
Modified: trunk/core/src/test/java/org/infinispan/container/SimpleDataContainerTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/container/SimpleDataContainerTest.java 2009-10-23 16:54:28 UTC (rev 997)
+++ trunk/core/src/test/java/org/infinispan/container/SimpleDataContainerTest.java 2009-10-23 17:28:08 UTC (rev 998)
@@ -215,7 +215,7 @@
int i = 0;
for (Object key : dc.keySet()) {
- dc.get(key);
+ dc.peek(key); // calling get in this situations will result on corruption the iteration.
i++;
}
More information about the infinispan-commits
mailing list