0

i'm wondering how can i stop a Rinda ring server, besides killing its process.

i'v checked ring.rb shipped with my ruby 1.9.3, and found the RingServer lacks api to stop itself. It opens an UDPSocket in initialize(), but it dose not contain any code to close that socket.

anybody knows it? thanks ahead. :D

Kaiqiang
  • 47
  • 1
  • 7

1 Answers1

0

Rinda is part of Distributed Ruby (DRb), so if the goal were to just stop all Rinda and other DRb services, you could do:

DRb.stop_service

If you use that, then in your Rinda service code (the looping method), you need to rescue DRb::DRbConnError to avoid problems trying to write to the TupleSpace, according to: http://www.ruby-forum.com/topic/97023

Not a Rinda service, but here is a simple example I tested that stops a DRb service. It just uses DRb (no Rinda) in Ruby 1.9.3, modified slightly from the example here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html

server.rb

#!/usr/local/bin/ruby
require 'drb/drb'
URI="druby://localhost:8787"
class StopAndGiveTimeServer
  def get_current_time
    DRb.stop_service
    return Time.now
  end
end
FRONT_OBJECT=StopAndGiveTimeServer.new
$SAFE = 1 # disable eval() and friends
DRb.start_service(URI, FRONT_OBJECT)
DRb.thread.join

client.rb

#!/usr/local/bin/ruby
require 'drb/drb'
SERVER_URI="druby://localhost:8787"
DRb.start_service
timeserver = DRbObject.new_with_uri(SERVER_URI)
puts timeserver.get_current_time

Update: It sounds like you want to monkey patch the ring server to close the socket.

Just create a way to get the existing socket via monkey patch:

module Rinda
  class RingServer
    attr_accessor :soc
  end
end

Then you can keep the instance of the ringserver in an instance variable, e.g. @ringserver, and use it to access the socket to close it, set a new socket, etc. e.g.

def bind_to_different_port(port)
  begin
    @ringserver.soc.close
  rescue => e
    puts "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
  end
  @ringserver.soc=UDPSocket.open
  @ringserver.soc.bind('', port)
end

Or skip the attr_accessor and just add a method to RingServer and call a method or two on the RingServer to close, open, bind the socket.

To see how it uses the socket in Ruby 1.9.3: https://github.com/ruby/ruby/blob/v1_9_3_374/lib/rinda/ring.rb

Gary S. Weaver
  • 7,966
  • 4
  • 37
  • 61
  • i'v tried this, but it doesnt work.consider the code here: DRb.start_service Rinda::RingServer.new Rinda::TupleSpace.new DRb.stop_service sleep(100000) then you can run another script trying to bind to port 7647, and you'll fail. Rinda only use DRb for manipulating TupleSpace. It listen to port 7647 for server auto discovery, and i cannot tell Rinda to close that port, except i kill its process – Kaiqiang Feb 14 '13 at 06:21
  • Instead of sleep, join to the DRb thread, that way when DRb stops, the ring server stops, e.g. `require 'rinda/ring'; require 'rinda/tuplespace'; DRb.start_service; Rinda::RingServer.new(Rinda::TupleSpace.new); DRb.thread.join`. I'll update the answer to suggest how to monkey patch `Rinda::RingServer` to close the socket, since it sounds like that is what you want. – Gary S. Weaver Feb 14 '13 at 14:13