程序员Ovirt

【Ovirt 笔记】事务相关实现分析与整理

2018-11-30  本文已影响2人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 4.2.3 版本。

1. Ovirt 中的事务管理

@Produces
@Singleton
public TransactionManager getTransactionManager() throws NamingException {
    return (TransactionManager) new InitialContext().lookup("java:jboss/TransactionManager");
}

1.1 事务传播行为

传播行为 说明
Required 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
Suppress 支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
RequiresNew 创建新事务,无论当前存不存在事务,都创建新事务。

1.2 事务的支持

静态方法 说明
findTransactionManager 获取事务管理器(单例对象,存在于 CDI 中)。
suspend 挂起当前线程关联的事务。
resume 继续当前线程关联的事务。
current 返回关联到当前线程的事务。
registerRollbackHandler 回调接口,以便在事务完成时得到通知从而触发一些处理工作,如清除缓存等。可以通过此接口将回调程序注入到事务中,当事务成功提交后,回调程序将被激活。
needToRollback 根据事务状态判断是否需要回滚。
executeInScope 执行事务(根据不同的传播行为)。
executeInNewTransaction 执行传播行为为 RequiresNew 的事务。
setRollbackOnly 标记当前事务将回滚。

1.3 执行事务

执行事务流程
public static <T> T executeInScope(TransactionScopeOption scope, TransactionMethod<T> code) {
        // check if we are already in rollback
        TransactionManager tm;
        try {
            tm = findTransactionManager();
            if (needToRollback(tm.getStatus())) {
                throw new TransactionRolledbackLocalException(
                        "Current transaction is marked for rollback, no further operations are possible or desired");
            }
        } catch (SystemException e) {
            throw new RuntimeException("Failed to check transaction status - this shouldn't ever happen");
        }
        switch (scope) {
        case RequiresNew:
            return executeInNewTransaction(code);
        case Suppress:
            return executeInSuppressed(tm, code);
        case Required:
            return executeInRequired(tm, code);
        default:
            throw new RuntimeException("Undefined Scope: " + scope);
        }
}

1.3.1 excute 方法

protected final void execute() {
        setCommandStatus(CommandStatus.ACTIVE);
        getReturnValue().setValid(true);
        getReturnValue().setIsSynchronous(true);

        if (shouldPersistCommand()) {
            persistCommandIfNeeded();
            commandCoordinatorUtil.persistCommandAssociatedEntities(getCommandId(), getSubjectEntities());
        }

        executionHandler.addStep(getExecutionContext(), StepEnum.EXECUTING, null);

        handleCommandStepAndEntities();

        try {
            handleTransactivity();
            TransactionSupport.executeInScope(scope, this);
        } catch (TransactionRolledbackLocalException e) {
            log.info("Transaction was aborted in '{}'", this.getClass().getName());
            // Transaction was aborted - we must sure we compensation for all previous applicative stages of the command
            compensate();
        } finally {
            try {
                if (getCommandShouldBeLogged()) {
                    logCommand();
                }
                if (getSucceeded()) {
                    if (getCommandShouldBeLogged()) {
                        logRenamedEntity();
                    }
                    // only after creating all tasks, we can start polling them (we
                    // don't want
                    // to start polling before all tasks were created, otherwise we
                    // might change
                    // the VM/VmTemplate status to 'Down'/'OK' too soon.
                    startPollingAsyncTasks();
                }
            } finally {
                if (noAsyncOperations() && !executionHandler.checkIfJobHasTasks(getExecutionContext())) {
                    executionHandler.endJob(getExecutionContext(), getSucceeded());
                }
            }
        }
}
步骤 说明
第一步 通过 Command 的参数设置该传播行为。
第二步 根据 Command 是否设置了 @NonTransactiveCommandAttribute,决定是否采用 Suppress 传播行为。
第三步 设置了 @NonTransactiveCommandAttribute,同时又设置了 forceCompensation 属性为 true,最终执行第一步的传播行为。

1.3.2 endAction 方法

private boolean handleCommandExecutionEnded() {
        boolean shouldEndAction = parentHasCallback() ? isEndProcedureApplicableToEndAction() : true;

        CommandStatus newStatus = isEndSuccessfully() ? CommandStatus.SUCCEEDED : CommandStatus.FAILED;
        if (getCallback() == null) {
            setCommandStatus(newStatus);

            if (!shouldEndAction) {
                logEndWillBeExecutedByParent(newStatus);
            }
        }

        return shouldEndAction;
}
上一篇下一篇

猜你喜欢

热点阅读