RingFinger
is used by RingServer
clients to discover the RingServer’s TupleSpace
. Typically, all a client needs to do is call RingFinger.primary
to retrieve the remote TupleSpace
, which it can then begin using.
To find the first available remote TupleSpace:
Rinda::RingFinger.primary
To create a RingFinger
that broadcasts to a custom list:
rf = Rinda::RingFinger.new ['localhost', '192.0.2.1'] rf.primary
Rinda::RingFinger
also understands multicast addresses and sets them up properly. This allows you to run multiple RingServers on the same host:
rf = Rinda::RingFinger.new ['239.0.0.1'] rf.primary
You can set the hop count (or TTL) for multicast searches using multicast_hops
.
If you use IPv6 multicast you may need to set both an address and the outbound interface index:
rf = Rinda::RingFinger.new ['ff02::1'] rf.multicast_interface = 1 rf.primary
At this time there is no easy way to get an interface index by name.
The list of addresses where RingFinger
will send query packets.
Maximum number of hops for sent multicast packets (if using a multicast address in the broadcast list). The default is 1 (same as UDP broadcast).
The interface index to send IPv6 multicast packets from.
The port that RingFinger
will send query packets to.
Contain the first advertised TupleSpace
after lookup_ring_any
is called.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 288
def self.finger
unless @@finger
@@finger = self.new
@@finger.lookup_ring_any
end
@@finger
end
Creates a singleton RingFinger
and looks for a RingServer
. Returns the created RingFinger
.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 344
def initialize(broadcast_list=@@broadcast_list, port=Ring_PORT)
@broadcast_list = broadcast_list || ['localhost']
@port = port
@primary = nil
@rings = []
@multicast_hops = 1
@multicast_interface = 0
end
Creates a new RingFinger
that will look for RingServers at port
on the addresses in broadcast_list
.
If broadcast_list
contains a multicast address then multicast queries will be made using the given multicast_hops
and multicast_interface.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 299
def self.primary
finger.primary
end
Returns the first advertised TupleSpace
.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 306
def self.to_a
finger.to_a
end
Contains all discovered TupleSpaces except for the primary.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 364
def each
lookup_ring_any unless @primary
return unless @primary
yield(@primary)
@rings.each { |x| yield(x) }
end
Iterates over all discovered TupleSpaces starting with the primary.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 376
def lookup_ring(timeout=5, &block)
return lookup_ring_any(timeout) unless block_given?
msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout])
@broadcast_list.each do |it|
send_message(it, msg)
end
sleep(timeout)
end
Looks up RingServers waiting timeout
seconds. RingServers will be given block
as a callback, which will be called with the remote TupleSpace
.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 390
def lookup_ring_any(timeout=5)
queue = Thread::Queue.new
Thread.new do
self.lookup_ring(timeout) do |ts|
queue.push(ts)
end
queue.push(nil)
end
@primary = queue.pop
raise('RingNotFound') if @primary.nil?
Thread.new do
while it = queue.pop
@rings.push(it)
end
end
@primary
end
Returns the first found remote TupleSpace
. Any further recovered TupleSpaces can be found by calling to_a
.
# File tmp/rubies/ruby-3.3.0/lib/rinda/ring.rb, line 357
def to_a
@rings
end
Contains all discovered TupleSpaces except for the primary.