变更内部状态

在这种情况下,简单代码替换就不够了。进程必须在切换到新版本的回调模块之前,明确地使用回调函数 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 的其他回调函数也需要进行修改,可能还需要添加新的借口函数,就不在此展示了)。