2007年09月05日

Erlang で付箋Webアプリケーションを作ってみました。

はてなブックマークに登録

インターネットを見ていて、そのときの感想とかページの内容に対して思っ たことなんかを簡単に書き留めておけると便利かなと思い、適当なWebのペー ジ上にブラウザで表示したまま付箋をつけられる WEB アプリケーションを、最近流 行の Erlang 作成してみました。

付箋 Web の実験デモサイトはこちらです。

http://husen.lab.klab.org/

Erlangを使う必要があったわけではないですが、面白そうなので練習を兼ねて はじめて使ってみました。

付箋Webの概要は

  1. 付箋のデータは専用の付箋Webサーバ上に保存される。
  2. ブラウザー上ではAjaxで付箋Webサーバと通信する。
  3. ブックマークレットを使って、任意のページで付箋を使えるようにする。

実際に作成しようとすると、他人のページに、ほかのサーバのデータを使って 重ね書きするので工夫が必要になります。最初に考えたのは、IFRAMEを使って 他人のページを表示する方法でしたが、これだけだと使いづらいので、ブック マークレットを使って表示中のページに付箋をつけられるようにしました。

IFRAMEタイプ

husen01

ブックマークレットタイプ

husen02

次にサーバサイドのErlangの説明をしたいと思います。

サーバサイドでは、Erlang で動作するHTTPサーバー Yaws を使用しています。Apacheと比較 しているサイト

http://www.sics.se/~joe/apachevsyaws.html

をみるとYawsは並列処理では圧倒的に速いようです。

#日本語読みはわかりませんが、内輪では「よーず」になりました。

debian パッケージの yaws が動作しないためソースからコンパイルしてイン ストールしました。設定は /usr/local/etc/yaws.conf に設定します。

以下 該当部分の抜粋 です

# --- 追加のerlangモジュールにパスを通す
ebin_dir = 追加モジュールのあるパス
# --- 起動時に起動する追加のプロセスを指定
run_mod=urlidx
# サーバの設定
<server サーバ名>
        port = ポート番号
        listen = 0.0.0.0
        docroot = ドキュメントのパス
</server>

実行するには

$ yaws -i

を実行します。オプションに --daemon を指定するとデーモンで起動します。

yawsを使っただけではErlangを使った面白みが無いので、データの保存に Erlangのdetsを使用してデータベースをつくり、それの管理用にErlangのプロ セスを上げてyawsのクライアントのプロセスと通信させて見ました。上記の yaws.conf内にある"run_mod = urlidx "がdetsデータベース用のプロセスを yaws起動時に立ち上げる指定になります。

データーベースの図

husen03

実際にプロセスとして立ち上げたのは、URL別のデータベースに対するインデッ クス情報を持ったデータベースの管理用だけです。この形であればurlidxプロ セスが付箋データのプロセスを立ち上げ、それをクライアントプロセスに渡す べきですが、今回はまだ、クライアントプロセスが直接付箋データベースを操 作するようになっています。

Erlangの特徴のひとつとして、Erlang独自のプロセスの起動とそのプロセス間 の通信が非常に容易にできることがあります。Erlangのプロセス間通信はプロ セスごとメールスロットを介して行われます。レシーブ側はメッセージをキュー に入れて、順番にパターンマッチし、パターンマッチしないメッセージは再度 キューに入れられます。

送信側 - メッセージの送信
          プロセスID ! メッセージ

受信側 - メッセージを受信
     receive
             パターン1 ->
           実行 ...,
             パターン2 ->
           実行 ....

以下は付箋のコード内での実行例です。

データベースプロセス。(urlidx.erl)

(Yaws起動時に実行されている。)

start() ->
    spawn(?MODULE, urldb, [] ). --- プロセスを生成

urldb() ->
    dets:open_file(urldb, ?DETSOPT),
    process_flag(trap_exit, true),
    register(url_indexer, self()),
    loop().

loop() ->
    receive                             --- 受信待ち
        {newdb, Url, ClientPid } ->     ---- (1)
            ClientPid ! get_note_db(newdb,Url); ----- 返信(1)
        {getdb, Url, ClientPid } ->      ----(1)
            ClientPid ! get_note_db(getdb,Url);  ----- 返信(1)
        {all,ClientPid} ->                 ----(2)
            ClientPid ! all_url_list()     ----- 返信(3)
    end,
    loop().

Erlangでは、変数は大文字で始まります。小文字で始まるものはatomと呼ばれ、 定数のように使われます。Yawsを起動するとyaws.confの設定に従ってデータ ベースプロセスが起動され、プロセスをurl_indexerの名前で登録してから loopでメッセージの受信待ちを行っています。

クライアントのコード

get_note_db(Url,Opt) ->
    url_indexer ! {Opt,Url,self()},     --- 送信(1)
        receive                      --- 応答の受信待ち .... 返信(1) または 返信(2)を受信
            {ok,NoteRef} ->
                {ok,NoteRef}; 
            {err,Msg} ->
                {err,Msg}
end.

all_url()->
    url_indexer ! {all,self()},            --- 送信(2)
        receive                      --- 応答の受信待ち ... 返信(3)を受信
            [] ->
                "//Index is Null.";
            [S|N]->
                Str = "\""++S++"\"",
                [ "[" ++ list_join(Str, N, ",") ++ "]" ]
end.

クライアントからはurl_indexerプロセスにメッセージを送っています。クラ イアントのget_note_db()内の送信(1)では3要素のタプルを送っていて最初の 要素はatomが代入されている変数になっています。3要素目はクライアント自 身のプロセスになります。受信側では、3要素のタプルで最初の要素のatomが 一致するところでパターンが一致しクライアントのプロセスにメッセージを返 信しています。all_url()では2要素のタプルで最初の要素がatomのallになっ ていいるのでデータベースプロセス側ではパターンマッチして返信(3)を返し ます。

ご覧のように Erlang ではプロセスの作成とプロセス間通信が非常に簡単に行 えることが魅力だと思います。今回のようなケースであれば、データベースに わざわざ Erlang を使う必要は無いかもしれませんが、Erlang前提でシステム の設計を考えると新しい発想でシステムを考えるきっかけになるかと思います。

Yawsのエスケープ処理について

今回、クライアントからはすべてエスケープ処理されたデータがGETで送られ てくるのですが、Yawsではエスケープ処理の部分が日本語に対応していません。 そこで、中身をみるとパターンマッチだけでできるようなのでパッチを作って みました。

--- yaws-1.68/src/yaws_api.erl.orig       2007-02-02 00:58:33.000000000 +0900
+++ yaws-1.68/src/yaws_api.erl     2007-05-24 16:55:04.000000000 +0900
@@ -398,6 +398,10 @@
 %% Key wil always be a regular atom.


+do_parse_spec(<<$%,$u, I1:8, I2:8,I3:8,I4:8, Tail/binary>>, Spec, Last, Cur, State) ->
+    Hex = yaws:hex_to_integer([I1,I2,I3,I4]),
+    do_parse_spec(Tail, Spec, Last, [ Hex | Cur],  State);
+
 do_parse_spec(<<$%, Hi:8, Lo:8, Tail/binary>>, Spec, Last, Cur, State) ->
     Hex = yaws:hex_to_integer([Hi, Lo]),
     do_parse_spec(Tail, Spec, Last, [ Hex | Cur],  State);
@@ -714,6 +718,9 @@
 find_cookie_val3([H|T], Ack) ->
     find_cookie_val3(T, [H|Ack]).

+url_decode([$%, $u, U1,U2,U3,U4 | Tail]) ->
+    Hex = yaws:hex_to_integer([U1, U2, U3, U4]),
+    [Hex | url_decode(Tail)];
 url_decode([$%, Hi, Lo | Tail]) ->
     Hex = yaws:hex_to_integer([Hi, Lo]),
     [Hex | url_decode(Tail)];
@@ -783,6 +790,10 @@
           [H|url_encode(T)];
       true ->
           case yaws:integer_to_hex(H) of
+             [I1,I2,I3,I4] ->
+                 [$%, $u, I1,I2,I3,I4 | url_encode(T)];
+             [I1,I2,I3] ->
+                 [$%, $u, $0, I1,I2,I3 | url_encode(T)];
              [X, Y] ->
                  [$%, X, Y | url_encode(T)];
              [X] ->
klab_gijutsu2 at 13:00│Comments(3)TrackBack(2)Erlang 

トラックバックURL

この記事へのトラックバック

1.  付箋アプリ  [ PetaPon開発日誌 ]   2007年09月05日 00:33
インターネットを見ていて、そのときの感想とかページの内容に対して思ったことなんかを簡単に書き留めておけると便利かなと思い、適当なWebのページ上にブラウザで表示したまま付箋をつけられる WEB アプリケーションを、最近流行の Erlang 作成してみました。 付箋 Web の
2. [WEB] 付箋アプリきてる?  [ lambda {|diary| lambda { diary += 1 } }.call(hatena) ]   2007年09月05日 01:46
http://dsas.blog.klab.org/archives/51094702.html KLabの付箋アプリを見て「Sticky Plus!と似たような感じだな〜…iframe方式は実装以外は同じかも…」と思っていたら、さらに似たようなことをやっている人がいてびびった。 付箋アプリ、なんかきてる?

この記事へのコメント

1. Posted by goma   2007年09月04日 21:25
IEで真っ白なページがおかしい
ブックマークレット動かすと表示される。
2. Posted by PetaPon   2007年09月05日 00:28
はじめまして。
PetaPonというサービスを先日リリースしたものです。http://www.petapon.net/
コンセプトが似ていたので驚きました。共時制ってやつでしょうか?

PetaPonは付箋の位置を、座標ではなくて、テキストマッチで決定しています。
3. Posted by fuwei   2007年11月23日 20:46
3 著作権法的にどうなんかな?
それと、
付箋より、メモ機能付きのMacのダッシュボード的な使い方にしたほうが僕は使う場面が増えそうかも。

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント