ximapdのHyper Estraier対応について
Rastといえば、ximapdをHyper Estraier対応にする実験もやられているみたいだな。実用段階までいくかどうかはわからないけど、コスモポリタニズムというか、ルネサンス的というか、そういうノリは大好きだ。
でも所詮は「比較対象」として、つまり引きたて役の扱いなんだよなぁ。ぶっちゃけ何がいけないんだろう。Hyper Estraierのコンセプトが適合していないのか、設計や実装に気に入らない点があるのか、どこの馬の骨ともわからぬ奴が作っているから信用ならないのか、その全部なのか。ダメ出ししてくれる人ってなかなかいないからわからないんだよなぁ。
[開発メモより引用]
(コメントを入れようと思ったら対応する記事がないというエラーになってしまったので、ここで。)
ximapdのMLで「比較対象くらいには」と書い(てしまっ)たのはHyper Estraierに何か問題があるとかそういうことではなくて、私自身の都合(能力、時間、その他)によってどこまで実装を進められるか分からないのでというような意味合いでした。私自身は、うまく実装が進められたらちゃんと使ってみようと思いつつコードを書いています。もしも気を悪くされたようならごめんなさい。
ximapd + Hyper Estraier
Hyper EstraierのRubyバインディング(SWIGのほう)を使って(少し手を加えて)、ximapdのバックエンドとしてHyper Estraierを使うというのをやってみた。
tests/runner.rbの実行時間がけっこう違うのだけど、こんなものだろうか。何かすっとばしていないかドキドキする。ただ、まあ、精度に関するデフォルトの設定が違っていそうな感じなので、そのあたりが効いてきているのかもなとも思う。パラメータをいじってみたりしたほうが良さそうかな。
ximapdのデータをチェックする 1
いろいろいじっているとおかしなことになることもあるので簡易チェックをするスクリプトを書いてみた。
一つめはMLメールボックスの内部的なリストと現存するMLメールボックスの比較をするもの:
#!/usr/bin/ruby
require 'yaml'
o = YAML.load(open("ximapd/mailbox.db", "r") {|i| i.read})
ml = o["mailing-lists"]
mb = o["mailboxes"]
puts "not listed in mailboxes:"
ml.each_key {|n|
eq = "x-ml-name = \"#{n.gsub(/[\\"]/n, "\\\\\\&")}\""
unless mb.detect {|k, i| i["query"] == eq}
puts " #{n}"
end
}
puts "not listed in mailing-lists:"
mb.each_pair {|n, i|
if i["query"] && /\Ax-ml-name = "(.*)"$/ =~ i["query"]
k = $1.gsub(/\\(.)/, "\\1")
puts " #{n}" unless ml.key?(k)
end
}
二つめはML宛のメールと判定されたメールのうち、現存するMLメールボックスでは参照できないメールの数と、それらを救い出すクエリーを出力するもの:
#!/usr/bin/ruby
require 'rast'
require 'yaml'
o = YAML.load(open("ximapd/mailbox.db", "r") {|i| i.read})
ml = o["mailing-lists"]
mb = o["mailboxes"]
test_query = ["x-ml-name > \"\""]
mb.each_pair {|n, i|
if i["query"] && /\Ax-ml-name = "(.*)"$/ =~ i["query"]
test_query << i["query"]
end
}
test_query = test_query.join(' ! ')
db = Rast::DB.open("ximapd/index", Rast::DB::RDONLY)
opt = {
"properties" => ["x-ml-name"],
}
tr = db.search(test_query, opt)
s = {}
query = []
tr.items.each {|i|
unless s.include?(i.properties[0])
query << "x-ml-name = \"%s\""%i.properties[0].gsub(/[\\"]/n, "\\\\\\&")
s[i.properties[0]] = 0
end
s[i.properties[0]] += 1
}
summary = ''
s.keys.sort {|a, b| s[b] <=> s[a]}.each {|k|
summary << sprintf("%60s : %3d\n", k, s[k])
}
query = query.join(' | ')
r = db.search(query, opt)
print <<E
query = #{query}
hit count = #{r.hit_count}
\#test query = #{test_query}
\#hit count = #{tr.hit_count}
summary:
#{summary}
E
二つめのスクリプトでひっかかるのは何もいじっていておかしくなった時だけではなくて、空ではないMLメールボックスを削除すればひっかかるようになる(はず)。もちろんqueryメールボックスで普通に救い出せるから、それがすぐに問題になるわけではない。もしも問題があるとしたらMLの検索キーを変更する方法がないことだろうが、しかし、これはどうしたものか。
メールボックスを削除したんだからメールも削除してしまえ、という考え方もあるかもしれないが、他のqueryメールボックスで参照している場合なんかには困ったことになる。
MLメールボックス削除→各メールのML検索キーを削除というのが分かりやすそうだが、そうするとINBOXにどばっとメールが入ってしまうことになるし、やっぱりもう一度MLのメールを集めたいとなったときに困る(かもしれない)。「INBOXにどば」はしょうがないにしても、検索キーを削除するだけでなくて付加したり変更したりする方法も合わせて必要になりそうな気がする。
ふむ、MLメールボックスを削除したときには検索キーをいじらず、その代わりに「その他のML」メールボックスのようなのがあると良かったりするのかな? それでもってML検索キーをいじる方法 = MLメールボックスに入れる方法があればさらに良さそう。たとえば、MLメールボックスにコピーしたり、あるいはMLメールボックスから削除したりするタイミングでML検索キーの付加または削除をするとか。
ximapdを試す(6)
いったんあるフォルダにインポートしておいて、その後で外部プログラム(具体的にはbsfilter)でINBOXに移すというのをやりたかったので、インポート先のフォルダを指定できるようにしてみた。
あとSSLサーバになれるコードも追加してみた。ただし機能としては最低限、とりあえず動くという程度。クライアント認証ほか、各種パラメータの指定ができるようにしないとならないと思う。今はコマンドラインオプションで指定するようにしているのだけど、設定ファイルで指定するようにすべきなのかもしれない。
というわけで、あんまりテストしていないコード→ximapd-20050501.diff (今までの差分も込みなのがアレだが)
ximapdを試す(4)
昨日のパッチには少しまずいところがあったので修正→ximapd-20050430.diff
前のとの違いは、タイムゾーンの表示のやり方を直した(%Z→%z)のと、フォルダをひといきになめてからindex更新というやり方だと更新している間にIMAP接続が切れてしまうことがあるのでちびちび取ってきては更新という形にした。
あと進行状況をいいかげんに表示させるようにもした。でもこれは動いているかどうかの確認程度。ただ、その表示によると更新のための時間が序々に長くなってきていて(バラつきがあるだけかもしれないけど)、ざっと5,000通を終えたあたりでは1通に0.4秒くらいかかっているようだ。
それからSEGVの件。これは最初の一回きりで、rm -rf ~/ximapd/したりもしているのだけど再現できていない。
ximapdを試す(5)
IMAPサーバからのインポートだが、だいぶ時間がかかりそうなのでしばらく放っておいたところ、SEGVではなくTMailのエラーで落っこちていた。
parser.y:366:in `scan': unterminated quoted-word (SyntaxError)
よく考えるとINTERNALDATEだけでなくENVELOPE情報をIMAPサーバから得るようにしたほうが良いかもしれない。が、それはそれとして、この現象って通常時(.forward経由のとき)にも起き得るってことかなあ。
追記(2005-05-01): SyntaxError問題については単にrescueにSyntaxErrorを追加指定してやれば良さそう。IMAPサーバからあらゆる情報を取り出して〜という話は、ximapdがテキストパートについてのインデックスを作っている関係で、メッセージ全体とパートとをそれぞれ取り出さねばならず、サーバへのアクセスを増やすことになりそうな気がしてきたのでヤメ。
ximapdを試す
0.0.0がリリースされたことだしximapdを試そうと思いたつ。
えーとrastが必要なのか。debがないかなーと検索するとtachさんとこがひっかかる。ありがたく使わせてもらう。あとはそろってるなというわけでsvn co(この時点で0.0.0とか関係ないんだが :-)。
ドキュメントを読む…… ふむ。何はともあれインポートしないと試せませんな。と思ったんだけど、既存のIMAP環境から直接にはインポートできないのね。ふうむ。と、うなっててもしょうがないので少しコードを書いて今あるサーバからINBOXだけインポートしてみる。
おー動いた動いた。テストテスト。net/imap.rbを使って…… ありゃ、examineだとエラーになっちゃうな。selectなら問題なし。selectできるんならいいか。でも一応報告しとこう。
次はMail.appでと…… ありゃ、ささる。デバッグモードで動かすとどうやらINTERNALDATEのFETCHができないのね。構造がよくわかんないんだけど少しコードをいじって足して…… おー、動いた動いた。
しかし、これ、ずいぶん重いなあ。ロードが2とか普通にいく。あ、librast-ruby1.8_0.0.1-0.1ってことはrastがちょっと古いのかな。最新は0.1.0か。新しくして後でもう一度試してみよう。
というわけでこれまでに書いたコード→ximapd-20050429.diff


