/** @param e Error. */ public void onError(Throwable e) { if (ERR_UPD.compareAndSet(this, null, e)) { boolean marked = tx.setRollbackOnly(); if (e instanceof IgniteTxRollbackCheckedException) { if (marked) { try { tx.rollback(); } catch (IgniteCheckedException ex) { U.error(log, "Failed to automatically rollback transaction: " + tx, ex); } } } else if (tx.isSystemInvalidate()) { // Invalidate remote transactions on heuristic error. finish(); try { get(); } catch (IgniteTxHeuristicCheckedException ignore) { // Future should complete with GridCacheTxHeuristicException. } catch (IgniteCheckedException err) { U.error(log, "Failed to invalidate transaction: " + tx, err); } } onComplete(); } }
/** * @param nodeId Sender. * @param res Result. */ public void onResult(UUID nodeId, GridDhtTxFinishResponse res) { if (!isDone()) { boolean found = false; for (IgniteInternalFuture<IgniteInternalTx> fut : futures()) { if (isMini(fut)) { MiniFuture f = (MiniFuture) fut; if (f.futureId().equals(res.miniId())) { found = true; assert f.node().id().equals(nodeId); f.onResult(res); } } } if (!found) { if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, failed to find mini future [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nodeId + ", res=" + res + ", fut=" + this + ']'); } } } else { if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, failed to find mini future [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nodeId + ", res=" + res + ", fut=" + this + ']'); } } }
/** Initializes future. */ @SuppressWarnings({"SimplifiableIfStatement", "IfMayBeConditional"}) public void finish() { boolean sync; if (!F.isEmpty(dhtMap) || !F.isEmpty(nearMap)) sync = finish(dhtMap, nearMap); else if (!commit && !F.isEmpty(tx.lockTransactionNodes())) sync = rollbackLockTransactions(tx.lockTransactionNodes()); else // No backup or near nodes to send commit message to (just complete then). sync = false; markInitialized(); if (!sync) onComplete(); }
/** {@inheritDoc} */ @Override public String toString() { Collection<String> futs = F.viewReadOnly( futures(), new C1<IgniteInternalFuture<?>, String>() { @SuppressWarnings("unchecked") @Override public String apply(IgniteInternalFuture<?> f) { return "[node=" + ((MiniFuture) f).node().id() + ", loc=" + ((MiniFuture) f).node().isLocal() + ", done=" + f.isDone() + "]"; } }); return S.toString( GridDhtTxFinishFuture.class, this, "xidVer", tx.xidVersion(), "innerFuts", futs, "super", super.toString()); }
/** * @param cctx Context. * @param tx Transaction. * @param commit Commit flag. */ public GridDhtTxFinishFuture( GridCacheSharedContext<K, V> cctx, GridDhtTxLocalAdapter tx, boolean commit) { super(F.<IgniteInternalTx>identityReducer(tx)); this.cctx = cctx; this.tx = tx; this.commit = commit; dhtMap = tx.dhtMap(); nearMap = tx.nearMap(); futId = IgniteUuid.randomUuid(); if (log == null) { msgLog = cctx.txFinishMessageLogger(); log = U.logger(cctx.kernalContext(), logRef, GridDhtTxFinishFuture.class); } }
/** * @param dhtMap DHT map. * @param nearMap Near map. * @return {@code True} in case there is at least one synchronous {@code MiniFuture} to wait for. */ private boolean finish( Map<UUID, GridDistributedTxMapping> dhtMap, Map<UUID, GridDistributedTxMapping> nearMap) { if (tx.onePhaseCommit()) return false; boolean sync = tx.syncMode() == FULL_SYNC; if (tx.explicitLock()) sync = true; boolean res = false; // Create mini futures. for (GridDistributedTxMapping dhtMapping : dhtMap.values()) { ClusterNode n = dhtMapping.node(); assert !n.isLocal(); GridDistributedTxMapping nearMapping = nearMap.get(n.id()); if (dhtMapping.empty() && nearMapping != null && nearMapping.empty()) // Nothing to send. continue; MiniFuture fut = new MiniFuture(dhtMapping, nearMapping); add(fut); // Append new future. Collection<Long> updCntrs = new ArrayList<>(dhtMapping.entries().size()); for (IgniteTxEntry e : dhtMapping.entries()) updCntrs.add(e.updateCounter()); GridDhtTxFinishRequest req = new GridDhtTxFinishRequest( tx.nearNodeId(), futId, fut.futureId(), tx.topologyVersion(), tx.xidVersion(), tx.commitVersion(), tx.threadId(), tx.isolation(), commit, tx.isInvalidate(), tx.system(), tx.ioPolicy(), tx.isSystemInvalidate(), sync, sync, tx.completedBase(), tx.committedVersions(), tx.rolledbackVersions(), tx.pendingVersions(), tx.size(), tx.subjectId(), tx.taskNameHash(), tx.activeCachesDeploymentEnabled(), updCntrs, false, false); req.writeVersion(tx.writeVersion() != null ? tx.writeVersion() : tx.xidVersion()); try { cctx.io().send(n, req, tx.ioPolicy()); if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, sent request dht [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ']'); } if (sync) res = true; else fut.onDone(); } catch (IgniteCheckedException e) { // Fail the whole thing. if (e instanceof ClusterTopologyCheckedException) fut.onNodeLeft((ClusterTopologyCheckedException) e); else { if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, failed to send request dht [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ", err=" + e + ']'); } fut.onResult(e); } } } for (GridDistributedTxMapping nearMapping : nearMap.values()) { if (!dhtMap.containsKey(nearMapping.node().id())) { if (nearMapping.empty()) // Nothing to send. continue; MiniFuture fut = new MiniFuture(null, nearMapping); add(fut); // Append new future. GridDhtTxFinishRequest req = new GridDhtTxFinishRequest( tx.nearNodeId(), futId, fut.futureId(), tx.topologyVersion(), tx.xidVersion(), tx.commitVersion(), tx.threadId(), tx.isolation(), commit, tx.isInvalidate(), tx.system(), tx.ioPolicy(), tx.isSystemInvalidate(), sync, sync, tx.completedBase(), tx.committedVersions(), tx.rolledbackVersions(), tx.pendingVersions(), tx.size(), tx.subjectId(), tx.taskNameHash(), tx.activeCachesDeploymentEnabled(), false, false); req.writeVersion(tx.writeVersion()); try { cctx.io().send(nearMapping.node(), req, tx.ioPolicy()); if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, sent request near [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nearMapping.node().id() + ']'); } if (sync) res = true; else fut.onDone(); } catch (IgniteCheckedException e) { // Fail the whole thing. if (e instanceof ClusterTopologyCheckedException) fut.onNodeLeft((ClusterTopologyCheckedException) e); else { if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, failed to send request near [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nearMapping.node().id() + ", err=" + e + ']'); } fut.onResult(e); } } } } return res; }
/** * @param nodes Nodes. * @return {@code True} in case there is at least one synchronous {@code MiniFuture} to wait for. */ private boolean rollbackLockTransactions(Collection<ClusterNode> nodes) { assert !commit; assert !F.isEmpty(nodes); if (tx.onePhaseCommit()) return false; boolean sync = tx.syncMode() == FULL_SYNC; if (tx.explicitLock()) sync = true; boolean res = false; for (ClusterNode n : nodes) { assert !n.isLocal(); MiniFuture fut = new MiniFuture(n); add(fut); // Append new future. GridDhtTxFinishRequest req = new GridDhtTxFinishRequest( tx.nearNodeId(), futId, fut.futureId(), tx.topologyVersion(), tx.xidVersion(), tx.commitVersion(), tx.threadId(), tx.isolation(), commit, tx.isInvalidate(), tx.system(), tx.ioPolicy(), tx.isSystemInvalidate(), sync, sync, tx.completedBase(), tx.committedVersions(), tx.rolledbackVersions(), tx.pendingVersions(), tx.size(), tx.subjectId(), tx.taskNameHash(), tx.activeCachesDeploymentEnabled(), false, false); try { cctx.io().send(n, req, tx.ioPolicy()); if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, sent request lock tx [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ']'); } if (sync) res = true; else fut.onDone(); } catch (IgniteCheckedException e) { // Fail the whole thing. if (e instanceof ClusterTopologyCheckedException) fut.onNodeLeft((ClusterTopologyCheckedException) e); else { if (msgLog.isDebugEnabled()) { msgLog.debug( "DHT finish fut, failed to send request lock tx [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + n.id() + ", err=" + e + ']'); } fut.onResult(e); } } } return res; }