PStore ファイルの内容を確認する方法
tDiary のプラグインを作っているときに、キャッシュデータを PStore ファイルに保存することがある。 PStore ファイルの中身はバイナリ (Marshal.dumpの結果) なので、保存されているデータの中身をエディタで見ることができない。 デバッグ時などでファイルの中身が見たい場合に、どうすればいいか考えてみた。 他にいい方法があれば、教えてください。
PStore の代わりに YAML::Store を使う
YAML::Store を使うとデータを YAML 形式で保存できるので、エディタでキャッシュの内容を確認できるようになる。 YAML をパースする分だけ PStore より速度が落ちるので、開発時だけ YAML::Store を使うというのもあり。 以下のように Store を切り替えられるようにしておくと便利かも。
case db_type when :pstore require 'pstore' @db = PStore.new("cache.pstore") when :yaml require 'yaml/store' @db = YAML::Store.new("cache.yaml") else raise ArgumentError.new("unsupported database type: #{db_type}") end
Marshal.dump はできるけど YAML ではダンプできないようなオブジェクトを格納する場合には、この方法は使えない。
PStore ファイルをダンプするスクリプトを書く
PStore の中身を開いてダンプするような、ちょっとしたスクリプト (pstoredump.rb) を書いておくと便利。
#!/usr/bin/env ruby require 'pstore' require 'pp' file = ARGV[0] db = PStore.new(file) db.transaction(true) do pp db end
このスクリプトを動かして PStore の内容をダンプする。
pstoredump.rb cache.pstore > cache.txt
irb を使って対話的に PStore データを読み書きする
irb から操作するときは、以下のようにしている。
$ irb > require 'pstore' > db = PStore.new("cache.pstore") > table = nil > db.transaction(true) { table = db.instance_variable_get("@table") } > table.keys
普通、 PStore の中身は transaction ブロックの中でしか読めない。 ブロックの中だとデータを対話的に表示できない(ブロックが閉じた時点でまとめて実行される)ので、 対話的に中身を読むにはちょっと不便。
そこで、 instance_variable_get を使ってデータの中身をローカル変数 (table) に取り出している。 こうすれば、 table 変数を使って PStore データを表示できる。
もちろん、 transaction ブロックの外なので、データの更新はできない。 データを更新したい場合は、もう一度 transaction を開いて、ローカル変数の値をセットする。
> db.transaction { db.instance_variable_set("@table", table) }
なお、読み込みと更新で transaction が2回に分かれているので、同時に他の環境から同じ PStore ファイルへアクセスされる場合にはこの方法は使えない。
参考
PStore, YAML::Store, さらに独自の Store を使う方法まで。分かりやすい。
そういえば、 PStore ではファイルサイズの上限の目安ってどれくらいなんだろう。 内部的にはファイルの中身をそのまま @table ハッシュに load しているだけなので、 DB のように値をどんどん追加していくと一気に処理が重くなる。 環境にもよるけど、 CGI で動かすなら最大でも 1MB くらいまでに収まるように設計した方がいいのかな。