Hatena::ブログ(Diary)

Twisted Mind

2012-05-01

Python Developers Meeting 2012.11 開催予定です

予定は未定です。

日時
2012-11-?? 、 10:00 開場 11:00 スタートの予定です。遅くても 21:00 までには解散します
懇親会
ビアバッシュやりたいです、ただ出来るかどうか不明です
会場
未定
住所
未定
開場時間
公式開場は 10:00 ~ 11:00 のみであとは #pyfes タグを付けて迎えに来て貰いましょう。
参加条件
指定した特定の OSS に対して 2012 年中に寄付をした経験がある事

参加条件詳細

注意: 寄付したからかならず参加出来るのではなく、参加条件を満たすだけです。

2012 年中に OSS寄付を行った経験がある事を参加条件としてみたいと思います

主催オススメ寄付

寄付先はどこでも良いです

寄付について

OSS寄付をするきっかけってあまり無いと思うので、これがきっかけになればいいなと思いました。

自分自身も Python 温泉に参加したこと以外では寄付経験はありません。

ただ、寄付って意外に簡単にできる貢献の一つなのかなと思っています

キャンセルについて

当日でのドタキャンでも構いません。ただ、Zusaar にてキャンセル処理だけはお願いします

運営

基本 @voluntas の独断偏見で色々決まっていきます。ご了承ください。

主催
@voluntas / @tokoroten / @blaue_fuchs
ハッシュタグ
#pyfes
公式協力者達
togetter
@blaue_fuchs
スチール
@hiroki_niinuma

お手伝いとか差し入れとか募集中です

募集中

定員は 30 名の予定です。

募集は 2012.07 が終わってから

プレゼン

がっちり Python やると見せかけて ...

  • @tk0miya
  • @atsuoishimoto
  • @shimizukawa
  • @ransui (交渉予定)
  • @nishio (交渉中)
  • @mopemope (交渉予定)
  • @flyingfoozy (交渉予定)
  • @voluntas
  • @itawasa (交渉予定)
  • @kenji_rikitake (交渉予定)

未決定事項

殆どが未定ですがハンズオンの開催はありません。

自由時間 + プレゼンの予定です。ビアバッシュやりたいですね。

2012-04-26

Sphinx で商用のウェブサイトを立てて 4 ヶ月が過ぎた

Sphinx会社製品サイトを作って 4 ヶ月以上過ぎました、実際に運用してみた感想などを。

前提

デザイナー @kinofumi に依頼して、Sphinx の専用テーマを作って貰いました。@kinofumi は Jinja2 も使いこなしてしまったりとデザイナー?なのか怪しいですが、とてもステキサイトが出来ました。

商用製品サイトなので、とにかく見やすいこと、知りたい情報が見つかることが第一に作って貰いました。

リリース環境

S3 にデプロイしてパーミッションを Public にしていますURLDNS 指定しているだけです。

それ以上は特にやっていません。

費用

アクセスが 1 日 100 人未満です。そもそも 1000 人も見に来るようになったら問題です。

で、実際いくらかかったのよ、という話しです。

今のところ三ヶ月連続で $ 0.03 で、今月も今のところ $ 0.03 でした。

円だと 2 円くらいですかね。12 ヶ月同じ調子だとして年間費用は 24 円の予定です。

デプロイ

PythonAWS ライブラリの boto で Sphinx デプロイツールを書いたのですが、

今ひとつ AWS 側のパーミッションをしっかり設定していないこともあり、今のところ手動です。

自動化したいんですけど、そこにかけるコストほどデプロイ作業がないんですよね ... あって 2 週間に 1 回くらいで、3 分かかりません ... 。

そのうち暇見つけて自動化しようと思います

リリース

基本的に github の issues にやりたい事などをため込んで貰ってある程度たまったらリリースしています

ただ、営業の要望は最優先でとりこんで出来るだけはやくリリースするようにしています

HTML を一切書かないでリリース出来るので気楽です。

拡張

開発チームに Sphinx に明るい人がいるのはおいておいても、かなり楽です。それっぽく書けば出来ちゃいます。この辺はさすがドキュメントツールというところですね。

バージョン管理

rst 形式で管理していくので、とにかく見やすいです。HTML管理してたら ... とおもうとぞっとします

感想

まりアクセスの無いサイト出あれば、すごくアリだと思いました。とにかくメンテナンスコストが低いです。Sphinx をいじるだけですし。

もっと速度が欲しければ CloudFront という手もあるでしょうけど、当面は不要そうです。

静的な製品ページやキャンペーンページにはぴったりだと思います。もし色々検討している方は導入をお勧めます

検討している人へ

@kinofumi に Sphinx で商用のサイト検討しているのですが ... と相談してみるとイイと思います

型を指定してバイナリから変換するライブラリ

誰得ライブラリな気がするので、微妙ですが ...

作った理由

Erlang で外部 API とかを使って Console とかからデータを貰えるような仕組みを作ると、

かならず必要なのがバリデータとかコンバーターです。

毎回似たようなの書いててだるいなぁって思っていたので、ライブラリ化してみました。

ただ、Erlang で外部向けの API をつくったりしないかぎりは、使いどころがあまりないライブラリです。

github

pull-request 待ってます

https://github.com/voluntas/satori

型の種類

単体では使い道無いので、 rebar の deps で呼んで貰うイメージです。

bitstring に対してバリデータ + 型変換を行って戻り値を返してくれます

  • binary
  • binary extend
  • integer
  • atom

今のところ 4 タイプに対応していますregexp も追加する予定です。

binary type

binary の長さのバリデーションが指定可能です。

固定で対応文字列範囲で 0x20 ~ 0x7E までの文字を許可します \00 とかはダメです。

{binary, {最小サイズ,最大サイズ}

サンプル

> satori:convert({binary, {1, 2}}, <<"ab">>).
<<"ab">>
> satori:convert({binary, {1, 2}}, <<"abc">>).
invalid_input

binary extend type

binary と一緒ですが許可する文字範囲を自分で指定出来ます。さらに、許可しない文字も指定出来ます

{binary, {最小サイズ, 最大サイズ}, {文字範囲スタート, 文字範囲エンド}, [許可しない文字]}

以下は 0x20 ~ 0x7E なのだけれど , は許可しないという設定をしている例です。

> satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"abc">>).
<<"abc">>
> satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"a,c">>).
invalid_input
> satori:convert({binary, {1, 5}, {16#20, 16#7E}, [$,]}, <<"\0\1\3">>).
invalid_input

integer type

数値変換です。マイナスも大丈夫です。

最小値と最大値が指定出来てバリデーション可能です。

{integer, {最小値, 最大値}}

> satori:convert({integer, {1, 32}}, <<"12">>).
12
> satori:convert({integer, {1, 32}}, <<"33">>).
invalid_input
> satori:convert({integer, {1, 32}}, <<"a">>).
invalid_input

atom type

atom に変換も入れてあります

ただ atom の動的生成はメモリーリークの原因になりますので、変換する際 binary_to_existing_atom を使っています

既に存在する atom 以外を変換しようとしたら例外が上がります。それでメモリリークを防いでいます

またリストatom を渡す事で、指定した atom 以外は変換出来ないようにしています

{atom, [atom]}

> satori:convert({atom, [spam]}, <<"spam">>).
spam
> satori:convert({atom, [spam]}, <<"egg">>).
invalid_input

名前の由来

妖怪から取ってますライブラリ作るとき名前は出来るだけ日本にまつわる名前にしてます

http://ja.wikipedia.org/wiki/%E8%A6%9A

雑感

1 時間くらいで書いたのですが、あったらいいなーと思った割にさくっと書きました。

あんまり需要は無いと思いますが、自分が嬉しいのでいいかなと。

今後は気軽に拡張出来るように拡張機能を強化していこうかなと。

ただシンプルにしていきたいので何かのアプリ依存な変換機能とかは付ける予定はありません。

参考

2012-04-21

ローカル開発時の継続ビルド+テスト Erlang 版

もちろん rebar 前提です。

OMake とか watch コマンドとか色々ありますが、自分Python の watchdog を使っています

watchdog は Python で出来てる監視ツールです、pip でインストールしましょう

$ pip install watchdog

Makefile ... 色々省いてます

.PHONY: test

compile:
        @./rebar compile skip_deps=true

xref: compile
        @./rebar xref skip_deps=true

clean:
        @./rebar clean skip_deps=true

test: xref
        @./rebar skip_deps=true eunit

watchdog はイベントライブラリなのですが、シェルコマンドとしても使えます

監視は *.erl と *.hrl を srctest 以下のディレクトリ監視します。

$ watchmedo shell-command --patterns="*.erl;*.hrl" --recursive --wait --command="make test" src test

こうするとファイルを変更する度にコンパイルテストが走ってくれるので便利です。

ただ、重いので適時 eunit suite と会わせて使いましょう。

参考

2012-04-17

string から term を生成する方法

文字列から Erlang Term を作る方法がわからなかったのでメモ

かなりマニアックですが ... 。もっと簡単な方法があったら教えてください。

> {ok,Tokens,_} = erl_scan:string("[{foo,bar},x,3].").
{ok,[{'[',1},
    {'{',1},
    {atom,1,foo},
    {',',1},
    {atom,1,bar},
    {'}',1},
    {',',1},
    {atom,1,x},
    {',',1},
    {integer,1,3},
    {']',1},
    {dot,1}],
   1}
> {ok,Term} = erl_parse:parse_term(Tokens).
{ok,[{foo,bar},x,3]}

2012-04-09

Erlang/OTP R15B01 を CentOS 6.2 にインストールする

インストールメモ

$ yum install gcc gcc-c++ ncurses-devel make openssl-devel systemtap-sdt-devel
$ curl -O http://dl.dropbox.com/u/89936/otp_src_R15B01.tar.gz
$ tar xvfz otp_src_R15B01.tar.gz
$ cd otp_src_R15B01
$ ./configure --prefix=/opt/local/erlang/R15B01 \
              --enable-smp-support \ 
              --enable-m64-build \
              --enable-halfword-emulator \
              --enable-kernel-poll \
              --without-javac \
              --disable-native-libs \
              --disable-hipe \
              --disable-sctp \
              --enable-threads \
              --with-dynamic-trace=systemtap
$ make -j8
$ sudo make install

2012-04-07

軽量ウェブサーバ Cowboy を試す

mochiweb を仕事でも使っているので特に困っていないのですが、せっかくなので cowboy を触ってみることにしました。

ちなみに、作者の @lhoguin が来月あたり日本に来るらしく、日本の Erlang な人と会いたいと行っているので興味ある人は是非。

環境と注意

Erlang: R15B01 前提です、出たばかりですが色々細かい修正がされていたりするので是非インストールしましょう。

github

今回のお試しアプリgithub においてあります。

https://github.com/voluntas/snowflake/tree/feature/cowboy

動かすときはこれを前提にしています。

インストール

もちろん rebar を使っていると思いますので、rebar.config に追加して終わりです。

{deps,
  [
   {cowboy,
    ".*", {git, "git://github.com/extend/cowboy.git", {branch, "master"}}},

構成

cowboy は application:start(cowboy) で起動した後、cowboy:start_listener/6 でトランスポートプロトコル、そして acceptor を指定する仕組みになっています。

cowboy のサンプルでは app にそのまま書かれていましたが、今回は cowboy 起動部分を独立させてみました。

-module(snowflake_cowboy).                                         

-export([start/0]).

-spec start() -> ok.
start() ->
    application:start(cowboy),
    Dispatch = [
        {'_', [
            {'_', snowflake_default_handler, []}
        ]}
    ],
    cowboy:start_listener(snowflake_http_handler, 100,
        cowboy_tcp_transport, [{port, 8080}],
        cowboy_http_protocol,  [{dispatch, Dispatch}]
    ),
    ok.

ディスパッチは {ホスト, [{パス, ハンドル名, オプション}]} のリストになっています。

今回は全部受け入れる例でにしてみました。

全てのアクセスを snowflake_default_handler に送ります。

snowflake_default_handler はただ文字列を返すだけです。

-module(snowflake_default_handler).                                

-behaviour(cowboy_http_handler).

-export([init/3, handle/2, terminate/2]).

init({_Any, http}, Req, []) ->
    {ok, Req, undefined}.

handle(Req, State) ->
    {ok, Res} = cowboy_http_req:reply(200, [], <<"Hello cowboy!">>, Req),
    {ok, Res, State}.

terminate(_Req, _State) ->
    ok.

Req は include/http.hrl にある http_req レコードです。

init でどのプロトコルを受け取るのか、state はどうするのかを指定します。

handle は Request が送られてきたときの処理を書きます。

behaviour で cowboy_http_handler を指定しておくと callback が指定されているので少しだけ便利です。

起動してみる

$ git clone git://github.com/voluntas/snowflake.git
$ cd snowflake
$ git checkout --track origin/feature/cowboy
$ make
$ sh start.sh

これで localhost:8080 にアクセスすれば起動が確認出来ると思います。

感想

まだソースを追いかけてないので良くわかっていませんが、URL Dispatch 周りがどう柔軟なのかが重要かなと感じています。

トランスポートプロトコルを分けているので、SPDY 対応とかも出来ると言えば出来るかも知れません。

軽量かどうかの負荷試験は誰かにお任せしておきます。

まだまだ発展途上ではありますが、押さえるところは押さえているフレームワークだなと感じました。

参考

2012-03-30

LDAP クライアントが erlang/otp に追加されてた

ErlangLDAP クライアントといえば eldap で、かなり古い実装で R8 か R9 くらいの頃の実装です。

もともとは GPL だったのが MIT になって github に公開されていました。

https://github.com/etnt/eldap


仕事で使うかも知れないと思って、たまにパッチを送ったりしていたのですが ...

なんと erlang/otp の maint にマージされてました ... 。

https://github.com/erlang/otp/commit/472a3d910595d7de1e49f241c1d241827b5c0bf4


テストドキュメントもしっかりと追加されていたり。maint ブランチは次のリリース向けのブランチなので R15B01 には eldap が入るのが確定しました。やったーと思って変更履歴見てたら、自分の、名前が、あった。

https://github.com/erlang/otp/commit/472a3d910595d7de1e49f241c1d241827b5c0bf4#L2R7

本名じゃないのはご愛敬 ... という自己満足エントリでした。

Erlang R15B01 で DTrace(SystemTap) を使ってみる

注意: DTrace まったくわかりません。D 言語(D スクリプト) は書けません。読めません。

とりあえずインストールして動かしてみたよ、程度のレベルです。

DTrace 使ったらこんなに幸せになったよエントリーではありません。

追記

  • 2012-04-04
    • R15B01 が出たので R15B01 に合わせました。

環境

OS
Mac OS X 10.7.3
CPU
Core 2 Duo 1.6 G
Mem
4G

インストール

R15B01 をビルドします。--with-dynamic-trace で dtrace を指定しましょう。

Linux場合systemtap を指定しましょう。--prefix の部分はお好きにどうぞ、あと hipe は自分が使う分には余り効果が無いので無効にしています

$ curl -O http://dl.dropbox.com/u/89936/otp_src_R15B01.tar.gz
$ cd otp_src_R15B01
$ ./configure --prefix=/opt/local/erlang/R15B01 --enable-smp-support \
              --enable-darwin-64bit --enable-kernel-poll --without-javac \ 
              --disable-native-libs --disable-hipe --disable-sctp \
              --enable-threads --with-dynamic-trace=dtrace
$ make
$ sudo make install

これで環境構築は終わりです。

サンプルを見てみる

注意: ファイル等は DTrace だけ表示していますSystemTap のも同様に入っています

サンプルは runtime_tools フォルダの examples にあります

$ cd /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples
$ ls
dist.d
driver1.d
efile_drv.d
function-calls.d
garbage-collection.d
memory1.d
messages.d
port1.d
process-scheduling.d
spawn-exit.d
user-probe.d

efile_drv.d を見てみます ... が正直良くわかりません。勉強不足 orz

BEGIN
{
    op_map[1] = "OPEN";
    op_map[2] = "READ";
    op_map[3] = "LSEEK";
    op_map[4] = "WRITE";
    op_map[5] = "FSTAT";
    op_map[6] = "PWD";
    op_map[7] = "READDIR";
    op_map[8] = "CHDIR";
    op_map[9] = "FSYNC";
    op_map[10] = "MKDIR";
    op_map[11] = "DELETE";
    op_map[12] = "RENAME";
    op_map[13] = "RMDIR";
    op_map[14] = "TRUNCATE";
    op_map[15] = "READ_FILE";
    op_map[16] = "WRITE_INFO";
    op_map[19] = "LSTAT";
    op_map[20] = "READLINK";
    op_map[21] = "LINK";
    op_map[22] = "SYMLINK";
    op_map[23] = "CLOSE";
    op_map[24] = "PWRITEV";
    op_map[25] = "PREADV";
    op_map[26] = "SETOPT";
    op_map[27] = "IPREAD";
    op_map[28] = "ALTNAME";
    op_map[29] = "READ_LINE";
    op_map[30] = "FDATASYNC";
    op_map[31] = "FADVISE";
}

erlang*:::aio_pool-add
{
    printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
}

erlang*:::aio_pool-get
{
    printf("async I/O pool port %s queue len %d\n", copyinstr(arg0), arg1);
}

erlang*:::efile_drv-entry
{
    printf("efile_drv enter tag={%d,%d} %s%s | %s (%d) | args: %s %s , %d %d (port %s)\n",
	   arg0, arg1,
           arg2 == NULL ? "" : "user tag ",
           arg2 == NULL ? "" : copyinstr(arg2),
           op_map[arg3], arg3,
	   arg4 == NULL ? "" : copyinstr(arg4),
	   arg5 == NULL ? "" : copyinstr(arg5), arg6, arg7,
           /* NOTE: port name in args[10] is experimental */
           (args[10] == NULL) ? 
	       "?" : copyinstr((user_addr_t) args[10]));
}

erlang*:::efile_drv-int*
{
    printf("async I/O worker tag={%d,%d} | %s (%d) | %s\n",
           arg0, arg1, op_map[arg2], arg2, probename);
}

/* efile_drv-return error case */
erlang*:::efile_drv-return
/arg4 == 0/
{
    printf("efile_drv return tag={%d,%d} %s%s | %s (%d) | errno %d\n",
           arg0, arg1,
           arg2 == NULL ? "" : "user tag ",
           arg2 == NULL ? "" : copyinstr(arg2),
           op_map[arg3], arg3,
           arg5);
}

/* efile_drv-return success case */
erlang*:::efile_drv-return
/arg4 != 0/
{
    printf("efile_drv return tag={%d,%d} %s | %s (%d) ok\n",
           arg0, arg1,
           arg2 == NULL ? "" : copyinstr(arg2),
           op_map[arg3], arg3);
}

ちょっと動かしてみる

まずは Erlang VM を起動しま

[dtrace] というのが表示されていればおkです。

$ /opt/local/erlang/maint/bin/erl                               
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:2:2] [async-threads:0] [kernel-poll:false] [dtrace]

Eshell V5.9.1  (abort with ^G)
1> 

DTrace を実行する。今回は efile_drv.d

$ sudo dtrace -qs efile_drv.d

Erlang VM 側でファイルを開いて書き込みしてみます

Eshell V5.9.1  (abort with ^G)
1> {ok, Fd} = file:open("/tmp/spam", [raw, append, binary]).
{ok,{file_descriptor,prim_file,{#Port<0.494>,14}}}
2> file:write(Fd, <<"abcdefg">>).
ok

DTrace 側に以下のようなのが表示されました。

efile_drv enter tag={0,470}  | PWD (6) | args:   , 0 0 (port #Port<0.474>)
async I/O worker tag={0,470} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,470} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,470}  | PWD (6) ok
efile_drv enter tag={0,471}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_scan.beam  , 0 0 (port #Port<0.475>)
async I/O worker tag={0,471} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,471} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,471} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,472}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_scan.beam  , 0 0 (port #Port<0.476>)
async I/O worker tag={0,472} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,472} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,472} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,473}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_scan.beam  , 0 0 (port #Port<0.477>)
async I/O worker tag={0,473} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,473} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,473}  | READ_FILE (15) ok
efile_drv enter tag={0,474}  | PWD (6) | args:   , 0 0 (port #Port<0.478>)
async I/O worker tag={0,474} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,474} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,474}  | PWD (6) ok
efile_drv enter tag={0,475}  | PWD (6) | args:   , 0 0 (port #Port<0.479>)
async I/O worker tag={0,475} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,475} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,475}  | PWD (6) ok
efile_drv enter tag={0,476}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_parse.beam  , 0 0 (port #Port<0.480>)
async I/O worker tag={0,476} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,476} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,476} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,477}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_parse.beam  , 0 0 (port #Port<0.481>)
async I/O worker tag={0,477} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,477} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,477} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,478}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_parse.beam  , 0 0 (port #Port<0.482>)
async I/O worker tag={0,478} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,478} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,478}  | READ_FILE (15) ok
efile_drv enter tag={0,479}  | PWD (6) | args:   , 0 0 (port #Port<0.483>)
async I/O worker tag={0,479} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,479} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,479}  | PWD (6) ok
efile_drv enter tag={0,480}  | PWD (6) | args:   , 0 0 (port #Port<0.484>)
async I/O worker tag={0,480} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,480} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,480}  | PWD (6) ok
efile_drv enter tag={0,481}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./otp_internal.beam  , 0 0 (port #Port<0.485>)
async I/O worker tag={0,481} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,481} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,481} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,482}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/otp_internal.beam  , 0 0 (port #Port<0.486>)
async I/O worker tag={0,482} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,482} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,482} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,483}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/otp_internal.beam  , 0 0 (port #Port<0.487>)
async I/O worker tag={0,483} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,483} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,483}  | READ_FILE (15) ok
efile_drv enter tag={0,484}  | PWD (6) | args:   , 0 0 (port #Port<0.488>)
async I/O worker tag={0,484} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,484} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,484}  | PWD (6) ok
efile_drv enter tag={0,485}  | PWD (6) | args:   , 0 0 (port #Port<0.489>)
async I/O worker tag={0,485} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,485} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,485}  | PWD (6) ok
efile_drv enter tag={0,486}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_internal.beam  , 0 0 (port #Port<0.490>)
async I/O worker tag={0,486} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,486} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,486} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,487}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_internal.beam  , 0 0 (port #Port<0.491>)
async I/O worker tag={0,487} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,487} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,487} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,488}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_internal.beam  , 0 0 (port #Port<0.492>)
async I/O worker tag={0,488} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,488} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,488}  | READ_FILE (15) ok
efile_drv enter tag={0,489}  | PWD (6) | args:   , 0 0 (port #Port<0.493>)
async I/O worker tag={0,489} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,489} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,489}  | PWD (6) ok
efile_drv enter tag={0,490}  | OPEN (1) | args: /tmp/spam  , 6 0 (port #Port<0.494>)
async I/O worker tag={0,490} | OPEN (1) | efile_drv-int_entry
async I/O worker tag={0,490} | OPEN (1) | efile_drv-int_return
efile_drv return tag={0,490}  | OPEN (1) ok
efile_drv enter tag={0,491}  | PWD (6) | args:   , 0 0 (port #Port<0.495>)
async I/O worker tag={0,491} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,491} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,491}  | PWD (6) ok
efile_drv enter tag={0,492}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./io_lib_pretty.beam  , 0 0 (port #Port<0.496>)
async I/O worker tag={0,492} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,492} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,492} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,493}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/io_lib_pretty.beam  , 0 0 (port #Port<0.497>)
async I/O worker tag={0,493} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,493} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,493} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,494}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/io_lib_pretty.beam  , 0 0 (port #Port<0.498>)
async I/O worker tag={0,494} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,494} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,494}  | READ_FILE (15) ok
efile_drv enter tag={0,495}  | PWD (6) | args:   , 0 0 (port #Port<0.499>)
async I/O worker tag={0,495} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,495} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,495}  | PWD (6) ok
efile_drv enter tag={0,496}  | PWD (6) | args:   , 0 0 (port #Port<0.500>)
async I/O worker tag={0,496} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,496} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,496}  | PWD (6) ok
efile_drv enter tag={0,497}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./erl_bits.beam  , 0 0 (port #Port<0.501>)
async I/O worker tag={0,497} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,497} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,497} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,498}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/erl_bits.beam  , 0 0 (port #Port<0.502>)
async I/O worker tag={0,498} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,498} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,498} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,499}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/erl_bits.beam  , 0 0 (port #Port<0.503>)
async I/O worker tag={0,499} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,499} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,499}  | READ_FILE (15) ok
efile_drv enter tag={0,500}  | PWD (6) | args:   , 0 0 (port #Port<0.504>)
async I/O worker tag={0,500} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,500} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,500}  | PWD (6) ok
efile_drv enter tag={0,501}  | PWD (6) | args:   , 0 0 (port #Port<0.505>)
async I/O worker tag={0,501} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,501} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,501}  | PWD (6) ok
efile_drv enter tag={0,502}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/runtime_tools-1.8.7/examples/./eval_bits.beam  , 0 0 (port #Port<0.506>)
async I/O worker tag={0,502} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,502} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,502} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,503}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/kernel-2.15.1/ebin/eval_bits.beam  , 0 0 (port #Port<0.507>)
async I/O worker tag={0,503} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,503} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,503} user tag  | READ_FILE (15) | errno 2
efile_drv enter tag={0,504}  | READ_FILE (15) | args: /opt/local/erlang/maint/lib/erlang/lib/stdlib-1.18.1/ebin/eval_bits.beam  , 0 0 (port #Port<0.508>)
async I/O worker tag={0,504} | READ_FILE (15) | efile_drv-int_entry
async I/O worker tag={0,504} | READ_FILE (15) | efile_drv-int_return
efile_drv return tag={0,504}  | READ_FILE (15) ok
efile_drv enter tag={0,505}  | PWD (6) | args:   , 0 0 (port #Port<0.509>)
async I/O worker tag={0,505} | PWD (6) | efile_drv-int_entry
async I/O worker tag={0,505} | PWD (6) | efile_drv-int_return
efile_drv return tag={0,505}  | PWD (6) ok
efile_drv enter tag={0,506}  | WRITE (4) | args:   , 14 6 (port #Port<0.494>)
async I/O worker tag={0,506} | WRITE (4) | efile_drv-int_entry
async I/O worker tag={0,506} | WRITE (4) | efile_drv-int_return
efile_drv return tag={0,506}  | WRITE (4) ok

なんとなくわかる気にはなりますが ... 正直わかりません。

感想

DTrace は仕事Solaris 触ってるときに使おうかなー使おうかなーとおもって結局使いませんでした。そして気付いたら仕事Linux メインになっていたので触る機会なし。ただ Erlang VM が DTrace(SystemTap) に対応したので、ドキドキワクワクしながら使ってみました。

良くわからないけど覚えたら凄く便利そう、というのが正直な感想です。

DTrace は OracleSystemTap は RH が中心になって開発しているっぽいので、当面はゴリゴリ開発されるのだと思います

Erlang の DTrace は 2008 年頃に一瞬出てきてしぼんでいたのを Basho のメンバーが復活させて最後には otp にまで突っ込むという素敵な方針に。

R15B01 が出たら標準で使えるようになる事もあり、今後は積極的に使っていこうと思います

Erlangアプリを書いている以上、I/O 周りとの戦いは終わることはありません。今回がいいきっかけになったと思っております

参考

広告

2012-03-28

Erlang + SPDY + TLS NPN が Firefix 11 で動いた

まったりと SPDY を追っかけたりしてます、今更かよ、遅いよとか禁止。

Chrome では既に動いていましたが、Firefox11 から有効に出来る様になりましたね。

Jetty対応したり、Netty が対応したり(Twitterパッチを送ったそうですね)とちょっとワクワクしています、流行らないで終わるかも知れませんが ... 。

結果

Firefox 11 + erlang-spdy + erlang/otp 'pu' ブランチで無事動きました。

f:id:Voluntas:20120328005522p:image

緑色の稲妻は SPDY で通信しているかどうかを確認する Firefox Add-On です。

経緯とかやったこととか

Google が出してる SPDY と TLS NPN の IETF draft をざっくり読んで何となく把握。

で、やっぱり動かしたいなぁと。

ただ TLS NPN は TLS 拡張なので TLS を色々いじらないと行けないのでやっかいなんですよね。

Erlang/OTP の 'pu' ブランチに NPN の実装が入っていたりしたのでそれをビルドしたりして動かしてみました。

RJ が前に書いた erlang-spdy というデモサーバを動かしてみました。普通の SPDY はデモ用で実際は使われないと思ったので HTTPS + SPDY やりたかったんですよね。

TLS NPN も無事動いて HTTPS 上の SPDY が動作しました。これを mochiweb に統合したりしたら楽しいだろうなぁと思ったりしています

そのうち SPDY について自分が理解したことをまとめたいと思っています

参考資料

2012-03-24

Erlang + UUID ライブラリを触ってみる

RFC 4122 で定義されている UUID を Erlang から使うにはどうやるのかなと思って調べてみました。

詳細は参考に書いた "UUID と Perl について" という記事が素晴らしいので、それを読んで下さい。

Erlang の NIF バインディングはこれ、rebar の設定が古いので後で pull-request かな。

使ってみる

なにやらバージョンが 5 つあるようです。

version 2 以外全てに対応しているようです、というか普通そうなのかな。

Version 1

> ossp_uuid:make(v1, binary).
<<70,47,19,80,117,181,17,225,140,150,88,85,202,250,121,45>>

Version 3

> ossp_uuid:make(v3, binary, "ns:URL", "http://example.com").
<<214,50,181,12,121,19,49,55,174,154,45,147,245,110,112,213>>

Version 4

> ossp_uuid:make(v4, binary).                                
<<219,96,70,1,157,163,74,19,149,208,197,55,50,210,184,125>>

Version 5

> ossp_uuid:make(v5, binary, "ns:URL", "http://example.com").
<<140,157,220,176,128,132,90,127,169,136,16,149,171,24,181,223>>

結論

負荷試験とかやってないので何ともですが、まぁ使えるかなぁって感じですね。

参考

Mac OS X に gevent をソースコードからインストールする

gevent: A coroutine-based network library for Python http://www.gevent.org/

pip からではなくソースから入れる方法を。pip でも dev を入れられたりするのかな。

追記

  • リポジトリに libev が含まれるようになったので何もいらないとのことです thx @nobonobo
    • homebrew と libev について削除する

環境

OS
10.7.3
Python
2.7.2

インストール

cython と greenlet を入れます

$ pip install cython greenlet

gevent リポジトリのミラーが github にあるのでそこから入れます

https://github.com/schmir/gevent

$ git clone git://github.com/schmir/gevent.git

build して install

$ python setup.py build

$ python setup.py install

@heavenshell 先生の確認コードをパクってみます

$ ipython
Python 2.7.2 (default, Jun 15 2011, 16:46:46) 
Type "copyright", "credits" or "license" for more information.

IPython 0.12 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.
>>> import gevent
>>> from gevent import socket
>>> urls = ['www.google.com', 'www.example.com', 'www.python.org']
>>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
>>> gevent.joinall(jobs, timeout=2)
>>> [job.value for job in jobs]
['74.125.235.178', '192.0.43.10', '82.94.164.162']

これで準備出来ました。ただ公式サイトドキュメントは 0.13 系なので、開発版とは色々違うと思うのでそこはソースを読みましょう。

参考

2012-03-22

自分の興味の範囲を再確認する

脳内を書き出して整理、技術系限定ですよ。

お仕事に関係しそうなのは省いてたりします

追記

  • 2012-04-27
    • Clojure は一旦撤退
    • OpenFlow は一旦撤退
  • 2012-04-08
    • eldap が otp に入った
    • cowboy も追いかける
    • flake/folsom を削除

Erlang

まぁ、自分がメインで使ってる言語仕事プライベートも。

バインディング系は外してます

  • rebar
  • meck
  • mochiweb
    • 一番使い慣れてるだけ、本当は cowboy も試したい
  • jiffy
  • eldap
  • webmachine
    • 使う機会がまったく無い .. が、ソースだけ読んでる
  • lager
    • こちらも使う機会が無いが ... が、ソースだけ読んでる
  • poolboy
    • 便利すぎて涙が出ます、愛用させて頂いております
  • proper
    • QC 使いたいけど、これで十分
  • cowboy
    • mochiweb だけじゃいかんので

一番良く使う言語なので、結構あるかなと思ったら意外になかった。

もともとライブラリが充実しているってのもあるのかも。

Python

ツール系とウェブアプリ系は Python で書いてる。

WSGI概念をもう少しきっちり理解しておきたい

  • Flask
    • 対したアプリを作るわけじゃ無いので Flask がメイン
  • boto
    • S3 を使うのがメインだったりする
  • bitstring
  • gevent

意外にない、Python 自体ほとんど書かないので実は無いのかも。

Django で素敵なウェブアプリ作りたいなぁ。

サービス

その他

色々抜けてるかも知れないけど、とりあえず書き出してみた。

結構手を広げすぎてる感があるな ...