Search in sources :

Example 1 with LockControlCommand

use of org.infinispan.commands.control.LockControlCommand in project infinispan by infinispan.

the class InfinispanNodeFailureTest method killedNodeDoesNotBreakReplaceCommand.

public void killedNodeDoesNotBreakReplaceCommand() throws Exception {
    defineConfigurationOnAllManagers(TEST_CACHE, new ConfigurationBuilder().read(manager(0).getDefaultCacheConfiguration()));
    waitForClusterToForm(TEST_CACHE);
    waitForNoRebalance(caches(TEST_CACHE));
    final Object replaceKey = new MagicKey("X", cache(0, TEST_CACHE));
    final Object putKey = new MagicKey("Z", cache(1, TEST_CACHE));
    cache(0, TEST_CACHE).put(replaceKey, INITIAL_VALUE);
    // prepare third node to notify us when put command is in progress so we can kill the node
    final CountDownLatch beforeKill = new CountDownLatch(1);
    final CountDownLatch afterKill = new CountDownLatch(1);
    advancedCache(1, TEST_CACHE).getAsyncInterceptorChain().addInterceptor(new BaseCustomAsyncInterceptor() {

        @Override
        public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
            return invokeNextAndFinally(ctx, command, (rCtx, rCommand, rv, t) -> {
                LockControlCommand cmd = (LockControlCommand) rCommand;
                if (putKey.equals(cmd.getSingleKey())) {
                    // notify main thread it can start killing third node
                    beforeKill.countDown();
                    // wait for completion and proceed
                    afterKill.await(10, TimeUnit.SECONDS);
                }
            });
        }
    }, 1);
    // execute replace command in separate thread so we can do something else meanwhile
    Future<Boolean> firstResult = fork(() -> {
        try {
            tm(0, TEST_CACHE).begin();
            // this should replace and lock REPLACE_KEY so other transactions can't pass this barrier
            boolean result = cache(0, TEST_CACHE).replace(replaceKey, INITIAL_VALUE, REPLACING_VALUE);
            // issue put command so it is retried while node-c is being killed
            cache(0, TEST_CACHE).put(putKey, "some-value");
            // apply new view
            viewLatch.countDown();
            tm(0, TEST_CACHE).commit();
            return result;
        } catch (Throwable t) {
            return null;
        }
    });
    // wait third node to complete replace command and kill it
    assertTrue(beforeKill.await(10, TimeUnit.SECONDS));
    // kill node-c, do not wait rehash, it is important to continue with put-retry before new view is received
    killMember(2, TEST_CACHE, false);
    afterKill.countDown();
    tm(1, TEST_CACHE).begin();
    // this replace should never succeed because first node has already replaced and locked value
    // but during put command replace lock is lost, so we can successfully replace the same value again, which is a bug
    boolean secondResult = cache(1, TEST_CACHE).replace(replaceKey, INITIAL_VALUE, REPLACING_VALUE);
    tm(1, TEST_CACHE).commit();
    // check that first node did not fail
    assertEquals(Boolean.TRUE, firstResult.get());
    assertEquals(REPLACING_VALUE, cache(0, TEST_CACHE).get(replaceKey));
    assertEquals(REPLACING_VALUE, cache(1, TEST_CACHE).get(replaceKey));
    // check that second node state is inconsistent, second result should be FALSE in read committed pessimistic cache
    // uncomment when this bug is fixed
    assertEquals(false, secondResult);
}
Also used : MagicKey(org.infinispan.distribution.MagicKey) TestDataSCI(org.infinispan.test.TestDataSCI) TestingUtil.waitForNoRebalance(org.infinispan.test.TestingUtil.waitForNoRebalance) ConfigurationBuilder(org.infinispan.configuration.cache.ConfigurationBuilder) MultipleCacheManagersTest(org.infinispan.test.MultipleCacheManagersTest) GlobalConfigurationBuilder(org.infinispan.configuration.global.GlobalConfigurationBuilder) LockingMode(org.infinispan.transaction.LockingMode) Test(org.testng.annotations.Test) AssertJUnit.assertTrue(org.testng.AssertJUnit.assertTrue) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) Future(java.util.concurrent.Future) CacheMode(org.infinispan.configuration.cache.CacheMode) IsolationLevel(org.infinispan.util.concurrent.IsolationLevel) BaseCustomAsyncInterceptor(org.infinispan.interceptors.BaseCustomAsyncInterceptor) TxInvocationContext(org.infinispan.context.impl.TxInvocationContext) DelayedViewJGroupsTransport(org.infinispan.test.transport.DelayedViewJGroupsTransport) LockControlCommand(org.infinispan.commands.control.LockControlCommand) EmbeddedTransactionManagerLookup(org.infinispan.transaction.lookup.EmbeddedTransactionManagerLookup) AssertJUnit.assertEquals(org.testng.AssertJUnit.assertEquals) ConfigurationBuilder(org.infinispan.configuration.cache.ConfigurationBuilder) GlobalConfigurationBuilder(org.infinispan.configuration.global.GlobalConfigurationBuilder) CountDownLatch(java.util.concurrent.CountDownLatch) BaseCustomAsyncInterceptor(org.infinispan.interceptors.BaseCustomAsyncInterceptor) TxInvocationContext(org.infinispan.context.impl.TxInvocationContext) MagicKey(org.infinispan.distribution.MagicKey) LockControlCommand(org.infinispan.commands.control.LockControlCommand)

Example 2 with LockControlCommand

use of org.infinispan.commands.control.LockControlCommand in project infinispan by infinispan.

the class CacheImpl method lock.

boolean lock(Collection<? extends K> keys, long flagsBitSet) {
    if (!transactional)
        throw new UnsupportedOperationException("Calling lock() on non-transactional caches is not allowed");
    if (keys == null || keys.isEmpty()) {
        throw new IllegalArgumentException("Cannot lock empty list of keys");
    }
    InvocationContext ctx = invocationContextFactory.createInvocationContext(true, UNBOUNDED);
    LockControlCommand command = commandsFactory.buildLockControlCommand(keys, flagsBitSet);
    if (ctx.getLockOwner() == null) {
        ctx.setLockOwner(command.getKeyLockOwner());
    }
    return invocationHelper.invoke(ctx, command);
}
Also used : InvocationContext(org.infinispan.context.InvocationContext) LockControlCommand(org.infinispan.commands.control.LockControlCommand)

Example 3 with LockControlCommand

use of org.infinispan.commands.control.LockControlCommand in project infinispan by infinispan.

the class PessimisticLockingInterceptor method visitDataWriteCommand.

@Override
protected Object visitDataWriteCommand(InvocationContext ctx, DataWriteCommand command) throws Throwable {
    Object maybeStage;
    Object key = command.getKey();
    if (hasSkipLocking(command)) {
        // Non-modifying functional write commands are executed in non-transactional context on non-originators
        if (ctx.isInTxScope()) {
            // Mark the key as affected even with SKIP_LOCKING
            ((TxInvocationContext<?>) ctx).addAffectedKey(key);
        }
        maybeStage = invokeNext(ctx, command);
    } else {
        if (!needRemoteLocks(ctx, key, command)) {
            maybeStage = acquireLocalLockAndInvokeNext(ctx, command);
        } else {
            final TxInvocationContext txContext = (TxInvocationContext) ctx;
            LockControlCommand lcc = cf.buildLockControlCommand(key, command.getFlagsBitSet(), txContext.getGlobalTransaction());
            lcc.setTopologyId(command.getTopologyId());
            // the chain again with the actual command
            return invokeNextThenApply(ctx, lcc, (rCtx, rCommand, rv) -> acquireLocalLockAndInvokeNext(rCtx, command));
        }
    }
    return maybeStage;
}
Also used : TxInvocationContext(org.infinispan.context.impl.TxInvocationContext) LockControlCommand(org.infinispan.commands.control.LockControlCommand)

Example 4 with LockControlCommand

use of org.infinispan.commands.control.LockControlCommand in project infinispan by infinispan.

the class AsyncInterceptorChainInvocationTest method testInvokeNextSubCommand.

public void testInvokeNextSubCommand() {
    AsyncInterceptorChain chain = newInterceptorChain(new BaseAsyncInterceptor() {

        @Override
        public Object visitCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
            return invokeNext(ctx, testSubCommand);
        }
    }, new BaseAsyncInterceptor() {

        @Override
        public Object visitCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
            return command instanceof LockControlCommand ? "subCommand" : "command";
        }
    });
    InvocationContext context = newInvocationContext();
    Object returnValue = chain.invoke(context, testCommand);
    assertEquals("subCommand", returnValue);
}
Also used : VisitableCommand(org.infinispan.commands.VisitableCommand) BaseAsyncInterceptor(org.infinispan.interceptors.BaseAsyncInterceptor) AsyncInterceptorChain(org.infinispan.interceptors.AsyncInterceptorChain) SingleKeyNonTxInvocationContext(org.infinispan.context.impl.SingleKeyNonTxInvocationContext) InvocationContext(org.infinispan.context.InvocationContext) LockControlCommand(org.infinispan.commands.control.LockControlCommand)

Example 5 with LockControlCommand

use of org.infinispan.commands.control.LockControlCommand in project infinispan by infinispan.

the class AsyncInterceptorChainInvocationTest method testInvokeNextAsyncSubCommand.

public void testInvokeNextAsyncSubCommand() throws Exception {
    CompletableFuture<Object> f = new CompletableFuture<>();
    AsyncInterceptorChain chain = newInterceptorChain(new BaseAsyncInterceptor() {

        @Override
        public Object visitCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
            return asyncInvokeNext(ctx, testSubCommand, f);
        }
    }, new BaseAsyncInterceptor() {

        @Override
        public Object visitCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
            return command instanceof LockControlCommand ? "subCommand" : "command";
        }
    });
    InvocationContext context = newInvocationContext();
    CompletableFuture<Object> invokeFuture = chain.invokeAsync(context, testCommand);
    assertFalse(invokeFuture.isDone());
    f.complete("v");
    assertEquals("subCommand", invokeFuture.get(10, SECONDS));
}
Also used : VisitableCommand(org.infinispan.commands.VisitableCommand) CompletableFuture(java.util.concurrent.CompletableFuture) BaseAsyncInterceptor(org.infinispan.interceptors.BaseAsyncInterceptor) AsyncInterceptorChain(org.infinispan.interceptors.AsyncInterceptorChain) SingleKeyNonTxInvocationContext(org.infinispan.context.impl.SingleKeyNonTxInvocationContext) InvocationContext(org.infinispan.context.InvocationContext) LockControlCommand(org.infinispan.commands.control.LockControlCommand)

Aggregations

LockControlCommand (org.infinispan.commands.control.LockControlCommand)11 TxInvocationContext (org.infinispan.context.impl.TxInvocationContext)6 InvocationContext (org.infinispan.context.InvocationContext)5 VisitableCommand (org.infinispan.commands.VisitableCommand)4 InvocationStage (org.infinispan.interceptors.InvocationStage)4 AsyncInterceptorChain (org.infinispan.interceptors.AsyncInterceptorChain)3 SyncInvocationStage (org.infinispan.interceptors.SyncInvocationStage)3 ArrayList (java.util.ArrayList)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Map (java.util.Map)2 CommandsFactory (org.infinispan.commands.CommandsFactory)2 FlagAffectedCommand (org.infinispan.commands.FlagAffectedCommand)2 TopologyAffectedCommand (org.infinispan.commands.TopologyAffectedCommand)2 ReadWriteKeyCommand (org.infinispan.commands.functional.ReadWriteKeyCommand)2 ReadWriteKeyValueCommand (org.infinispan.commands.functional.ReadWriteKeyValueCommand)2 ReadWriteManyCommand (org.infinispan.commands.functional.ReadWriteManyCommand)2 ReadWriteManyEntriesCommand (org.infinispan.commands.functional.ReadWriteManyEntriesCommand)2 WriteOnlyKeyCommand (org.infinispan.commands.functional.WriteOnlyKeyCommand)2 WriteOnlyKeyValueCommand (org.infinispan.commands.functional.WriteOnlyKeyValueCommand)2