source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rinda/rinda.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 5.8 KB
Line 
1require 'drb/drb'
2require 'thread'
3
4##
5# A module to implement the Linda distributed computing paradigm in Ruby.
6#
7# Rinda is part of DRb (dRuby).
8#
9# == Example(s)
10#
11# See the sample/drb/ directory in the Ruby distribution, from 1.8.2 onwards.
12#
13#--
14# TODO
15# == Introduction to Linda/rinda?
16#
17# == Why is this library separate from DRb?
18
19module Rinda
20
21 ##
22 # Rinda error base class
23
24 class RindaError < RuntimeError; end
25
26 ##
27 # Raised when a hash-based tuple has an invalid key.
28
29 class InvalidHashTupleKey < RindaError; end
30
31 ##
32 # Raised when trying to use a canceled tuple.
33
34 class RequestCanceledError < ThreadError; end
35
36 ##
37 # Raised when trying to use an expired tuple.
38
39 class RequestExpiredError < ThreadError; end
40
41 ##
42 # A tuple is the elementary object in Rinda programming.
43 # Tuples may be matched against templates if the tuple and
44 # the template are the same size.
45
46 class Tuple
47
48 ##
49 # Creates a new Tuple from +ary_or_hash+ which must be an Array or Hash.
50
51 def initialize(ary_or_hash)
52 if hash?(ary_or_hash)
53 init_with_hash(ary_or_hash)
54 else
55 init_with_ary(ary_or_hash)
56 end
57 end
58
59 ##
60 # The number of elements in the tuple.
61
62 def size
63 @tuple.size
64 end
65
66 ##
67 # Accessor method for elements of the tuple.
68
69 def [](k)
70 @tuple[k]
71 end
72
73 ##
74 # Fetches item +k+ from the tuple.
75
76 def fetch(k)
77 @tuple.fetch(k)
78 end
79
80 ##
81 # Iterate through the tuple, yielding the index or key, and the
82 # value, thus ensuring arrays are iterated similarly to hashes.
83
84 def each # FIXME
85 if Hash === @tuple
86 @tuple.each { |k, v| yield(k, v) }
87 else
88 @tuple.each_with_index { |v, k| yield(k, v) }
89 end
90 end
91
92 ##
93 # Return the tuple itself
94 def value
95 @tuple
96 end
97
98 private
99
100 def hash?(ary_or_hash)
101 ary_or_hash.respond_to?(:keys)
102 end
103
104 ##
105 # Munges +ary+ into a valid Tuple.
106
107 def init_with_ary(ary)
108 @tuple = Array.new(ary.size)
109 @tuple.size.times do |i|
110 @tuple[i] = ary[i]
111 end
112 end
113
114 ##
115 # Ensures +hash+ is a valid Tuple.
116
117 def init_with_hash(hash)
118 @tuple = Hash.new
119 hash.each do |k, v|
120 raise InvalidHashTupleKey unless String === k
121 @tuple[k] = v
122 end
123 end
124
125 end
126
127 ##
128 # Templates are used to match tuples in Rinda.
129
130 class Template < Tuple
131
132 ##
133 # Matches this template against +tuple+. The +tuple+ must be the same
134 # size as the template. An element with a +nil+ value in a template acts
135 # as a wildcard, matching any value in the corresponding position in the
136 # tuple. Elements of the template match the +tuple+ if the are #== or
137 # #===.
138 #
139 # Template.new([:foo, 5]).match Tuple.new([:foo, 5]) # => true
140 # Template.new([:foo, nil]).match Tuple.new([:foo, 5]) # => true
141 # Template.new([String]).match Tuple.new(['hello']) # => true
142 #
143 # Template.new([:foo]).match Tuple.new([:foo, 5]) # => false
144 # Template.new([:foo, 6]).match Tuple.new([:foo, 5]) # => false
145 # Template.new([:foo, nil]).match Tuple.new([:foo]) # => false
146 # Template.new([:foo, 6]).match Tuple.new([:foo]) # => false
147
148 def match(tuple)
149 return false unless tuple.respond_to?(:size)
150 return false unless tuple.respond_to?(:fetch)
151 return false unless self.size == tuple.size
152 each do |k, v|
153 begin
154 it = tuple.fetch(k)
155 rescue
156 return false
157 end
158 next if v.nil?
159 next if v == it
160 next if v === it
161 return false
162 end
163 return true
164 end
165
166 ##
167 # Alias for #match.
168
169 def ===(tuple)
170 match(tuple)
171 end
172
173 end
174
175 ##
176 # <i>Documentation?</i>
177
178 class DRbObjectTemplate
179
180 ##
181 # Creates a new DRbObjectTemplate that will match against +uri+ and +ref+.
182
183 def initialize(uri=nil, ref=nil)
184 @drb_uri = uri
185 @drb_ref = ref
186 end
187
188 ##
189 # This DRbObjectTemplate matches +ro+ if the remote object's drburi and
190 # drbref are the same. +nil+ is used as a wildcard.
191
192 def ===(ro)
193 return true if super(ro)
194 unless @drb_uri.nil?
195 return false unless (@drb_uri === ro.__drburi rescue false)
196 end
197 unless @drb_ref.nil?
198 return false unless (@drb_ref === ro.__drbref rescue false)
199 end
200 true
201 end
202
203 end
204
205 ##
206 # TupleSpaceProxy allows a remote Tuplespace to appear as local.
207
208 class TupleSpaceProxy
209
210 ##
211 # Creates a new TupleSpaceProxy to wrap +ts+.
212
213 def initialize(ts)
214 @ts = ts
215 end
216
217 ##
218 # Adds +tuple+ to the proxied TupleSpace. See TupleSpace#write.
219
220 def write(tuple, sec=nil)
221 @ts.write(tuple, sec)
222 end
223
224 ##
225 # Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take.
226
227 def take(tuple, sec=nil, &block)
228 port = []
229 @ts.move(DRbObject.new(port), tuple, sec, &block)
230 port[0]
231 end
232
233 ##
234 # Reads +tuple+ from the proxied TupleSpace. See TupleSpace#read.
235
236 def read(tuple, sec=nil, &block)
237 @ts.read(tuple, sec, &block)
238 end
239
240 ##
241 # Reads all tuples matching +tuple+ from the proxied TupleSpace. See
242 # TupleSpace#read_all.
243
244 def read_all(tuple)
245 @ts.read_all(tuple)
246 end
247
248 ##
249 # Registers for notifications of event +ev+ on the proxied TupleSpace.
250 # See TupleSpace#notify
251
252 def notify(ev, tuple, sec=nil)
253 @ts.notify(ev, tuple, sec)
254 end
255
256 end
257
258 ##
259 # An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still
260 # alive.
261
262 class SimpleRenewer
263
264 include DRbUndumped
265
266 ##
267 # Creates a new SimpleRenewer that keeps an object alive for another +sec+
268 # seconds.
269
270 def initialize(sec=180)
271 @sec = sec
272 end
273
274 ##
275 # Called by the TupleSpace to check if the object is still alive.
276
277 def renew
278 @sec
279 end
280 end
281
282end
283
Note: See TracBrowser for help on using the repository browser.