mnesia的普通transaction写过程(四)事务提交准备

上一篇博文介绍了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]),

   case Reason of

{aborted, R} ->

   mnesia:abort(R);

_ ->

   mnesia:abort(Reason)

   end;

{New, Prepared} ->

   {New, Prepared#prep{records = reverse(Prepared#prep.records)}}

    end.

临时ets表的nodes就是之前请求锁的目的结点,它们都是事务参与结点,此时事务提交类型为异步,其事务提交协议为sym_trans,及异步同构事务。

prep_recs([N | Nodes], Recs) ->

    prep_recs(Nodes, [#commit{decision = presume_commit, node = N} | Recs]);

prep_recs([], Recs) ->

Recs.

从临时ets表中取得所有的表操作记录,根据这些表操作,为每个事务参与结点构建一个事务提交结构commit并进行填充。


do_arrange(Tid, Store, {Tab, Key}, Prep, N) ->

    Oid = {Tab, Key},

    Items = ?ets_lookup(Store, Oid), %% Store is a bag

    P2 = prepare_items(Tid, Tab, Key, Items, Prep),

do_arrange(Tid, Store, ?ets_next(Store, Oid), P2, N + 1);

prepare_items(Tid, Tab, Key, Items, Prep) when Prep#prep.prev_tab == Tab ->

    Types = Prep#prep.prev_types,

    Snmp = Prep#prep.prev_snmp,

    Recs = Prep#prep.records,

    Recs2 = do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs),

    Prep#prep{records = Recs2};

prepare_items(Tid, Tab, Key, Items, Prep) ->

    Types = val({Tab, where_to_commit}),

    case Types of

         [] -> mnesia:abort({no_exists, Tab});

         {blocked, _} ->

             unblocked = req({unblock_me, Tab}),

             prepare_items(Tid, Tab, Key, Items, Prep);

         _ ->

             Majority = needs_majority(Tab, Prep),

             Snmp = val({Tab, snmp}),

             Recs2 = do_prepare_items(Tid, Tab, Key, Types,

                                          Snmp, Items, Prep#prep.records),

             Prep2 = Prep#prep{records = Recs2, prev_tab = Tab,

                                  majority = Majority,

                                  prev_types = Types, prev_snmp = Snmp},

             check_prep(Prep2, Types)

end.

构建事务提交的准备结构,将同一个表的操作合并在一起。

do_prepare_items(Tid, Tab, Key, Types, Snmp, Items, Recs) ->

    Recs2 = prepare_snmp(Tid, Tab, Key, Types, Snmp, Items, Recs), % May exit

prepare_nodes(Tid, Types, Items, Recs2, normal).

prepare_nodes(Tid, [{Node, Storage} | Rest], Items, C, Kind) ->

    {Rec, C2} = pick_node(Tid, Node, C, []),

    Rec2 = prepare_node(Node, Storage, Items, Rec, Kind),

    [Rec2 | prepare_nodes(Tid, Rest, Items, C2, Kind)];

prepare_nodes(_Tid, [], _Items, CommitRecords, _Kind) ->

    CommitRecords.

prepare_nodes根据表的where_to_commit属性进行处理,该表属性为一个{Node,StorageType}列表。

pick_node(Tid, Node, [Rec | Rest], Done) ->

    if

Rec#commit.node == Node ->

   {Rec, Done ++ Rest};

true ->

   pick_node(Tid, Node, Rest, [Rec | Done])

    end;

pick_node({dirty,_}, Node, [], Done) ->

    {#commit{decision = presume_commit, node = Node}, Done};

pick_node(_Tid, Node, [], _Done) ->

    mnesia:abort({bad_commit, {missing_lock, Node}}).

pick_node为一个事务参与结点整理出表的操作,形成{NodeCommit, Ops}元组

prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind == snmp ->

    Rec2 = Rec#commit{snmp = [Item | Rec#commit.snmp]},

    prepare_node(Node, Storage, Items, Rec2, Kind);

prepare_node(Node, Storage, [Item | Items], Rec, Kind) when Kind /= schema ->

    Rec2 =

case Storage of

   ram_copies ->

Rec#commit{ram_copies = [Item | Rec#commit.ram_copies]};

   disc_copies ->

Rec#commit{disc_copies = [Item | Rec#commit.disc_copies]};

   disc_only_copies ->

Rec#commit{disc_only_copies = [Item | Rec#commit.disc_only_copies]}

end,

    prepare_node(Node, Storage, Items, Rec2, Kind);

prepare_node(_Node, _Storage, Items, Rec, Kind)

  when Kind == schema, Rec#commit.schema_ops == []  ->

    Rec#commit{schema_ops = Items};

prepare_node(_Node, _Storage, [], Rec, _Kind) ->

Rec.

prepare_node根据事务参与结点的存储类型,进一步将表操作填充到事务参与结点的commit结构的具体存储类型中

t_commit(Type) ->
    {_Mod, Tid, Ts} = get(mnesia_activity_state),
    Store = Ts#tidstore.store,
    if
Ts#tidstore.level == 1 ->
   intercept_friends(Tid, Ts),
   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.
不考虑嵌套事务的情况,此时,已经为每个事务参与结点构建了一个commit结构,该结构根据事务参与结点的存储类型,在ram_copies、disc_copies、disc_only_copies之一中记录了所有的表操作记录。
事务提交准备过程需要根据此前的更新情况,为每个事务参与结点构造好commit结构,该结构记录了在结点的具体副本类型下需要进行的更新,在下一步的提交过程中,将向各个事务参与结点传递该结构,以完成提交。
未完待续...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值