/** * Adds listener to asynchronously log errors. * * @param f Future to listen to. * @param log Logger. */ public static void asyncLogError(GridFuture<?> f, final GridLogger log) { if (f != null) f.listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> f) { try { f.get(); } catch (GridException e) { U.error(log, "Failed to execute future: " + f, e); } } }); }
/** * @param ctx Context. * @param embedded Embedded future. * @param c Closure to execute upon completion of embedded future. */ public GridEmbeddedFuture(GridKernalContext ctx, GridFuture<B> embedded, final GridBiClosure<B, Exception, A> c) { super(ctx); assert embedded != null; assert c != null; this.embedded = embedded; embedded.listenAsync(new AL1() { @SuppressWarnings({"ErrorNotRethrown", "CatchGenericClass"}) @Override public void applyx(GridFuture<B> embedded) { try { onDone(c.apply(embedded.get(), null)); } catch (GridException| RuntimeException e) { onDone(c.apply(null, e)); } catch (Error e) { onDone(e); throw e; } } }); }
@Override @Nullable public Object call() throws Exception { storeBlocksAsync(blocks).listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> fut) { try { fut.get(); completionFut.onWriteAck(nodeId, batchId); } catch (GridException e) { completionFut.onError(nodeId, e); } } }); return null; } });
@Override @Nullable public Object call() throws Exception { storeBlocksAsync(blocks).listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> fut) { try { fut.get(); completionFut.onWriteAck(nodeId, batchId); } catch (GridException e) { completionFut.onError(nodeId, e); } } }); return null; } });
/** * @param <T> Type of command result. * @param fut Future to add. * @return Future for command. */ @SuppressWarnings("unchecked") private <T> Future<T> addFuture(GridFuture<T> fut) { synchronized (mux) { if (!fut.isDone()) { fut.listenAsync(lsnr); futs.add(fut); } return new TaskFutureWrapper<>(fut); } }
/** * @param nodeId Node ID. * @param blocksMsg Write request message. */ private void processBlocksMessage(final UUID nodeId, final GridGgfsBlocksMessage blocksMsg) { storeBlocksAsync(blocksMsg.blocks()).listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> fut) { GridException err = null; try { fut.get(); } catch (GridException e) { err = e; } try { // Send reply back to node. ggfsCtx.send(nodeId, topic, new GridGgfsAckMessage(blocksMsg.fileId(), blocksMsg.id(), err), SYSTEM_POOL); } catch (GridException e) { U.warn(log, "Failed to send batch acknowledgement (did node leave the grid?) [nodeId=" + nodeId + ", fileId=" + blocksMsg.fileId() + ", batchId=" + blocksMsg.id() + ']', e); } } }); }
/** * @param nodeId Node ID. * @param blocksMsg Write request message. */ private void processBlocksMessage(final UUID nodeId, final GridGgfsBlocksMessage blocksMsg) { storeBlocksAsync(blocksMsg.blocks()).listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> fut) { GridException err = null; try { fut.get(); } catch (GridException e) { err = e; } try { // Send reply back to node. ggfsCtx.send(nodeId, topic, new GridGgfsAckMessage(blocksMsg.fileId(), blocksMsg.id(), err), SYSTEM_POOL); } catch (GridException e) { U.warn(log, "Failed to send batch acknowledgement (did node leave the grid?) [nodeId=" + nodeId + ", fileId=" + blocksMsg.fileId() + ", batchId=" + blocksMsg.id() + ']', e); } } }); }
/** * @param cacheName Cache name ({@code null} for default cache). * @param compact {@code true} if data loader should transfer data in compact format. * @return Data loader. */ public GridDataLoader<K, V> dataLoader(@Nullable String cacheName, boolean compact) { if (!busyLock.enterBusy()) throw new IllegalStateException("Failed to create data loader (grid is stopping)."); try { final GridDataLoaderImpl<K, V> ldr = new GridDataLoaderImpl<>(ctx, cacheName, flushQ, compact); ldrs.add(ldr); ldr.future().listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> f) { boolean b = ldrs.remove(ldr); assert b : "Loader has not been added to set: " + ldr; if (log.isDebugEnabled()) log.debug("Loader has been completed: " + ldr); } }); return ldr; } finally { busyLock.leaveBusy(); } }
/** * 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<GridNodeCallable> queue, final GridCompoundFuture<GridTuple3<String, Boolean, String>, Collection<GridTuple3<String, Boolean, String>>> comp, final AtomicInteger cnt) { GridNodeCallable call = queue.poll(); if (call == null) return false; GridFuture<GridTuple3<String, Boolean, String>> fut = ctx.closure().callLocalSafe(call, true); comp.add(fut); if (cnt.decrementAndGet() == 0) comp.markInitialized(); fut.listenAsync(new CI1<GridFuture<GridTuple3<String, Boolean, String>>>() { @Override public void apply(GridFuture<GridTuple3<String, Boolean, String>> f) { runNextNodeCallable(queue, comp, cnt); } }); return true; }
/** * Adds a future to this compound future. * * @param fut Future to add. */ public void add(GridFuture<T> fut) { assert fut != null; pending.add(fut); futs.add(fut); fut.listenAsync(new Listener()); if (isCancelled()) try { fut.cancel(); } catch (GridException e) { onDone(e); } }
/** * Initializes this future. */ public void init() { if (F.isEmpty(txs)) { remainingTxs = Collections.emptySet(); onDone(true); } else { remainingTxs = new GridConcurrentHashSet<>(txs); for (final GridCacheTxEx<K, V> tx : txs) { if (!tx.done()) { tx.finishFuture().listenAsync(new CI1<GridFuture<GridCacheTx>>() { @Override public void apply(GridFuture<GridCacheTx> t) { remainingTxs.remove(tx); checkRemaining(); } }); } else remainingTxs.remove(tx); } checkRemaining(); } }
/** * @param nodeId Node ID. * @param req Request. */ private void processNearTxFinishRequest(UUID nodeId, GridNearTxFinishRequest<K, V> req) { assert isAffinityNode(cacheCfg); if (log.isDebugEnabled()) log.debug("Processing near tx finish request [nodeId=" + nodeId + ", req=" + req + "]"); GridFuture<?> f = finish(nodeId, req); if (f != null) // Only for error logging. f.listenAsync(CU.errorLogger(log)); }
/** * Executes local update. * * @param nodeId Node ID. * @param req Update request. * @param cached Cached entry if updating single local entry. * @param completionCb Completion callback. */ public void updateAllAsyncInternal( final UUID nodeId, final GridNearAtomicUpdateRequest<K, V> req, @Nullable final GridCacheEntryEx<K, V> cached, final CI2<GridNearAtomicUpdateRequest<K, V>, GridNearAtomicUpdateResponse<K, V>> completionCb ) { GridFuture<Object> forceFut = preldr.request(req.keys(), req.topologyVersion()); if (forceFut.isDone()) updateAllAsyncInternal0(nodeId, req, cached, completionCb); else { forceFut.listenAsync(new CI1<GridFuture<Object>>() { @Override public void apply(GridFuture<Object> t) { updateAllAsyncInternal0(nodeId, req, cached, completionCb); } }); } }
@Override protected void body() { try { GridFuture<GridRestResponse> res = handleRequest(req); res.listenAsync(new GridInClosure<GridFuture<GridRestResponse>>() { @Override public void apply(GridFuture<GridRestResponse> f) { try { fut.onDone(f.get()); } catch (Throwable e) { fut.onDone(e); if (e instanceof Error) { U.error(log, "Client request execution failed with error.", e); throw (Error)e; } } } }); } catch (Throwable e) { fut.onDone(U.cast(e)); if (e instanceof Error) { U.error(log, "Client request execution failed with error.", e); throw e; } } finally { workersCnt.decrement(); } } };
/** * Commits or rolls back prepared transaction. * * @param tx Transaction. * @param commit Whether transaction should be committed or rolled back. */ public void finishOptimisticTxOnRecovery(final GridCacheTxEx<K, V> tx, boolean commit) { if (log.isDebugEnabled()) log.debug("Finishing prepared transaction [tx=" + tx + ", commit=" + commit + ']'); if (!tx.markFinalizing(RECOVERY_FINISH)) { if (log.isDebugEnabled()) log.debug("Will not try to commit prepared transaction (could not mark finalized): " + tx); return; } if (tx instanceof GridDistributedTxRemoteAdapter) { GridCacheTxRemoteEx<K,V> rmtTx = (GridCacheTxRemoteEx<K, V>)tx; rmtTx.doneRemote(tx.xidVersion(), Collections.<GridCacheVersion>emptyList(), Collections.<GridCacheVersion>emptyList(), Collections.<GridCacheVersion>emptyList()); } if (commit) tx.commitAsync().listenAsync(new CommitListener(tx)); else tx.rollbackAsync(); }
/** * @param node Node originated request. * @param msg Force keys message. */ private void processForceKeysRequest(final GridNode node, final GridDhtForceKeysRequest<K, V> msg) { GridFuture<?> fut = cctx.mvcc().finishKeys(msg.keys(), msg.topologyVersion()); if (fut.isDone()) processForceKeysRequest0(node, msg); else fut.listenAsync(new CI1<GridFuture<?>>() { @Override public void apply(GridFuture<?> t) { processForceKeysRequest0(node, msg); } }); }
/** * @param node Node. * @param req Request. */ private void processAffinityAssignmentRequest(final GridNode node, final GridDhtAffinityAssignmentRequest<K, V> req) { final long topVer = req.topologyVersion(); if (log.isDebugEnabled()) log.debug("Processing affinity assignment request [node=" + node + ", req=" + req + ']'); cctx.affinity().affinityReadyFuture(req.topologyVersion()).listenAsync(new CI1<GridFuture<Long>>() { @Override public void apply(GridFuture<Long> fut) { if (log.isDebugEnabled()) log.debug("Affinity is ready for topology version, will send response [topVer=" + topVer + ", node=" + node + ']'); List<List<GridNode>> assignment = cctx.affinity().assignments(topVer); try { cctx.io().send(node, new GridDhtAffinityAssignmentResponse<K, V>(topVer, assignment), AFFINITY_POOL); } catch (GridException e) { U.error(log, "Failed to send affinity assignment response to remote node [node=" + node + ']', e); } } }); }
/** * @param nodeId Node ID. * @param req Request. */ protected final void processDhtLockRequest(final UUID nodeId, final GridDhtLockRequest<K, V> req) { GridFuture<Object> keyFut = F.isEmpty(req.keys()) ? null : ctx.dht().dhtPreloader().request(req.keys(), req.topologyVersion()); if (keyFut == null || keyFut.isDone()) processDhtLockRequest0(nodeId, req); else { keyFut.listenAsync(new CI1<GridFuture<Object>>() { @Override public void apply(GridFuture<Object> t) { processDhtLockRequest0(nodeId, req); } }); } }
/** * @param nodeId Node ID. * @param req Request. */ private void processNearLockRequest(UUID nodeId, GridNearLockRequest<K, V> req) { assert isAffinityNode(cacheCfg); assert nodeId != null; assert req != null; if (log.isDebugEnabled()) log.debug("Processing near lock request [locNodeId=" + locNodeId + ", nodeId=" + nodeId + ", req=" + req + ']'); GridNode nearNode = ctx.discovery().node(nodeId); if (nearNode == null) { U.warn(log, "Received lock request from unknown node (will ignore): " + nodeId); return; } // Group lock can be only started from local node, so we never start group lock transaction on remote node. GridFuture<?> f = lockAllAsync(nearNode, req, null); // Register listener just so we print out errors. // Exclude lock timeout exception since it's not a fatal exception. f.listenAsync(CU.errorLogger(log, GridCacheLockTimeoutException.class, GridDistributedLockCancelledException.class)); }
/** * @param tx Transaction to register for eviction policy notifications. */ public void touch(final GridCacheTxEx<K, V> tx) { if (!plcEnabled && memoryMode != OFFHEAP_TIERED) return; if (tx.internal() && !tx.groupLock()) return; if (!tx.local()) { if (cctx.isNear()) return; if (evictSync) return; } if (!busyLock.enterBusy()) return; try { if (log.isDebugEnabled()) log.debug("Touching transaction [tx=" + CU.txString(tx) + ", localNode=" + cctx.nodeId() + ']'); tx.finishFuture().listenAsync(txLsnr); } finally { busyLock.leaveBusy(); } }