use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class IgniteCacheClientMultiNodeUpdateTopologyLockTest method testPessimisticTx.
/**
* @throws Exception If failed.
*/
@Test
public void testPessimisticTx() throws Exception {
startGrids(3);
Ignite clientNode = startClientGrid(3);
IgniteCache<Integer, Integer> cache = clientNode.createCache(cacheConfiguration(0, FULL_SYNC));
awaitPartitionMapExchange();
Integer key1 = movingKeysAfterJoin(ignite(1), TEST_CACHE, 1).get(0);
Integer key2 = movingKeysAfterJoin(ignite(2), TEST_CACHE, 1).get(0);
log.info("Start tx [key1=" + key1 + ", key2=" + key2 + ']');
IgniteInternalFuture<?> startFut;
TestRecordingCommunicationSpi spi2 = TestRecordingCommunicationSpi.spi(ignite(2));
final TestRecordingCommunicationSpi clientSpi = TestRecordingCommunicationSpi.spi(clientNode);
final UUID node0Id = ignite(0).cluster().localNode().id();
final UUID node2Id = ignite(2).cluster().localNode().id();
spi2.record(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode node, Message msg) {
if (!node0Id.equals(node.id()))
return false;
return (msg instanceof GridDhtPartitionsSingleMessage) && ((GridDhtPartitionsSingleMessage) msg).exchangeId() != null;
}
});
clientSpi.blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(final ClusterNode node, final Message msg) {
if (!node2Id.equals(node.id()))
return false;
if (msg instanceof GridNearTxFinishRequest) {
log.info("Delay message [msg=" + msg + ']');
GridTestUtils.runAsync(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("Send delayed message [msg=" + msg + ']');
clientSpi.stopBlock(true);
}
});
return true;
}
return false;
}
});
try (Transaction tx = clientNode.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
cache.put(key1, 1);
startFut = GridTestUtils.runAsync(new Callable<Object>() {
@Override
public Object call() throws Exception {
startGrid(4);
return null;
}
}, "start-thread");
spi2.waitForRecorded();
U.sleep(5);
cache.put(key2, 2);
log.info("Commit tx");
tx.commit();
}
assertEquals((Integer) 1, cache.get(key1));
assertEquals((Integer) 2, cache.get(key2));
startFut.get();
assertEquals((Integer) 1, cache.get(key1));
assertEquals((Integer) 2, cache.get(key2));
awaitPartitionMapExchange();
assertEquals((Integer) 1, cache.get(key1));
assertEquals((Integer) 2, cache.get(key2));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class IgniteWalHistoryReservationsTest method testNodeLeftDuringExchange.
/**
* @throws Exception If failed.
*/
@Test
public void testNodeLeftDuringExchange() throws Exception {
MvccFeatureChecker.skipIfNotSupported(MvccFeatureChecker.Feature.ENTRY_LOCK);
System.setProperty(IGNITE_PDS_WAL_REBALANCE_THRESHOLD, "0");
final int entryCnt = 10_000;
final int initGridCnt = 4;
final Ignite ig0 = startGrids(initGridCnt);
ig0.cluster().active(true);
IgniteCache<Object, Object> cache = ig0.cache("cache1");
for (int k = 0; k < entryCnt; k++) cache.put(k, k);
forceCheckpoint();
TestRecordingCommunicationSpi spi = new TestRecordingCommunicationSpi();
spi.blockMessages((node, msg) -> {
if (msg instanceof GridDhtPartitionsSingleMessage) {
GridDhtPartitionsSingleMessage sm = (GridDhtPartitionsSingleMessage) msg;
return sm.exchangeId() != null;
}
return false;
});
GridTestUtils.runAsync(new Runnable() {
@Override
public void run() {
try {
IgniteConfiguration cfg = getConfiguration(getTestIgniteInstanceName(initGridCnt));
cfg.setCommunicationSpi(spi);
startGrid(optimize(cfg));
} catch (Exception e) {
fail(e.getMessage());
}
}
});
spi.waitForBlocked();
boolean reserved = GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override
public boolean apply() {
for (int g = 0; g < initGridCnt; g++) {
IgniteEx ig = grid(g);
if (isReserveListEmpty(ig))
return false;
}
return true;
}
}, 10_000);
assert reserved;
spi.stopBlock();
stopGrid(getTestIgniteInstanceName(initGridCnt - 1), true, false);
boolean released = GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override
public boolean apply() {
for (int g = 0; g < initGridCnt - 1; g++) {
IgniteEx ig = grid(g);
if (!isReserveListEmpty(ig))
return false;
}
return true;
}
}, 10_000);
assert released;
awaitPartitionMapExchange();
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class ExchangeMergeStaleServerNodesTest method testServersFailAfterDoubleMerge.
/**
* @throws Exception if failed.
*/
@Test
public void testServersFailAfterDoubleMerge() throws Exception {
commSpis = F.asMap(getTestIgniteInstanceName(0), new DelayableCommunicationSpi((msg) -> false), getTestIgniteInstanceName(1), new DelayableCommunicationSpi((msg) -> false), getTestIgniteInstanceName(2), new DelayableCommunicationSpi((msg) -> false), getTestIgniteInstanceName(3), new DelayableCommunicationSpi((msg) -> msg instanceof GridDhtPartitionsSingleMessage), getTestIgniteInstanceName(4), new DelayableCommunicationSpi((msg) -> false));
try {
IgniteEx crd = startGrid(0);
GridCachePartitionExchangeManager<Object, Object> exchMgr = crd.context().cache().context().exchange();
exchMgr.mergeExchangesTestWaitVersion(new AffinityTopologyVersion(4, 0), null);
// This start will trigger an exchange.
IgniteInternalFuture<IgniteEx> fut1 = GridTestUtils.runAsync(() -> startGrid(1), "starter1");
// This exchange will be merged.
IgniteInternalFuture<IgniteEx> fut2 = GridTestUtils.runAsync(() -> startGrid(2), "starter2");
GridTestUtils.waitForCondition(() -> exchMgr.lastTopologyFuture().exchangeId().topologyVersion().equals(new AffinityTopologyVersion(2, 0)), getTestTimeout());
// This exchange will be merged as well, but the node will be failed.
IgniteInternalFuture<IgniteEx> futFail = GridTestUtils.runAsync(() -> startGrid(3), "starter3");
GridTestUtils.waitForCondition(exchMgr::hasPendingExchange, getTestTimeout());
// Wait for merged exchange.
GridTestUtils.waitForCondition(() -> exchMgr.mergeExchangesTestWaitVersion() == null, getTestTimeout());
futFail.cancel();
stopGrid(getTestIgniteInstanceName(2), true);
fut1.get();
fut2.get();
try {
futFail.get();
} catch (IgniteCheckedException ignore) {
// No-op.
}
// Check that next nodes can successfully join topology.
startGrid(4);
} finally {
stopAllGrids();
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class GridCachePartitionsStateValidatorSelfTest method testPartitionCacheSizesValidation.
/**
* Test partition cache sizes validation.
*/
@Test
public void testPartitionCacheSizesValidation() {
UUID remoteNode = UUID.randomUUID();
UUID ignoreNode = UUID.randomUUID();
// For partitions 0 and 2 we have inconsistent update counters.
Map<Integer, T2<Long, Long>> updateCountersMap = new HashMap<>();
updateCountersMap.put(0, new T2<>(2L, 2L));
updateCountersMap.put(1, new T2<>(2L, 2L));
updateCountersMap.put(2, new T2<>(5L, 5L));
// For partitions 0 and 2 we have inconsistent cache sizes.
Map<Integer, Long> cacheSizesMap = new HashMap<>();
cacheSizesMap.put(0, 2L);
cacheSizesMap.put(1, 2L);
cacheSizesMap.put(2, 2L);
// Form single messages map.
Map<UUID, GridDhtPartitionsSingleMessage> messages = new HashMap<>();
messages.put(remoteNode, from(updateCountersMap, cacheSizesMap));
messages.put(ignoreNode, from(updateCountersMap, cacheSizesMap));
GridDhtPartitionsStateValidator validator = new GridDhtPartitionsStateValidator(cctxMock);
// (partId, (nodeId, cacheSize))
Map<Integer, Map<UUID, Long>> result = validator.validatePartitionsSizes(topologyMock, messages, Sets.newHashSet(ignoreNode));
// Check that validation result contains all necessary information.
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.containsKey(0));
Assert.assertTrue(result.containsKey(2));
Assert.assertTrue(result.get(0).get(localNodeId) == 1L);
Assert.assertTrue(result.get(0).get(remoteNode) == 2L);
Assert.assertTrue(result.get(2).get(localNodeId) == 3L);
Assert.assertTrue(result.get(2).get(remoteNode) == 2L);
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class GridCachePartitionsStateValidationTest method testPartitionCountersConsistencyOnExchange.
/**
* Test that all nodes send correct {@link GridDhtPartitionsSingleMessage} with consistent update counters.
*
* @throws Exception If failed.
*/
@Test
public void testPartitionCountersConsistencyOnExchange() throws Exception {
// Reopen https://issues.apache.org/jira/browse/IGNITE-10766 if starts failing with forced MVCC
IgniteEx ignite = startGrids(4);
ignite.cluster().active(true);
awaitPartitionMapExchange();
final String atomicCacheName = "atomic-cache";
final String txCacheName = "tx-cache";
Ignite client = startClientGrid(4);
IgniteCache atomicCache = client.getOrCreateCache(new CacheConfiguration<>(atomicCacheName).setAtomicityMode(CacheAtomicityMode.ATOMIC).setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC).setBackups(2).setAffinity(new RendezvousAffinityFunction(false, 32)));
IgniteCache txCache = client.getOrCreateCache(new CacheConfiguration<>(txCacheName).setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL).setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC).setBackups(2).setAffinity(new RendezvousAffinityFunction(false, 32)));
for (int it = 0; it < 10; it++) {
SingleMessageInterceptorCommunicationSpi spi = (SingleMessageInterceptorCommunicationSpi) ignite.configuration().getCommunicationSpi();
spi.clear();
// Stop load future.
final AtomicBoolean stop = new AtomicBoolean();
// Run atomic load.
IgniteInternalFuture atomicLoadFuture = GridTestUtils.runMultiThreadedAsync(() -> {
int k = 0;
while (!stop.get()) {
k++;
try {
atomicCache.put(k, k);
} catch (Exception ignored) {
}
}
}, 1, "atomic-load");
// Run tx load.
IgniteInternalFuture txLoadFuture = GridTestUtils.runMultiThreadedAsync(() -> {
final int txOps = 5;
while (!stop.get()) {
List<Integer> randomKeys = Stream.generate(() -> ThreadLocalRandom.current().nextInt(5)).limit(txOps).sorted().collect(Collectors.toList());
try (Transaction tx = ignite.transactions().txStart(OPTIMISTIC, READ_COMMITTED)) {
for (Integer key : randomKeys) txCache.put(key, key);
tx.commit();
} catch (Exception ignored) {
}
}
}, 4, "tx-load");
// Wait for some data.
Thread.sleep(1000);
// Prevent sending full message.
spi.blockFullMessage();
// Trigger exchange.
IgniteInternalFuture nodeStopFuture = GridTestUtils.runAsync(() -> stopGrid(3));
try {
spi.waitUntilAllSingleMessagesAreSent();
List<GridDhtPartitionsSingleMessage> interceptedMessages = spi.getMessages();
// Associate each message with existing node UUID.
Map<UUID, GridDhtPartitionsSingleMessage> messagesMap = new HashMap<>();
for (int i = 0; i < interceptedMessages.size(); i++) messagesMap.put(grid(i + 1).context().localNodeId(), interceptedMessages.get(i));
GridDhtPartitionsStateValidator validator = new GridDhtPartitionsStateValidator(ignite.context().cache().context());
// Validate partition update counters. If counters are not consistent, exception will be thrown.
validator.validatePartitionsUpdateCounters(ignite.cachex(atomicCacheName).context().topology(), messagesMap, Collections.emptySet());
validator.validatePartitionsUpdateCounters(ignite.cachex(txCacheName).context().topology(), messagesMap, Collections.emptySet());
} finally {
// Stop load and resume exchange.
spi.unblockFullMessage();
stop.set(true);
atomicLoadFuture.get();
txLoadFuture.get();
nodeStopFuture.get();
}
// Return grid to initial state.
startGrid(3);
awaitPartitionMapExchange();
}
}
Aggregations