Amon2の流れを掴む - 3
前回の続きから。
script/sample-server
unless (caller) { ... }
unlessの条件として caller が呼ばれています。
callerはperlの組み込み関数の1つで、サブルーチンの呼び出し元情報を取得出来ます。
詳しくはここを参照です。
ログを取る時とかに便利です。
で、今回の場合は呼び出しているのがサブルーチンの中ではないので、undefを返します。
つまり、 「外部から呼ばれた場合はブロック内を無視する」という意味です。
unlessはifの条件を反転したものなので、偽ならばブロック内を処理します。
my $port = 5000; my $host = '127.0.0.1'; my $max_workers = 4;
まず始めに、 port番号・ホスト名・プリフォークするプロセス数 を定義しています。
これがデフォルト値ですね。
require Getopt::Long;
Getopt::Long は、コマンドラインオプションを解析して良い感じに引数を取ってきてくれるモジュールです。
require Plack::Loader;
Plack::Loader は、指定したオプションに基づいた Plack::Hander のインスタンスを得られます。
Plack::Handler は、psgiアプリケーション
とWebサーバ
を結びつけるアダプターの役割を持ちます。
my $p = Getopt::Long::Parser->new( config => [qw(posix_default no_ignore_case auto_help)] );
ここではGetopt::Long
のオプション指定をしています。
詳しくはこちらを参照のこと。
簡単に説明すると以下のような感じ。
オプション | 意味 |
---|---|
posix_default | 色々余計な機能をOFFにしてくれる。 |
no_ignore_case | オプションの大文字小文字を区別する。 |
auto_help | 自動で--help が使えるようになる。pod2usage を呼んでくれる。 |
$p->getoptions( 'p|port=i' => \$port, 'host=s' => \$host, 'max-workers=i' => \$max_workers, 'version!' => \my $version, 'c|config=s' => \my $config_file, );
早速オプションの指定と、引数の指定を行っています。
順番に見て行くと、p|port=i
は -p
と --port
をオプションに指定している。そして i
は数値を引数とすることを表している。その引数を $port
に格納する、という感じです。
2つ目は --host
をオプションとして、s
は文字列を引数に指定しています。
3つ目も同様。
4つ目の !
は否定を表すオプションを定義している。この場合、 --noversion
と指定してやれば、 $version
を0に出来ます。(でも、ここのオプション指定の意義がよく分からない。。。)
5つ目も同じようなことをやっています。
if ($config_file) { my $config = do $config_file; Carp::croak("$config_file: $@") if $@; Carp::croak("$config_file: $!") unless defined $config; unless ( ref($config) eq 'HASH' ) { Carp::croak("$config_file does not return HashRef."); } no warnings 'redefine'; no warnings 'once'; *sample::load_config = sub { $config } }
このブロック内はオプション -c
または --config
にファイル名を指定すると実行されます。
ここで言うコンフィグファイルは、sample/config/
以下にある development.pl
等が対象となっています。
ではブロック内の処理を見て行きましょう。
my $config = do $config_file;
do
は指定したファイル名のファイルをperlスクリプトとして実行します。戻り値はそのスクリプトで最後に評価された値です。
ですので、$config
には sample/config/
以下のファイルを見るに、 各種設定を表すハッシュリファレンス が入ることが想定されているようです。
Carp::croak("$config_file: $@") if $@;
Carp::croak は die とほぼ同じ意味です。ただし、die
は「dieが実行された位置番号」を知らせるのに対し、croak
は「呼び出し元の位置情報」を知らせてくれます。
また、ここで出てきている $@
は、do
がコンパイルに失敗した時にエラーメッセージを格納する特殊変数です。成功なら undef
が返ってきます。
(ここでcroak使う理由ってなんだろう? このスクリプト自体さっきの caller
云々で外部から呼び出せないはずだし。。。)
Carp::croak("$config_file: $!") unless defined $config;
ここでは $config
が undef
の場合に、croak
が実行されます。
croakの中の $!
は、これまた do
がファイルを読み取ることが出来ない場合にエラーメッセージが入ります。こちらも成功なら undef
が返ります。
unless ( ref($config) eq 'HASH' ) { Carp::croak("$config_file does not return HashRef."); }
これはつまり、 「コンフィグファイルの戻り値はハッシュリファレンスじゃないとダメだよ」 ということです。
no warnings 'redefine'; no warnings 'once'; *sample::load_config = sub { $config }
サブルーチン名の前に *
を付けると、サブルーチンの再定義が出来ます。
その際に、use warnings
していると余計な警告が出るので、それを上の2行で抑制しています。
意味は以下のような感じです。
コード | 意味 |
---|---|
no warnings 'redefine' | 既に定義されているサブルーチンに対する上書きを警告する。 |
no warnings 'once' | 一度しか呼ばれていない変数に対して警告する。 |
print "sample: http://${host}:${port}/\n";
言わずもがな。
my $loader = Plack::Loader->load('Starlet', port => $port, host => $host, max_workers => $max_workers, );
Plack::Loader の load メソッドを呼んでいます。
第一引数にハンドラ名を指定して、後の引数にはオプションを指定しています。
return $loader->run($app);
そして最後に $loader
のrunメソッドに $app
を 渡すと、アプリケーションがPSGIサーバとアプリケーションがコネクトされ、起動します。
return $app;
最終行に書かれたこれは、おそらく外部からこのスクリプトが呼び出された場合に、 $app
を返すためでしょう。
これで plackup
でこのスクリプトファイルを指定しても起動します。
これで一先ずアプリケーションの起動部分までは把握出来ました。
次は sample/lib/
以下のPSGIアプリケーションを司るモジュール達を見て行きたいと思います。