/** * Starts cache stop request as cache change batch. * * @param reqs cache stop requests. * @return compound future. */ @NotNull public IgniteInternalFuture<?> dynamicChangeCaches(List<DynamicCacheChangeRequest> reqs) { GridCompoundFuture<?, ?> compoundFut = new GridCompoundFuture<>(); for (DynamicCacheStartFuture fut : initiateCacheChanges(reqs)) compoundFut.add((IgniteInternalFuture)fut); compoundFut.markInitialized(); return compoundFut; }
/** * Creates multi update finish future. Will return {@code null} if no multi-update locks are found. * * @param topVer Topology version. * @return Finish future. */ @Nullable public IgniteInternalFuture<?> multiUpdateFinishFuture(AffinityTopologyVersion topVer) { GridCompoundFuture<IgniteUuid, Object> fut = null; for (MultiUpdateFuture multiFut : multiTxFuts.values()) { if (multiFut.topologyVersion().compareTo(topVer) <= 0) { if (fut == null) fut = new GridCompoundFuture<>(); fut.add(multiFut); } } if (fut != null) fut.markInitialized(); return fut; }
/** * @param topVer Topology version to finish. * * @return Finish update future. */ @SuppressWarnings("unchecked") public IgniteInternalFuture<?> finishAtomicUpdates(AffinityTopologyVersion topVer) { GridCompoundFuture<Object, Object> res = new FinishAtomicUpdateFuture("AtomicUpdate", topVer); for (GridCacheAtomicFuture<?> fut : atomicFuts.values()) { IgniteInternalFuture<Void> complete = fut.completeFuture(topVer); if (complete != null) res.add((IgniteInternalFuture)complete); } res.markInitialized(); return res; }
/** * * @return Finish update future. */ public IgniteInternalFuture<?> finishDataStreamerUpdates(AffinityTopologyVersion topVer) { GridCompoundFuture<Void, Object> res = new CacheObjectsReleaseFuture<>("DataStreamer", topVer); for (DataStreamerFuture fut : dataStreamerFuts) { if (fut.topVer.compareTo(topVer) < 0) res.add(fut); } res.markInitialized(); return res; }
/** * Runs next callable from host node start queue. * * @param queue Queue of tasks to poll from. * @param comp Compound future that comprise all started node tasks. * @param cnt Atomic counter to check if all futures are added to compound future. * @return {@code True} if task was started, {@code false} if queue was empty. */ private boolean runNextNodeCallable(final ConcurrentLinkedQueue<StartNodeCallable> queue, final GridCompoundFuture<ClusterStartNodeResult, Collection<ClusterStartNodeResult>> comp, final AtomicInteger cnt) { StartNodeCallable call = queue.poll(); if (call == null) return false; IgniteInternalFuture<ClusterStartNodeResult> fut = ctx.closure().callLocalSafe(call, true); comp.add(fut); if (cnt.decrementAndGet() == 0) comp.markInitialized(); fut.listen(new CI1<IgniteInternalFuture<ClusterStartNodeResult>>() { @Override public void apply(IgniteInternalFuture<ClusterStartNodeResult> f) { runNextNodeCallable(queue, comp, cnt); } }); return true; }
/** * Creates a future that will wait for all explicit locks acquired on given topology * version to be released. * * @param topVer Topology version to wait for. * @return Explicit locks release future. */ public IgniteInternalFuture<?> finishExplicitLocks(AffinityTopologyVersion topVer) { GridCompoundFuture<Object, Object> res = new CacheObjectsReleaseFuture<>("ExplicitLock", topVer); for (GridCacheExplicitLockSpan span : pendingExplicit.values()) { AffinityTopologyVersion snapshot = span.topologyVersion(); if (snapshot != null && snapshot.compareTo(topVer) < 0) res.add(span.releaseFuture()); } res.markInitialized(); return res; }
/** * Resets cache state after the cache has been moved to recovery state. * * @param cacheNames Cache names. * @return Future that will be completed when state is changed for all caches. */ public IgniteInternalFuture<?> resetCacheState(Collection<String> cacheNames) { checkEmptyTransactions(); if (F.isEmpty(cacheNames)) cacheNames = cachesInfo.registeredCaches().keySet(); Collection<DynamicCacheChangeRequest> reqs = new ArrayList<>(cacheNames.size()); for (String cacheName : cacheNames) { DynamicCacheDescriptor desc = cacheDescriptor(cacheName); if (desc == null) { U.warn(log, "Failed to find cache for reset lost partition request, cache does not exist: " + cacheName); continue; } DynamicCacheChangeRequest req = DynamicCacheChangeRequest.resetLostPartitions(ctx, cacheName); reqs.add(req); } GridCompoundFuture fut = new GridCompoundFuture(); for (DynamicCacheStartFuture f : initiateCacheChanges(reqs)) fut.add(f); fut.markInitialized(); return fut; }
/** * Creates a future that will wait for finishing all remote transactions (primary -> backup) * with topology version less or equal to {@code topVer}. * * @param topVer Topology version. * @return Compound future of all {@link GridDhtTxFinishFuture} futures. */ public IgniteInternalFuture<?> finishRemoteTxs(AffinityTopologyVersion topVer) { GridCompoundFuture<?, ?> res = new CacheObjectsReleaseFuture<>("RemoteTx", topVer); for (GridCacheFuture<?> fut : futs.values()) { if (fut instanceof GridDhtTxFinishFuture) { GridDhtTxFinishFuture finishTxFuture = (GridDhtTxFinishFuture) fut; if (cctx.tm().needWaitTransaction(finishTxFuture.tx(), topVer)) res.add(ignoreErrors(finishTxFuture)); } } res.markInitialized(); return res; }
/** {@inheritDoc} */ @Override public void visit(SchemaIndexCacheVisitorClosure clo) throws IgniteCheckedException { assert clo != null; List<GridDhtLocalPartition> parts = cctx.topology().localPartitions(); if (parts.isEmpty()) return; GridCompoundFuture<Void, Void> fut = null; if (parallelism > 1) { fut = new GridCompoundFuture<>(); for (int i = 1; i < parallelism; i++) fut.add(processPartitionsAsync(parts, clo, i)); fut.markInitialized(); } processPartitions(parts, clo, 0); if (fut != null) fut.get(); }
/** * @param keysMap Keys to request. * @return Keys request future. */ private IgniteInternalFuture<Object> forceRebalanceKeys(Map<Integer, Collection<KeyCacheObject>> keysMap) { if (F.isEmpty(keysMap)) return null; GridCompoundFuture<Object, Object> compFut = null; IgniteInternalFuture<Object> lastForceFut = null; for (Map.Entry<Integer, Collection<KeyCacheObject>> entry : keysMap.entrySet()) { if (lastForceFut != null && compFut == null) { compFut = new GridCompoundFuture(); compFut.add(lastForceFut); } int cacheId = entry.getKey(); Collection<KeyCacheObject> keys = entry.getValue(); GridCacheContext ctx = cctx.cacheContext(cacheId); lastForceFut = ctx.group().preloader().request(ctx, keys, tx.topologyVersion()); if (compFut != null && lastForceFut != null) compFut.add(lastForceFut); } if (compFut != null) { compFut.markInitialized(); return compFut; } else return lastForceFut; }
/** * Creates a future that will wait for finishing all tx updates on backups after all local transactions are finished. * * NOTE: * As we send finish request to backup nodes after transaction successfully completed on primary node * it's important to ensure that all updates from primary to backup are finished or at least remote transaction has created on backup node. * * @param finishLocalTxsFuture Local transactions finish future. * @param topVer Topology version. * @return Future that will be completed when all ongoing transactions are finished. */ public IgniteInternalFuture<?> finishAllTxs(IgniteInternalFuture<?> finishLocalTxsFuture, AffinityTopologyVersion topVer) { final GridCompoundFuture finishAllTxsFuture = new CacheObjectsReleaseFuture("AllTx", topVer); // After finishing all local updates, wait for finishing all tx updates on backups. finishLocalTxsFuture.listen(future -> { finishAllTxsFuture.add(cctx.mvcc().finishRemoteTxs(topVer)); finishAllTxsFuture.markInitialized(); }); return finishAllTxsFuture; }
/** * @param nearVer Near version. * @return Finish future for related remote transactions. */ @SuppressWarnings("unchecked") public IgniteInternalFuture<?> remoteTxFinishFuture(GridCacheVersion nearVer) { GridCompoundFuture<Void, Void> fut = new GridCompoundFuture<>(); for (final IgniteInternalTx tx : activeTransactions()) { if (!tx.local() && nearVer.equals(tx.nearXidVersion())) fut.add((IgniteInternalFuture) tx.finishFuture()); } fut.markInitialized(); return fut; }
/** * @param timeMillis Loading time in milliseconds. */ public IgniteInternalFuture<?> loadByTime(int timeMillis) { GridCompoundFuture<?, ?> loadFut = new GridCompoundFuture(); for (CacheLoader cacheLoader : cacheLoaders) { long endTime = U.currentTimeMillis() + timeMillis; cacheLoader.stopPredicate = it -> U.currentTimeMillis() >= endTime; loadFut.add(GridTestUtils.runAsync(cacheLoader)); } loadFut.markInitialized(); return loadFut; }
/** * @throws Exception If failed. */ @Test public void testCompleteOnReducer() throws Exception { GridCompoundFuture<Boolean, Boolean> fut = new GridCompoundFuture<>(CU.boolReducer()); List<GridFutureAdapter<Boolean>> futs = new ArrayList<>(5); for (int i = 0; i < 5; i++) { GridFutureAdapter<Boolean> part = new GridFutureAdapter<>(); fut.add(part); futs.add(part); } fut.markInitialized(); assertFalse(fut.isDone()); assertFalse(fut.isCancelled()); for (int i = 0; i < 3; i++) { futs.get(i).onDone(true); assertFalse(fut.isDone()); } futs.get(3).onDone(false); assertTrue(fut.isDone()); }
/** * @throws Exception If failed. */ @Test public void testCompleteOnException() throws Exception { GridCompoundFuture<Boolean, Boolean> fut = new GridCompoundFuture<>(CU.boolReducer()); List<GridFutureAdapter<Boolean>> futs = new ArrayList<>(5); for (int i = 0; i < 5; i++) { GridFutureAdapter<Boolean> part = new GridFutureAdapter<>(); fut.add(part); futs.add(part); } fut.markInitialized(); assertFalse(fut.isDone()); assertFalse(fut.isCancelled()); for (int i = 0; i < 3; i++) { futs.get(i).onDone(true); assertFalse(fut.isDone()); } futs.get(3).onDone(new IgniteCheckedException("Test message")); assertTrue(fut.isDone()); }
/** * @throws Exception If failed. */ @Test public void testConcurrentCompletion() throws Exception { GridCompoundFuture<Boolean, Boolean> fut = new GridCompoundFuture<>(CU.boolReducer()); final ConcurrentLinkedDeque<GridFutureAdapter<Boolean>> futs = new ConcurrentLinkedDeque<>(); for (int i = 0; i < 1000; i++) { GridFutureAdapter<Boolean> part = new GridFutureAdapter<>(); fut.add(part); futs.add(part); } fut.markInitialized(); IgniteInternalFuture<?> complete = multithreadedAsync(new Runnable() { @Override public void run() { GridFutureAdapter<Boolean> part; while ((part = futs.poll()) != null) part.onDone(true); } }, 20); complete.get(); assertTrue(fut.isDone()); }
/** * @throws Exception If failed. */ @Test public void testMarkInitialized() throws Exception { GridCompoundFuture<Boolean, Boolean> fut = new GridCompoundFuture<>(); for (int i = 0; i < 5; i++) { IgniteInternalFuture<Boolean> part = new GridFinishedFuture<>(true); fut.add(part); } assertFalse(fut.isDone()); assertFalse(fut.isCancelled()); fut.markInitialized(); assertTrue(fut.isDone()); }