/** * Gets transaction ID map depending on transaction type. * * @param tx Transaction. * @return Transaction map. */ private ConcurrentMap<GridCacheVersion, IgniteInternalTx> transactionMap(IgniteInternalTx tx) { return (tx.near() && !tx.local()) ? nearIdMap : idMap; }
@Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near(); } });
@Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near(); } };
@Override public boolean apply(IgniteInternalTx tx) { return tx.local() && tx.near() && start - tx.startTime() >= duration; } };
/** */ 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(); }
/** * @param cctx Cache context. * @return Transaction for current thread. */ public GridNearTxLocal threadLocalTx(GridCacheContext cctx) { IgniteInternalTx tx = tx(cctx, Thread.currentThread().getId()); if (tx != null && tx.local() && (!tx.dht() || tx.colocated()) && !tx.implicit()) { assert tx instanceof GridNearTxLocal : tx; return (GridNearTxLocal)tx; } return null; }
/** * @param tx Transaction. * @return {@code True} if should notify continuous query manager. */ public boolean notifyContinuousQueries(@Nullable IgniteInternalTx tx) { return cctx.isLocal() || cctx.isReplicated() || (!cctx.isNear() && !(tx != null && tx.onePhaseCommit() && !tx.local())); }
/** * @param tx Transaction to clear. */ public void clearThreadMap(IgniteInternalTx tx) { if (tx.local() && !tx.dht()) { assert tx instanceof GridNearTxLocal : tx; if (!tx.system()) threadMap.remove(tx.threadId(), tx); else { Integer cacheId = tx.txState().firstCacheId(); if (cacheId != null) sysThreadMap.remove(new TxThreadKey(tx.threadId(), cacheId), tx); else { for (Iterator<IgniteInternalTx> it = sysThreadMap.values().iterator(); it.hasNext(); ) { IgniteInternalTx txx = it.next(); if (tx == txx) { it.remove(); break; } } } } } }
/** * * @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; }
/** * @param tx Transaction to notify evictions for. */ private void notifyEvictions(IgniteInternalTx tx) { if (tx.internal()) return; for (IgniteTxEntry txEntry : tx.allEntries()) txEntry.cached().context().evicts().touch(txEntry, tx.local()); }
/** * 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); } } }
/** * Sets MVCC state. * * @param tx Transaction. * @param state New state. */ public void setMvccState(IgniteInternalTx tx, byte state) { if (cctx.kernalContext().clientNode() || tx.mvccSnapshot() == null || tx.near() && !tx.local()) return; cctx.database().checkpointReadLock(); try { cctx.coordinators().updateState(tx.mvccSnapshot(), state, tx.local()); } finally { cctx.database().checkpointReadUnlock(); } }
/** * 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; }
/** * @param ses Session. * @param load {@code True} if {@link #loadAll} method is called. */ private void checkTx(@Nullable CacheStoreSession ses, boolean load) { Transaction tx = ses != null ? ses.transaction() : null; if (tx == null) return; txs.add(tx); IgniteInternalTx tx0 = GridTestUtils.getFieldValue(tx, "tx"); if (!tx0.local()) throw new IgniteException("Tx is not local: " + tx); if (tx0.dht() && !load) throw new IgniteException("Tx is DHT: " + tx); }
/** * Handles prepare stage. * * @param tx Transaction to prepare. * @param entries Entries to lock or {@code null} if use default {@link IgniteInternalTx#optimisticLockEntries()}. * @throws IgniteCheckedException If preparation failed. */ public void prepareTx(IgniteInternalTx tx, @Nullable Collection<IgniteTxEntry> entries) throws IgniteCheckedException { if (tx.state() == MARKED_ROLLBACK) { if (tx.remainingTime() == -1) throw new IgniteTxTimeoutCheckedException("Transaction timed out: " + this); throw new IgniteCheckedException("Transaction is marked for rollback: " + tx); } // One-phase commit tx cannot timeout on prepare because it is expected to be committed. if (tx.remainingTime() == -1 && !tx.onePhaseCommit()) { tx.setRollbackOnly(); throw new IgniteTxTimeoutCheckedException("Transaction timed out: " + this); } if (tx.pessimistic() && tx.local()) return; // Nothing else to do in pessimistic mode. // Optimistic. assert tx.optimistic() || !tx.local(); if (!lockMultiple(tx, entries != null ? entries : tx.optimisticLockEntries())) { tx.setRollbackOnly(); throw new IgniteTxOptimisticCheckedException("Failed to prepare transaction (lock conflict): " + tx); } }
/** * Commits or rolls back prepared transaction. * * @param tx Transaction. * @param commit Whether transaction should be committed or rolled back. */ public void finishTxOnRecovery(final IgniteInternalTx tx, boolean commit) { if (log.isInfoEnabled()) log.info("Finishing prepared transaction [commit=" + commit + ", tx=" + tx + ']'); if (!tx.markFinalizing(RECOVERY_FINISH)) { if (log.isInfoEnabled()) log.info("Will not try to commit prepared transaction (could not mark finalized): " + tx); return; } if (tx instanceof IgniteTxRemoteEx) { IgniteTxRemoteEx rmtTx = (IgniteTxRemoteEx)tx; rmtTx.doneRemote(tx.xidVersion(), Collections.<GridCacheVersion>emptyList(), Collections.<GridCacheVersion>emptyList(), Collections.<GridCacheVersion>emptyList()); } if (commit) tx.commitAsync().listen(new CommitListener(tx)); else if (tx.mvccSnapshot() != null && !tx.local()) // remote (backup) mvcc transaction sends partition counters to other backup transaction // in order to keep counters consistent neighborcastPartitionCountersAndRollback(tx); else tx.rollbackAsync(); }
assert cctx.transactionalSnapshot(); if (tx.local()) { // For remote tx we log all updates in batch: GridDistributedTxRemoteAdapter.commitIfLocked() GridCacheOperation op; if (val == null)
/** * @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; }
/** * @param tx Transaction. */ private void removeObsolete(IgniteInternalTx tx) { Collection<IgniteTxEntry> entries = tx.local() ? tx.allEntries() : tx.writeEntries(); for (IgniteTxEntry entry : entries) { GridCacheEntryEx cached = entry.cached(); GridCacheContext cacheCtx = entry.context(); if (cached == null) cached = cacheCtx.cache().peekEx(entry.key()); if (cached.detached()) continue; try { if (cached.obsolete() || cached.markObsoleteIfEmpty(tx.xidVersion())) cacheCtx.cache().removeEntry(cached); if (!tx.near() && isNearEnabled(cacheCtx)) { GridNearCacheAdapter near = cacheCtx.isNear() ? cacheCtx.near() : cacheCtx.dht().near(); GridNearCacheEntry e = near.peekExx(entry.key()); if (e != null && e.markObsoleteIfEmpty(null)) near.removeEntry(e); } } catch (IgniteCheckedException e) { U.error(log, "Failed to remove obsolete entry from cache: " + cached, e); } } }