日期:2014-05-16 浏览次数:20419 次
上一篇博文介绍了mnesia的锁请求过程,在请求到锁后,mnesia:write将更新写入临时ets表,此后mnesia:write将完成其使命,重新回到mnesia_tm:apply_fun函数中,此后将继续分析。
apply_fun(Fun, Args, Type) ->
? ? Result = apply(Fun, Args),
? ? case t_commit(Type) of
do_commit ->
? ? ? ? ? ? {atomic, Result};
? ? ? ? do_commit_nested ->
? ? ? ? ? ? {nested_atomic, Result};
? ? ? ? {do_abort, {aborted, Reason}} ->
? ? ? ? ? ? {'EXIT', {aborted, Reason}};
? ? ? ? {do_abort, Reason} ->
? ? ? ? ? ? {'EXIT', {aborted, Reason}}
? ? end.
Type参数为async
t_commit(Type) ->
? ? {_Mod, Tid, Ts} = get(mnesia_activity_state),
? ? Store = Ts#tidstore.store,
? ? if
Ts#tidstore.level == 1 ->
? ?intercept_friends(Tid, Ts),
? ?%% N is number of updates
? ?case arrange(Tid, Store, Type) of
{N, Prep} when N > 0 ->
? ?multi_commit(Prep#prep.protocol,
majority_attr(Prep),
Tid, Prep#prep.records, Store);
{0, Prep} ->
? ?multi_commit(read_only,
majority_attr(Prep),
Tid, Prep#prep.records, Store)
? ?end;
...
? ? end.
在进行事务提交前,需要为每个事务参与结点计算其更新内容。
arrange(Tid, Store, Type) ->
? ? Nodes = get_elements(nodes,Store),
? ? Recs = prep_recs(Nodes, []),
? ? Key = ?ets_first(Store),
? ? N = 0,
? ? Prep =
case Type of
? ?async -> #prep{protocol = sym_trans, records = Recs};
? ?sync -> #prep{protocol = sync_sym_trans, records = Recs}
end,
? ? case catch do_arrange(Tid, Store, Key, Prep, N) of
{'EXIT', Reason} ->
? ?dbg_out("do_arrange failed ~p ~p~n", [Reason, Tid]),
?