在Erlang的gen_server中实现代码交换 [英] Achieving code swapping in Erlang's gen_server

查看:134
本文介绍了在Erlang的gen_server中实现代码交换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找在gen_server上使用Erlang的热代码交换功能,这样我就不用重新启动它了。我该怎么办?当我搜索时,我可以找到的是一篇文章,提到我需要使用 gen_server:code_change 回调。

I am looking to make use of Erlang's hot code swapping feature on a gen_server, so that I don't have to restart it. How should I do that? When I searched, all I could find was one article which mentioned that I need to make use of gen_server:code_change callback.

但是,我找不到任何关于如何使用的文档/示例。任何帮助或资源的链接非常感谢!

However, I could not really find any documentation/examples on how to use this. Any help or links to resources greatly appreciated!

推荐答案

正如我已经提到的正常的升级方式是创建正确的.appup和.relup文件,让release_handler做什么需要做的。但是,您可以手动执行所涉及的步骤,如此处所述。对于长的答案,对不起。

As I already mentioned the normal way of upgrading is creating the proper .appup and .relup files, and let release_handler do what needs to be done. However you can manually execute the steps involved, as described here. Sorry for the long answer.

以下虚拟gen_server实现了一个计数器。旧版本(0)简单地将整数存储为状态,而新版本(1)将{tschak,Int}存储为状态。正如我所说,这是一个虚拟的例子。

The following dummy gen_server implements a counter. The old version ("0") simply stores an integer as state, while the new version ("1") stores {tschak, Int} as state. As I said, this is a dummy example.

z.erl(old):

z.erl (old):

-module(z).
-version("0").

-export([start_link/0, boing/0]).

-behavior(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], [{debug, [trace]}]). 

boing() -> gen_server:call(?MODULE, boom).


init([]) -> {ok, 0}.

handle_call(boom, _From, Num) -> {reply, Num, Num+1};
handle_call(_Call, _From, State) -> {noreply, State}.

handle_cast(_Cast, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change(_OldVsn, State, _Extra) -> {ok, State}.

z.erl(new):

z.erl (new):

-module(z).
-version("1").

-export([start_link/0, boing/0]).

-behavior(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], [{debug, [trace]}]).

boing() -> gen_server:call(?MODULE, boom).


init([]) -> {ok, {tschak, 0}}.

handle_call(boom, _From, {tschak, Num}) -> {reply, Num, {tschak, Num+1}};
handle_call(_Call, _From, State) -> {noreply, State}.

handle_cast(_Cast, State) -> {noreply, State}.

handle_info(_Info, State) -> {noreply, State}.

terminate(_Reason, _State) -> ok.

code_change("0", Num, _Extra) -> {ok, {tschak, Num}}.

启动shell并编译旧代码。注意gen_server以调试跟踪开始。

Start the shell, and compile the old code. Notice the gen_server is started with debug trace.

1> c(z).
{ok,z}
2> z:start_link().
{ok,<0.38.0>}
3> z:boing().
*DBG* z got call boom from <0.31.0>
*DBG* z sent 0 to <0.31.0>, new state 1
0
4> z:boing().
*DBG* z got call boom from <0.31.0>
*DBG* z sent 1 to <0.31.0>, new state 2
1

按预期工作:返回Int,新状态为Int + 1。

Works as expected: returns the Int, and new state is Int+1.

现在将z.erl替换为新的,然后执行以下操作步骤。

Now replace z.erl with the new one, and execute the following steps.

5> compile:file(z).
{ok,z}
6> sys:suspend(z).
ok
7> code:purge(z).
false
8> code:load_file(z).
{module,z}
9> sys:change_code(z,z,"0",[]).
ok
10> sys:resume(z).
ok

你刚刚做了什么:5:编译新的代码。 6:挂起服务器。 7:清除较旧的代码(以防万一)。 8:加载新的代码。 9:通过[]作为额外传递给code_change,从版本0调用模块z的进程'z'中的代码更改。 10:恢复服务器。

What you just did: 5: compiled the new code. 6: suspended the server. 7: purged older code (just in case). 8: loaded the new code. 9: invoked code change in process 'z' for module 'z' from version "0" with [] passed as "Extra" to code_change. 10: resumed the server.

现在,如果您再运行一些测试,可以看到服务器使用新的状态格式:

Now if you run some more tests, you can see, that the server works with the new state format:

11> z:boing().
*DBG* z got call boom from <0.31.0>
*DBG* z sent 2 to <0.31.0>, new state {tschak,3}
2
12> z:boing().
*DBG* z got call boom from <0.31.0>
*DBG* z sent 3 to <0.31.0>, new state {tschak,4}
3

这篇关于在Erlang的gen_server中实现代码交换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆