/** * @param tx Committed transaction. */ public void addCommittedTxReturn(IgniteInternalTx tx, GridCacheReturnCompletableWrapper ret) { addCommittedTxReturn(tx.nearXidVersion(), null, ret); }
/** * @param tx Tx. Must be instance of {@link GridNearTxLocal}. * @param cls Future class. * @return Cache future. */ private IgniteInternalFuture mvccFuture(IgniteInternalTx tx, Class<? extends IgniteInternalFuture> cls) { assert tx instanceof GridNearTxLocal : tx; Collection<GridCacheVersionedFuture<?>> futs = cctx.mvcc().futuresForVersion(tx.nearXidVersion()); if (futs != null) { for (GridCacheVersionedFuture<?> fut : futs) { if (fut.getClass().equals(cls)) return fut; } } return null; }
/** * @param tx Committed transaction. */ public void addCommittedTx(IgniteInternalTx tx) { addCommittedTx(tx, tx.xidVersion(), tx.nearXidVersion()); }
/** {@inheritDoc} */ @Override public void apply(StringBuilder sb, GridKernalContext ctx) { sb.append(U.nl()) .append("Related transactions [dhtVer=").append(dhtVer) .append(", nearVer=").append(nearVer).append("]: "); boolean found = false; for (IgniteInternalTx tx : ctx.cache().context().tm().activeTransactions()) { if (dhtVer.equals(tx.xidVersion()) || nearVer.equals(tx.nearXidVersion())) { sb.append(U.nl()) .append(" ") .append(tx.getClass().getSimpleName()) .append(" [ver=").append(tx.xidVersion()) .append(", nearVer=").append(tx.nearXidVersion()) .append(", topVer=").append(tx.topologyVersion()) .append(", state=").append(tx.state()) .append(", fullTx=").append(tx).append(']'); found = true; } } if (!found) sb.append(U.nl()).append("Failed to find related transactions."); }
/** * @param tx Transaction. * @param txNum Expected number of transactions on remote node. * @param nearTxCheck {@code True} if should check only tx on near node. * @param futId Future ID. * @param miniId Mini future ID. * @param addDepInfo Deployment info flag. */ public GridCacheTxRecoveryRequest(IgniteInternalTx tx, int txNum, boolean nearTxCheck, IgniteUuid futId, IgniteUuid miniId, boolean addDepInfo) { super(tx.xidVersion(), 0, addDepInfo); nearXidVer = tx.nearXidVersion(); sys = tx.system(); this.futId = futId; this.miniId = miniId; this.txNum = txNum; this.nearTxCheck = nearTxCheck; }
/** */ private void handleDeadlockProbeForDht(DeadlockProbe probe) { // a probe is simply discarded if next wait-for edge is not found cctx.tm().activeTransactions().stream() .filter(IgniteInternalTx::local) .filter(tx -> tx.nearXidVersion().equals(probe.blocker().nearXidVersion())) .findAny() .map(GridDhtTxLocalAdapter.class::cast) .ifPresent(tx -> { // search for locally checked tx (identified as blocker previously) in the wait chain Optional<ProbedTx> repeatedTx = probe.waitChain().stream() .filter(wTx -> wTx.xidVersion().equals(tx.xidVersion())) .findAny(); if (repeatedTx.isPresent()) { // a deadlock found resolveDeadlock(probe, repeatedTx.get(), tx); } else relayProbeIfLocalTxIsWaiting(probe, tx); }); }
msgLog.info("Tx recovery fut, failed to find mini future [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nodeId + msgLog.info("Tx recovery fut, response for finished future [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nodeId +
/** * * @param tx Transaction to check. * @return {@code True} if transaction has been committed or rolled back, * {@code false} otherwise. */ private boolean isCompleted(IgniteInternalTx tx) { boolean completed = completedVersHashMap.containsKey(tx.xidVersion()); // Need check that for tx rollback message was not received before lock. // This could happen on timeout or async rollback. if (!completed && tx.local() && tx.dht()) return completedVersHashMap.containsKey(tx.nearXidVersion()); return completed; }
/** */ private static List<IgniteInternalTx> txsOnNode(IgniteEx node, GridCacheVersion xidVer) { List<IgniteInternalTx> txs = node.context().cache().context().tm().activeTransactions().stream() .peek(tx -> assertEquals(xidVer, tx.nearXidVersion())) .collect(Collectors.toList()); assert !txs.isEmpty(); return txs; }
/** * Detects deadlock starting from given keys. * * @param tx Target tx. * @param keys Keys. * @return {@link TxDeadlock} if found, otherwise - {@code null}. */ TxDeadlockFuture detectDeadlock(IgniteInternalTx tx, Set<IgniteTxKey> keys) { GridCacheVersion txId = tx.nearXidVersion(); if (log.isDebugEnabled()) { log.debug("Deadlock detection started " + "[nodeId=" + cctx.localNodeId() + ", xidVersion=" + txId + ", keys=" + keys + ']'); } TxDeadlockFuture fut = new TxDeadlockFuture(cctx, txId, tx.topologyVersion(), keys); fut.init(); return fut; }
/** * @param nodeId Failed node ID. */ private void onNodeLeft(UUID nodeId) { if (msgLog.isInfoEnabled()) { msgLog.info("Tx recovery fut, mini future node left [txId=" + tx.nearXidVersion() + ", dhtTxId=" + tx.xidVersion() + ", node=" + nodeId + ", nearTxCheck=" + nearTxCheck + ']'); } if (nearTxCheck) { if (tx.state() == PREPARED) { Set<UUID> failedNodeIds0 = new HashSet<>(failedNodeIds); failedNodeIds0.add(nodeId); // Near and originating nodes left, need initiate tx check. cctx.tm().commitIfPrepared(tx, failedNodeIds0); } onDone(new ClusterTopologyCheckedException("Transaction node left grid (will ignore).")); } else onDone(true); }
/** */ private static List<IgniteInternalTx> txsOnNode(IgniteEx node, GridCacheVersion xidVer) { return node.context().cache().context().tm().activeTransactions().stream() .peek(tx -> assertEquals(xidVer, tx.nearXidVersion())) .collect(Collectors.toList()); } }
/** * @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; }
/** * Commits transaction in case when node started transaction failed, but all related * transactions were prepared (invalidates transaction if it is not fully prepared). * * @param tx Transaction. * @param failedNodeIds Failed nodes IDs. */ public void commitIfPrepared(IgniteInternalTx tx, Set<UUID> failedNodeIds) { assert tx instanceof GridDhtTxLocal || tx instanceof GridDhtTxRemote : tx; assert !F.isEmpty(tx.transactionNodes()) : tx; assert tx.nearXidVersion() != null : tx; GridCacheTxRecoveryFuture fut = new GridCacheTxRecoveryFuture( cctx, tx, failedNodeIds, tx.transactionNodes()); cctx.mvcc().addFuture(fut, fut.futureId()); if (log.isInfoEnabled()) log.info("Checking optimistic transaction state on remote nodes [tx=" + tx + ", fut=" + fut + ']'); fut.prepare(); }
val, op, tx.nearXidVersion(), tx.writeVersion(), expireTime,
/** * @param tx Transaction. * @param val Value. * @param expireTime Expire time (or 0 if not applicable). * @param updCntr Update counter. * @throws IgniteCheckedException In case of log failure. */ protected WALPointer logTxUpdate(IgniteInternalTx tx, CacheObject val, long expireTime, long updCntr) throws IgniteCheckedException { assert cctx.transactional() && !cctx.transactionalSnapshot(); if (tx.local()) { // For remote tx we log all updates in batch: GridDistributedTxRemoteAdapter.commitIfLocked() GridCacheOperation op; if (val == null) op = DELETE; else op = this.val == null ? GridCacheOperation.CREATE : UPDATE; return cctx.shared().wal().log(new DataRecord(new DataEntry( cctx.cacheId(), key, val, op, tx.nearXidVersion(), tx.writeVersion(), expireTime, key.partition(), updCntr))); } else return null; }
/** * Starts processing. */ public void init() { if (log.isInfoEnabled()) { log.info("Starting delivery partition countres to remote nodes [txId=" + tx.nearXidVersion() + ", futId=" + futId); } HashSet<UUID> siblings = siblingBackups(); cctx.mvcc().addFuture(this, futId); for (UUID peer : siblings) { List<PartitionUpdateCountersMessage> cntrs = cctx.tm().txHandler() .filterUpdateCountersForBackupNode(tx, cctx.node(peer)); if (F.isEmpty(cntrs)) continue; MiniFuture miniFut = new MiniFuture(peer); try { cctx.io().send(peer, new PartitionCountersNeighborcastRequest(cntrs, futId), SYSTEM_POOL); add(miniFut); } catch (IgniteCheckedException e) { if (!(e instanceof ClusterTopologyCheckedException)) log.warning("Failed to send partition counters to remote node [node=" + peer + ']', e); else logNodeLeft(peer); miniFut.onDone(); } } markInitialized(); }
tx.nearXidVersion(), tx.nodeId(), tx.threadId(),
"\n" + tx.nearXidVersion() + "\n nodeId=" + cctx.localNodeId() + "\n tx=" + tx);
GridCacheVersion serOrder = (tx.serializable() && tx.optimistic()) ? tx.nearXidVersion() : null;