[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