Dynamic Code Loading

某所で apache に負荷をかける為に erlang を使おうとして、知らずに http module を上書きしててハマったという書き込みをみて、Programming Erlang の APPENDIX E. Dynamic Code Loading の内容を思い出したので紹介。

まず、下記の source code を準備。

-module(a).
-compile(export_all).

start(Tag) -> spawn(?MODULE, loop, [Tag]).

loop(Tag) ->
  V = b:x(),
  io:format("Ver1 ~p : ~p~n", [Tag, V]),
  timer:sleep(3000),
  loop(Tag).
-module(b).
-compile(export_all).

x() -> 1.

コンパイルして実行開始。

% erl
1> c(a).
{ok,a}
2> c(b).
{ok,b}
3> a:start(one).
Ver1 one : 1
Ver1 one : 1
4> a:start(two).
Ver1 two : 1
Ver1 one : 1
Ver1 two : 1
Ver1 one : 1

module b のコードを書き換える。(この時、上記で実行した erl を停止しない)

-module(b).
-compile(export_all).

x() -> 2.

起動しっぱなしの erl で module b をコンパイルする。

Ver1 one : 1
Ver1 two : 1
5> c(b).
{ok,b}
Ver1 one : 2
Ver1 two : 2

b:x/0 の戻り値が変わった事が即反映される。

更に、module a を書き換える。

-module(a).
-compile(export_all).

start(Tag) -> spawn(?MODULE, loop, [Tag]).

loop(Tag) ->
  V = b:x(),
  io:format("Ver2 ~p : ~p~n", [Tag, V]),
  timer:sleep(3000),
  loop(Tag).

起動しっぱなしの erl で module a をコンパイルして、a:start/1 を実行する。

Ver1 one : 2
Ver1 two : 2
6> c(a).
{ok,a}
Ver1 one : 2
Ver1 two : 2
6> start:a(three).
Ver2 three : 2
Ver1 one : 2
Ver1 two : 2
Ver2 three : 2

spawn された Ver1 は動作し続けている事が解る。

erlang では、無停止運用の為に、動的にコードが読み込まれる特性を理解してコードを書く事が大切。