rinda 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2e451398199be205b7e5de56d4764525709c6a0f7e68c67989bd3b792b5fd8ce
4
+ data.tar.gz: 68eb2f17f82fbc9dc2bee6f2770b81a05cb16133965166b821c54da90df575cf
5
+ SHA512:
6
+ metadata.gz: 9aace6a91d22a4aca501ca02390c0b2da349154e19e819b68c2b7d977f33318fac199d07b13dca7b07195de75843dd7af67b9070d04ab923ed7717d92772d74d
7
+ data.tar.gz: 3ab9372edeab86fcb407cf281a1276f72d0236e9b25c6b811b2edfc99d617194db9f9e2fe8f0cfbda5e891eebc0dbec6aa748abd31710c6776a1f17c4684aa9a
@@ -0,0 +1,24 @@
1
+ name: test
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 2.7, 2.6, 2.5, head ]
11
+ os: [ ubuntu-latest, macos-latest ]
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@master
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+ - name: Install dependencies
20
+ run: |
21
+ gem install bundler --no-document
22
+ bundle install
23
+ - name: Run test
24
+ run: rake test
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rake"
4
+ gem "test-unit"
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,36 @@
1
+ # Rinda
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rinda`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'rinda'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rinda
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hsbt/rinda.
36
+
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test/lib"
6
+ t.test_files = FileList["test/**/test_*.rb"]
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rinda"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,327 @@
1
+ # frozen_string_literal: false
2
+ require 'drb/drb'
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
+
19
+ module 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
+ # A Port ensures that a moved tuple arrives properly at its destination
211
+ # and does not get lost.
212
+ #
213
+ # See https://bugs.ruby-lang.org/issues/8125
214
+
215
+ class Port # :nodoc:
216
+ attr_reader :value
217
+
218
+ def self.deliver
219
+ port = new
220
+
221
+ begin
222
+ yield(port)
223
+ ensure
224
+ port.close
225
+ end
226
+
227
+ port.value
228
+ end
229
+
230
+ def initialize
231
+ @open = true
232
+ @value = nil
233
+ end
234
+
235
+ ##
236
+ # Don't let the DRb thread push to it when remote sends tuple
237
+
238
+ def close
239
+ @open = false
240
+ end
241
+
242
+ ##
243
+ # Stores +value+ and ensure it does not get marshaled multiple times.
244
+
245
+ def push value
246
+ raise 'port closed' unless @open
247
+
248
+ @value = value
249
+
250
+ nil # avoid Marshal
251
+ end
252
+ end
253
+
254
+ ##
255
+ # Creates a new TupleSpaceProxy to wrap +ts+.
256
+
257
+ def initialize(ts)
258
+ @ts = ts
259
+ end
260
+
261
+ ##
262
+ # Adds +tuple+ to the proxied TupleSpace. See TupleSpace#write.
263
+
264
+ def write(tuple, sec=nil)
265
+ @ts.write(tuple, sec)
266
+ end
267
+
268
+ ##
269
+ # Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take.
270
+
271
+ def take(tuple, sec=nil, &block)
272
+ Port.deliver do |port|
273
+ @ts.move(DRbObject.new(port), tuple, sec, &block)
274
+ end
275
+ end
276
+
277
+ ##
278
+ # Reads +tuple+ from the proxied TupleSpace. See TupleSpace#read.
279
+
280
+ def read(tuple, sec=nil, &block)
281
+ @ts.read(tuple, sec, &block)
282
+ end
283
+
284
+ ##
285
+ # Reads all tuples matching +tuple+ from the proxied TupleSpace. See
286
+ # TupleSpace#read_all.
287
+
288
+ def read_all(tuple)
289
+ @ts.read_all(tuple)
290
+ end
291
+
292
+ ##
293
+ # Registers for notifications of event +ev+ on the proxied TupleSpace.
294
+ # See TupleSpace#notify
295
+
296
+ def notify(ev, tuple, sec=nil)
297
+ @ts.notify(ev, tuple, sec)
298
+ end
299
+
300
+ end
301
+
302
+ ##
303
+ # An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still
304
+ # alive.
305
+
306
+ class SimpleRenewer
307
+
308
+ include DRbUndumped
309
+
310
+ ##
311
+ # Creates a new SimpleRenewer that keeps an object alive for another +sec+
312
+ # seconds.
313
+
314
+ def initialize(sec=180)
315
+ @sec = sec
316
+ end
317
+
318
+ ##
319
+ # Called by the TupleSpace to check if the object is still alive.
320
+
321
+ def renew
322
+ @sec
323
+ end
324
+ end
325
+
326
+ end
327
+