今回のエントリは、「4.3 未知のオブジェクトとDRbUnknown」です。前回のエントリでは4章全体のまとめも合わせて一つのエントリにすると言いましたが、(あわせると長くなりそうなので)やっぱり分けることにしました。
はい、ではDRbUnknownって何なんでしょう、何のためにあるのでしょう。本を読みます。
DRbUnknownとは知らないクラスをMarshal.loadしてしまったときの例外を捉え、ロードできなかったオブジェクトの代わりにロードされるオブジェクトです。 DRbUnknownはロードに失敗した原因を、二つ保持しています。一つはロードに失敗したバッファ、もう一つは定義が不明なクラス名/モジュール名です。
それぞれ次のメソッドで問い合わせることができます。
- DRbUnknown#buf
- Marshal.loadに失敗した直列化されたオブジェクトのバッファ。
- DRbUnknown#name
- 例外のメッセージから調べた、未知のクラス/モジュール名。
- DRbUnknown#reload
- もう一度Marshal.loadしてみる。
4.3 未知のオブジェクトとDRbUnknown
メモメモ。続きも読んでみます。
dRubyのライブラリは知らないクラスを受けとってしまっても、そのバッファを包んだ DRbUnknownオブジェクトを自動的に生成します。 DRbUnknownに対して元のオブジェクトのつもりでメソッドを呼ぶことはできませんが、DRbUnknownを回送することはできます。
4.3 未知のオブジェクトとDRbUnknown
ほうほうです。Marshalを使うと、マーシャルデータからオブジェクトを復元するとき(Marshal.loadするとき)に、そのオブジェクトの型を知っていないと復元できないみたいです。dRubyではオブジェクトを渡すときにMarshalの仕組みを利用していますので、この挙動から影響を受けるんですね。
DRbUnknownの中身をちょっとだけ見てみます。小さなクラスなので見やすいです。まずは_dumpメソッドから。
def _dump(lv) # :nodoc: @buf end
_dumpはMarshalでのdump時に呼ばれるメソッドであることは前回のエントリで勉強しました。なので、DRbUnknownが別プロセスに渡されるときには、DRbUnknownが包んでいる元々のマーシャルデータが渡されます。で、受け取ったプロセスで復元できたらそれでよし、復元できなければそこでもDRbUnknownになります。ってことですね。
ちなみに、@nameを設定している部分はここです。
def initialize(err, buf) case err.to_s when /uninitialized constant (\S+)/ @name = $1 when /undefined class\/module (\S+)/ @name = $1 else @name = nil end @buf = buf end
例外の文字列から名前を取っているみたいです。$1ってのは、正規表現にマッチした最初の文字列が入ってる組み込み変数です。@nameがnilになることもあるのか。elseに入るのはどういうときなのかなあ、名前すらわからないエラーのときですよねきっと。多分marchal.cの
static VALUE r_object0(arg, proc, ivp, extmod) struct load_arg *arg; VALUE proc; int *ivp; VALUE extmod; { ・・・
のメソッドあたりで投げられている例外の大半が該当するのだと思います。実際にDRbUnknownが捕捉している例外の文字列はvariable.cから出るやつのようです。中身はややこしそうなので追わないことにしました。このくらいにして本を読み進めます。
DRbUnknownの機構によって、クラス定義を知らないオブジェクトを(メソッド呼び出しはできないが)保持しておくことが可能になります。
プロセス間でオブジェクトを交換するためのQueueを考えてみましょう。中継するQueueのサービスがpushされる可能性のある全てのクラス定義を事前に知らなくてはならないのは、難しいことがあります。 DRbUnknownはこういった局面で特に有用な機能です。
4.3 未知のオブジェクトとDRbUnknown
本に書かれていることはよくわかります。プロセス間通信を行う上では、サービス側が全てのオブジェクトの型を知っておくことは非現実的であったり面倒であったりすることが多いです。なので、dRubyでは、マーシャルデータからオブジェクトを復元することが出来なくても、それを保持できる仕組みを提供しています。それがDRbUnknownです。
ちょっとかなり端折り気味ですが、以下にまとめを書いてDRbUnknownは終わりにします。一度は本の内容にそって実験してみて下さいね。
DRbUnknownのまとめ
つまりdRubyでのプロセス間通信時には、気にせずそのままホイホイ渡せばいい
次回こそ、4章を終わりにします。