use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class ClientSlowDiscoveryTopologyChangeTest method testClientJoinAndCacheStop.
/**
* Test check that client join works well if cache configured on it stopped on server nodes
* but discovery event about cache stop is not delivered to client node immediately.
* When client node joins to cluster it sends SingleMessage to coordinator.
* During this time topology on server nodes can be changed,
* because client exchange doesn't require acknowledgement for SingleMessage on coordinator.
* Delay is simulated by blocking sending this SingleMessage and resume sending after topology is changed.
*/
@Test
public void testClientJoinAndCacheStop() throws Exception {
IgniteEx crd = (IgniteEx) startGridsMultiThreaded(3);
awaitPartitionMapExchange();
for (int k = 0; k < 64; k++) crd.cache(CACHE_NAME).put(k, k);
TestRecordingCommunicationSpi clientCommSpi = new TestRecordingCommunicationSpi();
// Delay client join process.
clientCommSpi.blockMessages((node, msg) -> {
if (!(msg instanceof GridDhtPartitionsSingleMessage))
return false;
GridDhtPartitionsSingleMessage singleMsg = (GridDhtPartitionsSingleMessage) msg;
return Optional.ofNullable(singleMsg.exchangeId()).map(GridDhtPartitionExchangeId::topologyVersion).filter(topVer -> topVer.equals(new AffinityTopologyVersion(4, 0))).isPresent();
});
communicationSpiSupplier = () -> clientCommSpi;
CustomMessageInterceptingDiscoverySpi clientDiscoSpi = new CustomMessageInterceptingDiscoverySpi();
CountDownLatch clientDiscoSpiBlock = new CountDownLatch(1);
// Delay cache destroying on client node.
clientDiscoSpi.interceptor = (msg) -> {
if (!(msg instanceof DynamicCacheChangeBatch))
return;
DynamicCacheChangeBatch cacheChangeBatch = (DynamicCacheChangeBatch) msg;
boolean hasCacheStopReq = cacheChangeBatch.requests().stream().anyMatch(req -> req.stop() && req.cacheName().equals(CACHE_NAME));
if (hasCacheStopReq)
U.awaitQuiet(clientDiscoSpiBlock);
};
discoverySpiSupplier = () -> clientDiscoSpi;
IgniteInternalFuture<IgniteEx> clientStartFut = GridTestUtils.runAsync(() -> startClientGrid(3));
// Wait till client node starts join process.
clientCommSpi.waitForBlocked();
// Destroy cache on server nodes.
crd.destroyCache(CACHE_NAME);
// Resume client join.
clientCommSpi.stopBlock();
// Client join should succeed.
IgniteEx client = clientStartFut.get();
IgniteCache<Object, Object> clientCache = client.cache(CACHE_NAME);
Assert.assertNotNull("Cache should exists on client node", clientCache);
IgniteInternalFuture<?> cacheGet = GridTestUtils.runAsync(() -> clientCache.get(0));
try {
// Reasonable timeout.
cacheGet.get(5_000);
fail("Cache get operation should throw " + CacheStoppedException.class);
} catch (Exception e) {
assertTrue("Got unexpected exception during cache get " + e, X.hasCause(e, CacheStoppedException.class));
} finally {
// Resume processing cache destroy on client node.
clientDiscoSpiBlock.countDown();
}
// Wait till cache destroyed on client node.
GridTestUtils.waitForCondition(() -> {
AffinityTopologyVersion topVer = client.context().cache().context().exchange().lastFinishedFuture().topologyVersion();
// Cache destroy version.
return topVer.equals(new AffinityTopologyVersion(4, 1));
}, // Reasonable timeout.
5_000);
Assert.assertNull("Cache should be destroyed on client node", client.cache(CACHE_NAME));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class IgniteClientReconnectDelayedSpiTest method testReconnectCacheDestroyedDelayedAffinityChange.
/**
* Test checks correctness of stale {@link CacheAffinityChangeMessage} processing by client node as delayed
* {@link GridDhtPartitionsSingleMessage} with exchId = null sends after client node reconnect happens.
*
* @throws Exception If failed.
*/
@Test
public void testReconnectCacheDestroyedDelayedAffinityChange() throws Exception {
Ignite ignite = ignite(1);
TestRecordingCommunicationSpi spi = TestRecordingCommunicationSpi.spi(ignite);
spi.blockMessages(GridDhtPartitionsSingleMessage.class, ignite.name());
spi.blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode node, Message msg) {
return (msg instanceof GridDhtPartitionsSingleMessage) && ((GridDhtPartitionsAbstractMessage) msg).exchangeId() == null;
}
});
final Ignite client = startClientGrid(getConfiguration());
client.getOrCreateCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME));
final Ignite srv = clientRouter(client);
reconnectClientNode(client, srv, new Runnable() {
@Override
public void run() {
srv.destroyCache(DEFAULT_CACHE_NAME);
srv.getOrCreateCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME));
}
});
// Resend delayed GridDhtPartitionsSingleMessage.
spi.waitForBlocked();
spi.stopBlock();
assertNotNull(client.cache(DEFAULT_CACHE_NAME));
final GridDiscoveryManager srvDisco = ((IgniteEx) srv).context().discovery();
assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override
public boolean apply() {
return F.eq(true, srvDisco.cacheClientNode(client.cluster().localNode(), DEFAULT_CACHE_NAME));
}
}, 5000));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class TxPartitionCounterStateConsistencyTest method testLateAffinityChangeDuringExchange.
/**
* Tests a scenario when stale partition state message can trigger spurious late affinity switching followed by
* possible primary mapping to moving partition.
*/
@Test
public void testLateAffinityChangeDuringExchange() throws Exception {
backups = 2;
Ignite crd = startGridsMultiThreaded(3);
crd.cluster().active(true);
awaitPartitionMapExchange();
for (int p = 0; p < PARTS_CNT; p++) crd.cache(DEFAULT_CACHE_NAME).put(p, p);
forceCheckpoint();
int key = primaryKey(grid(2).cache(DEFAULT_CACHE_NAME));
TestRecordingCommunicationSpi.spi(grid(1)).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode clusterNode, Message msg) {
if (msg instanceof GridDhtPartitionsSingleMessage) {
GridDhtPartitionsSingleMessage msg0 = (GridDhtPartitionsSingleMessage) msg;
return msg0.exchangeId() == null && msg0.partitions().get(CU.cacheId(DEFAULT_CACHE_NAME)).topologyVersion().equals(new AffinityTopologyVersion(4, 0));
}
return false;
}
});
stopGrid(2);
// Fill a queue with a lot of messages.
for (int i = 0; i < 1000; i++) grid(1).context().cache().context().exchange().refreshPartitions();
TestRecordingCommunicationSpi.spi(grid(1)).waitForBlocked(1000);
// Create counter delta for triggering counter rebalance.
for (int p = 0; p < PARTS_CNT; p++) crd.cache(DEFAULT_CACHE_NAME).put(p, p + 1);
IgniteConfiguration cfg2 = getConfiguration(getTestIgniteInstanceName(2));
TestRecordingCommunicationSpi spi2 = (TestRecordingCommunicationSpi) cfg2.getCommunicationSpi();
spi2.blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode clusterNode, Message msg) {
if (msg instanceof GridDhtPartitionDemandMessage)
// Prevent any rebalancing to avoid switching partitions to owning.
return true;
if (msg instanceof GridDhtPartitionsSingleMessage) {
GridDhtPartitionsSingleMessage msg0 = (GridDhtPartitionsSingleMessage) msg;
return msg0.exchangeId() != null && msg0.exchangeId().topologyVersion().equals(new AffinityTopologyVersion(5, 0));
}
return false;
}
});
GridTestUtils.runAsync(new Callable<Void>() {
@Override
public Void call() throws Exception {
startGrid(cfg2);
return null;
}
});
// Delay last single message. It should trigger PME for version 5,0
spi2.waitForBlocked();
// Start processing single messages.
TestRecordingCommunicationSpi.spi(grid(1)).stopBlock();
// Allow PME to finish.
spi2.stopBlock();
grid(0).context().cache().context().exchange().affinityReadyFuture(new AffinityTopologyVersion(5, 1)).get();
// Primary node for a key will be stopped by FH without a fix.
grid(0).cache(DEFAULT_CACHE_NAME).put(key, -1);
for (int i = 0; i < 1000; i++) assertEquals(-1, grid(2).cache(DEFAULT_CACHE_NAME).get(key));
assertPartitionsSame(idleVerify(crd, DEFAULT_CACHE_NAME));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class CacheMvccPartitionedSqlTxQueriesWithReducerTest method testQueryUpdateOnUnstableTopologyDoesNotCauseDeadlock.
/**
* @throws Exception If failed.
*/
@Test
public void testQueryUpdateOnUnstableTopologyDoesNotCauseDeadlock() throws Exception {
ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, DFLT_PARTITION_COUNT).setIndexedTypes(Integer.class, CacheMvccSqlTxQueriesAbstractTest.MvccTestSqlIndexValue.class);
testSpi = true;
Ignite updateNode = startGrids(3);
CountDownLatch latch = new CountDownLatch(1);
TestRecordingCommunicationSpi spi = TestRecordingCommunicationSpi.spi(grid(1));
spi.blockMessages((node, msg) -> {
if (msg instanceof GridDhtPartitionsSingleMessage) {
latch.countDown();
return true;
}
return false;
});
CompletableFuture.runAsync(() -> stopGrid(2));
assertTrue(latch.await(TX_TIMEOUT, TimeUnit.MILLISECONDS));
CompletableFuture<Void> queryFut = CompletableFuture.runAsync(() -> updateNode.cache(DEFAULT_CACHE_NAME).query(new SqlFieldsQuery("INSERT INTO MvccTestSqlIndexValue (_key, idxVal1) VALUES (1,1),(2,2),(3,3)")).getAll());
Thread.sleep(300);
spi.stopBlock();
try {
queryFut.get(TX_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
assertTrue(X.hasCause(e, ClusterTopologyException.class));
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class IgniteClusterSnapshotRestoreSelfTest method checkNodeLeftOnExchangeFinish.
/**
* @param crdStop {@code True} to stop coordinator node.
* @param expCls Expected exception class.
* @param expMsg Expected exception message.
* @throws Exception If failed.
*/
private void checkNodeLeftOnExchangeFinish(boolean crdStop, Class<? extends Throwable> expCls, String expMsg) throws Exception {
startGridsWithSnapshot(3, CACHE_KEYS_RANGE, true);
TestRecordingCommunicationSpi node1spi = TestRecordingCommunicationSpi.spi(grid(1));
TestRecordingCommunicationSpi node2spi = TestRecordingCommunicationSpi.spi(grid(2));
node1spi.blockMessages((node, msg) -> msg instanceof GridDhtPartitionsSingleMessage);
node2spi.blockMessages((node, msg) -> msg instanceof GridDhtPartitionsSingleMessage);
IgniteFuture<Void> fut = grid(1).snapshot().restoreSnapshot(SNAPSHOT_NAME, Collections.singleton(DEFAULT_CACHE_NAME));
node1spi.waitForBlocked();
node2spi.waitForBlocked();
stopGrid(crdStop ? 0 : 2, true);
node1spi.stopBlock();
if (crdStop)
node2spi.stopBlock();
GridTestUtils.assertThrowsAnyCause(log, () -> fut.get(TIMEOUT), expCls, expMsg);
awaitPartitionMapExchange();
ensureCacheAbsent(dfltCacheCfg);
}
Aggregations