# class Rinda::RingFinger

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

### 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 288
    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 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

primary() click to toggle source

Returns the first advertised `TupleSpace`.

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

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

to_a() click to toggle source

Contains all discovered TupleSpaces except for the primary.

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