/** {@inheritDoc} */ @Override public Xid[] recover(int i) { if (cacheTx.state() == PREPARED) return new Xid[] { xid }; return NO_XID; }
/** * * @return {@code true} if jta was already committed or rolled back. */ boolean isFinished() { TransactionState state = cacheTx.state(); return state == COMMITTED || state == ROLLED_BACK; }
/** * Changing state for this transaction as well as chained(parent) transactions. * * @param state Transaction state. * @return {@code True} if transition was valid, {@code false} otherwise. */ public boolean chainState(TransactionState state) { if (parentTx != null) parentTx.state(state); return state(state); }
/** * Checks transaction state. * @param tx Transaction. * @return Checked transaction. */ public static GridNearTxLocal checkActive(GridNearTxLocal tx) { if (tx != null && tx.state() != TransactionState.ACTIVE) throw new IgniteSQLException("Transaction is already completed.", TRANSACTION_COMPLETED); return tx; }
/** * @param clearThreadMap {@code True} if need remove tx from thread map. */ @Override public void finish(boolean commit, boolean clearThreadMap, boolean onTimeout) { try { if (commit) { tx.state(PREPARING); tx.state(PREPARED); tx.state(COMMITTING); tx.context().tm().fastFinishTx(tx, true, true); tx.state(COMMITTED); } else { tx.state(PREPARING); tx.state(PREPARED); tx.state(ROLLING_BACK); tx.context().tm().fastFinishTx(tx, false, clearThreadMap); tx.state(ROLLED_BACK); } } finally { onDone(tx); } }
/** * Suspends transaction. * Should not be used directly. Use tx.suspend() instead. * * @param tx Transaction to be suspended. * * @see #resumeTx(GridNearTxLocal, long) * @see GridNearTxLocal#suspend() * @see GridNearTxLocal#resume() * @throws IgniteCheckedException If failed to suspend transaction. */ public void suspendTx(final GridNearTxLocal tx) throws IgniteCheckedException { assert tx != null && !tx.system() : tx; if (!tx.state(SUSPENDED)) { throw new IgniteCheckedException("Trying to suspend transaction with incorrect state " + "[expected=" + ACTIVE + ", actual=" + tx.state() + ']'); } clearThreadMap(tx); transactionMap(tx).remove(tx.xidVersion(), tx); }
/** * @param tx Transaction. */ private String composeTx(final GridNearTxLocal tx) { final TransactionState txState = tx.state(); String top = txState + ", NEAR, "; if (txState == TransactionState.PREPARING) { final Map<UUID, Collection<UUID>> transactionNodes = tx.transactionNodes(); if (!F.isEmpty(transactionNodes)) { final Set<UUID> primaryNodes = transactionNodes.keySet(); if (!F.isEmpty(primaryNodes)) top += "PRIMARY: " + composeNodeInfo(primaryNodes) + ", "; } } final Long duration = System.currentTimeMillis() - tx.startTime(); return top + "DURATION: " + duration; }
/** * @param tx Transaction to close. * @throws IgniteCheckedException If failed. */ public void endTx(GridNearTxLocal tx) throws IgniteCheckedException { boolean clearThreadMap = txMgr.threadLocalTx(null) == tx; if (clearThreadMap) tx.txState().awaitLastFuture(this); else tx.state(MARKED_ROLLBACK); tx.close(clearThreadMap); }
/** * @param tx Transaction to rollback. * @throws IgniteCheckedException If failed. * @return Rollback future. */ public IgniteInternalFuture rollbackTxAsync(GridNearTxLocal tx) throws IgniteCheckedException { boolean clearThreadMap = txMgr.threadLocalTx(null) == tx; if (clearThreadMap) tx.txState().awaitLastFuture(this); else tx.state(MARKED_ROLLBACK); return tx.rollbackNearTxLocalAsync(clearThreadMap, false); }
/** {@inheritDoc} */ @Override public boolean onDone(@Nullable IgniteInternalTx res, @Nullable Throwable err) { if (err != null) ERR_UPD.compareAndSet(GridNearPessimisticTxPrepareFuture.this, null, err); err = this.err; if ((!tx.onePhaseCommit() || tx.mappings().get(cctx.localNodeId()) == null) && (err == null || tx.needCheckBackup())) tx.state(PREPARED); if (super.onDone(tx, err)) { cctx.mvcc().removeVersionedFuture(this); return true; } return false; }
/** {@inheritDoc} */ @Override public int prepare(Xid xid) throws XAException { assert this.xid.equals(xid); if (log.isDebugEnabled()) log.debug("XA resource prepare(...) [xid=" + xid + "]"); if (cacheTx.state() != ACTIVE) throw new XAException("Cache transaction is not in active state."); try { cacheTx.prepare(true); } catch (IgniteCheckedException e) { throwException("Failed to prepare cache transaction.", e); } return XA_OK; }
/** * 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); }
/** {@inheritDoc} */ @Override public void beforeCompletion() { if (log.isDebugEnabled()) log.debug("Synchronization.beforeCompletion() [xid=" + cacheTx.xid() + "]"); if (cacheTx.state() != ACTIVE) throw new CacheException("Cache transaction is not in active state."); try { cacheTx.prepare(true); } catch (IgniteCheckedException e) { throw new CacheException("Failed to prepare cache transaction.", e); } }
/** {@inheritDoc} */ @Override public void prepare() { if (!tx.state(PREPARING)) { if (tx.isRollbackOnly() || tx.setRollbackOnly()) { if (tx.remainingTime() == -1) onDone(tx.timeoutException()); else onDone(tx.rollbackException()); } else onDone(new IgniteCheckedException("Invalid transaction state for prepare " + "[state=" + tx.state() + ", tx=" + this + ']')); return; } try { tx.userPrepare(Collections.<IgniteTxEntry>emptyList()); cctx.mvcc().addFuture(this); preparePessimistic(); } catch (IgniteCheckedException e) { onDone(e); } }
/** * Initializes future. * * @param remap Remap flag. */ @Override protected void prepare0(boolean remap, boolean topLocked) { boolean txStateCheck = remap ? tx.state() == PREPARING : tx.state(PREPARING); if (!txStateCheck) { if (tx.isRollbackOnly() || tx.setRollbackOnly()) { if (tx.timedOut()) onDone(null, tx.timeoutException()); else onDone(null, tx.rollbackException()); } else onDone(null, new IgniteCheckedException("Invalid transaction state for " + "prepare [state=" + tx.state() + ", tx=" + this + ']')); return; } boolean set = cctx.tm().setTxTopologyHint(tx.topologyVersionSnapshot()); try { prepare(tx.readEntries(), tx.writeEntries(), remap, topLocked); markInitialized(); } finally { if (set) cctx.tm().setTxTopologyHint(null); } }
/** * Completeness callback. * * @return {@code True} if future was finished by this call. */ private boolean onComplete() { Throwable err0 = err; if ((!tx.onePhaseCommit() || tx.mappings().get(cctx.localNodeId()) == null) && (err0 == null || tx.needCheckBackup())) tx.state(PREPARED); if (super.onDone(tx, err0)) { // Don't forget to clean up. cctx.mvcc().removeVersionedFuture(this); return true; } return false; }
/** * Completeness callback. * * @return {@code True} if future was finished by this call. */ private boolean onComplete() { Throwable err0 = err; if ((!tx.onePhaseCommit() || tx.mappings().get(cctx.localNodeId()) == null) && (err0 == null || tx.needCheckBackup())) tx.state(PREPARED); if (super.onDone(tx, err0)) { if (err0 != null) tx.setRollbackOnly(); // Don't forget to clean up. cctx.mvcc().removeVersionedFuture(this); return true; } return false; }
@Override public void run() { for (int i = 0; i < txCnt; i++) { GridNearTxLocal tx0 = ctx.tm().threadLocalTx(cctx); assertTrue(tx0 == null || tx0.state() == ROLLED_BACK); try (Transaction tx = tryLockNode.transactions().txStart(PESSIMISTIC, REPEATABLE_READ, useTimeout ? 50 : 0, 1)) { txReadyFut.onDone(tx); // Will block on lock request until rolled back asynchronously. Object o = tryLockNode.cache(CACHE_NAME).getAndPut(0, 0); assertNull(o); // If rolled back by close, previous get will return null. } catch (Exception e) { // If rolled back by rollback, previous get will throw an exception. } } txReadyFut.onDone((Transaction)null); } }, 1, "tx-get-thread");
/** */ private void onFinishFutureDone(IgniteInternalFuture<IgniteInternalTx> fut) { GridNearTxLocal tx = tx(); Throwable err = fut.error(); if (tx.state() == TransactionState.COMMITTED) tx.context().coordinators().ackTxCommit(tx.mvccSnapshot()) .listen(fut0 -> onDone(tx, addSuppressed(err, fut0.error()))); else { tx.context().coordinators().ackTxRollback(tx.mvccSnapshot()); onDone(tx, err); } }