[infinispan-commits] Infinispan SVN: r340 - in trunk/core/src: main/java/org/infinispan/interceptors and 1 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Tue May 26 07:22:05 EDT 2009


Author: vblagojevic at jboss.com
Date: 2009-05-26 07:22:05 -0400 (Tue, 26 May 2009)
New Revision: 340

Added:
   trunk/core/src/test/java/org/infinispan/replication/SyncReplImplicitLockingTest.java
Modified:
   trunk/core/src/main/java/org/infinispan/commands/LockControlCommand.java
   trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java
Log:
[ISPN-70] - Transparent eager locking for transactions
tuning, unit test

Modified: trunk/core/src/main/java/org/infinispan/commands/LockControlCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/LockControlCommand.java	2009-05-26 10:42:08 UTC (rev 339)
+++ trunk/core/src/main/java/org/infinispan/commands/LockControlCommand.java	2009-05-26 11:22:05 UTC (rev 340)
@@ -32,6 +32,12 @@
 import java.util.Collection;
 
 /**
+ * LockControlCommand is a command that enables distributed locking across infinispan nodes.
+ * <p> 
+ * For more details refer to:
+ * https://jira.jboss.org/jira/browse/ISPN-70
+ * https://jira.jboss.org/jira/browse/ISPN-48
+ * 
  * @author Vladimir Blagojevic (<a href="mailto:vblagoje at redhat.com">vblagoje at redhat.com</a>)
  * @param
  * @since 4.0
@@ -129,6 +135,7 @@
       return "LockControlCommand{" +
             "gtx=" + globalTx +
             ", cacheName='" + cacheName +
+            ", implicit='" + implicit +
             ", keys=" + keys + '}';
    }
 }

Modified: trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java	2009-05-26 10:42:08 UTC (rev 339)
+++ trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java	2009-05-26 11:22:05 UTC (rev 340)
@@ -19,6 +19,11 @@
  * Interceptor in charge of eager, implicit locking of cache keys across cluster within
  * transactional context
  * 
+ * <p> 
+ * For more details refer to:
+ * https://jira.jboss.org/jira/browse/ISPN-70
+ * https://jira.jboss.org/jira/browse/ISPN-48
+ * 
  * @author <a href="mailto:vblagoje at redhat.com">Vladimir Blagojevic (vblagoje at redhat.com)</a>
  * @since 4.0
  */
@@ -36,7 +41,7 @@
             throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, Collections.singleton(command.getKey()));
+         lockEagerly(ctx, Collections.singleton(command.getKey()));
       }
       return invokeNextInterceptor(ctx, command);
    }
@@ -45,7 +50,7 @@
    public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, Collections.singleton(command.getKey()));
+         lockEagerly(ctx, Collections.singleton(command.getKey()));
       }
       return invokeNextInterceptor(ctx, command);
    }
@@ -55,7 +60,7 @@
             throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, Collections.singleton(command.getKey()));
+         lockEagerly(ctx, Collections.singleton(command.getKey()));
       }
       return invokeNextInterceptor(ctx, command);
    }
@@ -64,7 +69,7 @@
    public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, command.getMap().keySet());
+         lockEagerly(ctx, command.getMap().keySet());
       }
       return invokeNextInterceptor(ctx, command);
    }
@@ -73,7 +78,7 @@
    public Object visitEvictCommand(InvocationContext ctx, EvictCommand command) throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, Collections.singleton(command.getKey()));
+         lockEagerly(ctx, Collections.singleton(command.getKey()));
       }
       return invokeNextInterceptor(ctx, command);
    }
@@ -83,7 +88,7 @@
             throws Throwable {
       boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
       if (localTxScope) {
-         return lockEagerly(ctx, Collections.singleton(command.getKey()));
+         lockEagerly(ctx, Collections.singleton(command.getKey()));
       }
       return invokeNextInterceptor(ctx, command);
    }

Added: trunk/core/src/test/java/org/infinispan/replication/SyncReplImplicitLockingTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/SyncReplImplicitLockingTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/replication/SyncReplImplicitLockingTest.java	2009-05-26 11:22:05 UTC (rev 340)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.replication;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.transaction.TransactionManager;
+
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.lookup.DummyTransactionManagerLookup;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for implicit locking
+ * 
+ * Transparent eager locking for transactions 
+ * https://jira.jboss.org/jira/browse/ISPN-70
+ * 
+ * @author <a href="mailto:vblagoje at redhat.com">Vladimir Blagojevic (vblagoje at redhat.com)</a>
+ */
+ at Test(groups = "functional", testName = "replication.SyncReplImplicitLockingTest")
+public class SyncReplImplicitLockingTest extends MultipleCacheManagersTest {
+   Cache<String, String> cache1, cache2;
+   String k = "key", v = "value";
+
+   protected void createCacheManagers() throws Throwable {
+      Configuration replSync = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC);
+      replSync.setLockAcquisitionTimeout(500);
+      replSync.setUseEagerLocking(true);
+      replSync.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+      createClusteredCaches(2, "replication.SyncReplImplicitLockingTest", replSync);
+
+      cache1 = manager(0).getCache("replication.SyncReplImplicitLockingTest");
+      cache2 = manager(1).getCache("replication.SyncReplImplicitLockingTest");
+   }
+
+   public void testLocksReleasedWithoutExplicitUnlock() throws Exception {
+      locksReleasedWithoutExplicitUnlockHelper(false);
+      locksReleasedWithoutExplicitUnlockHelper(true);
+   }
+
+   public void testConcurrentNonTxLocking() throws Exception {
+      concurrentLockingHelper(false, false);
+      concurrentLockingHelper(true, false);
+   }
+
+   public void testConcurrentTxLocking() throws Exception {
+      concurrentLockingHelper(false, true);
+      concurrentLockingHelper(true, true);
+   }
+
+   public void testLocksReleasedWithNoMods() throws Exception {
+      assertClusterSize("Should only be 2  caches in the cluster!!!", 2);
+
+      assertNull("Should be null", cache1.get(k));
+      assertNull("Should be null", cache2.get(k));
+
+      TransactionManager mgr = TestingUtil.getTransactionManager(cache1);
+      mgr.begin();
+
+      // do a dummy read
+      cache1.get(k);
+      mgr.commit();
+
+      assertNoLocks(cache1);
+      assertNoLocks(cache2);
+
+      cleanup();
+   }
+
+   private void concurrentLockingHelper(final boolean sameNode, final boolean useTx)
+            throws Exception {
+      assertClusterSize("Should only be 2  caches in the cluster!!!", 2);
+
+      assertNull("Should be null", cache1.get(k));
+      assertNull("Should be null", cache2.get(k));
+      final CountDownLatch latch = new CountDownLatch(1);
+
+      Thread t = new Thread() {
+         @Override
+         public void run() {
+            log.info("Concurrent " + (useTx ? "tx" : "non-tx") + " write started "
+                     + (sameNode ? "on same node..." : "on a different node..."));
+            TransactionManager mgr = null;
+            try {
+               if (useTx) {
+                  mgr = TestingUtil.getTransactionManager(sameNode ? cache1 : cache2);
+                  mgr.begin();
+               }
+               if (sameNode) {
+                  cache1.put(k, "JBC");
+               } else {
+                  cache2.put(k, "JBC");
+               }
+            } catch (Exception e) {
+               if (useTx) {
+                  try {
+                     mgr.commit();
+                  } catch (Exception e1) {
+                  }
+               }
+               latch.countDown();
+            }
+         }
+      };
+
+      String name = "Infinispan";
+      TransactionManager mgr = TestingUtil.getTransactionManager(cache1);
+      mgr.begin();
+      // lock node and start other thread whose write should now block
+      cache1.put(k, name);
+      t.start();
+
+      // wait till the put in thread t times out
+      assert latch.await(1, TimeUnit.SECONDS) : "Concurrent put didn't time out!";
+      mgr.commit();
+
+      t.join();
+
+      cache2.remove(k);
+      cleanup();
+   }
+
+   private void locksReleasedWithoutExplicitUnlockHelper(boolean useCommit) throws Exception {
+      assertClusterSize("Should only be 2  caches in the cluster!!!", 2);
+
+      assertNull("Should be null", cache1.get(k));
+      assertNull("Should be null", cache2.get(k));
+
+      String name = "Infinispan";
+      TransactionManager mgr = TestingUtil.getTransactionManager(cache1);
+      mgr.begin();
+
+      cache1.put(k, name);
+
+      if (useCommit)
+         mgr.commit();
+      else
+         mgr.rollback();
+
+      if (useCommit) {
+         assertEquals(name, cache1.get(k));
+         assertEquals("Should have replicated", name, cache2.get(k));
+      } else {
+         assertEquals(null, cache1.get(k));
+         assertEquals("Should not have replicated", null, cache2.get(k));
+      }
+
+      cache2.remove(k);
+      cleanup();
+   }
+
+   @SuppressWarnings("unchecked")
+   protected void assertNoLocks(Cache cache) {
+      /*
+       * TODO cache.keySet() is not implemented yet LockManager lm =
+       * TestingUtil.extractLockManager(cache); for (Object key : cache.keySet()) assert
+       * !lm.isLocked(key);
+       */
+   }
+
+   protected void cleanup() {
+      assert cache1.isEmpty();
+      assert cache2.isEmpty();
+      cache1.clear();
+      cache2.clear();
+   }
+}




More information about the infinispan-commits mailing list