use of org.apache.ignite.internal.managers.discovery.DiscoCache in project ignite by apache.
the class SnapshotRestoreProcess method preload.
/**
* @param reqId Request id.
* @return Future which will be completed when the preload ends.
*/
private IgniteInternalFuture<Boolean> preload(UUID reqId) {
if (ctx.clientNode())
return new GridFinishedFuture<>();
SnapshotRestoreContext opCtx0 = opCtx;
GridFutureAdapter<Boolean> retFut = new GridFutureAdapter<>();
if (opCtx0 == null)
return new GridFinishedFuture<>(new IgniteCheckedException("Snapshot restore process has incorrect restore state: " + reqId));
if (opCtx0.dirs.isEmpty())
return new GridFinishedFuture<>();
try {
if (ctx.isStopping())
throw new NodeStoppingException("Node is stopping: " + ctx.localNodeId());
Set<SnapshotMetadata> allMetas = opCtx0.metasPerNode.values().stream().flatMap(List::stream).collect(Collectors.toSet());
AbstractSnapshotVerificationTask.checkMissedMetadata(allMetas);
IgniteSnapshotManager snpMgr = ctx.cache().context().snapshotMgr();
synchronized (this) {
opCtx0.stopFut = new IgniteFutureImpl<>(retFut.chain(f -> null));
}
if (log.isInfoEnabled()) {
log.info("Starting snapshot preload operation to restore cache groups " + "[reqId=" + reqId + ", snapshot=" + opCtx0.snpName + ", caches=" + F.transform(opCtx0.dirs, FilePageStoreManager::cacheGroupName) + ']');
}
CompletableFuture<Void> metaFut = ctx.localNodeId().equals(opCtx0.opNodeId) ? CompletableFuture.runAsync(() -> {
try {
SnapshotMetadata meta = F.first(opCtx0.metasPerNode.get(opCtx0.opNodeId));
File binDir = binaryWorkDir(snpMgr.snapshotLocalDir(opCtx0.snpName).getAbsolutePath(), meta.folderName());
ctx.cacheObjects().updateMetadata(binDir, opCtx0.stopChecker);
} catch (Throwable t) {
log.error("Unable to perform metadata update operation for the cache groups restore process", t);
opCtx0.errHnd.accept(t);
}
}, snpMgr.snapshotExecutorService()) : CompletableFuture.completedFuture(null);
Map<String, GridAffinityAssignmentCache> affCache = new HashMap<>();
for (StoredCacheData data : opCtx0.cfgs.values()) {
affCache.computeIfAbsent(CU.cacheOrGroupName(data.config()), grp -> calculateAffinity(ctx, data.config(), opCtx0.discoCache));
}
Map<Integer, Set<PartitionRestoreFuture>> allParts = new HashMap<>();
Map<Integer, Set<PartitionRestoreFuture>> rmtLoadParts = new HashMap<>();
ClusterNode locNode = ctx.cache().context().localNode();
List<SnapshotMetadata> locMetas = opCtx0.metasPerNode.get(locNode.id());
// First preload everything from the local node.
for (File dir : opCtx0.dirs) {
String cacheOrGrpName = cacheGroupName(dir);
int grpId = CU.cacheId(cacheOrGrpName);
File tmpCacheDir = formatTmpDirName(dir);
tmpCacheDir.mkdir();
Set<PartitionRestoreFuture> leftParts;
// Partitions contained in the snapshot.
Set<Integer> availParts = new HashSet<>();
for (SnapshotMetadata meta : allMetas) {
Set<Integer> parts = meta.partitions().get(grpId);
if (parts != null)
availParts.addAll(parts);
}
List<List<ClusterNode>> assignment = affCache.get(cacheOrGrpName).idealAssignment().assignment();
Set<PartitionRestoreFuture> partFuts = availParts.stream().filter(p -> p != INDEX_PARTITION && assignment.get(p).contains(locNode)).map(p -> new PartitionRestoreFuture(p, opCtx0.processedParts)).collect(Collectors.toSet());
allParts.put(grpId, partFuts);
rmtLoadParts.put(grpId, leftParts = new HashSet<>(partFuts));
if (leftParts.isEmpty())
continue;
SnapshotMetadata full = findMetadataWithSamePartitions(locMetas, grpId, leftParts.stream().map(p -> p.partId).collect(Collectors.toSet()));
for (SnapshotMetadata meta : full == null ? locMetas : Collections.singleton(full)) {
if (leftParts.isEmpty())
break;
File snpCacheDir = new File(ctx.cache().context().snapshotMgr().snapshotLocalDir(opCtx0.snpName), Paths.get(databaseRelativePath(meta.folderName()), dir.getName()).toString());
leftParts.removeIf(partFut -> {
boolean doCopy = ofNullable(meta.partitions().get(grpId)).orElse(Collections.emptySet()).contains(partFut.partId);
if (doCopy) {
copyLocalAsync(ctx.cache().context().snapshotMgr(), opCtx0, snpCacheDir, tmpCacheDir, partFut);
}
return doCopy;
});
if (meta == full) {
assert leftParts.isEmpty() : leftParts;
if (log.isInfoEnabled()) {
log.info("The snapshot was taken on the same cluster topology. The index will be copied to " + "restoring cache group if necessary [reqId=" + reqId + ", snapshot=" + opCtx0.snpName + ", dir=" + dir.getName() + ']');
}
File idxFile = new File(snpCacheDir, FilePageStoreManager.getPartitionFileName(INDEX_PARTITION));
if (idxFile.exists()) {
PartitionRestoreFuture idxFut;
allParts.computeIfAbsent(grpId, g -> new HashSet<>()).add(idxFut = new PartitionRestoreFuture(INDEX_PARTITION, opCtx0.processedParts));
copyLocalAsync(ctx.cache().context().snapshotMgr(), opCtx0, snpCacheDir, tmpCacheDir, idxFut);
}
}
}
}
// Load other partitions from remote nodes.
List<PartitionRestoreFuture> rmtAwaitParts = rmtLoadParts.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
// This is necessary for sending only one partitions request per each cluster node.
Map<UUID, Map<Integer, Set<Integer>>> snpAff = snapshotAffinity(opCtx0.metasPerNode.entrySet().stream().filter(e -> !e.getKey().equals(ctx.localNodeId())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)), (grpId, partId) -> rmtLoadParts.get(grpId) != null && rmtLoadParts.get(grpId).remove(new PartitionRestoreFuture(partId, opCtx0.processedParts)));
Map<Integer, File> grpToDir = opCtx0.dirs.stream().collect(Collectors.toMap(d -> CU.cacheId(FilePageStoreManager.cacheGroupName(d)), d -> d));
try {
if (log.isInfoEnabled() && !snpAff.isEmpty()) {
log.info("Trying to request partitions from remote nodes " + "[reqId=" + reqId + ", snapshot=" + opCtx0.snpName + ", map=" + snpAff.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> partitionsMapToCompactString(e.getValue()))) + ']');
}
for (Map.Entry<UUID, Map<Integer, Set<Integer>>> m : snpAff.entrySet()) {
ctx.cache().context().snapshotMgr().requestRemoteSnapshotFiles(m.getKey(), opCtx0.snpName, m.getValue(), opCtx0.stopChecker, (snpFile, t) -> {
if (opCtx0.stopChecker.getAsBoolean())
throw new IgniteInterruptedException("Snapshot remote operation request cancelled.");
if (t == null) {
int grpId = CU.cacheId(cacheGroupName(snpFile.getParentFile()));
int partId = partId(snpFile.getName());
PartitionRestoreFuture partFut = F.find(allParts.get(grpId), null, new IgnitePredicate<PartitionRestoreFuture>() {
@Override
public boolean apply(PartitionRestoreFuture f) {
return f.partId == partId;
}
});
assert partFut != null : snpFile.getAbsolutePath();
File tmpCacheDir = formatTmpDirName(grpToDir.get(grpId));
Path partFile = Paths.get(tmpCacheDir.getAbsolutePath(), snpFile.getName());
try {
Files.move(snpFile.toPath(), partFile);
partFut.complete(partFile);
} catch (Exception e) {
opCtx0.errHnd.accept(e);
completeListExceptionally(rmtAwaitParts, e);
}
} else {
opCtx0.errHnd.accept(t);
completeListExceptionally(rmtAwaitParts, t);
}
});
}
} catch (IgniteCheckedException e) {
opCtx0.errHnd.accept(e);
completeListExceptionally(rmtAwaitParts, e);
}
List<PartitionRestoreFuture> allPartFuts = allParts.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
int size = allPartFuts.size();
opCtx0.totalParts = size;
CompletableFuture.allOf(allPartFuts.toArray(new CompletableFuture[size])).runAfterBothAsync(metaFut, () -> {
try {
if (opCtx0.stopChecker.getAsBoolean())
throw new IgniteInterruptedException("The operation has been stopped on temporary directory switch.");
for (File src : opCtx0.dirs) Files.move(formatTmpDirName(src).toPath(), src.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
throw new IgniteException(e);
}
}, snpMgr.snapshotExecutorService()).whenComplete((r, t) -> opCtx0.errHnd.accept(t)).whenComplete((res, t) -> {
Throwable t0 = ofNullable(opCtx0.err.get()).orElse(t);
if (t0 == null)
retFut.onDone(true);
else {
log.error("Unable to restore cache group(s) from a snapshot " + "[reqId=" + opCtx.reqId + ", snapshot=" + opCtx.snpName + ']', t0);
retFut.onDone(t0);
}
});
} catch (Exception ex) {
opCtx0.errHnd.accept(ex);
return new GridFinishedFuture<>(ex);
}
return retFut;
}
use of org.apache.ignite.internal.managers.discovery.DiscoCache in project ignite by apache.
the class GridClusterStateProcessor method listInMemoryUserCaches.
/**
* @return Lists in-memory user defined caches.
*/
private List<String> listInMemoryUserCaches() {
IgniteBiPredicate<DynamicCacheDescriptor, DataRegionConfiguration> inMemoryPred = (desc, dataRegionCfg) -> {
return !(dataRegionCfg != null && dataRegionCfg.isPersistenceEnabled()) && (!desc.cacheConfiguration().isWriteThrough() || !desc.cacheConfiguration().isReadThrough());
};
if (ctx.discovery().localNode().isClient()) {
// Need to check cache descriptors using server node storage configurations.
// The reason for this is that client node may not be configured with the required data region configuration.
List<ClusterNode> srvs = ctx.discovery().discoCache().serverNodes();
if (F.isEmpty(srvs))
return Collections.emptyList();
return ctx.cache().cacheDescriptors().values().stream().filter(desc -> !CU.isSystemCache(desc.cacheName())).filter(desc -> {
String dataRegionName = desc.cacheConfiguration().getDataRegionName();
// We always should use server data storage configurations instead of client node config,
// because it is not validated when the client node joins the cluster
// and so it cannot be the source of truth.
DataRegionConfiguration dataRegionCfg = null;
// Need to find out the first server node that knows about this data region and its configuration.
for (ClusterNode n : srvs) {
dataRegionCfg = CU.findRemoteDataRegionConfiguration(n, ctx.marshallerContext().jdkMarshaller(), U.resolveClassLoader(ctx.config()), dataRegionName);
if (dataRegionCfg != null)
break;
}
return inMemoryPred.apply(desc, dataRegionCfg);
}).map(DynamicCacheDescriptor::cacheName).collect(Collectors.toList());
}
return ctx.cache().cacheDescriptors().values().stream().filter(desc -> !CU.isSystemCache(desc.cacheName())).filter(desc -> {
String dataRegionName = desc.cacheConfiguration().getDataRegionName();
DataRegionConfiguration dataRegionCfg = CU.findDataRegionConfiguration(ctx.config().getDataStorageConfiguration(), dataRegionName);
if (dataRegionCfg == null) {
List<ClusterNode> srvs = ctx.discovery().discoCache().serverNodes();
// Need to find out the first server node that knows about this data region and its configuration.
for (ClusterNode n : srvs) {
dataRegionCfg = CU.findRemoteDataRegionConfiguration(n, ctx.marshallerContext().jdkMarshaller(), U.resolveClassLoader(ctx.config()), dataRegionName);
if (dataRegionCfg != null)
break;
}
}
return inMemoryPred.apply(desc, dataRegionCfg);
}).map(DynamicCacheDescriptor::cacheName).collect(Collectors.toList());
}
use of org.apache.ignite.internal.managers.discovery.DiscoCache in project ignite by apache.
the class GridContinuousProcessor method processStartRequestV2.
/**
* @param topVer Current topology version.
* @param snd Sender.
* @param msg Start request.
*/
private void processStartRequestV2(final AffinityTopologyVersion topVer, final ClusterNode snd, final StartRoutineDiscoveryMessageV2 msg) {
StartRequestDataV2 reqData = msg.startRequestData();
ContinuousRoutineInfo routineInfo = new ContinuousRoutineInfo(snd.id(), msg.routineId(), reqData.handlerBytes(), reqData.nodeFilterBytes(), reqData.bufferSize(), reqData.interval(), reqData.autoUnsubscribe());
routinesInfo.addRoutineInfo(routineInfo);
final DiscoCache discoCache = ctx.discovery().discoCache(topVer);
// Should not use marshaller and send messages from discovery thread.
ctx.pools().getSystemExecutorService().execute(new Runnable() {
@Override
public void run() {
if (snd.id().equals(ctx.localNodeId())) {
StartFuture fut = startFuts.get(msg.routineId());
if (fut != null)
fut.initRemoteNodes(discoCache);
return;
}
StartRequestDataV2 reqData = msg.startRequestData();
Exception err = null;
IgnitePredicate<ClusterNode> nodeFilter = null;
byte[] cntrs = null;
if (reqData.nodeFilterBytes() != null) {
try {
if (ctx.config().isPeerClassLoadingEnabled() && reqData.className() != null) {
String clsName = reqData.className();
GridDeploymentInfo depInfo = reqData.deploymentInfo();
GridDeployment dep = ctx.deploy().getGlobalDeployment(depInfo.deployMode(), clsName, clsName, depInfo.userVersion(), snd.id(), depInfo.classLoaderId(), depInfo.participants(), null);
if (dep == null) {
throw new IgniteDeploymentCheckedException("Failed to obtain deployment " + "for class: " + clsName);
}
nodeFilter = U.unmarshal(marsh, reqData.nodeFilterBytes(), U.resolveClassLoader(dep.classLoader(), ctx.config()));
} else {
nodeFilter = U.unmarshal(marsh, reqData.nodeFilterBytes(), U.resolveClassLoader(ctx.config()));
}
if (nodeFilter != null)
ctx.resource().injectGeneric(nodeFilter);
} catch (Exception e) {
err = e;
U.error(log, "Failed to unmarshal continuous routine filter [" + "routineId=" + msg.routineId + ", srcNodeId=" + snd.id() + ']', e);
}
}
boolean register = err == null && (nodeFilter == null || nodeFilter.apply(ctx.discovery().localNode()));
if (register) {
try {
GridContinuousHandler hnd = U.unmarshal(marsh, reqData.handlerBytes(), U.resolveClassLoader(ctx.config()));
if (ctx.config().isPeerClassLoadingEnabled())
hnd.p2pUnmarshal(snd.id(), ctx);
if (msg.keepBinary()) {
assert hnd instanceof CacheContinuousQueryHandler : hnd;
((CacheContinuousQueryHandler) hnd).keepBinary(true);
}
registerHandler(snd.id(), msg.routineId, hnd, reqData.bufferSize(), reqData.interval(), reqData.autoUnsubscribe(), false);
if (hnd.isQuery()) {
GridCacheProcessor proc = ctx.cache();
if (proc != null) {
GridCacheAdapter cache = ctx.cache().internalCache(hnd.cacheName());
if (cache != null && !cache.isLocal() && cache.context().userCache()) {
CachePartitionPartialCountersMap cntrsMap = cache.context().topology().localUpdateCounters(false);
cntrs = U.marshal(marsh, cntrsMap);
}
}
}
} catch (Exception e) {
err = e;
U.error(log, "Failed to register continuous routine handler [" + "routineId=" + msg.routineId + ", srcNodeId=" + snd.id() + ']', e);
}
}
sendMessageStartResult(snd, msg.routineId(), cntrs, err);
}
});
}
use of org.apache.ignite.internal.managers.discovery.DiscoCache in project ignite by apache.
the class IgniteDiscoveryCacheReuseSelfTest method assertDiscoCacheReuse.
/**
* Assert disco cache reuse.
*
* @param v1 First version.
* @param v2 Next version.
*/
private void assertDiscoCacheReuse(AffinityTopologyVersion v1, AffinityTopologyVersion v2) {
for (Ignite ignite : G.allGrids()) {
GridBoundedConcurrentLinkedHashMap<AffinityTopologyVersion, DiscoCache> discoCacheHist = U.field(((IgniteEx) ignite).context().discovery(), "discoCacheHist");
DiscoCache discoCache1 = discoCacheHist.get(v1);
DiscoCache discoCache2 = discoCacheHist.get(v2);
assertEquals(v1, discoCache1.version());
assertEquals(v2, discoCache2.version());
String[] props = new String[] { "state", "loc", "rmtNodes", "allNodes", "srvNodes", "daemonNodes", "rmtNodesWithCaches", "allCacheNodes", "allCacheNodes", "cacheGrpAffNodes", "nodeMap", "minNodeVer" };
for (String prop : props) assertSame(U.field(discoCache1, prop), U.field(discoCache2, prop));
assertNotSame(U.field(discoCache1, "alives"), U.field(discoCache2, "alives"));
GridConcurrentHashSet alives1 = U.field(discoCache1, "alives");
GridConcurrentHashSet alives2 = U.field(discoCache2, "alives");
assertEquals("Discovery caches are not equal", alives1, alives2);
}
}
use of org.apache.ignite.internal.managers.discovery.DiscoCache in project ignite by apache.
the class GridCachePartitionExchangeManager method onKernalStart0.
/** {@inheritDoc} */
@Override
protected void onKernalStart0(boolean reconnect) throws IgniteCheckedException {
super.onKernalStart0(reconnect);
ClusterNode loc = cctx.localNode();
long startTime = loc.metrics().getStartTime();
assert startTime > 0;
// Generate dummy discovery event for local node joining.
T2<DiscoveryEvent, DiscoCache> locJoin = cctx.discovery().localJoin();
DiscoveryEvent discoEvt = locJoin.get1();
DiscoCache discoCache = locJoin.get2();
GridDhtPartitionExchangeId exchId = initialExchangeId();
GridDhtPartitionsExchangeFuture fut = exchangeFuture(exchId, discoEvt, discoCache, null, null);
if (reconnect)
reconnectExchangeFut = new GridFutureAdapter<>();
exchWorker.addFirstExchangeFuture(fut);
if (!cctx.kernalContext().clientNode()) {
for (int cnt = 0; cnt < cctx.gridConfig().getRebalanceThreadPoolSize(); cnt++) {
final int idx = cnt;
cctx.io().addOrderedHandler(rebalanceTopic(cnt), new CI2<UUID, GridCacheMessage>() {
@Override
public void apply(final UUID id, final GridCacheMessage m) {
if (!enterBusy())
return;
try {
GridCacheContext cacheCtx = cctx.cacheContext(m.cacheId);
if (cacheCtx != null) {
if (m instanceof GridDhtPartitionSupplyMessage)
cacheCtx.preloader().handleSupplyMessage(idx, id, (GridDhtPartitionSupplyMessage) m);
else if (m instanceof GridDhtPartitionDemandMessage)
cacheCtx.preloader().handleDemandMessage(idx, id, (GridDhtPartitionDemandMessage) m);
else
U.error(log, "Unsupported message type: " + m.getClass().getName());
}
} finally {
leaveBusy();
}
}
});
}
}
new IgniteThread(cctx.igniteInstanceName(), "exchange-worker", exchWorker).start();
if (reconnect) {
fut.listen(new CI1<IgniteInternalFuture<AffinityTopologyVersion>>() {
@Override
public void apply(IgniteInternalFuture<AffinityTopologyVersion> fut) {
try {
fut.get();
for (GridCacheContext cacheCtx : cctx.cacheContexts()) cacheCtx.preloader().onInitialExchangeComplete(null);
reconnectExchangeFut.onDone();
} catch (IgniteCheckedException e) {
for (GridCacheContext cacheCtx : cctx.cacheContexts()) cacheCtx.preloader().onInitialExchangeComplete(e);
reconnectExchangeFut.onDone(e);
}
}
});
} else {
if (log.isDebugEnabled())
log.debug("Beginning to wait on local exchange future: " + fut);
boolean first = true;
while (true) {
try {
fut.get(cctx.preloadExchangeTimeout());
break;
} catch (IgniteFutureTimeoutCheckedException ignored) {
if (first) {
U.warn(log, "Failed to wait for initial partition map exchange. " + "Possible reasons are: " + U.nl() + " ^-- Transactions in deadlock." + U.nl() + " ^-- Long running transactions (ignore if this is the case)." + U.nl() + " ^-- Unreleased explicit locks.");
first = false;
} else
U.warn(log, "Still waiting for initial partition map exchange [fut=" + fut + ']');
} catch (IgniteNeedReconnectException e) {
throw e;
} catch (Exception e) {
if (fut.reconnectOnError(e))
throw new IgniteNeedReconnectException(cctx.localNode(), e);
throw e;
}
}
AffinityTopologyVersion nodeStartVer = new AffinityTopologyVersion(discoEvt.topologyVersion(), 0);
for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
if (nodeStartVer.equals(cacheCtx.startTopologyVersion()))
cacheCtx.preloader().onInitialExchangeComplete(null);
}
if (log.isDebugEnabled())
log.debug("Finished waiting for initial exchange: " + fut.exchangeId());
}
}
Aggregations