# class Rinda::RingFinger

RingFinger is used by RingServer clients to discover the RingServer's TupleSpace. Typically, all a client needs to do is call ::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.

### Attributes

broadcast_list[RW]

The list of addresses where RingFinger will send query packets.

multicast_hops[RW]

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).

multicast_interface[RW]

The interface index to send IPv6 multicast packets from.

port[RW]

The port that RingFinger will send query packets to.

primary[RW]

Contain the first advertised TupleSpace after #lookup_ring_any is called.

### Public Class Methods

finger() click to toggle source

Creates a singleton RingFinger and looks for a RingServer. Returns the created RingFinger.

    # File lib/rinda/ring.rb, line 287
    def self.finger
      unless @@finger
        @@finger = self.new
        @@finger.lookup_ring_any
      end
      @@finger
    end

new(broadcast_list=@@broadcast_list, port=Ring_PORT) click to toggle source

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 lib/rinda/ring.rb, line 343
    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

primary() click to toggle source

Returns the first advertised TupleSpace.

    # File lib/rinda/ring.rb, line 298
    def self.primary
      finger.primary
    end

to_a() click to toggle source

Contains all discovered TupleSpaces except for the primary.

    # File lib/rinda/ring.rb, line 305
    def self.to_a
      finger.to_a
    end

### Public Instance Methods

each() { |primary| ... } click to toggle source

Iterates over all discovered TupleSpaces starting with the primary.

    # File lib/rinda/ring.rb, line 363
    def each
      lookup_ring_any unless @primary
      return unless @primary
      yield(@primary)
      @rings.each { |x| yield(x) }
    end

lookup_ring(timeout=5, &block) click to toggle source

Looks up RingServers waiting `timeout` seconds. RingServers will be given `block` as a callback, which will be called with the remote TupleSpace.

    # File lib/rinda/ring.rb, line 375
    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

lookup_ring_any(timeout=5) click to toggle source

Returns the first found remote TupleSpace. Any further recovered TupleSpaces can be found by calling `to_a`.

    # File lib/rinda/ring.rb, line 389
    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

to_a() click to toggle source

Contains all discovered TupleSpaces except for the primary.

    # File lib/rinda/ring.rb, line 356
    def to_a
      @rings
    end