aboutsummaryrefslogtreecommitdiffstats
path: root/lib/rinda/ring.rb
diff options
context:
space:
mode:
authorseki <seki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-10-24 15:38:47 +0000
committerseki <seki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-10-24 15:38:47 +0000
commitdef653cd80e55d9e760e3803f815cc9dcdc1131e (patch)
treea766e5634849dc5d5a7d957ff6bd810caa31e593 /lib/rinda/ring.rb
parent141666b1e2738844532266a81be5c6438ee6e400 (diff)
downloadruby-def653cd80e55d9e760e3803f815cc9dcdc1131e.tar.gz
RDoc documentation from Eric Hodel <drbrain@segment7.net> added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9459 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rinda/ring.rb')
-rw-r--r--lib/rinda/ring.rb111
1 files changed, 109 insertions, 2 deletions
diff --git a/lib/rinda/ring.rb b/lib/rinda/ring.rb
index bc952032e9..5b2d412451 100644
--- a/lib/rinda/ring.rb
+++ b/lib/rinda/ring.rb
@@ -6,10 +6,29 @@ require 'rinda/rinda'
require 'thread'
module Rinda
+
+ ##
+ # The default port Ring discovery will use.
+
Ring_PORT = 7647
+
+ ##
+ # A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts.
+ # Service location uses the following steps:
+ #
+ # 1. A RingServer begins listening on the broadcast UDP address.
+ # 2. A RingFinger sends a UDP packet containing the DRb URI where it will
+ # listen for a reply.
+ # 3. The RingServer recieves the UDP packet and connects back to the
+ # provided DRb URI with the DRb service.
+
class RingServer
+
include DRbUndumped
+ ##
+ # Advertises +ts+ on the UDP broadcast address at +port+.
+
def initialize(ts, port=Ring_PORT)
@ts = ts
@soc = UDPSocket.open
@@ -18,6 +37,10 @@ module Rinda
@r_service = reply_service
end
+ ##
+ # Creates a thread that picks up UDP packets and passes them to do_write
+ # for decoding.
+
def write_service
Thread.new do
loop do
@@ -27,6 +50,10 @@ module Rinda
end
end
+ ##
+ # Extracts the response URI from +msg+ and adds it to TupleSpace where it
+ # will be picked up by +reply_service+ for notification.
+
def do_write(msg)
Thread.new do
begin
@@ -37,6 +64,9 @@ module Rinda
end
end
+ ##
+ # Creates a thread that notifies waiting clients from the TupleSpace.
+
def reply_service
Thread.new do
loop do
@@ -45,15 +75,34 @@ module Rinda
end
end
+ ##
+ # Pulls lookup tuples out of the TupleSpace and sends their DRb object the
+ # address of the local TupleSpace.
+
def do_reply
tuple = @ts.take([:lookup_ring, DRbObject])
Thread.new { tuple[1].call(@ts) rescue nil}
rescue
end
+
end
+ ##
+ # 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.
+
class RingFinger
+
+ @@broadcast_list = ['<broadcast>', 'localhost']
+
@@finger = nil
+
+ ##
+ # Creates a singleton RingFinger and looks for a RingServer. Returns the
+ # created RingFinger.
+
def self.finger
unless @@finger
@@finger = self.new
@@ -62,27 +111,56 @@ module Rinda
@@finger
end
+ ##
+ # Returns the first advertised TupleSpace.
+
def self.primary
finger.primary
end
+ ##
+ # Contains all discoverd TupleSpaces except for the primary.
+
def self.to_a
finger.to_a
end
- @@broadcast_list = ['<broadcast>', 'localhost']
+ ##
+ # The list of addresses where RingFinger will send query packets.
+
+ attr_accessor :broadcast_list
+
+ ##
+ # The port that RingFinger will send query packets to.
+
+ attr_accessor :port
+
+ ##
+ # Contain the first advertised TupleSpace after lookup_ring_any is called.
+
+ attr_accessor :primary
+
+ ##
+ # Creates a new RingFinger that will look for RingServers at +port+ on
+ # the addresses in +broadcast_list+.
+
def initialize(broadcast_list=@@broadcast_list, port=Ring_PORT)
@broadcast_list = broadcast_list || ['localhost']
@port = port
@primary = nil
@rings = []
end
- attr_accessor :broadcast_list, :port, :primary
+
+ ##
+ # Contains all discovered TupleSpaces except for the primary.
def to_a
@rings
end
+ ##
+ # Iterates over all discovered TupleSpaces starting with the primary.
+
def each
lookup_ring_any unless @primary
return unless @primary
@@ -90,6 +168,11 @@ module Rinda
@rings.each { |x| yield(x) }
end
+ ##
+ # Looks up RingServers waiting +timeout+ seconds. RingServers will be
+ # given +block+ as a callback, which will be called with the remote
+ # TupleSpace.
+
def lookup_ring(timeout=5, &block)
return lookup_ring_any(timeout) unless block_given?
@@ -108,6 +191,10 @@ module Rinda
sleep(timeout)
end
+ ##
+ # Returns the first found remote TupleSpace. Any further recovered
+ # TupleSpaces can be found by calling +to_a+.
+
def lookup_ring_any(timeout=5)
queue = Queue.new
@@ -125,19 +212,38 @@ module Rinda
raise('RingNotFound') if @primary.nil?
@primary
end
+
end
+ ##
+ # RingProvider uses a RingServer advertised TupleSpace as a name service.
+ # TupleSpace clients can register themselves with the remote TupleSpace and
+ # look up other provided services via the remote TupleSpace.
+ #
+ # Services are registered with a tuple of the format [:name, klass,
+ # DRbObject, description].
+
class RingProvider
+
+ ##
+ # Creates a RingProvider that will provide a +klass+ service running on
+ # +front+, with a +description+. +renewer+ is optional.
+
def initialize(klass, front, desc, renewer = nil)
@tuple = [:name, klass, front, desc]
@renewer = renewer || Rinda::SimpleRenewer.new
end
+ ##
+ # Advertises this service on the primary remote TupleSpace.
+
def provide
ts = Rinda::RingFinger.primary
ts.write(@tuple, @renewer)
end
+
end
+
end
if __FILE__ == $0
@@ -162,3 +268,4 @@ if __FILE__ == $0
end
end
end
+