use of org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion in project ignite by apache.
the class CacheExchangeMergeTest method blockExchangeFinish.
/**
* @param crd Exchange coordinator.
* @param topVer Exchange topology version.
*/
private void blockExchangeFinish(Ignite crd, long topVer) {
final AffinityTopologyVersion topVer0 = new AffinityTopologyVersion(topVer);
TestRecordingCommunicationSpi.spi(crd).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode node, Message msg) {
if (msg instanceof GridDhtPartitionsFullMessage) {
GridDhtPartitionsFullMessage msg0 = (GridDhtPartitionsFullMessage) msg;
return msg0.exchangeId() != null && msg0.exchangeId().topologyVersion().equals(topVer0);
}
return false;
}
});
}
use of org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion in project ignite by apache.
the class CacheExchangeMergeTest method checkExchanges.
/**
* @param node Node.
* @param vers Expected exchange versions.
*/
private void checkExchanges(Ignite node, long... vers) {
IgniteKernal node0 = (IgniteKernal) node;
List<AffinityTopologyVersion> expVers = new ArrayList<>();
for (long ver : vers) expVers.add(new AffinityTopologyVersion(ver));
List<AffinityTopologyVersion> doneVers = new ArrayList<>();
List<GridDhtPartitionsExchangeFuture> futs = node0.context().cache().context().exchange().exchangeFutures();
for (int i = futs.size() - 1; i >= 0; i--) {
GridDhtPartitionsExchangeFuture fut = futs.get(i);
if (fut.exchangeDone() && fut.firstEvent().type() != EVT_DISCOVERY_CUSTOM_EVT) {
AffinityTopologyVersion resVer = fut.topologyVersion();
if (resVer != null)
doneVers.add(resVer);
}
}
assertEquals(expVers, doneVers);
for (CacheGroupContext grpCtx : node0.context().cache().cacheGroups()) {
for (AffinityTopologyVersion ver : grpCtx.affinity().cachedVersions()) {
if (ver.minorTopologyVersion() > 0)
continue;
assertTrue("Unexpected version [ver=" + ver + ", exp=" + expVers + ']', expVers.contains(ver));
}
}
}
use of org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion in project ignite by apache.
the class CacheExchangeMergeTest method blockExchangeFinish.
/**
* @param crd Exchange coordinator.
* @param topVer Exchange topology version.
* @param blockNodes Nodes which do not receive messages.
* @param waitMsgNodes Nodes which should receive messages.
* @return Awaited state latch.
*/
private CountDownLatch blockExchangeFinish(Ignite crd, long topVer, final List<Integer> blockNodes, final List<Integer> waitMsgNodes) {
log.info("blockExchangeFinish [crd=" + crd.cluster().localNode().id() + ", block=" + blockNodes + ", wait=" + waitMsgNodes + ']');
final AffinityTopologyVersion topVer0 = new AffinityTopologyVersion(topVer);
final CountDownLatch latch = new CountDownLatch(waitMsgNodes.size());
TestRecordingCommunicationSpi.spi(crd).blockMessages(new IgniteBiPredicate<ClusterNode, Message>() {
@Override
public boolean apply(ClusterNode node, Message msg) {
if (msg instanceof GridDhtPartitionsFullMessage) {
GridDhtPartitionsFullMessage msg0 = (GridDhtPartitionsFullMessage) msg;
if (msg0.exchangeId() == null || msg0.exchangeId().topologyVersion().compareTo(topVer0) < 0)
return false;
String name = node.attribute(IgniteNodeAttributes.ATTR_IGNITE_INSTANCE_NAME);
assert name != null : node;
for (Integer idx : blockNodes) {
if (name.equals(getTestIgniteInstanceName(idx)))
return true;
}
for (Integer idx : waitMsgNodes) {
if (name.equals(getTestIgniteInstanceName(idx))) {
log.info("Coordinators sends awaited message [node=" + node.id() + ']');
latch.countDown();
}
}
}
return false;
}
});
return latch;
}
use of org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion in project ignite by apache.
the class CacheBaselineTopologyTest method testPrimaryLeftAndClusterRestart.
/**
* @throws Exception If failed.
*/
public void testPrimaryLeftAndClusterRestart() throws Exception {
startGrids(NODE_COUNT);
IgniteEx ig = grid(0);
ig.cluster().active(true);
IgniteCache<Integer, Integer> cache = ig.createCache(new CacheConfiguration<Integer, Integer>().setName(CACHE_NAME).setWriteSynchronizationMode(FULL_SYNC).setCacheMode(PARTITIONED).setBackups(1).setPartitionLossPolicy(READ_ONLY_SAFE).setReadFromBackup(true).setRebalanceDelay(-1));
int key = 1;
List<ClusterNode> affNodes = (List<ClusterNode>) ig.affinity(CACHE_NAME).mapKeyToPrimaryAndBackups(key);
assert affNodes.size() == 2;
int primaryIdx = -1;
int backupIdx = -1;
IgniteEx primary = null;
IgniteEx backup = null;
for (int i = 0; i < NODE_COUNT; i++) {
grid(i).cache(CACHE_NAME).rebalance().get();
if (grid(i).localNode().equals(affNodes.get(0))) {
primaryIdx = i;
primary = grid(i);
} else if (grid(i).localNode().equals(affNodes.get(1))) {
backupIdx = i;
backup = grid(i);
}
}
assert primary != null;
assert backup != null;
Integer val1 = 1;
Integer val2 = 2;
cache.put(key, val1);
assertEquals(val1, primary.cache(CACHE_NAME).get(key));
assertEquals(val1, backup.cache(CACHE_NAME).get(key));
if (ig == primary) {
ig = backup;
cache = ig.cache(CACHE_NAME);
}
stopGrid(primaryIdx, false);
backup.context().cache().context().exchange().affinityReadyFuture(new AffinityTopologyVersion(5, 0)).get();
assertEquals(backup.localNode(), ig.affinity(CACHE_NAME).mapKeyToNode(key));
cache.put(key, val2);
assertEquals(val2, backup.cache(CACHE_NAME).get(key));
stopAllGrids(false);
startGrids(NODE_COUNT);
ig = grid(0);
primary = grid(primaryIdx);
backup = grid(backupIdx);
boolean activated = GridTestUtils.waitForCondition(() -> {
for (int i = 0; i < NODE_COUNT; i++) {
if (!grid(i).cluster().active())
return false;
}
return true;
}, 10_000);
assert activated;
// assertEquals(backup.localNode(), ig.affinity(CACHE_NAME).mapKeyToNode(key));
assertEquals(val2, primary.cache(CACHE_NAME).get(key));
assertEquals(val2, backup.cache(CACHE_NAME).get(key));
for (int i = 0; i < NODE_COUNT; i++) grid(i).cache(CACHE_NAME).rebalance().get();
awaitPartitionMapExchange();
affNodes = (List<ClusterNode>) ig.affinity(CACHE_NAME).mapKeyToPrimaryAndBackups(key);
assertEquals(primary.localNode(), affNodes.get(0));
assertEquals(backup.localNode(), affNodes.get(1));
assertEquals(val2, primary.cache(CACHE_NAME).get(key));
assertEquals(val2, backup.cache(CACHE_NAME).get(key));
}
use of org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion in project ignite by apache.
the class CacheContinuousQueryHandler method register.
/**
* {@inheritDoc}
*/
@Override
public RegisterStatus register(final UUID nodeId, final UUID routineId, final GridKernalContext ctx) throws IgniteCheckedException {
assert nodeId != null;
assert routineId != null;
assert ctx != null;
if (locLsnr != null) {
if (locLsnr instanceof JCacheQueryLocalListener) {
ctx.resource().injectGeneric(((JCacheQueryLocalListener) locLsnr).impl);
asyncCb = ((JCacheQueryLocalListener) locLsnr).async();
} else {
ctx.resource().injectGeneric(locLsnr);
asyncCb = U.hasAnnotation(locLsnr, IgniteAsyncCallback.class);
}
}
final CacheEntryEventFilter filter = getEventFilter();
if (filter != null) {
if (filter instanceof JCacheQueryRemoteFilter) {
if (((JCacheQueryRemoteFilter) filter).impl != null)
ctx.resource().injectGeneric(((JCacheQueryRemoteFilter) filter).impl);
if (!asyncCb)
asyncCb = ((JCacheQueryRemoteFilter) filter).async();
} else {
ctx.resource().injectGeneric(filter);
if (!asyncCb)
asyncCb = U.hasAnnotation(filter, IgniteAsyncCallback.class);
}
}
entryBufs = new ConcurrentHashMap<>();
ackBuf = new CacheContinuousQueryAcknowledgeBuffer();
rcvs = new ConcurrentHashMap<>();
this.nodeId = nodeId;
this.routineId = routineId;
this.ctx = ctx;
final boolean loc = nodeId.equals(ctx.localNodeId());
assert !skipPrimaryCheck || loc;
log = ctx.log(CU.CONTINUOUS_QRY_LOG_CATEGORY);
CacheContinuousQueryListener<K, V> lsnr = new CacheContinuousQueryListener<K, V>() {
@Override
public void onExecution() {
GridCacheContext<K, V> cctx = cacheContext(ctx);
if (cctx != null && cctx.events().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
ctx.event().record(new CacheQueryExecutedEvent<>(ctx.discovery().localNode(), "Continuous query executed.", EVT_CACHE_QUERY_EXECUTED, CacheQueryType.CONTINUOUS.name(), cacheName, null, null, null, filter instanceof CacheEntryEventSerializableFilter ? (CacheEntryEventSerializableFilter) filter : null, null, nodeId, taskName()));
}
}
@Override
public boolean keepBinary() {
return keepBinary;
}
@Override
public void onEntryUpdated(final CacheContinuousQueryEvent<K, V> evt, boolean primary, final boolean recordIgniteEvt, GridDhtAtomicAbstractUpdateFuture fut) {
if (ignoreExpired && evt.getEventType() == EventType.EXPIRED)
return;
if (log.isDebugEnabled())
log.debug("Entry updated on affinity node [evt=" + evt + ", primary=" + primary + ']');
final GridCacheContext<K, V> cctx = cacheContext(ctx);
// Check that cache stopped.
if (cctx == null)
return;
// skipPrimaryCheck is set only when listen locally for replicated cache events.
assert !skipPrimaryCheck || (cctx.isReplicated() && ctx.localNodeId().equals(nodeId));
if (asyncCb) {
ContinuousQueryAsyncClosure clsr = new ContinuousQueryAsyncClosure(primary, evt, recordIgniteEvt, fut);
ctx.asyncCallbackPool().execute(clsr, evt.partitionId());
} else {
final boolean notify = filter(evt);
if (log.isDebugEnabled())
log.debug("Filter invoked for event [evt=" + evt + ", primary=" + primary + ", notify=" + notify + ']');
if (primary || skipPrimaryCheck) {
if (fut == null)
onEntryUpdate(evt, notify, loc, recordIgniteEvt);
else {
fut.addContinuousQueryClosure(new CI1<Boolean>() {
@Override
public void apply(Boolean suc) {
if (!suc)
evt.entry().markFiltered();
onEntryUpdate(evt, notify, loc, recordIgniteEvt);
}
}, sync);
}
} else
handleBackupEntry(cctx, evt.entry());
}
}
@Override
public void onUnregister() {
if (filter instanceof PlatformContinuousQueryFilter)
((PlatformContinuousQueryFilter) filter).onQueryUnregister();
}
@Override
public void cleanupBackupQueue(Map<Integer, Long> updateCntrs) {
for (Map.Entry<Integer, Long> e : updateCntrs.entrySet()) {
CacheContinuousQueryEventBuffer buf = entryBufs.get(e.getKey());
if (buf != null)
buf.cleanupBackupQueue(e.getValue());
}
}
@Override
public void flushBackupQueue(GridKernalContext ctx, AffinityTopologyVersion topVer) {
assert topVer != null;
try {
GridCacheContext<K, V> cctx = cacheContext(ctx);
ClusterNode node = ctx.discovery().node(nodeId);
for (Map.Entry<Integer, CacheContinuousQueryEventBuffer> bufE : entryBufs.entrySet()) {
CacheContinuousQueryEventBuffer buf = bufE.getValue();
Collection<CacheContinuousQueryEntry> backupQueue = buf.flushOnExchange();
if (backupQueue != null && node != null) {
for (CacheContinuousQueryEntry e : backupQueue) {
e.markBackup();
if (!e.isFiltered())
prepareEntry(cctx, nodeId, e);
}
ctx.continuous().addBackupNotification(nodeId, routineId, backupQueue, topic);
}
}
} catch (IgniteCheckedException e) {
U.error(ctx.log(CU.CONTINUOUS_QRY_LOG_CATEGORY), "Failed to send backup event notification to node: " + nodeId, e);
}
}
@Override
public void acknowledgeBackupOnTimeout(GridKernalContext ctx) {
sendBackupAcknowledge(ackBuf.acknowledgeOnTimeout(), routineId, ctx);
}
@Override
public void skipUpdateEvent(CacheContinuousQueryEvent<K, V> evt, AffinityTopologyVersion topVer, boolean primary) {
assert evt != null;
CacheContinuousQueryEntry e = evt.entry();
e.markFiltered();
onEntryUpdated(evt, primary, false, null);
}
@Override
public CounterSkipContext skipUpdateCounter(final GridCacheContext cctx, @Nullable CounterSkipContext skipCtx, int part, long cntr, AffinityTopologyVersion topVer, boolean primary) {
if (skipCtx == null)
skipCtx = new CounterSkipContext(part, cntr, topVer);
if (loc) {
assert !locCache;
final Collection<CacheEntryEvent<? extends K, ? extends V>> evts = handleEvent(ctx, skipCtx.entry());
if (!evts.isEmpty()) {
if (asyncCb) {
ctx.asyncCallbackPool().execute(new Runnable() {
@Override
public void run() {
notifyLocalListener(evts, getTransformer());
}
}, part);
} else
skipCtx.addProcessClosure(new Runnable() {
@Override
public void run() {
notifyLocalListener(evts, getTransformer());
}
});
}
return skipCtx;
}
CacheContinuousQueryEventBuffer buf = partitionBuffer(cctx, part);
final Object entryOrList = buf.processEntry(skipCtx.entry(), !primary);
if (entryOrList != null) {
skipCtx.addProcessClosure(new Runnable() {
@Override
public void run() {
try {
ctx.continuous().addNotification(nodeId, routineId, entryOrList, topic, false, true);
} catch (ClusterTopologyCheckedException ex) {
if (log.isDebugEnabled())
log.debug("Failed to send event notification to node, node left cluster " + "[node=" + nodeId + ", err=" + ex + ']');
} catch (IgniteCheckedException ex) {
U.error(ctx.log(CU.CONTINUOUS_QRY_LOG_CATEGORY), "Failed to send event notification to node: " + nodeId, ex);
}
}
});
}
return skipCtx;
}
@Override
public void onPartitionEvicted(int part) {
entryBufs.remove(part);
}
@Override
public boolean oldValueRequired() {
return oldValRequired;
}
@Override
public boolean notifyExisting() {
return notifyExisting;
}
private String taskName() {
return ctx.security().enabled() ? ctx.task().resolveTaskName(taskHash) : null;
}
};
CacheContinuousQueryManager mgr = manager(ctx);
if (mgr == null)
return RegisterStatus.DELAYED;
return mgr.registerListener(routineId, lsnr, internal);
}
Aggregations