文前说明
作为码农中的一员, 需要不断的学习, 我工作之余将一些分析总结和学习笔记写成博客与大家一起交流, 也希望采用这种方式记录自己的学习之旅.
本文仅供学习交流使用, 侵权必删.
分析整理的版本为 Ovirt 4.2.3 版本.
1. Ovirt 中的事务管理
engine 中的 事务管理 是交由 JBoss 容器来完成的, 由 JBoss 容器基于 JTA 实现.
JNDI 命名目录为 java:jboss/TransactionManager.
TransactionManagerProducer
类中通过 Java CDI 将 TransactionManager 的实现类注入到程序中.
- @Produces
- @Singleton
- public TransactionManager getTransactionManager() throws NamingException {
- return (TransactionManager) new InitialContext().lookup("java:jboss/TransactionManager");
- }
1.1 事务传播行为
engine 中只定义了三种传播行为, 在
TransactionScopeOption
枚举类中进行了定义.
传播行为 | 说明 |
---|---|
Required | 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。 |
Suppress | 支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。 |
RequiresNew | 创建新事务,无论当前存不存在事务,都创建新事务。 |
1.2 事务的支持
engine 中定义了 TransactionSupport 工具类, 用于事务的支持.
静态方法 | 说明 |
---|---|
findTransactionManager | 获取事务管理器(单例对象,存在于 CDI 中)。 |
suspend | 挂起当前线程关联的事务。 |
resume | 继续当前线程关联的事务。 |
current | 返回关联到当前线程的事务。 |
registerRollbackHandler | 回调接口,以便在事务完成时得到通知从而触发一些处理工作,如清除缓存等。可以通过此接口将回调程序注入到事务中,当事务成功提交后,回调程序将被激活。 |
needToRollback | 根据事务状态判断是否需要回滚。 |
executeInScope | 执行事务(根据不同的传播行为)。 |
executeInNewTransaction | 执行传播行为为 RequiresNew 的事务。 |
setRollbackOnly | 标记当前事务将回滚。 |
1.3 执行事务
执行事务流程
其中深蓝色箭头连线表示公共执行.
橘黄色箭头连线表示 RequiresNew 执行.
绿色箭头连线表示 Required 执行.
浅蓝色箭头连线表示 Suppress 执行.
- 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());
- }
- }
- }
- }
handleTransactivity 通过该方法来设置传播行为.
步骤 | 说明 |
---|---|
第一步 | 通过 Command 的参数设置该传播行为。 |
第二步 | 根据 Command 是否设置了 @NonTransactiveCommandAttribute ,决定是否采用 Suppress 传播行为。 |
第三步 | 设置了 @NonTransactiveCommandAttribute,同时又设置了 forceCompensation 属性为 true,最终执行第一步的传播行为。 |
executeInScope 执行过程抛出异常, 则会执行补偿机制.
可以通过 Command 参数中的 shouldbelogged 属性设置是否在执行完成 excuete 后打印日志.
也可以在 Command 过程中通过 setCommandShouldBeLogged 方法设置.
excuete 执行成功后, 开始跟轮询踪异步任务.
1.3.2 endAction 方法
handleCommandExecutionEnded
判断是否需要执行 endAction.
所有的 Command 命令默认执行 endAction.
但是如果该 Command 中包含父 Command 参数, 则判断该 Command 的结束程序的属性 (Command 参数中可以设置(默认为 PARENT_MANAGED 不自动执行 endAction)) 是否为 FLOW_MANAGED 或 COMMAND_MANAGED, 如果是则执行, 否则不执行.
- 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;
- }
endAction 与 execute 有类似的流程, 同样需要设置传播行为和是否打印日志.
来源: http://www.jianshu.com/p/966345f7165f