use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class BaselineAutoAdjustTest method testExchangeMerge.
/**
* Tests that merging exchanges properly triggers baseline changing.
*
* @throws Exception If failed.
*/
@Test
public void testExchangeMerge() throws Exception {
// Latch that waits for PME (intTopVer == 3.0)
CountDownLatch exchangeWorkerLatch = new CountDownLatch(1);
// Lyficycle bean is needed in order to register EVT_NODE_JOIN lister that is called
// right after GridCachePartitionExchangeManager and before GridClusterStateProcessor.
lifecycleBean = new LifecycleBean() {
/**
* Ignite instance.
*/
@IgniteInstanceResource
IgniteEx ignite;
/**
* {@inheritDoc}
*/
@Override
public void onLifecycleEvent(LifecycleEventType evt) throws IgniteException {
if (evt == LifecycleEventType.BEFORE_NODE_START) {
ignite.context().internalSubscriptionProcessor().registerDistributedMetastorageListener(new DistributedMetastorageLifecycleListener() {
@Override
public void onReadyForRead(ReadableDistributedMetaStorage metastorage) {
ignite.context().event().addDiscoveryEventListener((evt, disco) -> {
if (evt.type() == EVT_NODE_JOINED && evt.topologyVersion() == 3) {
try {
// Let's wait for exchange worker starts PME
// that related to the first node joined the cluster.
exchangeWorkerLatch.await(getTestTimeout(), MILLISECONDS);
} catch (InterruptedException e) {
throw new IgniteException("exchangeWorkerLatch has been interrupted.", e);
}
}
}, EVT_NODE_JOINED);
}
});
}
}
};
// Start the coordinator node.
IgniteEx crd = startGrid(0);
// This bean is only required on the coordinator node.
lifecycleBean = null;
// Latch indicates that EVT_NODE_JOINED (topVer == 4.0) was processed by all listeners.
CountDownLatch nodeJoinLatch = new CountDownLatch(1);
// This listener is the last one in the queue of handlers.
crd.context().event().addDiscoveryEventListener((evt, disco) -> {
if (evt.type() == EVT_NODE_JOINED && evt.topologyVersion() == 4)
nodeJoinLatch.countDown();
}, EVT_NODE_JOINED);
IgniteEx nonCrd = startGrid(1);
crd.cluster().state(ACTIVE);
crd.cluster().baselineAutoAdjustEnabled(true);
crd.cluster().baselineAutoAdjustTimeout(autoAdjustTimeout);
awaitPartitionMapExchange(false, true, null);
TestRecordingCommunicationSpi spi1 = TestRecordingCommunicationSpi.spi(nonCrd);
spi1.blockMessages((node, msg) -> msg instanceof GridDhtPartitionsSingleMessage);
// Target major topology version (4 nodes)
long targetTopVer = 4;
// Let's block exchange process in order to merge two following exchanges (3.0 && 4.0).
crd.context().cache().context().exchange().mergeExchangesTestWaitVersion(new AffinityTopologyVersion(targetTopVer, 0), null);
AtomicInteger cnt = new AtomicInteger(G.allGrids().size());
runMultiThreadedAsync(new Callable<Void>() {
@Override
public Void call() throws Exception {
startGrid(cnt.getAndIncrement());
return null;
}
}, 2, "async-grid-starter");
// Make sure that PME is in progress.
assertTrue("Failed to wait for PME [topVer=3]", spi1.waitForBlocked(1, getTestTimeout()));
assertTrue("Failed to wait for the first started exchange.", waitForCondition(() -> {
GridDhtPartitionsExchangeFuture fut = crd.context().cache().context().exchange().lastTopologyFuture();
return fut.initialVersion().topologyVersion() == 3;
}, getTestTimeout()));
// This guarantees that BaselineAutoAdjustData listens to real GridDhtPartitionsExchangeFuture
// instead of readyAffinityFuture.
exchangeWorkerLatch.countDown();
assertTrue("Failed to wait for processing node join event [topVer=3]", nodeJoinLatch.await(getTestTimeout(), MILLISECONDS));
// Unblock PME
spi1.stopBlock();
assertTrue("Failed to wait for changing baseline in " + autoAdjustTimeout * 2 + " ms.", waitForCondition(() -> crd.cluster().currentBaselineTopology().size() == targetTopVer, autoAdjustTimeout * 2));
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class PartitionsExchangeCoordinatorFailoverTest method testChangeCoordinatorToLocallyJoiningNode.
/**
* Test checks that changing coordinator to a node that joining to cluster at the moment works correctly
* in case of exchanges merge and completed exchange on other joining nodes.
*/
@Test
@WithSystemProperty(key = IgniteSystemProperties.IGNITE_SKIP_CONFIGURATION_CONSISTENCY_CHECK, value = "true")
public void testChangeCoordinatorToLocallyJoiningNode() throws Exception {
newCaches = false;
spiFactory = TestRecordingCommunicationSpi::new;
IgniteEx crd = startGrid(CRD_NONE);
final int newCrdNodeIdx = 1;
// A full message shouldn't be send to new coordinator.
blockSendingFullMessage(crd, node -> node.consistentId().equals(getTestIgniteInstanceName(newCrdNodeIdx)));
CountDownLatch joiningNodeSentSingleMsg = new CountDownLatch(1);
// For next joining node delay sending single message to emulate exchanges merge.
spiFactory = () -> new DynamicDelayingCommunicationSpi(msg -> {
final int delay = 5_000;
if (msg instanceof GridDhtPartitionsSingleMessage) {
GridDhtPartitionsSingleMessage singleMsg = (GridDhtPartitionsSingleMessage) msg;
if (singleMsg.exchangeId() != null) {
joiningNodeSentSingleMsg.countDown();
return delay;
}
}
return 0;
});
IgniteInternalFuture<?> newCrdJoinFut = GridTestUtils.runAsync(() -> startGrid(newCrdNodeIdx));
// Wait till new coordinator node sent single message.
joiningNodeSentSingleMsg.await();
spiFactory = TcpCommunicationSpi::new;
// Additionally start 2 new nodes. Their exchange should be merged with exchange on join new coordinator node.
startGridsMultiThreaded(2, 2);
Assert.assertFalse("New coordinator join shouldn't be happened before stopping old coordinator.", newCrdJoinFut.isDone());
// Stop coordinator.
stopGrid(CRD_NONE);
// New coordinator join process should succeed after that.
newCrdJoinFut.get();
awaitPartitionMapExchange();
// Check that affinity are equal on all nodes.
AffinityTopologyVersion affVer = ((IgniteEx) ignite(1)).cachex(CACHE_NAME).context().shared().exchange().readyAffinityVersion();
List<List<ClusterNode>> expAssignment = null;
IgniteEx expAssignmentNode = null;
for (Ignite node : G.allGrids()) {
IgniteEx nodeEx = (IgniteEx) node;
List<List<ClusterNode>> assignment = nodeEx.cachex(CACHE_NAME).context().affinity().assignments(affVer);
if (expAssignment == null) {
expAssignment = assignment;
expAssignmentNode = nodeEx;
} else
Assert.assertEquals("Affinity assignments are different " + "[expectedNode=" + expAssignmentNode + ", actualNode=" + nodeEx + "]", expAssignment, assignment);
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class ExchangeMergeStaleServerNodesTest method testServersFailAfterMerge.
/**
* @throws Exception if failed.
*/
@Test
public void testServersFailAfterMerge() throws Exception {
DelayableCommunicationSpi delaySpi1 = new DelayableCommunicationSpi((msg) -> {
if (msg instanceof GridDhtPartitionsSingleMessage) {
GridDhtPartitionsSingleMessage singleMsg = (GridDhtPartitionsSingleMessage) msg;
return singleMsg.exchangeId() != null && singleMsg.exchangeId().topologyVersion().equals(new AffinityTopologyVersion(2, 0));
}
return false;
});
commSpis = F.asMap(getTestIgniteInstanceName(0), new DelayableCommunicationSpi((msg) -> false), getTestIgniteInstanceName(1), delaySpi1, getTestIgniteInstanceName(2), new DelayableCommunicationSpi((msg) -> msg instanceof GridDhtPartitionsSingleMessage), getTestIgniteInstanceName(3), new DelayableCommunicationSpi((msg) -> false));
try {
IgniteEx crd = startGrid(0);
GridCachePartitionExchangeManager<Object, Object> exchMgr = crd.context().cache().context().exchange();
exchMgr.mergeExchangesTestWaitVersion(new AffinityTopologyVersion(3, 0), null);
// Single message for this node is blocked until further notice.
IgniteInternalFuture<IgniteEx> fut = GridTestUtils.runAsync(() -> startGrid(1), "starter1");
GridTestUtils.waitForCondition(() -> exchMgr.lastTopologyFuture().exchangeId().topologyVersion().equals(new AffinityTopologyVersion(2, 0)), getTestTimeout());
IgniteInternalFuture<IgniteEx> futFail = GridTestUtils.runAsync(() -> startGrid(2), "starter2");
GridTestUtils.waitForCondition(exchMgr::hasPendingExchange, getTestTimeout());
// Unblock message to proceed merging.
delaySpi1.replay(crd.cluster().localNode().id());
// Wait for merged exchange.
GridTestUtils.waitForCondition(() -> exchMgr.mergeExchangesTestWaitVersion() == null, getTestTimeout());
futFail.cancel();
stopGrid(getTestIgniteInstanceName(2), true);
fut.get();
try {
futFail.get();
} catch (IgniteCheckedException ignore) {
// No-op.
}
// Check that next nodes can successfully join topology.
startGrid(3);
} finally {
stopAllGrids();
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsSingleMessage in project ignite by apache.
the class IgniteWalHistoryReservationsTest method testReservedOnExchange.
/**
* @throws Exception If failed.
*/
@Test
public void testReservedOnExchange() 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 IgniteEx ig0 = (IgniteEx) startGrids(initGridCnt + 1);
ig0.cluster().active(true);
stopGrid(initGridCnt);
Assert.assertEquals(5, ig0.context().state().clusterState().baselineTopology().consistentIds().size());
long start = U.currentTimeMillis();
log.warning("Start loading");
try (IgniteDataStreamer<Object, Object> st = ig0.dataStreamer("cache1")) {
for (int k = 0; k < entryCnt; k++) {
st.addData(k, k);
printProgress(k);
}
}
log.warning("Finish loading time:" + (U.currentTimeMillis() - start));
forceCheckpoint();
start = U.currentTimeMillis();
log.warning("Start loading");
try (IgniteDataStreamer<Object, Object> st = ig0.dataStreamer("cache1")) {
st.allowOverwrite(true);
for (int k = 0; k < entryCnt; k++) {
st.addData(k, k * 2);
printProgress(k);
}
}
log.warning("Finish loading time:" + (U.currentTimeMillis() - start));
forceCheckpoint();
start = U.currentTimeMillis();
log.warning("Start loading");
try (IgniteDataStreamer<Object, Object> st = ig0.dataStreamer("cache1")) {
st.allowOverwrite(true);
for (int k = 0; k < entryCnt; k++) {
st.addData(k, k);
printProgress(k);
}
}
log.warning("Finish loading time:" + (U.currentTimeMillis() - start));
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();
boolean released = 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 released;
}
Aggregations