Q4Mを使う上で避けて通れないのが「q4m-forward」
これを使えば、テーブルの中身がRelayされるんだけど、内部的になにをしているのか知りたくてコードを読んでみました。
(q4m-forwardはPerlで書かれているんだけど、Perlを普段使わないので、言語自体も調べつつのメモです)
q4m-forwardの構成
構成自体は非常にシンプル。大まかに書くとこんな感じ。
// -- モジュール読み込み -- // use DBI; //DB用 use Getopt::Long; //コマンドラインのオプション用 // -- サブルーチン -- // sub usage{} //使い方 sub connect_to_db{} //DB接続 // -- main処理 -- // // コマンドライン引数からDBへ接続 while(1){ // 転送元を待つ // 転送元からレコードを取り出す // 転送先にレコードを書き込む }
main処理について
サブルーチンはシンプルなので保留にして、main処理をまとめます。
コマンドライン引数からDBへ接続
my ($src, $dst) = @ARGV; my ($src_conn, $src_table) = connect_to_db($src); my ($dst_conn, $dst_table) = connect_to_db($dst); my $mode = $do_reset ? 'w' : 'a';
ここでは、コマンドライン引数(@ARGV)から、転送元DB($src)、転送先DB($dst)への接続設定をしています。
また、do_resetオプションの判定もしています。$modo変数によってあとの処理が変わります。
このあと、無限ループに入ります。
転送元を待つ
# wait until a row gets ready my $wait = $src_conn->selectall_arrayref( 'select queue_wait(?)', {}, $src_table, ) or die $src_conn->errstr; die "received an error from source (table not found?)\n" unless defined $wait->[0][0]; next unless $wait->[0][0];
ここでは、$src_conn->selectall_arrayrefによって$src_tableからqueueを取得します。
オープンに失敗したらdie。
取得した結果は、{}と指定しているようにハッシュで取得します。
$waitがハッシュとなるのですが、$wait[0][0]が未定義だったらdie。空じゃなければ次のループです。
転送元からレコードを取り出す
# receive row my $rowid = $src_conn->selectall_arrayref('select queue_rowid()') or die $src_conn->errstr; die "unexpected response from source\n" unless $rowid->[0][0]; my $row = $src_conn->selectall_arrayref( "select * from $src_table", { Slice => {} }, ) or die $src_conn->errstr;
$src_conn->selectall_arrayref("select * from $src_table",{ Slice => {} },)で$rowに転送元からレコードを取り出してます。
その前の、select queue_rowid()についてはちょっと勉強不足で不明。
ちなみにqueue_rowid()は、ownerモードのときにだけ動きます。
転送先にレコードを書き込む
# write row my $res = $dst_conn->selectall_arrayref( "select queue_set_srcid(?,?,?)", {}, $sender_index, $mode, $rowid->[0][0], ) or die $dst_conn->errstr; die "failed to set source id (sender index out of range?)\n" unless $res->[0][0]; $mode = 'a'; $dst_conn->do( "insert into $dst_table (" . join(',', sort keys %{$row->[0]}) . ') values (' . join( ',', map { $dst_conn->quote($row->[0]{$_}) } sort keys %{$row->[0]}, ) . ')', ) or die $dst_conn->errstr;
joinは、指定文字で配列を結合して文字列で返しています。
sort 関数は、keys 関数が任意にリスト化したキーの順番を、文字コード順で並び替えます。
mapは、引数同士で評価して一致したものを返しています。
insert into できるように正しく並べ替えていると言った感じでしょうか。
このあとwhile(1)のループに戻ります。