• 变更内部状态

    变更内部状态

    在这种情况下,简单代码替换就不够了。进程必须在切换到新版本的回调模块之前,明确地使用回调函数 code_change 转换它的状态。这样就必须使用同步代码替换。

    例如:想一下来自 gen_server行为 一章的 gen_server ch3 。内部状态是一个表示可用频道的 Chs 值。假设我们想添加一个计数器 N 用来跟踪目前的 alloc 请求数。这就表示我们需要将格式更改为 {Chs,N}

    .appup 文件可以为:

    1. {"2",
    2. [{"1", [{update, ch3, {advanced, []}}]}],
    3. [{"1", [{update, ch3, {advanced, []}}]}]
    4. }.

    update 指令的第三个元素是一个元组 {advanced,Extra} ,它说受影响的进程要在载入新版本的模块之前进行一个状态转换。进程会调用回调函数 code_change (参见 gen_server(3) )。 Extra ,在这里是 [], 会原样传递给该函数:

    1. -module(ch3).
    2. ...
    3. -export([code_change/3]).
    4. ...
    5. code_change({down, _Vsn}, {Chs, N}, _Extra) ->
    6. {ok, Chs};
    7. code_change(_Vsn, Chs, _Extra) ->
    8. {ok, {Chs, 0}}.

    如果是降级,那么第一个参数是 {down,Vsn} ,如果是升级,那么则是 Vsn 。表达式 Vsn 是由模块的“原始”版本中获得的,即,由哪个版本升级来的,或者要降级到哪个版本。

    版本由模块属性 vsn 定义——如果有。在 ch3 中没有这种属性,这种情况下则是BEAM文件的校验和(一个大整数),这个值没什么意思所以在这里忽略掉。

    ch3 的其他回调函数也需要进行修改,可能还需要添加新的借口函数,就不在此展示了)。