use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.PartitionsExchangeAware in project ignite by apache.
the class IgniteClusterSnapshotSelfTest method testSnapshotPartitionExchangeAwareOrder.
/**
* @throws Exception If fails.
*/
@Test
public void testSnapshotPartitionExchangeAwareOrder() throws Exception {
IgniteEx ignite = startGridsWithCache(3, dfltCacheCfg, CACHE_KEYS_RANGE);
Map<UUID, PartitionsExchangeAware> comps = new HashMap<>();
for (Ignite ig : G.allGrids()) {
PartitionsExchangeAware comp;
((IgniteEx) ig).context().cache().context().exchange().registerExchangeAwareComponent(comp = new PartitionsExchangeAware() {
private final AtomicInteger order = new AtomicInteger();
@Override
public void onInitBeforeTopologyLock(GridDhtPartitionsExchangeFuture fut) {
assertEquals("Exchange order violated: " + fut.firstEvent(), 0, order.getAndIncrement());
}
@Override
public void onInitAfterTopologyLock(GridDhtPartitionsExchangeFuture fut) {
assertEquals("Exchange order violated: " + fut.firstEvent(), 1, order.getAndIncrement());
}
@Override
public void onDoneBeforeTopologyUnlock(GridDhtPartitionsExchangeFuture fut) {
assertEquals("Exchange order violated: " + fut.firstEvent(), 2, order.getAndIncrement());
}
@Override
public void onDoneAfterTopologyUnlock(GridDhtPartitionsExchangeFuture fut) {
assertEquals("Exchange order violated: " + fut.firstEvent(), 3, order.getAndSet(0));
}
});
comps.put(((IgniteEx) ig).localNode().id(), comp);
}
ignite.snapshot().createSnapshot(SNAPSHOT_NAME).get();
for (Ignite ig : G.allGrids()) {
((IgniteEx) ig).context().cache().context().exchange().unregisterExchangeAwareComponent(comps.get(((IgniteEx) ig).localNode().id()));
}
awaitPartitionMapExchange();
assertEquals("Some of ignite instances failed during snapshot", 3, G.allGrids().size());
stopAllGrids();
IgniteEx snp = startGridsFromSnapshot(3, SNAPSHOT_NAME);
assertSnapshotCacheKeys(snp.cache(dfltCacheCfg.getName()));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.PartitionsExchangeAware in project ignite by apache.
the class IgniteClusterSnapshotSelfTest method testClusterSnapshotOnMovingPartitionsCoordinatorLeft.
/**
* @throws Exception If fails.
*/
@Test
public void testClusterSnapshotOnMovingPartitionsCoordinatorLeft() throws Exception {
startGridsWithCache(2, dfltCacheCfg, CACHE_KEYS_RANGE);
for (Ignite grid : G.allGrids()) {
TestRecordingCommunicationSpi.spi(grid).blockMessages((node, msg) -> msg instanceof GridDhtPartitionSupplyMessage);
}
Ignite ignite = startGrid(2);
ignite.cluster().setBaselineTopology(ignite.cluster().topologyVersion());
TestRecordingCommunicationSpi.spi(grid(0)).waitForBlocked();
CountDownLatch latch = new CountDownLatch(G.allGrids().size());
IgniteInternalFuture<?> stopFut = GridTestUtils.runAsync(() -> {
try {
U.await(latch);
stopGrid(0);
} catch (IgniteInterruptedCheckedException e) {
fail("Must not fail here: " + e.getMessage());
}
});
Queue<T2<GridDhtPartitionExchangeId, Boolean>> exchFuts = new ConcurrentLinkedQueue<>();
for (Ignite ig : G.allGrids()) {
((IgniteEx) ig).context().cache().context().exchange().registerExchangeAwareComponent(new PartitionsExchangeAware() {
/**
* {@inheritDoc}
*/
@Override
public void onInitBeforeTopologyLock(GridDhtPartitionsExchangeFuture fut) {
if (!(fut.firstEvent() instanceof DiscoveryCustomEvent))
return;
try {
exchFuts.add(new T2<>(fut.exchangeId(), fut.rebalanced()));
latch.countDown();
stopFut.get();
} catch (IgniteCheckedException e) {
U.log(log, "Interrupted on coordinator: " + e.getMessage());
}
}
});
}
IgniteFuture<Void> fut = ignite.snapshot().createSnapshot(SNAPSHOT_NAME);
stopFut.get();
assertThrowsAnyCause(log, fut::get, IgniteException.class, "Snapshot creation has been finished with an error");
assertEquals("Snapshot futures expected: " + exchFuts, 3, exchFuts.size());
for (T2<GridDhtPartitionExchangeId, Boolean> exch : exchFuts) assertFalse("Snapshot `rebalanced` must be false with moving partitions: " + exch.get1(), exch.get2());
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.PartitionsExchangeAware in project ignite by apache.
the class IgniteWalRebalanceTest method testRebalanceReassignAndOwnPartitions.
/**
* Tests that owning partitions (that are trigged by rebalance future) cannot be mapped to a new rebalance future
* that was created by RebalanceReassignExchangeTask.
*
* @throws Exception If failed.
*/
@Test
public void testRebalanceReassignAndOwnPartitions() throws Exception {
backups = 3;
IgniteEx supplier1 = startGrid(0);
IgniteEx supplier2 = startGrid(1);
IgniteEx demander = startGrid(2);
supplier1.cluster().state(ACTIVE);
String cacheName1 = "test-cache-1";
String cacheName2 = "test-cache-2";
IgniteCache<Integer, IndexedObject> c1 = supplier1.getOrCreateCache(new CacheConfiguration<Integer, IndexedObject>(cacheName1).setBackups(backups).setAffinity(new RendezvousAffinityFunction(false, PARTS_CNT)).setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC).setRebalanceOrder(10));
IgniteCache<Integer, IndexedObject> c2 = supplier1.getOrCreateCache(new CacheConfiguration<Integer, IndexedObject>(cacheName2).setBackups(backups).setAffinity(new RendezvousAffinityFunction(false, PARTS_CNT)).setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC).setRebalanceOrder(20));
// Fill initial data.
final int entryCnt = PARTS_CNT * 200;
final int preloadEntryCnt = PARTS_CNT * 400;
int val = 0;
for (int k = 0; k < preloadEntryCnt; k++) {
c1.put(k, new IndexedObject(val++));
c2.put(k, new IndexedObject(val++));
}
forceCheckpoint();
stopGrid(2);
// This is an easy way to emulate missing partitions on the first rebalance.
for (int i = 0; i < entryCnt; i++) c1.put(i, new IndexedObject(val++));
// Full rebalance for the cacheName2.
for (int i = 0; i < preloadEntryCnt; i++) c2.put(i, new IndexedObject(val++));
// Delay rebalance process for specified groups.
blockMsgPred = (node, msg) -> {
if (msg instanceof GridDhtPartitionDemandMessage) {
GridDhtPartitionDemandMessage msg0 = (GridDhtPartitionDemandMessage) msg;
return msg0.groupId() == CU.cacheId(cacheName1) || msg0.groupId() == CU.cacheId(cacheName2);
}
return false;
};
// Emulate missing partitions and trigger RebalanceReassignExchangeTask which should re-trigger a new rebalance.
FailingIOFactory ioFactory = injectFailingIOFactory(supplier1);
demander = startGrid(2);
TestRecordingCommunicationSpi demanderSpi = TestRecordingCommunicationSpi.spi(grid(2));
// Wait until demander starts rebalancning.
demanderSpi.waitForBlocked();
// Need to start a client node in order to block RebalanceReassignExchangeTask (and do not change the affinity)
// until cacheName2 triggers a checkpoint after rebalancing.
CountDownLatch blockClientJoin = new CountDownLatch(1);
CountDownLatch unblockClientJoin = new CountDownLatch(1);
demander.context().cache().context().exchange().registerExchangeAwareComponent(new PartitionsExchangeAware() {
@Override
public void onInitBeforeTopologyLock(GridDhtPartitionsExchangeFuture fut) {
blockClientJoin.countDown();
try {
if (!unblockClientJoin.await(getTestTimeout(), MILLISECONDS))
throw new IgniteException("Failed to wait for client node joinning the cluster.");
} catch (InterruptedException e) {
throw new IgniteException("Unexpected exception.", e);
}
}
});
startClientGrid(4);
// Wait for a checkpoint after rebalancing cacheName2.
CountDownLatch blockCheckpoint = new CountDownLatch(1);
CountDownLatch unblockCheckpoint = new CountDownLatch(1);
((GridCacheDatabaseSharedManager) demander.context().cache().context().database()).addCheckpointListener(new CheckpointListener() {
/**
* {@inheritDoc}
*/
@Override
public void onCheckpointBegin(Context ctx) throws IgniteCheckedException {
if (!ctx.progress().reason().contains(String.valueOf(CU.cacheId(cacheName2))))
return;
blockCheckpoint.countDown();
try {
if (!unblockCheckpoint.await(getTestTimeout(), MILLISECONDS))
throw new IgniteCheckedException("Failed to wait for unblocking checkpointer.");
} catch (InterruptedException e) {
throw new IgniteCheckedException("Unexpected exception", e);
}
}
/**
* {@inheritDoc}
*/
@Override
public void beforeCheckpointBegin(Context ctx) throws IgniteCheckedException {
}
/**
* {@inheritDoc}
*/
@Override
public void onMarkCheckpointBegin(Context ctx) throws IgniteCheckedException {
}
});
// Unblock the first rebalance.
demanderSpi.stopBlock();
// Wait for start of the checkpoint after rebalancing cacheName2.
assertTrue("Failed to wait for checkpoint.", blockCheckpoint.await(getTestTimeout(), MILLISECONDS));
// Block the second rebalancing.
demanderSpi.blockMessages((node, msg) -> {
if (msg instanceof GridDhtPartitionDemandMessage) {
GridDhtPartitionDemandMessage msg0 = (GridDhtPartitionDemandMessage) msg;
return msg0.groupId() == CU.cacheId(cacheName1);
}
return false;
});
ioFactory.reset();
// Let's unblock client exchange and, therefore, handling of RebalanceReassignExchangeTask,
// which is already scheduled.
unblockClientJoin.countDown();
// Wait for starting the second rebalance (new chain of rebalance futures should be created at this point).
demanderSpi.waitForBlocked();
GridFutureAdapter checkpointFut = ((GridCacheDatabaseSharedManager) demander.context().cache().context().database()).getCheckpointer().currentProgress().futureFor(FINISHED);
// Unblock checkpointer.
unblockCheckpoint.countDown();
assertTrue("Failed to wait for a checkpoint.", GridTestUtils.waitForCondition(() -> checkpointFut.isDone(), getTestTimeout()));
// Well, there is a race between we unblock rebalance and the current checkpoint executes all its listeners.
demanderSpi.stopBlock();
awaitPartitionMapExchange(false, true, null);
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.PartitionsExchangeAware in project ignite by apache.
the class IgniteSnapshotWithMetastorageTest method testMetastorageUpdateDuringSnapshot.
/**
* @throws Exception If fails.
*/
@Test
public void testMetastorageUpdateDuringSnapshot() throws Exception {
AtomicInteger keyCnt = new AtomicInteger();
AtomicBoolean stop = new AtomicBoolean();
CountDownLatch latch = new CountDownLatch(1);
IgniteEx ignite = startGridsWithCache(2, dfltCacheCfg, CACHE_KEYS_RANGE);
IgniteInternalFuture<?> updFut = GridTestUtils.runMultiThreadedAsync(() -> {
while (!Thread.currentThread().isInterrupted() && !stop.get()) {
try {
ignite.context().distributedMetastorage().write(SNAPSHOT_PREFIX + keyCnt.getAndIncrement(), "value");
} catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
}, 3, "dms-updater");
DmsDataWriterWorker worker = GridTestUtils.getFieldValue(ignite.context().distributedMetastorage(), DistributedMetaStorageImpl.class, "worker");
LinkedBlockingQueue<RunnableFuture<?>> queue = GridTestUtils.getFieldValue(worker, DmsDataWriterWorker.class, "updateQueue");
RunnableFuture<?> testTask = new FutureTask<>(() -> {
U.await(latch);
return null;
});
queue.offer(testTask);
assertTrue(GridTestUtils.waitForCondition(() -> queue.size() > 10, getTestTimeout()));
ignite.context().cache().context().exchange().registerExchangeAwareComponent(new PartitionsExchangeAware() {
/**
* {@inheritDoc}
*/
@Override
public void onInitAfterTopologyLock(GridDhtPartitionsExchangeFuture fut) {
latch.countDown();
}
});
ignite.snapshot().createSnapshot(SNAPSHOT_NAME).get();
stop.set(true);
updFut.get();
stopAllGrids();
Function<IgniteConfiguration, String> pathProv = cfg -> resolveSnapshotWorkDirectory(cfg).getAbsolutePath();
Set<String> keySet0 = new TreeSet<>();
Set<String> keySet1 = new TreeSet<>();
IgniteEx snp0 = startGridsFromSnapshot(Collections.singleton(0), pathProv, SNAPSHOT_NAME, false);
snp0.context().distributedMetastorage().iterate(SNAPSHOT_PREFIX, (key, val) -> keySet0.add(key));
stopGrid(0);
IgniteEx snp1 = startGridsFromSnapshot(Collections.singleton(1), pathProv, SNAPSHOT_NAME, false);
snp1.context().distributedMetastorage().iterate(SNAPSHOT_PREFIX, (key, val) -> keySet1.add(key));
assertEquals("Keys must be the same on all nodes", keySet0, keySet1);
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.PartitionsExchangeAware in project ignite by apache.
the class IgnitePdsConsistencyOnDelayedPartitionOwning method checkConsistencyNodeLeft.
/**
*/
@Test
public void checkConsistencyNodeLeft() throws Exception {
IgniteEx crd = (IgniteEx) startGridsMultiThreaded(4);
crd.cluster().active(true);
for (int i = 0; i < PARTS; i++) crd.cache(DEFAULT_CACHE_NAME).put(i, i);
forceCheckpoint();
stopGrid(1);
for (int i = 0; i < PARTS; i++) crd.cache(DEFAULT_CACHE_NAME).put(i, i + 1);
// Block supply messages from all owners.
TestRecordingCommunicationSpi spi0 = TestRecordingCommunicationSpi.spi(grid(0));
TestRecordingCommunicationSpi spi2 = TestRecordingCommunicationSpi.spi(grid(2));
TestRecordingCommunicationSpi spi3 = TestRecordingCommunicationSpi.spi(grid(3));
IgniteBiPredicate<ClusterNode, Message> pred = new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode clusterNode, Message msg) {
return msg instanceof GridDhtPartitionSupplyMessage;
}
};
spi0.blockMessages(pred);
spi2.blockMessages(pred);
spi3.blockMessages(pred);
GridTestUtils.runAsync(new Callable<Void>() {
@Override
public Void call() throws Exception {
startGrid(1);
return null;
}
});
spi0.waitForBlocked();
spi2.waitForBlocked();
spi3.waitForBlocked();
spi0.stopBlock();
spi2.stopBlock();
CountDownLatch topInitLatch = new CountDownLatch(1);
CountDownLatch enableDurabilityCPStartLatch = new CountDownLatch(1);
CountDownLatch delayedOnwningLatch = new CountDownLatch(1);
GridCacheDatabaseSharedManager dbMgr = (GridCacheDatabaseSharedManager) grid(1).context().cache().context().database();
dbMgr.addCheckpointListener(new CheckpointListener() {
@Override
public void onMarkCheckpointBegin(Context ctx) throws IgniteCheckedException {
// No-op.
}
@Override
public void onCheckpointBegin(Context ctx) throws IgniteCheckedException {
// No-op.
}
@Override
public void beforeCheckpointBegin(Context ctx) throws IgniteCheckedException {
String reason = ctx.progress().reason();
String reason0 = WalStateManager.reason(cacheId(DEFAULT_CACHE_NAME), new AffinityTopologyVersion(6, 0));
if (reason != null && reason.equals(reason0)) {
enableDurabilityCPStartLatch.countDown();
try {
assertTrue(U.await(delayedOnwningLatch, 10_000, TimeUnit.MILLISECONDS));
} catch (IgniteInterruptedCheckedException e) {
fail(X.getFullStackTrace(e));
}
}
}
});
TestRecordingCommunicationSpi.spi(grid(1)).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode clusterNode, Message msg) {
if (msg instanceof GridDhtPartitionDemandMessage) {
GridDhtPartitionDemandMessage msg0 = (GridDhtPartitionDemandMessage) msg;
return msg0.topologyVersion().equals(new AffinityTopologyVersion(7, 0));
}
return false;
}
});
grid(1).context().cache().context().exchange().registerExchangeAwareComponent(new PartitionsExchangeAware() {
@Override
public void onDoneBeforeTopologyUnlock(GridDhtPartitionsExchangeFuture fut) {
if (fut.initialVersion().equals(new AffinityTopologyVersion(7, 0))) {
topInitLatch.countDown();
try {
assertTrue(U.await(enableDurabilityCPStartLatch, 20_000, TimeUnit.MILLISECONDS));
} catch (IgniteInterruptedCheckedException e) {
fail(X.getFullStackTrace(e));
}
System.out.println();
}
}
});
// Trigger rebalancing remap because owner has left.
IgniteInternalFuture stopFut = GridTestUtils.runAsync(new Runnable() {
@Override
public void run() {
// TODO start cache.
stopGrid(2);
}
});
// Wait for topology (7,0) init on grid1 before finishing rebalancing on (6,0).
assertTrue(U.await(topInitLatch, 20_000, TimeUnit.MILLISECONDS));
// Release last supply message, causing triggering a cp for enabling durability.
spi3.stopBlock();
// Wait for new rebalancing assignments ready on grid1.
TestRecordingCommunicationSpi.spi(grid(1)).waitForBlocked();
// Triggers spurious ideal switching before rebalancing has finished for (7,0).
delayedOnwningLatch.countDown();
stopFut.get();
TestRecordingCommunicationSpi.spi(grid(1)).stopBlock();
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(0), DEFAULT_CACHE_NAME));
CacheGroupContext grpCtx = grid(1).context().cache().cacheGroup(cacheId(DEFAULT_CACHE_NAME));
if (grpCtx != null)
assertTrue(grpCtx.localWalEnabled());
}
Aggregations