/** {@inheritDoc} */ @Override public boolean onDone(@Nullable GridCacheCommittedTxInfo<K, V> res, @Nullable Throwable err) { if (super.onDone(res, err)) { cctx.mvcc().removeFuture(this); if (log.isDebugEnabled()) log.debug( "Completing check committed tx future for transaction [tx=" + tx + ", res=" + res + ", err=" + err + ']'); if (err == null) cctx.tm().finishPessimisticTxOnRecovery(tx, res); else { if (log.isDebugEnabled()) log.debug( "Failed to check prepared transactions, " + "invalidating transaction [err=" + err + ", tx=" + tx + ']'); if (nearCheck) return true; cctx.tm().salvageTx(tx); } return true; } return false; }
/** Initializes future. */ public void prepare() { if (log.isDebugEnabled()) log.debug("Checking if transaction was committed on remote nodes: " + tx); // Check local node first (local node can be a backup node for some part of this transaction). long originatingThreadId = tx.threadId(); if (tx instanceof GridCacheTxRemoteEx) originatingThreadId = ((GridCacheTxRemoteEx) tx).remoteThreadId(); GridCacheCommittedTxInfo<K, V> txInfo = cctx.tm().txCommitted(tx.nearXidVersion(), tx.eventNodeId(), originatingThreadId); if (txInfo != null) { onDone(txInfo); markInitialized(); return; } Collection<GridNode> checkNodes = CU.remoteNodes(cctx, tx.topologyVersion()); if (tx instanceof GridDhtTxRemote) { // If we got primary node failure and near node has not failed. if (tx.nodeId().equals(failedNodeId) && !tx.eventNodeId().equals(failedNodeId)) { nearCheck = true; GridNode nearNode = cctx.discovery().node(tx.eventNodeId()); if (nearNode == null) { // Near node failed, separate check prepared future will take care of it. onDone( new GridTopologyException( "Failed to check near transaction state (near node left grid): " + tx.eventNodeId())); return; } checkNodes = Collections.singletonList(nearNode); } } for (GridNode rmtNode : checkNodes) { // Skip left nodes and local node. if (rmtNode.id().equals(failedNodeId)) continue; /* * Send message to all cache nodes in the topology. */ MiniFuture fut = new MiniFuture(rmtNode.id()); GridCachePessimisticCheckCommittedTxRequest<K, V> req = new GridCachePessimisticCheckCommittedTxRequest<>( tx, originatingThreadId, futureId(), fut.futureId()); add(fut); try { cctx.io().send(rmtNode.id(), req); } catch (GridTopologyException ignored) { fut.onNodeLeft(); } catch (GridException e) { fut.onError(e); break; } } markInitialized(); }