use of org.apache.ignite.internal.processors.cache.CacheAffinityChangeMessage in project ignite by apache.
the class ServiceDeploymentTask method init.
/**
* Initializes deployment task.
*
* @throws IgniteCheckedException In case of an error.
*/
protected void init() throws IgniteCheckedException {
if (isCompleted() || initTaskFut.isDone())
return;
assert evt != null && evtTopVer != null : "Illegal state to perform task's initialization :" + this;
if (log.isDebugEnabled()) {
log.debug("Started services deployment task init: [depId=" + depId + ", locId=" + ctx.localNodeId() + ", evt=" + evt + ']');
}
try {
if (depActions != null && depActions.deactivate()) {
srvcProc.onDeActivate(ctx);
completeSuccess();
return;
}
if (depActions == null) {
Map<IgniteUuid, ServiceInfo> toDeploy = new HashMap<>();
final int evtType = evt.type();
if (evtType == EVT_DISCOVERY_CUSTOM_EVT) {
DiscoveryCustomMessage msg = ((DiscoveryCustomEvent) evt).customMessage();
if (msg instanceof CacheAffinityChangeMessage) {
CacheAffinityChangeMessage msg0 = (CacheAffinityChangeMessage) msg;
Map<IgniteUuid, ServiceInfo> services = srvcProc.deployedServices();
if (!services.isEmpty()) {
Map<Integer, IgniteUuid> change = msg0.cacheDeploymentIds();
if (change != null) {
Set<String> names = new HashSet<>();
ctx.cache().cacheDescriptors().forEach((name, desc) -> {
if (change.containsKey(desc.groupId()))
names.add(name);
});
services.forEach((srvcId, desc) -> {
if (names.contains(desc.cacheName()))
toDeploy.put(srvcId, desc);
});
}
}
}
} else {
assert evtType == EVT_NODE_JOINED || evtType == EVT_NODE_LEFT || evtType == EVT_NODE_FAILED;
final ClusterNode eventNode = evt.eventNode();
final Map<IgniteUuid, ServiceInfo> deployedServices = srvcProc.deployedServices();
if (evtType == EVT_NODE_LEFT || evtType == EVT_NODE_FAILED) {
deployedServices.forEach((srvcId, desc) -> {
if (desc.topologySnapshot().containsKey(eventNode.id()) || // If affinity service
(desc.cacheName() != null && !eventNode.isClient()))
toDeploy.put(srvcId, desc);
});
} else {
toDeploy.putAll(deployedServices);
toDeploy.putAll(srvcProc.servicesReceivedFromJoin(eventNode.id()));
}
}
if (toDeploy.isEmpty()) {
completeSuccess();
if (log.isDebugEnabled())
log.debug("No services deployment deployment action required.");
return;
}
depActions = new ServiceDeploymentActions();
depActions.servicesToDeploy(toDeploy);
}
ClusterNode crd = srvcProc.coordinator();
if (crd == null) {
onAllServersLeft();
return;
}
crdId = crd.id();
if (crd.isLocal())
initCoordinator(evtTopVer);
processDeploymentActions(depActions);
} catch (Exception e) {
log.error("Error occurred while initializing deployment task, err=" + e.getMessage(), e);
completeError(e);
throw new IgniteCheckedException(e);
} finally {
if (!initTaskFut.isDone())
initTaskFut.onDone();
if (log.isDebugEnabled()) {
log.debug("Finished services deployment future init: [depId=" + deploymentId() + ", locId=" + ctx.localNodeId() + ']');
}
}
}
use of org.apache.ignite.internal.processors.cache.CacheAffinityChangeMessage 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.CacheAffinityChangeMessage in project ignite by apache.
the class TxPartitionCounterStateConsistencyTest method testPartitionConsistencyDuringRebalanceAndConcurrentUpdates_LateAffinitySwitch.
/**
* Tests tx load concurrently with PME for switching late affinity.
* <p>
* Scenario: two keys tx mapped locally on late affinity topology and when mapped and prepared remotely on ideal
* topology, first key is mapped to non-moving partition, second is mapped on moving partition.
* <p>
* Success: key over moving partition is prepared on new owner (choosed after late affinity switch),
* otherwise it's possible txs are prepared on different primaries after late affinity switch.
*/
@Test
public void testPartitionConsistencyDuringRebalanceAndConcurrentUpdates_LateAffinitySwitch() throws Exception {
backups = 1;
customDiscoSpi = new BlockTcpDiscoverySpi().setIpFinder(IP_FINDER);
Field rndAddrsField = U.findField(BlockTcpDiscoverySpi.class, "skipAddrsRandomization");
assertNotNull(rndAddrsField);
rndAddrsField.set(customDiscoSpi, true);
// Start coordinator with custom discovery SPI.
IgniteEx crd = startGrid(0);
IgniteEx g1 = startGrid(1);
startGrid(2);
crd.cluster().baselineAutoAdjustEnabled(false);
crd.cluster().active(true);
// Same name pattern as in test configuration.
String consistentId = "node" + getTestIgniteInstanceName(3);
List<Integer> g1Keys = primaryKeys(g1.cache(DEFAULT_CACHE_NAME), 10);
List<Integer> movingFromG1 = movingKeysAfterJoin(g1, DEFAULT_CACHE_NAME, 10, null, consistentId);
// Retain only stable keys;
g1Keys.removeAll(movingFromG1);
// The key will move from grid0 to grid3.
Integer key = movingKeysAfterJoin(crd, DEFAULT_CACHE_NAME, 1, null, consistentId).get(0);
IgniteEx g3 = startGrid(3);
assertEquals(consistentId, g3.localNode().consistentId());
resetBaselineTopology();
awaitPartitionMapExchange();
assertTrue(crd.affinity(DEFAULT_CACHE_NAME).isPrimary(g1.localNode(), g1Keys.get(0)));
stopGrid(3);
Ignite client = startClientGrid(CLIENT_GRID_NAME);
IgniteCache<Object, Object> cache = client.cache(DEFAULT_CACHE_NAME);
IgniteCache<Object, Object> cache2 = client.getOrCreateCache(cacheConfiguration(DEFAULT_CACHE_NAME + "2"));
// Put one key per partition.
for (int k = 0; k < partitions(); k++) {
cache.put(k, 0);
cache2.put(k, 0);
}
CountDownLatch resumeDiscoSndLatch = new CountDownLatch(1);
BlockTcpDiscoverySpi crdDiscoSpi = (BlockTcpDiscoverySpi) grid(0).configuration().getDiscoverySpi();
CyclicBarrier sync = new CyclicBarrier(2);
crdDiscoSpi.setClosure((node, msg) -> {
if (msg instanceof CacheAffinityChangeMessage) {
U.awaitQuiet(sync);
U.awaitQuiet(resumeDiscoSndLatch);
}
return null;
});
// Locks mapped wait.
IgniteInternalFuture fut = GridTestUtils.runAsync(() -> {
try {
startGrid(SERVER_NODES);
awaitPartitionMapExchange();
} catch (Exception e) {
fail(X.getFullStackTrace(e));
}
});
sync.await();
TestRecordingCommunicationSpi clientSpi = TestRecordingCommunicationSpi.spi(client);
clientSpi.blockMessages((node, msg) -> msg instanceof GridNearLockRequest);
IgniteInternalFuture txFut = GridTestUtils.runAsync(() -> {
try (Transaction tx = client.transactions().txStart()) {
Map<Integer, Integer> map = new LinkedHashMap<>();
// clientFirst=true in lockAll mapped to stable part.
map.put(g1Keys.get(0), g1Keys.get(0));
// clientFirst=false in lockAll mapped to moving part.
map.put(key, key);
cache.putAll(map);
cache2.putAll(new LinkedHashMap<>(map));
// Will start preparing in the middle of PME.
tx.commit();
}
});
IgniteInternalFuture lockFut = GridTestUtils.runAsync(() -> {
try {
// Wait for first lock request sent on local (late) topology.
clientSpi.waitForBlocked();
// Continue late switch PME.
resumeDiscoSndLatch.countDown();
crdDiscoSpi.setClosure(null);
// Wait late affinity switch.
awaitPartitionMapExchange();
// Continue tx mapping and preparing.
clientSpi.stopBlock();
} catch (InterruptedException e) {
fail(X.getFullStackTrace(e));
}
});
fut.get();
txFut.get();
lockFut.get();
assertPartitionsSame(idleVerify(crd, DEFAULT_CACHE_NAME));
// TX must be prepared over new owner.
PartitionUpdateCounter cntr = counter(key, grid(3).name());
assertNotNull(cntr);
assertEquals(cntr.toString(), 2, cntr.reserved());
PartitionUpdateCounter cntr2 = counter(key, DEFAULT_CACHE_NAME + "2", grid(3).name());
assertNotNull(cntr2);
assertEquals(cntr2.toString(), 2, cntr2.reserved());
}
use of org.apache.ignite.internal.processors.cache.CacheAffinityChangeMessage in project ignite by apache.
the class GridDhtPartitionsExchangeFuture method onAffinityInitialized.
/**
* @param fut Affinity future.
*/
private void onAffinityInitialized(IgniteInternalFuture<Map<Integer, Map<Integer, List<UUID>>>> fut) {
try {
assert fut.isDone();
Map<Integer, Map<Integer, List<UUID>>> assignmentChange = fut.get();
GridDhtPartitionsFullMessage m = createPartitionsMessage(false, false);
CacheAffinityChangeMessage msg = new CacheAffinityChangeMessage(exchId, m, assignmentChange);
if (log.isDebugEnabled())
log.debug("Centralized affinity exchange, send affinity change message: " + msg);
cctx.discovery().sendCustomEvent(msg);
} catch (IgniteCheckedException e) {
onDone(e);
}
}
Aggregations