6. 全体の構造
app 起動と停止
クライアントの要求によりsupervisor for
supervisor serverの起動を行う
1サーバに一つ起動し、サーバクラッシュ
supervisor
supervisor 時の再起動と、KVSテーブル保持
for server
for server
1クライアントに一つ起動し、KVSの操作
gen_server
gen_server を実施
gen_serverのコールバックとして実装する
ekvs ETSを利用したKVSモジュール(not OTP)
なるだけOTPモジュールを組み合わせるのがOTP way
7. ekvs
• ekvsはETS(erlang term strage)を利用し
て簡単にすます
defmodule Ekvs do
def new(id) do
defp keys(_id, :"$end_of_table", a) do
new(id, [])
a
end
end
def new(id, opts) do
defp keys(id, r, a) do
:ets.new(id, opts)
keys(id, :ets.next(id, r), [r | a])
end
end
def put(id, k, v) do
def keys(id) do
true = :ets.insert(id, {k, v})
keys(id, :ets.first(id), [])
id
end
end
def delete(id, k) do
def get(id, k) do
:ets.delete(id, k)
case :ets.lookup(id, k) do
id
[] -> nil
end
[{^k, v}] -> v
end
end
end
11. supervisor for
GenServer
• init()は以下のとおり
defmodule Kvs.Srv.Sup do
• :ets.newでテーブルを作成し、 use Supervisor.Behavior, []
def init(args) do
それをKvs.Serverへ渡すように key = args
childspecを記述。 tbl_id = :ets.new(key, [:public])
childspec = {key,
{Kvs.Server, :start_link, [key, tbl_id]},
• :one_for_oneタイプと
:permanent,
し、:permanent に存在さ 100000,
:worker,
せ、:workerタイプの子プロセス [Kvs.Server]}
{:ok, {{:one_for_one,
• サーバの起動は、 10, # AllowedRestart(count)
100}, # MaxSeconds(sec)
Kvs.Server.start_linkを呼び出
[childspec]}}
す。 end
end
• 以上でsupervisor完了
12. Supervisor for
Supervisor
defmodule Kvs.Sup do
• クライアントからの要求に応じ use Supervisor.Behavior, []
def init(_args) do
て、子プロセスを起動するような {:ok, {{:one_for_one,
supervisorは、 10, # AllowedRestart(count)
100}, # MaxSeconds(sec)
supervisor.start_childと []}}
end
supervisor.terminate_childを使う。 def connect(super_ref, key) do
childspec = {key,
• connect関数: Kvs.SrvSupの生成 {Kvs.Srv.Sup, :start_link, [key]},
:temporary,
supervisor.start_child 関数によ
10000, #shutown wait time(milisec)
り動的に開始 :supervisor,
[Kvs.Srv.Sup]}
• quit関数: Kvs.SrvSupの終了 :supervisor.start_child(super_ref, childspec)
end
supervisor.terminate_child関数 def quit(super_ref, key) do
:supervisor.terminate_child(super_ref, key)
呼び出し
end
end
13. application
defmodule KvsApp do
• OTPアプリケーションと @behaviour :application
def start() do
して start, stop関数を用意 :ok = :application.start(:kvs)
end
def start(_type, args) do
する必要がある。 Kvs.Sup.start_link(:kvs_sup, args)
end
def stop() do
• 中身はトップレベルの :application.stop(:kvs)
end
supervisorモジュールであ def stop(state) do
Kvs.Sup.stop(:application_stop, state)
end
るKvs.Sup.start_linkや end
Kvs.Sup.stopを呼び出す
だけ。
14. mix.exs
defmodule MyApp.MixFile do
• ビルド用のmix.exs use Mix.Project
def project do
• ビルド定義もelixirスクリプトで記 [app: :kvs,
version: "0.0.1"]
述。 end
def application do
[mod: {KvsApp,[]},
• バージョンやアプリケーションの applications: [:sasl ],
registered: [:kvs],
メインモジュール、デスクリプ description: 'Hello Server App']
ションを指定するだけで、kvs.app end
end
は自動でmixがビルドしてくれる。
• mix new <app>で<app>用のセッ
トアップをしてくれる。