Hatena::ブログ(Diary)

Yet Another Hackadelic

2007-09-15 Shibuya.JS行けなかった組

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を使うようです。具体的には後で書く。

2007-09-12 全ての回答はコードを書く事で

mogadmコマンドが多機能になってた件

全然気づかなかったんだけど、MogileFS-Utils-2.12にて下記の機能がいつの間にやら使えるようになっていました。w

stas
MogileFSの状態表示
slave
Slaveデータベースの管理
fsck
File systemの監視workerの管理
settings
動的な設定値管理

それとdeviceにmodifyコマンドが付きました。

2.08くらいから状況が変わってたみたいですね。

そのうち調べること

  • fsck workerのまとめ、一度読んだけど忘れた
  • slaveの使い方と何がウマーか

ちなみにsettingsは便利

$ mogadm settings memcache_servers 127.0.0.1:11211

みたいにして設定出来ます。

設定できそうな値はMogileFS::Config辺りを漁ると、いいかもしれない。

2007-08-20 ねれねーよ

Software Design 9月号でMogileFSの記事を書きました

3回連続でMogileFSについて記事を書きます。

今回はその第1回目でShibuya.pmのテクニカルトークで話した内容を現在の状況に合わせた形で収録しています。

基本的な内容を誰でも出来る位の形で書いたので、まだMogileFS使った事無いって人は本誌を是非購入して、読んで試してみて下さい。

以上、宣伝終わり。

そして現在第2回目の記事の執筆ラストスパート。。。

追記

- × Softwere

- ○ Software

orz...

2007-07-13

指定したdomainのファイルを全て消す

こんな感じかなー。

#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Long;
use MogileFS::Client;

my ($domain, $host);

GetOptions(
        "domain=s" => \$domain,
        "host=s@" => \$host
);

die("host or domain is not valid") unless ($domain && $host);

my $mogc = MogileFS::Client->new(domain => $domain, hosts => $host);

for (my ($after, $list) = $mogc->list_keys("", "", 10); ($list && @$list > 0); ($after, $list) = $mogc->list_keys("", "", 10)) {
        for my $key (@$list) {
                print $key, "\n";
                $mogc->delete($key);
        }
}

list_keysはdefaultが1000件と言うlimitが付いてる*1ので、ここではとりあえず10件ずつ取得する感じ。

mogadmでdomainごと消しても良さそう。

そういえばやった事ないです。うそ、やった事あったw

今試したけど、ファイルがあるとdomainは消せません。

2007-06-26 ウェディングドレス

MogileFS::Plugin::FilePaths, MogileFS::Client::FilePathsを試してみる

はじめに

MogileFS::Client::FilePathsのドキュメントですが、激しく適当に書かれているのと、使い方だとかセットアップの仕方とかは笑えるくらい情報が無いので、ソース嫁しか手段が無い事を予めお断りしておきます。

FilePathsプラグインとは?

MogileFSでは実際のファイルシステムのようにパスが存在する訳では無く、実態としては

  • domain
  • key

によって管理されています。

特定のdomainに存在するファイルの探索はlist_keysメソッドで探すと言う手法しかデフォルトではありません。

で、MogileFSのサーバー側のプラグインとして、FilePathsプラグインと言う物がありますが、こちらを有効にしておくと実際のファイルシステムのようにパスと言う概念を持ち込む事が出来るようになります。

インストール

mogdbsetupコマンドを実行する際にpluginsオプションを付けて実行します。

$ mogdbsetup --plugins FilePaths

ユーザー名とかデータベース名はデフォルトのままだとして、mogilefsデータベースにmysqlコマンドでログインして、

mysql> SHOW TABLES LIKE 'plugin_%';
+-------------------------------+
| Tables_in_mogilefs (plugin_%) |
+-------------------------------+
| plugin_filepaths_domains      | 
| plugin_filepaths_paths        | 
| plugin_metadata_data          | 
| plugin_metadata_names         | 
+-------------------------------+
4 rows in set (0.00 sec)

とするとplugin用のテーブルが生成されているのが分かります。

mysql> desc plugin_filepaths_domains;
+-------+----------------------+------+-----+---------+-------+
| Field | Type                 | Null | Key | Default | Extra |
+-------+----------------------+------+-----+---------+-------+
| dmid  | smallint(5) unsigned | NO   | PRI |         |       | 
+-------+----------------------+------+-----+---------+-------+
1 row in set (0.00 sec)

このテーブルですが、FilePathsが有効なdomain一覧を管理するテーブルになっているようです。

手動で有効にしたいdomainのdmidを突っ込みましょう。

mysql> SELECT * FROM domain;
+------+------------+
| dmid | namespace  |
+------+------------+
|    1 | testdomain | 
+------+------------+
1 row in set (0.01 sec)

と言う状態なので、

mysql> INSERT INTO plugin_filepaths_domains(dmid) VALUES(1);
Query OK, 1 row affected (0.00 sec)

として設定しておきます。

これで多分完了です。(ぇ

MogileFS::Client::FilePathsを使ってFilePathsを実感してみる

普通のClientでは何も起きません。あしからず。

MogileFS::Client::FilePathsを使って、対応しているdomainにアクセスする時のみ有効になります。

/home/zigorou/fizzbuzz.plをMogileFS上のパスで/mogdata/zigorou/fizzbuzz.plとしてデータをstoreする例です。

#!/usr/bin/perl

use strict;
use warnings;

use MogileFS::Client::FilePaths;

my $mogc = MogileFS::Client::FilePaths->new(
             host => [qw/127.0.0.1:7001/],
             domain => q|testdomain|
           );

$mogc->store_file('/mogdata/zigorou/fizzbuzz.pl', 'testclass', '/home/zigorou/fizzbuzz.pl');

次に、/mogdata/zigorouをリストアップしてみる例です。

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dump qw(dump);
use MogileFS::Client::FilePaths;

my $mogc = MogileFS::Client::FilePaths->new(
             host => [qw/127.0.0.1:7001/],
             domain => q|testdomain|
           );

print dump($mogc->list("/mogdata/zigorou"));

とすれば、

{ is_file => 1, name => "fizzbazz.pl", path => "/mogdata/zigorou/fizzbuzz.pl", size => 256 }

のように返って来ます。

雑感

  • Serverはpluginによる拡張が可能
  • Client側の機能拡張もplugin化しないと使い勝手が悪すぎる
  • Pathのように扱う事は不可能じゃないけど、domainを極力分ける事が肝要

特に最後のdomainを細かく分ける利点は、

mysql> SHOW CREATE TABLE file\G
*************************** 1. row ***************************
       Table: file
Create Table: CREATE TABLE `file` (
  `fid` int(10) unsigned NOT NULL,
  `dmid` smallint(5) unsigned NOT NULL,
  `dkey` varchar(255) default NULL,
  `length` int(10) unsigned default NULL,
  `classid` tinyint(3) unsigned NOT NULL,
  `devcount` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY  (`fid`),
  UNIQUE KEY `dkey` (`dmid`,`dkey`),
  KEY `devcount` (`dmid`,`classid`,`devcount`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

UNIQUE制約としてdmid, dkeyの組み合わせを持って来てるので、予めdmidで絞り込めればSELECTが速くなるからです。

PerlbalのPluginはMFさんが有名ですけど、MogileFS自体も拡張出来るんだぜーって話でした。

ここら辺ですかね。