/** * @param cctx Cache context. * @param tx Transaction. * @param timeout Timeout. * @param rdc Compound future reducer. */ public GridNearTxAbstractEnlistFuture( GridCacheContext<?, ?> cctx, GridNearTxLocal tx, long timeout, @Nullable IgniteReducer<T, T> rdc) { super(rdc); assert cctx != null; assert tx != null; this.cctx = cctx; this.tx = tx; this.timeout = timeout; threadId = tx.threadId(); lockVer = tx.xidVersion(); futId = IgniteUuid.randomUuid(); mvccSnapshot = tx.mvccSnapshot(); assert mvccSnapshot != null; log = cctx.logger(getClass()); }
/** * Suspends transaction. It could be resumed later. Supported only for optimistic transactions. * * @throws IgniteCheckedException If the transaction is in an incorrect state, or timed out. */ public void suspend() throws IgniteCheckedException { if (log.isDebugEnabled()) log.debug("Suspend near local tx: " + this); if (pessimistic()) throw new UnsupportedOperationException("Suspension is not supported for pessimistic transactions."); if (threadId() != Thread.currentThread().getId()) throw new IgniteCheckedException("Only thread started transaction can suspend it."); synchronized (this) { checkValid(); cctx.tm().suspendTx(this); } }
/** * Resume transaction in current thread. * Please don't use directly. Use tx.resume() instead. * * @param tx Transaction to be resumed. * @param threadId Thread id to restore. * * @see #suspendTx(GridNearTxLocal) * @see GridNearTxLocal#suspend() * @see GridNearTxLocal#resume() * @throws IgniteCheckedException If failed to resume tx. */ public void resumeTx(GridNearTxLocal tx, long threadId) throws IgniteCheckedException { assert tx != null && !tx.system() : tx; if (!tx.state(ACTIVE)) { throw new IgniteCheckedException("Trying to resume transaction with incorrect state " + "[expected=" + SUSPENDED + ", actual=" + tx.state() + ']'); } assert !threadMap.containsValue(tx) : tx; assert !transactionMap(tx).containsValue(tx) : tx; assert !haveSystemTxForThread(Thread.currentThread().getId()); if (threadMap.putIfAbsent(threadId, tx) != null) throw new IgniteCheckedException("Thread already has started a transaction."); if (transactionMap(tx).putIfAbsent(tx.xidVersion(), tx) != null) throw new IgniteCheckedException("Thread already has started a transaction."); tx.threadId(threadId); }
threadId = tx == null ? Thread.currentThread().getId() : tx.threadId();
/** * * @param req Request. * @param nodeId Remote node ID. * @param fut Result future. * @throws IgniteCheckedException if failed to send. */ private void sendRequest(GridCacheMessage req, UUID nodeId, MiniFuture fut) throws IgniteCheckedException { IgniteInternalFuture<?> txSync = cctx.tm().awaitFinishAckAsync(nodeId, tx.threadId()); if (txSync == null || txSync.isDone()) cctx.io().send(nodeId, req, QUERY_POOL); // Process query requests in query pool. else txSync.listen(new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> f) { try { cctx.io().send(nodeId, req, cctx.ioPolicy()); } catch (IgniteCheckedException e) { fut.onResult(null, e); } } }); }
/** * * @param req Request. * @param nodeId Remote node ID * @throws IgniteCheckedException if failed to send. */ private void sendRequest(GridCacheMessage req, UUID nodeId) throws IgniteCheckedException { IgniteInternalFuture<?> txSync = cctx.tm().awaitFinishAckAsync(nodeId, tx.threadId()); if (txSync == null || txSync.isDone()) cctx.io().send(nodeId, req, cctx.ioPolicy()); else txSync.listen(new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> future) { try { cctx.io().send(nodeId, req, cctx.ioPolicy()); } catch (IgniteCheckedException e) { GridNearTxQueryResultsEnlistFuture.this.onDone(e); } } }); }
/** * @param req Request. * @param nodeId Remote node ID * @throws IgniteCheckedException if failed to send. */ private void sendRequest(GridCacheMessage req, UUID nodeId) throws IgniteCheckedException { IgniteInternalFuture<?> txSync = cctx.tm().awaitFinishAckAsync(nodeId, tx.threadId()); if (txSync == null || txSync.isDone()) cctx.io().send(nodeId, req, cctx.ioPolicy()); else txSync.listen(new CI1<IgniteInternalFuture<?>>() { @Override public void apply(IgniteInternalFuture<?> future) { try { cctx.io().send(nodeId, req, cctx.ioPolicy()); } catch (IgniteCheckedException e) { GridNearTxEnlistFuture.this.onDone(e); } } }); }
threadId = tx == null ? Thread.currentThread().getId() : tx.threadId();
/** {@inheritDoc} */ @Override protected void updateExplicitVersion(IgniteTxEntry txEntry, GridCacheEntryEx entry) throws GridCacheEntryRemovedException { if (entry.detached()) { GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId(), entry.txKey()); if (cand != null && !xidVersion().equals(cand.version())) { GridCacheVersion candVer = cand.version(); txEntry.explicitVersion(candVer); if (candVer.compareTo(minVer) < 0) minVer = candVer; } } else super.updateExplicitVersion(txEntry, entry); }
/** {@inheritDoc} */ @Override public void onTimeout() { if (state() == SUSPENDED) { try { resume(false, threadId()); } catch (IgniteCheckedException e) { log.warning("Error resuming suspended transaction on timeout: " + this, e); } } boolean proceed; synchronized (this) { proceed = state() != PREPARED && state(MARKED_ROLLBACK, true); } if (proceed || (state() == MARKED_ROLLBACK)) { cctx.kernalContext().closure().runLocalSafe(new Runnable() { @Override public void run() { // Note: if rollback asynchronously on timeout should not clear thread map // since thread started tx still should be able to see this tx. rollbackNearTxLocalAsync(false, true); U.warn(log, "The transaction was forcibly rolled back because a timeout is reached: " + CU.txString(GridNearTxLocal.this)); } }); } else { if (log.isDebugEnabled()) log.debug("Skip rollback tx on timeout: " + this); } }
tx0.nearXidVersion(), tx0.mvccSnapshot(), tx0.threadId(), IgniteUuid.randomUuid(), -1,
tx.xidVersion(), tx.commitVersion(), tx.threadId(), tx.isolation(), true,
txSync = cctx.tm().awaitFinishAckAsync(node.id(), tx.threadId());
txSync = cctx.tm().awaitFinishAckAsync(node.id(), tx.threadId());
/** * @param cctx Cache context. * @param tx Transaction. * @param timeout Timeout. * @param rdc Compound future reducer. */ public GridNearTxAbstractEnlistFuture( GridCacheContext<?, ?> cctx, GridNearTxLocal tx, long timeout, @Nullable IgniteReducer<T, T> rdc) { super(rdc); assert cctx != null; assert tx != null; this.cctx = cctx; this.tx = tx; this.timeout = timeout; threadId = tx.threadId(); lockVer = tx.xidVersion(); futId = IgniteUuid.randomUuid(); mvccSnapshot = tx.mvccSnapshot(); assert mvccSnapshot != null; log = cctx.logger(getClass()); }
/** * Suspends transaction. It could be resumed later. Supported only for optimistic transactions. * * @throws IgniteCheckedException If the transaction is in an incorrect state, or timed out. */ public void suspend() throws IgniteCheckedException { if (log.isDebugEnabled()) log.debug("Suspend near local tx: " + this); if (pessimistic()) throw new UnsupportedOperationException("Suspension is not supported for pessimistic transactions."); if (threadId() != Thread.currentThread().getId()) throw new IgniteCheckedException("Only thread started transaction can suspend it."); synchronized (this) { checkValid(); cctx.tm().suspendTx(this); } }
/** {@inheritDoc} */ @Override protected void updateExplicitVersion(IgniteTxEntry txEntry, GridCacheEntryEx entry) throws GridCacheEntryRemovedException { if (entry.detached()) { GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId(), entry.txKey()); if (cand != null && !xidVersion().equals(cand.version())) { GridCacheVersion candVer = cand.version(); txEntry.explicitVersion(candVer); if (candVer.compareTo(minVer) < 0) minVer = candVer; } } else super.updateExplicitVersion(txEntry, entry); }