« 2章.Hello, dRuby (その3) | メイン | [番外]今までの整理 »

2章.Hello, dRuby (その4)

本の続きに戻ります。サーバを停止させた状態でリモート呼び出しをしたらどうなるか実験してみます。puts00のサーバーを停止してthere.putsを実行っと。

DRb::DRbConnErrorという例外が発生しました。 DRbConnErrorはdRuby内部で通信エラーが発生したことを示します。サーバが停止してしまったので、メソッド呼出しに失敗してしまったのです。

2.1.2. irbからの利用

確かに本の通りにDRbConnErrorがでました。

def initialize(remote_uri)   # :nodoc:
  @uri = remote_uri
  @protocol = DRbProtocol.open(remote_uri, DRb.config)
end

場所はここ、DRbConnのインスタンス生成時のDRbProtocol.open。このメソッドは

def open(uri, config, first=true) 
  @protocol.each do |prot|
    begin
      return prot.open(uri, config)
    rescue DRbBadScheme
    rescue DRbConnError
      raise($!)
    rescue
      raise(DRbConnError, "#{uri} - #{$!.inspect}")
    end
  end
  ・・・

 です。このprot.openでは、実際にはDRbTCPSocketのクラスメソッドopenが呼ばれるので、この中のTCPSocket.openで例外が発生している感じですね。それをrescueでつかまえてraiseしてるのか。ふむふむ。ではopenは成功したけどその後に通信エラーになった場合はどうなるのかなあ。DbConnのopenの中身の一部です。

  ・・・
@pool.each do |c|
   if conn.nil? and c.uri == remote_uri
     conn = c if c.alive?
   else
     new_pool.push c
   end
end
@pool = new_pool
  ・・・

 プールから取る時の、「conn = c if c.alive?」で、この時点でサーバー側が死んでいたらそれを使わないようになっています。で、もしここでも接続は生きてたけど、送信までに死んだ場合は、recv_replyのどこかで例外が出るようです。
 ここでは、@poolの要素群をnew_poolという入れ物に一度移し替えて、それを@poolに戻しています。ただ今回使われることになった接続オブジェクトは、この時点ではnew_poolに入っていません。プールに接続オブジェクトを入れているのは、その下に記載されているのensureです。(ensureってのは、javaでいうfinallyみたいなやつです。)

@pool.unshift(conn)
@pool.pop.close while @pool.size > POOL_SIZE

 新しいconnをプール用配列の先頭に入れ、プールの要素数の上限を越えた要素は取り除いて閉じる。ってことか。whileも右側に書けるのですね。かっこいいコードだなあ。

 
 ところで、サーバーは無事生きているけど、リモートオブジェクトに存在しない操作を行なった場合はどうなるのでしょうか。ここではhogeメソッド(Putsに存在しない操作)を呼んでみました。

there.hoge

すると以下のようなresultになりました。ちなみに、成功/失敗が設定されるsuccの値はfalseになっています。

result undefined method `hoge' for #<Puts:0x29ba790 @stream=#<IO:0x294e758>>

トラックバック

このエントリーのトラックバックURL:
http://www.grandnature.net/bin/mt-tb.cgi/57

コメントを投稿

About

2007年09月10日 14:44に投稿されたエントリーのページです。

ひとつ前の投稿は「2章.Hello, dRuby (その3)」です。

次の投稿は「[番外]今までの整理」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。