use of org.infinispan.statetransfer.StateChunk in project infinispan by infinispan.
the class ScatteredStateProviderImpl method invalidateChunks.
private void invalidateChunks(Collection<StateChunk> stateChunks, Set<Address> otherMembers, AtomicInteger outboundInvalidations, CompletableFuture<Void> invalidationFuture, CacheTopology cacheTopology) {
int numEntries = stateChunks.stream().mapToInt(chunk -> chunk.getCacheEntries().size()).sum();
if (numEntries == 0) {
log.tracef("Nothing to invalidate");
return;
}
Object[] keys = new Object[numEntries];
int[] topologyIds = new int[numEntries];
long[] versions = new long[numEntries];
int i = 0;
for (StateChunk chunk : stateChunks) {
for (InternalCacheEntry entry : chunk.getCacheEntries()) {
// we have replicated the non-versioned entries but we won't invalidate them elsewhere
if (entry.getMetadata() != null && entry.getMetadata().version() != null) {
keys[i] = entry.getKey();
SimpleClusteredVersion version = (SimpleClusteredVersion) entry.getMetadata().version();
topologyIds[i] = version.getTopologyId();
versions[i] = version.getVersion();
++i;
}
}
}
if (log.isTraceEnabled()) {
log.tracef("Invalidating %d entries from segments %s", numEntries, stateChunks.stream().map(StateChunk::getSegmentId).collect(Collectors.toList()));
}
outboundInvalidations.incrementAndGet();
rpcManager.invokeCommand(otherMembers, commandsFactory.buildInvalidateVersionsCommand(cacheTopology.getTopologyId(), keys, topologyIds, versions, true), MapResponseCollector.ignoreLeavers(otherMembers.size()), rpcManager.getSyncRpcOptions()).whenComplete((r, t) -> {
try {
if (t != null) {
log.failedInvalidatingRemoteCache(t);
}
} finally {
if (outboundInvalidations.decrementAndGet() == 0) {
invalidationFuture.complete(null);
}
}
});
}
use of org.infinispan.statetransfer.StateChunk 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