/** @param m Mapping. */ @SuppressWarnings({"unchecked"}) private void finish(GridDistributedTxMapping<K, V> m) { GridRichNode n = m.node(); assert !m.empty(); GridNearTxFinishRequest req = new GridNearTxFinishRequest<K, V>( futId, tx.xidVersion(), tx.commitVersion(), tx.threadId(), commit, tx.isInvalidate(), m.explicitLock(), tx.topologyVersion(), null, null, null, commit && tx.pessimistic() ? m.writes() : null, tx.syncCommit() && commit || tx.syncRollback() && !commit); // If this is the primary node for the keys. if (n.isLocal()) { req.miniId(GridUuid.randomUuid()); if (CU.DHT_ENABLED) { GridFuture<GridCacheTx> fut = commit ? dht().commitTx(n.id(), req) : dht().rollbackTx(n.id(), req); // Add new future. add(fut); } else // Add done future for testing. add(new GridFinishedFuture<GridCacheTx>(ctx)); } else { MiniFuture fut = new MiniFuture(m); req.miniId(fut.futureId()); add(fut); // Append new future. try { cctx.io().send(n, req); // If we don't wait for result, then mark future as done. if (!isSync() && !m.explicitLock()) fut.onDone(); } catch (GridTopologyException e) { // Remove previous mapping. mappings.remove(m.node().id()); fut.onResult(e); } catch (GridException e) { // Fail the whole thing. fut.onResult(e); } } }
/** * @param cctx Context. * @param tx Transaction. * @param commit Commit flag. */ public GridNearTxFinishFuture( GridCacheContext<K, V> cctx, GridNearTxLocal<K, V> tx, boolean commit) { super(cctx.kernalContext(), F.<GridCacheTx>identityReducer(tx)); assert cctx != null; this.cctx = cctx; this.tx = tx; this.commit = commit; mappings = tx.mappings(); futId = GridUuid.randomUuid(); log = U.logger(ctx, logRef, GridNearTxFinishFuture.class); }
/** * @param ctx Grid kernal context. * @param cacheName Cache name. * @param flushQ Flush queue. */ public GridDataLoaderImpl( final GridKernalContext ctx, @Nullable final String cacheName, DelayQueue<GridDataLoaderImpl<K, V>> flushQ) { assert ctx != null; this.ctx = ctx; this.cacheName = cacheName; this.flushQ = flushQ; log = U.logger(ctx, logRef, GridDataLoaderImpl.class); discoLsnr = new GridLocalEventListener() { @Override public void onEvent(GridEvent evt) { assert evt.type() == EVT_NODE_FAILED || evt.type() == EVT_NODE_LEFT; GridDiscoveryEvent discoEvt = (GridDiscoveryEvent) evt; UUID id = discoEvt.eventNodeId(); // Remap regular mappings. final Buffer buf = bufMappings.remove(id); if (buf != null) { // Only async notification is possible since // discovery thread may be trapped otherwise. ctx.closure() .callLocalSafe( new Callable<Object>() { @Override public Object call() throws Exception { buf.onNodeLeft(); return null; } }, true /* system pool */); } } }; ctx.event().addLocalEventListener(discoLsnr, EVT_NODE_FAILED, EVT_NODE_LEFT); // Generate unique topic for this loader. topic = TOPIC_DATALOAD.topic(GridUuid.fromUuid(ctx.localNodeId())); ctx.io() .addMessageListener( topic, new GridMessageListener() { @Override public void onMessage(UUID nodeId, Object msg) { assert msg instanceof GridDataLoadResponse; GridDataLoadResponse res = (GridDataLoadResponse) msg; if (log.isDebugEnabled()) log.debug("Received data load response: " + res); Buffer buf = bufMappings.get(nodeId); if (buf != null) buf.onResponse(res); else if (log.isDebugEnabled()) log.debug("Ignoring response since node has left [nodeId=" + nodeId + ", "); } }); if (log.isDebugEnabled()) log.debug("Added response listener within topic: " + topic); fut = new GridDataLoaderFuture(ctx, this); }
/** * Mini-future for get operations. Mini-futures are only waiting on a single node as opposed to * multiple nodes. */ private class MiniFuture extends GridFutureAdapter<GridCacheTx> { /** */ private final GridUuid futId = GridUuid.randomUuid(); /** Keys. */ @GridToStringInclude private GridDistributedTxMapping<K, V> m; /** Empty constructor required for {@link Externalizable}. */ public MiniFuture() { // No-op. } /** @param m Mapping. */ MiniFuture(GridDistributedTxMapping<K, V> m) { super(cctx.kernalContext()); this.m = m; } /** @return Future ID. */ GridUuid futureId() { return futId; } /** @return Node ID. */ public GridRichNode node() { return m.node(); } /** @return Keys. */ public GridDistributedTxMapping<K, V> mapping() { return m; } /** @param e Error. */ void onResult(Throwable e) { if (log.isDebugEnabled()) log.debug("Failed to get future result [fut=" + this + ", err=" + e + ']'); // Fail. onDone(e); } /** @param e Node failure. */ void onResult(GridTopologyException e) { if (log.isDebugEnabled()) log.debug( "Remote node left grid while sending or waiting for reply (will ignore): " + this); onDone(tx); } /** @param res Result callback. */ void onResult(GridNearTxFinishResponse<K, V> res) { onDone(tx); } /** {@inheritDoc} */ @Override public String toString() { return S.toString( MiniFuture.class, this, "done", isDone(), "cancelled", isCancelled(), "err", error()); } }