日向夏特殊応援部隊

俺様向けメモ

MogileFSのplugin機構のメモ (1)

以前書いた記事、d:id:ZIGOROu:20070626:1182850060 にてMogileFS::Client::FilePathsと、この記事では思い切り書き忘れてましたけど、MogileFS::Plugin::MetaData, MogileFS::Plugin::FilePathsに関する雑多なメモです。

詳しくは来月上旬にあるShibuya.pmにてお話します。

pluginの読み込み箇所

mogilefsdを起動するとMogileFS::Serverのrunメソッドが叩かれます。この後すぐにMogileFS::Configのload_configメソッドが呼ばれます。

この中で、

my @plugins;
push @plugins, $cfgfile{plugins}    if $cfgfile{plugins};
push @plugins, @{$cmdline{plugins}} if $cmdline{plugins};

foreach my $plugin (@plugins) {
    load_plugins($plugin);
}

とあるように、コマンドライン引数としても設定ファイルmogilefsd.confのどちらでも設定がイケる事が分かります。

で、load_plugins関数なんですけど、

sub load_plugins {
    my $plugins = shift;
    foreach my $plugin (split(/\s*,\s*/, $plugins)) {
        my $rv = eval "use MogileFS::Plugin::$plugin; MogileFS::Plugin::$plugin->load; 1;";
        die "Unable to load $plugin: $@\n" unless $rv;
    }
}

となってます。

  1. configファイル、コマンド引数のどちらでもOK
  2. 設定の仕方はカンマ区切りで複数のpluginが指定可能
  3. pluginは必ずloadメソッドが呼ばれなければならない

ここでのloadメソッドってのは、普通のCPANモジュールで言うところのimportに近い物だと考えて良さそうです。

loadでやること

今度はMogileFS::Plugin::FilePathsのloadメソッドを見てみます。

MogileFS::register_global_hook( 'cmd_create_open', sub {
    my $args = shift;
    return 1 unless _check_dmid($args->{dmid});

    my $fullpath = delete $args->{key};
    my ($path, $filename) = _parse_path($fullpath);
    die "Filename is not a valid absolute path."
        unless defined($path) && length($path) && defined($filename) && length($filename);
    return 1;
});

もうすぐ分かると思いますが、hook形式になってます。

あとBradが好んで使うのが、異なるファイル名に別のpackageをガンガン宣言するので、分かりにくいのですが、ここでのMogileFSと言うpackageはMogileFS::Serverに居ます。

register_global_hookも見ておきましょう。

sub register_global_hook {
    $hooks{$_[0]} = $_[1];
    return 1;
}

と言う訳でpackage内でmy宣言された%hooksって変数に

  1. hook名
  2. callback

と言う形で保存されていきます。さらに言うと同じhook名に複数のcallbackって使えないみたいですね。余りpluggableでは無いですな。

このhook、cmd_create_openがどこで走るかと言えば、MogileFS::Worker::Queryのcmd_create_openメソッドの中です。

sub cmd_create_open {
    my MogileFS::Worker::Query $self = shift;
    my $args = shift;

    # has to be filled out for some plugins
    $args->{dmid} = $self->check_domain($args)
        or return $self->err_line('domain_not_found');

    # first, pass this to a hook to do any manipulations needed
    eval {MogileFS::run_global_hook('cmd_create_open', $args)};

evalしてるところがそうですね。

このhookの呼び出しで渡してるargsはcommandに渡された引数と同じ物です。
ちと悲しいのはworkerのインスタンスくらい渡してくれないと面白い事出来ないんじゃないかなと思いました。

で結果的にpluginで何が出来るって言われると、cmd引数を弄ったりするだけ…って事になりますねぇ。
結果的にhookを使った拡張はコマンド引数のみ操作出来るだけで、もっと大掛かりな拡張をしたい場合はregister_worker_commandを使うようです。具体的には後で書く。