Search in sources :

Example 51 with TransactionException

use of io.seata.core.exception.TransactionException in project XHuiCloud by sindaZeng.

the class FileLocker method acquireLock.

@Override
public boolean acquireLock(List<RowLock> rowLocks) {
    if (CollectionUtils.isEmpty(rowLocks)) {
        // no lock
        return true;
    }
    String resourceId = branchSession.getResourceId();
    long transactionId = branchSession.getTransactionId();
    ConcurrentMap<BucketLockMap, Set<String>> bucketHolder = branchSession.getLockHolder();
    ConcurrentMap<String, ConcurrentMap<Integer, BucketLockMap>> dbLockMap = CollectionUtils.computeIfAbsent(LOCK_MAP, resourceId, key -> new ConcurrentHashMap<>());
    for (RowLock lock : rowLocks) {
        String tableName = lock.getTableName();
        String pk = lock.getPk();
        ConcurrentMap<Integer, BucketLockMap> tableLockMap = CollectionUtils.computeIfAbsent(dbLockMap, tableName, key -> new ConcurrentHashMap<>());
        int bucketId = pk.hashCode() % BUCKET_PER_TABLE;
        BucketLockMap bucketLockMap = CollectionUtils.computeIfAbsent(tableLockMap, bucketId, key -> new BucketLockMap());
        Long previousLockTransactionId = bucketLockMap.get().putIfAbsent(pk, transactionId);
        if (previousLockTransactionId == null) {
            // No existing lock, and now locked by myself
            Set<String> keysInHolder = CollectionUtils.computeIfAbsent(bucketHolder, bucketLockMap, key -> new ConcurrentSet<>());
            keysInHolder.add(pk);
        } else if (previousLockTransactionId == transactionId) {
            // Locked by me before
            continue;
        } else {
            LOGGER.info("Global lock on [" + tableName + ":" + pk + "] is holding by " + previousLockTransactionId);
            try {
                // Release all acquired locks.
                branchSession.unlock();
            } catch (TransactionException e) {
                throw new FrameworkException(e);
            }
            return false;
        }
    }
    return true;
}
Also used : Set(java.util.Set) ConcurrentSet(io.netty.util.internal.ConcurrentSet) FrameworkException(io.seata.common.exception.FrameworkException) ConcurrentMap(java.util.concurrent.ConcurrentMap) TransactionException(io.seata.core.exception.TransactionException) RowLock(io.seata.core.lock.RowLock)

Example 52 with TransactionException

use of io.seata.core.exception.TransactionException in project XHuiCloud by sindaZeng.

the class DefaultCoordinator method handleAsyncCommitting.

/**
 * Handle async committing.
 */
protected void handleAsyncCommitting() {
    Collection<GlobalSession> asyncCommittingSessions = SessionHolder.getAsyncCommittingSessionManager().allSessions();
    if (CollectionUtils.isEmpty(asyncCommittingSessions)) {
        return;
    }
    for (GlobalSession asyncCommittingSession : asyncCommittingSessions) {
        try {
            // Instruction reordering in DefaultCore#asyncCommit may cause this situation
            if (GlobalStatus.AsyncCommitting != asyncCommittingSession.getStatus()) {
                continue;
            }
            asyncCommittingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
            core.doGlobalCommit(asyncCommittingSession, true);
        } catch (TransactionException ex) {
            LOGGER.error("Failed to async committing [{}] {} {}", asyncCommittingSession.getXid(), ex.getCode(), ex.getMessage(), ex);
        }
    }
}
Also used : TransactionException(io.seata.core.exception.TransactionException) GlobalSession(io.seata.server.session.GlobalSession)

Example 53 with TransactionException

use of io.seata.core.exception.TransactionException in project XHuiCloud by sindaZeng.

the class DefaultCore method doGlobalCommit.

@Override
public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
    boolean success = true;
    // start committing event
    eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus()));
    if (globalSession.isSaga()) {
        success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying);
    } else {
        for (BranchSession branchSession : globalSession.getSortedBranches()) {
            // if not retrying, skip the canBeCommittedAsync branches
            if (!retrying && branchSession.canBeCommittedAsync()) {
                continue;
            }
            BranchStatus currentStatus = branchSession.getStatus();
            if (currentStatus == BranchStatus.PhaseOne_Failed) {
                globalSession.removeBranch(branchSession);
                continue;
            }
            try {
                BranchStatus branchStatus = getCore(branchSession.getBranchType()).branchCommit(globalSession, branchSession);
                switch(branchStatus) {
                    case PhaseTwo_Committed:
                        globalSession.removeBranch(branchSession);
                        continue;
                    case PhaseTwo_CommitFailed_Unretryable:
                        if (globalSession.canBeCommittedAsync()) {
                            LOGGER.error("Committing branch transaction[{}], status: PhaseTwo_CommitFailed_Unretryable, please check the business log.", branchSession.getBranchId());
                            continue;
                        } else {
                            SessionHelper.endCommitFailed(globalSession);
                            LOGGER.error("Committing global transaction[{}] finally failed, caused by branch transaction[{}] commit failed.", globalSession.getXid(), branchSession.getBranchId());
                            return false;
                        }
                    default:
                        if (!retrying) {
                            globalSession.queueToRetryCommit();
                            return false;
                        }
                        if (globalSession.canBeCommittedAsync()) {
                            LOGGER.error("Committing branch transaction[{}], status:{} and will retry later", branchSession.getBranchId(), branchStatus);
                            continue;
                        } else {
                            LOGGER.error("Committing global transaction[{}] failed, caused by branch transaction[{}] commit failed, will retry later.", globalSession.getXid(), branchSession.getBranchId());
                            return false;
                        }
                }
            } catch (Exception ex) {
                StackTraceLogger.error(LOGGER, ex, "Committing branch transaction exception: {}", new String[] { branchSession.toString() });
                if (!retrying) {
                    globalSession.queueToRetryCommit();
                    throw new TransactionException(ex);
                }
            }
        }
        if (globalSession.hasBranch()) {
            LOGGER.info("Committing global transaction is NOT done, xid = {}.", globalSession.getXid());
            return false;
        }
    }
    if (success && globalSession.getBranchSessions().isEmpty()) {
        SessionHelper.endCommitted(globalSession);
        // committed event
        eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), globalSession.getStatus()));
        LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid());
    }
    return success;
}
Also used : TransactionException(io.seata.core.exception.TransactionException) BranchSession(io.seata.server.session.BranchSession) BranchStatus(io.seata.core.model.BranchStatus) GlobalTransactionEvent(io.seata.core.event.GlobalTransactionEvent) TransactionException(io.seata.core.exception.TransactionException) NotSupportYetException(io.seata.common.exception.NotSupportYetException)

Example 54 with TransactionException

use of io.seata.core.exception.TransactionException in project XHuiCloud by sindaZeng.

the class DefaultCore method doGlobalRollback.

@Override
public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
    boolean success = true;
    // start rollback event
    eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getBeginTime(), null, globalSession.getStatus()));
    if (globalSession.isSaga()) {
        success = getCore(BranchType.SAGA).doGlobalRollback(globalSession, retrying);
    } else {
        for (BranchSession branchSession : globalSession.getReverseSortedBranches()) {
            BranchStatus currentBranchStatus = branchSession.getStatus();
            if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {
                globalSession.removeBranch(branchSession);
                continue;
            }
            try {
                BranchStatus branchStatus = branchRollback(globalSession, branchSession);
                switch(branchStatus) {
                    case PhaseTwo_Rollbacked:
                        globalSession.removeBranch(branchSession);
                        LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
                        continue;
                    case PhaseTwo_RollbackFailed_Unretryable:
                        SessionHelper.endRollbackFailed(globalSession);
                        LOGGER.info("Rollback branch transaction fail and stop retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
                        return false;
                    default:
                        LOGGER.info("Rollback branch transaction fail and will retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
                        if (!retrying) {
                            globalSession.queueToRetryRollback();
                        }
                        return false;
                }
            } catch (Exception ex) {
                StackTraceLogger.error(LOGGER, ex, "Rollback branch transaction exception, xid = {} branchId = {} exception = {}", new String[] { globalSession.getXid(), String.valueOf(branchSession.getBranchId()), ex.getMessage() });
                if (!retrying) {
                    globalSession.queueToRetryRollback();
                }
                throw new TransactionException(ex);
            }
        }
        // In db mode, there is a problem of inconsistent data in multiple copies, resulting in new branch
        // transaction registration when rolling back.
        // 1. New branch transaction and rollback branch transaction have no data association
        // 2. New branch transaction has data association with rollback branch transaction
        // The second query can solve the first problem, and if it is the second problem, it may cause a rollback
        // failure due to data changes.
        GlobalSession globalSessionTwice = SessionHolder.findGlobalSession(globalSession.getXid());
        if (globalSessionTwice != null && globalSessionTwice.hasBranch()) {
            LOGGER.info("Rollbacking global transaction is NOT done, xid = {}.", globalSession.getXid());
            return false;
        }
    }
    if (success) {
        SessionHelper.endRollbacked(globalSession);
        // rollbacked event
        eventBus.post(new GlobalTransactionEvent(globalSession.getTransactionId(), GlobalTransactionEvent.ROLE_TC, globalSession.getTransactionName(), globalSession.getBeginTime(), System.currentTimeMillis(), globalSession.getStatus()));
        LOGGER.info("Rollback global transaction successfully, xid = {}.", globalSession.getXid());
    }
    return success;
}
Also used : TransactionException(io.seata.core.exception.TransactionException) GlobalSession(io.seata.server.session.GlobalSession) BranchSession(io.seata.server.session.BranchSession) BranchStatus(io.seata.core.model.BranchStatus) GlobalTransactionEvent(io.seata.core.event.GlobalTransactionEvent) TransactionException(io.seata.core.exception.TransactionException) NotSupportYetException(io.seata.common.exception.NotSupportYetException)

Aggregations

TransactionException (io.seata.core.exception.TransactionException)54 BranchStatus (io.seata.core.model.BranchStatus)14 GlobalSession (io.seata.server.session.GlobalSession)9 ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)7 StoreException (io.seata.common.exception.StoreException)7 ExecutionException (io.seata.tm.api.TransactionalExecutor.ExecutionException)6 GlobalTransaction (io.seata.tm.api.GlobalTransaction)5 IOException (java.io.IOException)5 TimeoutException (java.util.concurrent.TimeoutException)5 NotSupportYetException (io.seata.common.exception.NotSupportYetException)4 GlobalTransactionEvent (io.seata.core.event.GlobalTransactionEvent)4 GlobalTransactionException (io.seata.core.exception.GlobalTransactionException)4 GlobalStatus (io.seata.core.model.GlobalStatus)4 EngineExecutionException (io.seata.saga.engine.exception.EngineExecutionException)4 BranchSession (io.seata.server.session.BranchSession)4 SQLException (java.sql.SQLException)4 StateMachineInstance (io.seata.saga.statelang.domain.StateMachineInstance)3 TransactionalExecutor (io.seata.tm.api.TransactionalExecutor)3 XAException (javax.transaction.xa.XAException)3 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)3