use of org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler in project infinispan by infinispan.
the class ConditionalOperationPrimaryOwnerFailTest method testEntryNotWrapped.
public void testEntryNotWrapped() throws Throwable {
assertClusterSize("Wrong cluster size!", 3);
final Object key = new MagicKey(cache(0), cache(1));
final Cache<Object, Object> futureBackupOwnerCache = cache(2);
cache(0).put(key, INITIAL_VALUE);
final PerCacheInboundInvocationHandler spyHandler = spyInvocationHandler(futureBackupOwnerCache);
final EntryFactory spyEntryFactory = spyEntryFactory(futureBackupOwnerCache);
// it blocks the StateResponseCommand.class
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
doAnswer(invocation -> {
CacheRpcCommand command = (CacheRpcCommand) invocation.getArguments()[0];
if (command instanceof StateResponseCommand) {
log.debugf("Blocking command %s", command);
latch2.countDown();
latch1.await();
}
return invocation.callRealMethod();
}).when(spyHandler).handle(any(CacheRpcCommand.class), any(Reply.class), any(DeliverOrder.class));
doAnswer(invocation -> {
InvocationContext context = (InvocationContext) invocation.getArguments()[0];
log.debugf("wrapEntryForWriting invoked with %s", context);
CompletionStage<Void> stage = (CompletionStage<Void>) invocation.callRealMethod();
CompletionStages.join(stage);
assertNull(context.lookupEntry(key), "Entry should not be wrapped!");
return stage;
}).when(spyEntryFactory).wrapEntryForWriting(any(InvocationContext.class), any(), anyInt(), anyBoolean(), anyBoolean(), any());
Future<?> killMemberResult = fork(() -> killMember(1));
// await until the key is received from state transfer (the command is blocked now...)
latch2.await(30, TimeUnit.SECONDS);
futureBackupOwnerCache.put(key, FINAL_VALUE);
latch1.countDown();
killMemberResult.get(30, TimeUnit.SECONDS);
}
use of org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler in project infinispan by infinispan.
the class PrepareProcessedAfterOriginatorCrashTest method testBelatedTransactionDoesntLeak.
public void testBelatedTransactionDoesntLeak() throws Throwable {
CountDownLatch prepareReceived = new CountDownLatch(1);
CountDownLatch prepareBlocked = new CountDownLatch(1);
CountDownLatch prepareExecuted = new CountDownLatch(1);
Cache receiver = cache(1);
PerCacheInboundInvocationHandler originalInvocationHandler = TestingUtil.extractComponent(receiver, PerCacheInboundInvocationHandler.class);
PerCacheInboundInvocationHandler blockingInvocationHandler = new AbstractDelegatingHandler(originalInvocationHandler) {
@Override
public void handle(CacheRpcCommand command, Reply reply, DeliverOrder order) {
if (!(command instanceof PrepareCommand)) {
delegate.handle(command, reply, order);
return;
}
try {
prepareReceived.countDown();
prepareBlocked.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalLifecycleStateException(e);
}
log.trace("Processing belated prepare");
delegate.handle(command, returnValue -> {
prepareExecuted.countDown();
reply.reply(returnValue);
}, order);
}
};
TestingUtil.replaceComponent(receiver, PerCacheInboundInvocationHandler.class, blockingInvocationHandler, true);
TestingUtil.extractComponentRegistry(receiver).cacheComponents();
final Object key = getKeyForCache(1);
fork(() -> {
try {
cache(0).put(key, "v");
} catch (Throwable e) {
// possible as the node is being killed
}
});
prepareReceived.await(10, TimeUnit.SECONDS);
killMember(0);
// give TransactionTable.cleanupStaleTransactions some time to run
Thread.sleep(5000);
prepareBlocked.countDown();
prepareExecuted.await(10, TimeUnit.SECONDS);
log.trace("Finished waiting for belated prepare to complete");
final TransactionTable transactionTable = TestingUtil.getTransactionTable(receiver);
assertEquals(0, transactionTable.getRemoteTxCount());
assertEquals(0, transactionTable.getLocalTxCount());
assertFalse(receiver.getAdvancedCache().getLockManager().isLocked(key));
}
use of org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler in project infinispan by infinispan.
the class PushTransferTest method testNodeJoin.
public void testNodeJoin() throws Exception {
List<MagicKey> keys = init();
EmbeddedCacheManager cm4 = addClusterEnabledCacheManager(TestDataSCI.INSTANCE, null, TRANSPORT_FLAGS);
cm4.defineConfiguration(CACHE_NAME, defaultConfig.build());
int startTopologyId = c1.getAdvancedCache().getDistributionManager().getCacheTopology().getTopologyId();
BlockingLocalTopologyManager bltm = BlockingLocalTopologyManager.replaceTopologyManager(cm4, CACHE_NAME);
CountDownLatch statePushedLatch = new CountDownLatch(1);
CountDownLatch stateAppliedLatch = new CountDownLatch(1);
TestingUtil.addCacheStartingHook(cm4, (name, cr) -> {
PerCacheInboundInvocationHandler originalHandler = cr.getComponent(PerCacheInboundInvocationHandler.class);
AbstractDelegatingHandler newHandler = new AbstractDelegatingHandler(originalHandler) {
@Override
public void handle(CacheRpcCommand command, Reply reply, DeliverOrder order) {
// StateResponseCommand is topology-aware, so handle() just queues it on the remote executor
if (command instanceof StateResponseCommand) {
log.tracef("State received on %s", cm4.getAddress());
statePushedLatch.countDown();
}
originalHandler.handle(command, response -> {
log.tracef("State applied on %s", cm4.getAddress());
stateAppliedLatch.countDown();
reply.reply(response);
}, order);
}
};
BasicComponentRegistry bcr = cr.getComponent(BasicComponentRegistry.class);
bcr.replaceComponent(PerCacheInboundInvocationHandler.class.getName(), newHandler, false);
cr.rewire();
cr.cacheComponents();
});
Future<Cache> c4Future = fork(() -> cm4.getCache(CACHE_NAME));
// Any StateResponseCommand should be delayed until node 4 has the TRANSITORY topology
assertTrue(statePushedLatch.await(10, TimeUnit.SECONDS));
assertFalse(stateAppliedLatch.await(100, TimeUnit.MILLISECONDS));
// Finish the rebalance, unblocking the StateResponseCommand(s)
bltm.confirmTopologyUpdate(CacheTopology.Phase.TRANSITORY);
assertEquals(0, stateAppliedLatch.getCount());
bltm.confirmTopologyUpdate(CacheTopology.Phase.NO_REBALANCE);
Cache c4 = c4Future.get(30, TimeUnit.SECONDS);
TestingUtil.blockUntilViewsReceived(30000, false, c1, c2, c3, c4);
TestingUtil.waitForNoRebalance(c1, c2, c3, c4);
for (MagicKey key : keys) {
int copies = Stream.of(c1, c2, c3, c4).mapToInt(c -> c.getAdvancedCache().getDataContainer().containsKey(key) ? 1 : 0).sum();
assertEquals("Key " + key + " has incorrect number of copies", 2, copies);
}
}
use of org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler in project infinispan by infinispan.
the class TestingUtil method wrapInboundInvocationHandler.
public static <T extends PerCacheInboundInvocationHandler> T wrapInboundInvocationHandler(Cache<?, ?> cache, Function<PerCacheInboundInvocationHandler, T> ctor) {
PerCacheInboundInvocationHandler current = extractComponent(cache, PerCacheInboundInvocationHandler.class);
T wrap = ctor.apply(current);
replaceComponent(cache, PerCacheInboundInvocationHandler.class, wrap, true);
return wrap;
}
use of org.infinispan.remoting.inboundhandler.PerCacheInboundInvocationHandler in project infinispan by infinispan.
the class StateResponseOrderingTest method testSimulatedOldStateResponse.
public void testSimulatedOldStateResponse() throws Throwable {
// Initial owners for both segments are cache 1, 2, and 3
// Start a rebalance, with cache 0 becoming an owner of both CH segments
// Block the first StateTransferStartCommand on cache 0
// While state transfer is blocked, simulate an old state response command on cache 0
// Check that the old command is ignored and state transfer completes successfully
StateSequencer sequencer = new StateSequencer();
sequencer.logicalThread("st", "st:block_state_request", "st:simulate_old_response", "st:resume_state_request");
cache(1).put("k1", "v1");
cache(2).put("k2", "v2");
cache(3).put("k3", "v3");
DistributionManager dm0 = advancedCache(0).getDistributionManager();
final int initialTopologyId = dm0.getCacheTopology().getTopologyId();
assertEquals(Arrays.asList(address(1), address(2), address(3)), dm0.getCacheTopology().getDistribution("k1").readOwners());
assertNull(dm0.getCacheTopology().getPendingCH());
// Block when cache 0 sends the first state request to cache 1
CommandMatcher segmentRequestMatcher = command -> command instanceof StateTransferStartCommand && ((StateTransferStartCommand) command).getTopologyId() == initialTopologyId + 1;
advanceOnOutboundRpc(sequencer, cache(0), segmentRequestMatcher).before("st:block_state_request", "st:resume_state_request");
// Cache 0 will become an owner and will request state from cache 1
consistentHashFactory.setOwnerIndexes(new int[][] { { 0, 1, 2 }, { 0, 1, 2 } });
consistentHashFactory.triggerRebalance(cache(0));
sequencer.enter("st:simulate_old_response");
assertNotNull(dm0.getCacheTopology().getPendingCH());
assertEquals(Arrays.asList(address(0), address(1), address(2)), dm0.getCacheTopology().getPendingCH().locateOwnersForSegment(0));
assertEquals(Arrays.asList(address(1), address(2), address(3), address(0)), dm0.getCacheTopology().getDistribution("k1").writeOwners());
// Cache 0 didn't manage to request any segments yet, but it has registered all the inbound transfer tasks.
// We'll pretend it got a StateResponseCommand with an older topology id.
PerCacheInboundInvocationHandler handler = TestingUtil.extractComponent(cache(0), PerCacheInboundInvocationHandler.class);
StateChunk stateChunk0 = new StateChunk(0, Arrays.asList(new ImmortalCacheEntry("k0", "v0")), true);
StateChunk stateChunk1 = new StateChunk(1, Arrays.asList(new ImmortalCacheEntry("k0", "v0")), true);
String cacheName = manager(0).getCacheManagerConfiguration().defaultCacheName().get();
StateResponseCommand stateResponseCommand = new StateResponseCommand(ByteString.fromString(cacheName), initialTopologyId, Arrays.asList(stateChunk0, stateChunk1), true, false);
// Call with preserveOrder = true to force the execution in the same thread
stateResponseCommand.setOrigin(address(3));
handler.handle(stateResponseCommand, Reply.NO_OP, DeliverOrder.PER_SENDER);
sequencer.exit("st:simulate_old_response");
waitForNoRebalance(cache(0), cache(1), cache(2), cache(3));
// Check that state wasn't lost
assertTrue(dm0.getCacheTopology().isReadOwner("k1"));
assertTrue(dm0.getCacheTopology().isReadOwner("k2"));
assertTrue(dm0.getCacheTopology().isReadOwner("k3"));
assertEquals("v1", cache(0).get("k1"));
assertEquals("v2", cache(0).get("k2"));
assertEquals("v3", cache(0).get("k3"));
// Check that the old state response was ignored
assertNull(cache(0).get("k0"));
}
Aggregations