/**
* Copyright 2014-2016 yangming.liu<bytefox@126.com>.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*/
package org.bytesoft.bytetcc;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.commons.lang3.StringUtils;
import org.bytesoft.bytejta.supports.jdbc.RecoveredResource;
import org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor;
import org.bytesoft.bytejta.supports.wire.RemoteCoordinator;
import org.bytesoft.bytetcc.supports.resource.LocalResourceCleaner;
import org.bytesoft.common.utils.ByteUtils;
import org.bytesoft.common.utils.CommonUtils;
import org.bytesoft.compensable.CompensableBeanFactory;
import org.bytesoft.compensable.CompensableInvocation;
import org.bytesoft.compensable.CompensableTransaction;
import org.bytesoft.compensable.ContainerContext;
import org.bytesoft.compensable.TransactionContext;
import org.bytesoft.compensable.archive.CompensableArchive;
import org.bytesoft.compensable.archive.TransactionArchive;
import org.bytesoft.compensable.logging.CompensableLogger;
import org.bytesoft.transaction.CommitRequiredException;
import org.bytesoft.transaction.RollbackRequiredException;
import org.bytesoft.transaction.Transaction;
import org.bytesoft.transaction.TransactionRepository;
import org.bytesoft.transaction.archive.XAResourceArchive;
import org.bytesoft.transaction.supports.TransactionListener;
import org.bytesoft.transaction.supports.TransactionListenerAdapter;
import org.bytesoft.transaction.supports.TransactionResourceListener;
import org.bytesoft.transaction.supports.resource.XAResourceDescriptor;
import org.bytesoft.transaction.supports.serialize.XAResourceDeserializer;
import org.bytesoft.transaction.xa.TransactionXid;
import org.bytesoft.transaction.xa.XidFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CompensableTransactionImpl extends TransactionListenerAdapter implements CompensableTransaction {
static final Logger logger = LoggerFactory.getLogger(CompensableTransactionImpl.class);
private final TransactionContext transactionContext;
private final List<CompensableArchive> archiveList = new ArrayList<CompensableArchive>();
private final Map<String, XAResourceArchive> resourceMap = new HashMap<String, XAResourceArchive>();
private final List<XAResourceArchive> resourceList = new ArrayList<XAResourceArchive>();
private final Map<String, XAResourceArchive> applicationMap = new HashMap<String, XAResourceArchive>();
private final Map<Thread, Transaction> transactionMap = new ConcurrentHashMap<Thread, Transaction>(4);
private CompensableBeanFactory beanFactory;
private int transactionVote;
private int transactionStatus = Status.STATUS_ACTIVE;
/* current comensable-decision in confirm/cancel phase. */
private transient Boolean positive;
/* current compense-archive in confirm/cancel phase. */
private transient CompensableArchive archive;
/* current compensable-archive list in try phase. */
private transient final List<CompensableArchive> currentArchiveList = new ArrayList<CompensableArchive>();
private transient final Map<Xid, List<CompensableArchive>> archiveMap = new HashMap<Xid, List<CompensableArchive>>();
private boolean participantStickyRequired;
private Map<String, Serializable> variables = new HashMap<String, Serializable>();
private Thread currentThread;
private final Lock lock = new ReentrantLock();
public CompensableTransactionImpl(TransactionContext txContext) {
this.transactionContext = txContext;
}
public TransactionArchive getTransactionArchive() {
TransactionArchive transactionArchive = new TransactionArchive();
transactionArchive.setVariables(this.variables);
transactionArchive.setCoordinator(this.transactionContext.isCoordinator());
transactionArchive.setPropagated(this.transactionContext.isPropagated());
transactionArchive.setCompensable(this.transactionContext.isCompensable());
transactionArchive.setCompensableStatus(this.transactionStatus);
transactionArchive.setVote(this.transactionVote);
transactionArchive.setXid(this.transactionContext.getXid());
transactionArchive.getRemoteResources().addAll(this.resourceList);
transactionArchive.getCompensableResourceList().addAll(this.archiveList);
transactionArchive.setPropagatedBy(this.transactionContext.getPropagatedBy());
return transactionArchive;
}
public synchronized void participantCommit(boolean opc) throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException, IllegalStateException, CommitRequiredException, SystemException {
// Recover if transaction is recovered from tx-log.
this.recoverIfNecessary();
if (this.transactionStatus != Status.STATUS_COMMITTED) {
this.fireCommit(); // TODO
}
}
// 当前事务节点,进行commit操作(该方法由监听器回调调用)
public synchronized void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
SecurityException, IllegalStateException, SystemException {
if (this.transactionStatus == Status.STATUS_ACTIVE) { // 事务状态: 活跃有效
this.fireCommit();
} else if (this.transactionStatus == Status.STATUS_MARKED_ROLLBACK) { // 事务状态: 标志回滚
this.fireRollback();
throw new HeuristicRollbackException();
} else if (this.transactionStatus == Status.STATUS_ROLLEDBACK) /* should never happen */ { // 事务状态:异常回滚,理论上不会出现这种情况
throw new RollbackException();
} else if (this.transactionStatus == Status.STATUS_COMMITTED) /* should never happen */ { // 事务状态: 已经提交,理论上不会出现这种情况
logger.debug("Current transaction has already been committed.");
} else {
throw new IllegalStateException();
}
}
// 执行发送提交
private void fireCommit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException,
IllegalStateException, SystemException {
CompensableLogger compensableLogger = this.beanFactory.getCompensableLogger();
this.transactionContext.setCompensating(true); // 正在补偿
this.transactionStatus = Status.STATUS_COMMITTING; // 事务状态:节点事务提交中
compensableLogger.updateTransaction(this.getTransactionArchive()); // 更新记录一下事务归档
SystemException systemEx = null;
try {
this.fireNativeParticipantConfirm(); // 执行本地事务参与者 提交节点事务
} catch (SystemException ex) {
systemEx = ex;
logger.info("{}| confirm native branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
} catch (RuntimeException ex) {
systemEx = new SystemException();
systemEx.initCause(ex);
logger.info("{}| confirm native branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
}
try {
this.fireRemoteParticipantConfirm(); // 执行远程事务参与者 提交节点事务
} catch (HeuristicMixedException ex) {
logger.info("{}| confirm remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
throw ex;
} catch (HeuristicRollbackException ex) {
logger.info("{}| confirm remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
throw ex;
} catch (SystemException ex) {
logger.info("{}| confirm remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
throw ex;
} catch (RuntimeException ex) {
logger.info("{}| confirm remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
throw ex;
}
if (systemEx != null) {
throw systemEx;
} else {
this.transactionStatus = Status.STATUS_COMMITTED; // 提交完成,事务状态更新为 已提交
compensableLogger.updateTransaction(this.getTransactionArchive()); // 更新记录一下节点事务归档
logger.info("{}| compensable transaction committed!",
ByteUtils.byteArrayToString(transactionContext.getXid().getGlobalTransactionId()));
}
}
public synchronized void recoveryCommit() throws CommitRequiredException, SystemException {
this.recoverIfNecessary(); // Recover if transaction is recovered from tx-log.
try {
this.fireCommit();
} catch (SecurityException ex) {
logger.error("{}| confirm native/remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
SystemException sysEx = new SystemException();
sysEx.initCause(ex);
throw sysEx;
} catch (RollbackException ex) {
logger.error("{}| confirm native/remote branchs failed!",
ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
SystemException sysEx = new SystemException();
sysEx.initC
ByteTCC源码分析(一)
最新推荐文章于 2023-09-07 18:40:32 发布