/** {@inheritDoc} */ @Override public Collection<Transaction> localActiveTransactions() { return F.viewReadOnly(cctx.tm().activeTransactions(), new IgniteClosure<IgniteInternalTx, Transaction>() { @Override public Transaction apply(IgniteInternalTx tx) { return ((GridNearTxLocal)tx).rollbackOnlyProxy(); } }, new IgnitePredicate<IgniteInternalTx>() { @Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near(); } }); }
/** */ private Optional<GridDhtTxLocalAdapter> findTx(MvccVersion mvccVer) { return cctx.tm().activeTransactions().stream() .filter(tx -> tx.local() && tx.mvccSnapshot() != null) .filter(tx -> belongToSameTx(mvccVer, tx.mvccSnapshot())) .map(GridDhtTxLocalAdapter.class::cast) .findAny(); }
/** {@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."); }
/** * Checks that transaction manager for cache context does not have any pending transactions. * * @param ctx Cache context. */ private void checkTxsEmpty(GridCacheContext ctx) { Collection txs = ctx.tm().activeTransactions(); assert txs.isEmpty() : "Not all transactions were salvaged: " + txs; }
/** * */ private Collection<GridNearTxLocal> nearTxs(long duration) { final long start = System.currentTimeMillis(); IgniteClosure<IgniteInternalTx, GridNearTxLocal> c = new IgniteClosure<IgniteInternalTx, GridNearTxLocal>() { @Override public GridNearTxLocal apply(IgniteInternalTx tx) { return ((GridNearTxLocal)tx); } }; IgnitePredicate<IgniteInternalTx> pred = new IgnitePredicate<IgniteInternalTx>() { @Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near() && start - tx.startTime() >= duration; } }; return F.viewReadOnly(gridKernalCtx.cache().context().tm().activeTransactions(), c, pred); }
/** */ 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); }); }
/** * */ private long nearTxNum() { IgnitePredicate<IgniteInternalTx> pred = new IgnitePredicate<IgniteInternalTx>() { @Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near(); } }; return F.size(gridKernalCtx.cache().context().tm().activeTransactions(), pred); }
/** * Checks that transaction manager for cache context has expected number of pending transactions. * * @param ctx Cache context. * @param exp Expected amount of transactions. */ private void checkTxsNotEmpty(GridCacheContext ctx, int exp) { int size = ctx.tm().activeTransactions().size(); assertEquals("Some transactions were salvaged unexpectedly", exp, size); } }
@Override public boolean apply() { GridDhtTxLocal locTx = null; for (IgniteInternalTx tx : tm.activeTransactions()) { if (tx instanceof GridDhtTxLocal) { assertNull("Only one tx is expected.", locTx); locTx = (GridDhtTxLocal)tx; } } log.info("Wait for tx, state: " + (locTx != null ? locTx.state() : null)); return locTx != null && locTx.state() == PREPARED; } }, 5000);
/** */ 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; }
/** */ 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()); } }
/** * Rollback transactions blocking partition map exchange. * * @param topVer Initial exchange version. */ public void rollbackOnTopologyChange(AffinityTopologyVersion topVer) { for (IgniteInternalTx tx : activeTransactions()) { if (tx.local() && tx.near() && needWaitTransaction(tx, topVer)) { U.warn(log, "The transaction was forcibly rolled back on partition map exchange because a timeout is " + "reached: [tx=" + CU.txString(tx) + ", topVer=" + topVer + ']'); ((GridNearTxLocal)tx).rollbackNearTxLocalAsync(false, false); } } }
/** * Count total number of holding locks on local node. */ private long txHoldingLockNum() { long holdingLockCounter = 0; IgniteTxManager tm = gridKernalCtx.cache().context().tm(); for (IgniteInternalTx tx : tm.activeTransactions()) { if ((tx.optimistic() && tx.state() == TransactionState.ACTIVE) || tx.empty() || !tx.local()) continue; holdingLockCounter++; } return holdingLockCounter; }
/** * @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; }
for (IgniteInternalTx tx : activeTransactions()) { if (needWaitTransaction(tx, topVer)) res.add(tx.finishFuture());
/** * @param g Grid. * @param tm Transaction manager. */ private void checkTm(Ignite g, IgniteTxManager tm) { Collection<IgniteInternalTx> txs = tm.activeTransactions(); info(">>> Number of transactions in the set [size=" + txs.size() + ", nodeId=" + g.cluster().localNode().id() + ']'); for (IgniteInternalTx tx : txs) assert tx.done() : "Transaction is not finished: " + tx; } }
/** * Check whether caches still has all transactions before salvage timeout. * * @param mode Transaction mode (PESSIMISTIC, OPTIMISTIC). * @param prepare Whether to prepare transaction state * (i.e. call {@link GridNearTxLocal#prepare(boolean)}). * @throws Exception If failed. */ private void checkSalvageBeforeTimeout(TransactionConcurrency mode, boolean prepare) throws Exception { startTxAndPutKeys(mode, prepare); List<Integer> nearSizes = new ArrayList<>(GRID_CNT - 1); List<Integer> dhtSizes = new ArrayList<>(GRID_CNT - 1); for (int i = 1; i < GRID_CNT; i++) { nearSizes.add(near(i).context().tm().activeTransactions().size()); dhtSizes.add(dht(i).context().tm().activeTransactions().size()); } stopNodeAndSleep(SALVAGE_TIMEOUT - DELTA_BEFORE); for (int i = 1; i < GRID_CNT; i++) { checkTxsNotEmpty(near(i).context(), nearSizes.get(i - 1)); checkTxsNotEmpty(dht(i).context(), dhtSizes.get(i - 1)); } }
/** {@inheritDoc} */ @Override protected void afterTest() throws Exception { try { for (Ignite node : G.allGrids()) { Collection<IgniteInternalTx> txs = ((IgniteKernal)node).context().cache().context().tm().activeTransactions(); assertTrue("Unfinished txs [node=" + node.name() + ", txs=" + txs + ']', txs.isEmpty()); } } finally { stopAllGrids(); storeMap.clear(); super.afterTest(); } }
/** * Checks if all txs and mvcc futures are finished. */ protected void checkFutures() { for (Ignite ignite : G.allGrids()) { IgniteEx ig = (IgniteEx)ignite; final Collection<GridCacheFuture<?>> futs = ig.context().cache().context().mvcc().activeFutures(); boolean hasFutures = false; for (GridCacheFuture<?> fut : futs) { if (!fut.isDone()) { log.error("Expecting no active future [node=" + ig.localNode().id() + ", fut=" + fut + ']'); hasFutures = true; } } if (hasFutures) fail("Some mvcc futures are not finished"); Collection<IgniteInternalTx> txs = ig.context().cache().context().tm().activeTransactions(); for (IgniteInternalTx tx : txs) log.error("Expecting no active transaction [node=" + ig.localNode().id() + ", tx=" + tx + ']'); if (!txs.isEmpty()) fail("Some transaction are not finished"); } }
/** * @param ignite Node. */ public void dumpCacheDebugInfo(Ignite ignite) { GridKernalContext ctx = ((IgniteKernal)ignite).context(); log.error("Cache information update [node=" + ignite.name() + ", client=" + ignite.configuration().isClientMode() + ']'); GridCacheSharedContext cctx = ctx.cache().context(); log.error("Pending transactions:"); for (IgniteInternalTx tx : cctx.tm().activeTransactions()) log.error(">>> " + tx); log.error("Pending explicit locks:"); for (GridCacheExplicitLockSpan lockSpan : cctx.mvcc().activeExplicitLocks()) log.error(">>> " + lockSpan); log.error("Pending cache futures:"); for (GridCacheFuture<?> fut : cctx.mvcc().activeFutures()) log.error(">>> " + fut); log.error("Pending atomic cache futures:"); for (GridCacheFuture<?> fut : cctx.mvcc().atomicFutures()) log.error(">>> " + fut); }