スポンサーリンク

2016年3月16日

Using OTP with Elixir (Part4-1)

とある錬金術師の万能薬(Elixir)

Goal

  • ElixirからOTPを利用したサンプルを作成する
  • OTPを利用したシステムの基本的なアーキテクチャを習得する
  • OTPを使うとはどういうことなのか疑問を解消する

Dev-Environment

  • OS: Windows8.1
  • Erlang: Eshell V7.2.1, OTP-Version 18.1
  • Elixir: v1.2.0

Using OTP with Elixir (Part4-1)

  • 汎用イベントハンドラで使われる考え方
  • エラーロガーの仕組み
  • アラーム管理
  • アプリケーションサーバの構築(いまここ!)
  • 監視ツリーの作成とサーバの追加
  • アプリケーションのパッケージ化(これはやるか分からない…)
前回はアラーム管理についてやりました。
今日からは、アプリケーションサーバの構築を行います。
まずは、素数を計算するサーバを構築します。

File: lib/prime_server.ex

defmodule PrimeServer do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  def new_prime(n) do
    GenServer.call(__MODULE__, {:prime, n}, 20000)
  end

  def init([]) do
    Process.flag(:trap_exit, true)
    IO.inspect("#{__MODULE__} starting\n")
    {:ok, 0}
  end

  def handle_call({:prime, k}, _from, n) do
    {:reply, make_new_prime(k), n+1}
  end

  def handle_cast(_msg, n) do
    {:noreply, n}
  end

  def handle_info(_info, n) do
    {:noreply, n}
  end

  def terminate(_reason, _n) do
    IO.inspect("#{__MODULE__} stopping\n")
  end

  def code_change(_old_vsn, n, _extra) do
    {:ok, n}
  end

  defp make_new_prime(k) do
    if k > 100 do
      :alarm_handler.set_alarm(:tooHot)
      n = :lib_primes.make_prime(k)
      :alarm_handler.clear_alarm(:tooHot)
      n
    else
      :lib_primes.make_prime(k)
    end
  end
end
前回やったアラームの処理をどのように組み込んでいるかが重要なポイントです。
lib_primesモジュールなんてない…
そのため、プログラミングErlangのソースコードが置いてあるGitのリポジトリからコピペしコンパイルする。
lib_primesモジュールのソースを見てみるとlib_linモジュールというものを使っている。
これもコピペしてコンパイルする。
ソースコードの作成場所は、プロジェクト内に”erl”と言うディレクトリを作成した。
lib_primesモジュールの方だが、
コピペでコンパイルすると「古いAPI使わないで新しいの使ってね。詳しくはこのドキュメントに書いてあるよ」っと警告が出る。
折角なので、新しいAPIに変更しておく。

File: erl/lib_primes.erl

...

new_seed() ->
    {_,_,X} = erlang:timestamp(),
    {H,M,S} = time(),
    H1 = H * X rem 32767,
    M1 = M * X rem 32767,
    S1 = S * X rem 32767,
    put(random_seed, {H1,M1,S1}).

Note:

erlang:now/0は古いAPIのようです。
(何か、前にも同じことで警告見た気が...)
それではコンパイルする。

Example:

> cd erl
> erl -compile lib_primes.erl
> erl -compile lib_lin.erl
erlディレクトリの直下にbeamファイルが作成されている。
そのbeamファイルを以下のディレクトリへコピーする。

Directory: _build/dev/lib/otp_system_sample/ebin

これでとりあえずは動くようになった。
試してみよう。

Example:

> iex --erl "-boot start_sasl -config elog" -S mix

iex> PrimeServer.start_link
"Elixir.PrimeServer starting\n"
{:ok, #PID<0.96.0>}
iex> PrimeServer.new_prime(5)
Generating a 5 digit prime ................
62119
iex> PrimeServer.new_prime(101)
Generating a 101 digit prime ...........
15:15:45.421 [info]  [alarm_handler: {:set, :tooHot}]
................................................................................................................
74803864321717153802874416588765054708248376608110687060712594131517770913540462697216660049919938923

15:15:45.719 [info]  [alarm_handler: {:clear, :tooHot}]
100より大きい値は、アラームも動いていますね。
よしよし、問題ないです。
長くなってしまうので記事を分割します。
Part4-1はここまで、これで素数の計算を行うサーバが作成できました。
お次のPart4-2では、面積を求めるサーバを作成していきます。

Bibliography

人気の投稿