package org.infinispan.lock;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.context.InvocationContext;
import org.infinispan.distribution.MagicKey;
import org.infinispan.interceptors.base.BaseCustomInterceptor;
import org.infinispan.interceptors.locking.NonTransactionalLockingInterceptor;
import org.infinispan.test.MultipleCacheManagersTest;
import org.infinispan.test.TestingUtil;
import org.infinispan.util.concurrent.locks.LockManager;
import org.testng.annotations.Test;
/**
* Tests if the {@link org.infinispan.remoting.inboundhandler.NonTotalOrderPerCacheInboundInvocationHandler} releases
* locks if an exception occurs before the locking interceptor.
*
* @author Pedro Ruivo
* @since 8.1
*/
@Test(groups = "functional", testName = "lock.SimpleRemoteLockTest")
public class SimpleRemoteLockTest extends MultipleCacheManagersTest {
@Override
protected void createCacheManagers() throws Throwable {
ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false);
builder.clustering().hash().numOwners(1);
builder.clustering().stateTransfer().fetchInMemoryState(false);
builder.customInterceptors().addInterceptor().before(NonTransactionalLockingInterceptor.class).interceptorClass(ExceptionInRemotePutInterceptor.class);
createClusteredCaches(2, builder);
}
public void testExceptionBeforeLockingInterceptor() {
final Object key = new MagicKey(cache(1));
final LockManager lockManager = TestingUtil.extractLockManager(cache(1));
assertFalse(lockManager.isLocked(key));
try {
cache(0).put(key, "foo");
fail("Exception expected!");
} catch (Exception e) {
//expected
assertEquals("Induced Exception!", e.getCause().getMessage());
}
//it sends the reply before invoke the finally. So, we need to use eventually :)
eventually(() -> !lockManager.isLocked(key));
}
public static class ExceptionInRemotePutInterceptor extends BaseCustomInterceptor {
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
if (ctx.isOriginLocal()) {
return invokeNextInterceptor(ctx, command);
}
assertTrue(TestingUtil.extractLockManager(cache).isLocked(command.getKey()));
throw new RuntimeException("Induced Exception!");
}
}
}