archipelago 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/TODO CHANGED
@@ -1,3 +1,13 @@
1
1
 
2
- * Create a new HashishProvider with built in redundancy, for example
3
- using the Chord project: http://pdos.csail.mit.edu/chord/
2
+ * Create a new HashishProvider with built in redundancy,
3
+ for example using the Chord project: http://pdos.csail.mit.edu/chord/
4
+
5
+ * Make Chest aware about whether transactions have affected it 'for real' ie
6
+ check whether the instance before the call differs from the instance after
7
+ the call. Preferably without incurring performance lossage.
8
+
9
+ * Test the transaction recovery mechanism of Chest.
10
+
11
+ * Make Archipelago::Treasure::Dubloons work after an Archipelago::Treasure::Chest
12
+ has rebooted. For example: demand that the chest always run the same host+port
13
+ or make Dubloons able to lookup their home Chest by service_id.
File without changes
@@ -19,7 +19,7 @@ require 'socket'
19
19
  require 'thread'
20
20
  require 'ipaddr'
21
21
  require 'pp'
22
- require 'current'
22
+ require 'archipelago/current'
23
23
  require 'drb'
24
24
  require 'set'
25
25
 
@@ -83,6 +83,30 @@ module Archipelago
83
83
  #
84
84
  module Publishable
85
85
 
86
+ #
87
+ # Also add the ClassMethods to +base+.
88
+ #
89
+ def self.append_features(base)
90
+ super
91
+ base.extend(ClassMethods)
92
+ end
93
+
94
+ module ClassMethods
95
+ #
96
+ # Just load whatever we have in +s+.
97
+ #
98
+ def _load(s)
99
+ DRbObject._load(s)
100
+ end
101
+ end
102
+
103
+ #
104
+ # Dump a DRbObject refering to us.
105
+ #
106
+ def _dump(dummy_param)
107
+ DRbObject.new(self)._dump(dummy_param)
108
+ end
109
+
86
110
  #
87
111
  # Will initialize this instance with @service_description and @jockey_options
88
112
  # and merge these with the optionally given <i>:service_description</i> and
@@ -91,8 +115,8 @@ module Archipelago
91
115
  def initialize_publishable(options = {})
92
116
  @service_description = {
93
117
  :service_id => service_id,
94
- :validator => DRbObject.new(self),
95
- :service => DRbObject.new(self),
118
+ :validator => self,
119
+ :service => self,
96
120
  :class => self.class.name
97
121
  }.merge(options[:service_description] || {})
98
122
  @jockey_options = options[:jockey_options] || {}
@@ -106,7 +130,7 @@ module Archipelago
106
130
  # <i>:service_description</i>.
107
131
  #
108
132
  def publish!(options = {})
109
- @jockey ||= Archipelago::Disco::Jockey.new(@jockey_options.merge(options[:jockey_options] || {}))
133
+ @jockey ||= defined?(Archipelago::Disco::MC) ? Archipelago::Disco::MC : Archipelago::Disco::Jockey.new(@jockey_options.merge(options[:jockey_options] || {}))
110
134
  @jockey.publish(Archipelago::Disco::Record.new(@service_description.merge(options[:service_description] || {})))
111
135
  end
112
136
 
@@ -203,7 +227,7 @@ module Archipelago
203
227
  # Initialize this Record with a hash that must contain an <i>:service_id</i> and a <i>:validator</i>.
204
228
  #
205
229
  def initialize(hash)
206
- raise "Record must have an :service_id" unless hash.include?(:service_id)
230
+ raise "Record must have a :service_id" unless hash.include?(:service_id)
207
231
  raise "Record must have a :validator" unless hash.include?(:validator)
208
232
  super(hash)
209
233
  end
@@ -278,8 +302,6 @@ module Archipelago
278
302
  #
279
303
  class Jockey
280
304
 
281
- attr_reader :new_service_semaphore
282
-
283
305
  #
284
306
  # Will create a Jockey service running on <i>:address</i> and <i>:port</i> or
285
307
  # ADDRESS and PORT if none are given.
@@ -366,7 +388,7 @@ module Archipelago
366
388
  #
367
389
  # Stops all the threads in this instance.
368
390
  #
369
- def stop
391
+ def stop!
370
392
  @listener_thread.kill
371
393
  @unilistener_thread.kill
372
394
  @shouter_thread.kill
@@ -412,6 +434,7 @@ module Archipelago
412
434
  #
413
435
  def publish(service)
414
436
  if service.valid?
437
+ service[:published_at] = Time.now
415
438
  @local_services[service[:service_id]] = service
416
439
  @new_service_semaphore.broadcast
417
440
  unless @thrifty_publishing
@@ -543,6 +566,8 @@ module Archipelago
543
566
 
544
567
  end
545
568
 
569
+ MC = Jockey.new(defined?(MC_OPTIONS) ? MC_OPTIONS : {}) unless defined?(MC_DISABLED) && MC_DISABLED
570
+
546
571
  end
547
572
 
548
573
  end
@@ -15,7 +15,7 @@
15
15
  # along with this program; if not, write to the Free Software
16
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
- require 'current'
18
+ require 'archipelago/current'
19
19
  require 'bdb'
20
20
 
21
21
  module Archipelago
@@ -15,9 +15,9 @@
15
15
  # along with this program; if not, write to the Free Software
16
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
- require 'disco'
19
- require 'tranny'
20
- require 'treasure'
18
+ require 'archipelago/disco'
19
+ require 'archipelago/tranny'
20
+ require 'archipelago/treasure'
21
21
  require 'pp'
22
22
  require 'drb'
23
23
  require 'digest/sha1'
@@ -65,7 +65,7 @@ module Archipelago
65
65
  # Archipelago::Treasure:Dubloons in them.
66
66
  #
67
67
  class Captain
68
- attr_reader :chests, :treasure_map, :trannies, :transaction
68
+ attr_reader :chests, :treasure_map, :trannies
69
69
  #
70
70
  # Initialize an instance using an Archipelago::Disco::Jockey with <i>:jockey_options</i>
71
71
  # if given, that looks for new services <i>:initial_service_update_interval</i> or INITIAL_SERVICE_UPDATE_INTERVAL,
@@ -74,13 +74,20 @@ module Archipelago
74
74
  # Will look for Archipelago::Treasure::Chests matching <i>:chest_description</i> or CHEST_DESCRIPTION and
75
75
  # Archipelago::Tranny::Managers matching <i>:tranny_description</i> or TRANNY_DESCRIPTION.
76
76
  #
77
+ # Will send off all <i>:chest_eval_files</i> to any chest found for possible evaluation to ensure existence
78
+ # of required classes and modules at the chest.
79
+ #
77
80
  def initialize(options = {})
78
- @treasure_map = Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
81
+ @treasure_map = defined?(Archipelago::Disco::MC) ? Archipelago::Disco::MC : Archipelago::Disco::Jockey.new(options[:jockey_options] || {})
79
82
 
80
83
  @chest_description = CHEST_DESCRIPTION.merge(options[:chest_description] || {})
81
84
  @tranny_description = TRANNY_DESCRIPTION.merge(options[:tranny_description] || {})
82
85
  @jockey_options = options[:jockey_options] || {}
83
86
 
87
+ @chest_eval_files = options[:chest_eval_files] || []
88
+
89
+ @chests_having_evaluated = {}
90
+
84
91
  start_service_updater(options[:initial_service_update_interval] || INITIAL_SERVICE_UPDATE_INTERVAL,
85
92
  options[:maximum_service_update_interval] || MAXIMUM_SERVICE_UPDATE_INTERVAL)
86
93
 
@@ -135,6 +142,38 @@ module Archipelago
135
142
  return rval
136
143
  end
137
144
 
145
+ #
146
+ # Execute +block+ within a transaction.
147
+ #
148
+ # Will commit! transaction after the block is finished unless
149
+ # the transaction is aborted or commited already.
150
+ #
151
+ # Will abort! the transaction if any exception is raised.
152
+ #
153
+ def transaction(&block) #:yields: transaction
154
+ raise NoTransactionManagerAvailableException.new(self) if @trannies.empty?
155
+
156
+ @transaction = @trannies.values.first[:service].begin
157
+ begin
158
+ yield(@transaction)
159
+ @transaction.commit! if @transaction.state == :active
160
+ rescue Exception => e
161
+ @transaction.abort! unless @transaction.state == :aborted
162
+ puts e
163
+ pp e.backtrace
164
+ ensure
165
+ @transaction = nil
166
+ end
167
+ end
168
+
169
+ #
170
+ # Evaluate this file in all known chests.
171
+ #
172
+ def evaluate!(filename)
173
+ @chest_eval_files << filename
174
+ evaluate_in_chests
175
+ end
176
+
138
177
  #
139
178
  # Commit the transaction we are a member of and forget about it.
140
179
  #
@@ -159,6 +198,13 @@ module Archipelago
159
198
  'yar!'
160
199
  end
161
200
 
201
+ #
202
+ # Stops the service update thread for this Pirate.
203
+ #
204
+ def stop!
205
+ @service_update_thread.kill
206
+ end
207
+
162
208
  private
163
209
 
164
210
  #
@@ -175,14 +221,60 @@ module Archipelago
175
221
  return @chests[sorted_chest_ids.first]
176
222
  end
177
223
 
224
+ #
225
+ # Make sure all our known chests have evaluated
226
+ # all files we need them to.
227
+ #
228
+ def evaluate_in_chests
229
+ #
230
+ # For all chests
231
+ #
232
+ @chests.values.each do |chest|
233
+ #
234
+ # Ensure that this chest has a Set of evaluated files
235
+ #
236
+ @chests_having_evaluated[
237
+ [
238
+ chest[:service_id],
239
+ chest[:published_at]
240
+ ]
241
+ ] ||= Set.new
242
+ @chest_eval_files.each do |filename|
243
+ unless @chests_having_evaluated[
244
+ [
245
+ chest[:service_id],
246
+ chest[:published_at]
247
+ ]
248
+ ].include?(filename)
249
+ begin
250
+ chest[:service].evaluate!(filename,
251
+ File.ctime(filename),
252
+ open(filename).read)
253
+ rescue Exception => e
254
+ puts e
255
+ pp e.backtrace
256
+ ensure
257
+ @chests_having_evaluated[
258
+ [
259
+ chest[:service_id],
260
+ chest[:published_at]
261
+ ]
262
+ ] << filename
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
268
+
178
269
  #
179
270
  # Start a thread looking up existing chests between every
180
271
  # +initial+ and +maximum+ seconds.
181
272
  #
182
273
  def start_service_updater(initial, maximum)
183
274
  @chests = @treasure_map.lookup(Archipelago::Disco::Query.new(@chest_description), 0)
275
+ evaluate_in_chests
184
276
  @trannies = @treasure_map.lookup(Archipelago::Disco::Query.new(@tranny_description), 0)
185
- Thread.start do
277
+ @service_update_thread = Thread.start do
186
278
  standoff = initial
187
279
  loop do
188
280
  begin
@@ -190,6 +282,7 @@ module Archipelago
190
282
  standoff *= 2
191
283
  standoff = maximum if standoff > maximum
192
284
  @chests = @treasure_map.lookup(Archipelago::Disco::Query.new(@chest_description), 0)
285
+ evaluate_in_chests
193
286
  @trannies = @treasure_map.lookup(Archipelago::Disco::Query.new(@tranny_description), 0)
194
287
  rescue Exception => e
195
288
  puts e
@@ -18,9 +18,10 @@
18
18
  require 'bdb'
19
19
  require 'pathname'
20
20
  require 'drb'
21
- require 'current'
21
+ require 'archipelago/current'
22
22
  require 'digest/sha1'
23
- require 'disco'
23
+ require 'archipelago/disco'
24
+ require 'archipelago/hashish'
24
25
 
25
26
  module Archipelago
26
27
 
@@ -91,7 +92,6 @@ module Archipelago
91
92
  #
92
93
  class Manager
93
94
 
94
- include DRb::DRbUndumped
95
95
  include Archipelago::Disco::Publishable
96
96
 
97
97
  attr_accessor :error_logger
@@ -113,7 +113,6 @@ module Archipelago
113
113
 
114
114
  @transaction_timeout = options[:transaction_timeout] || TRANSACTION_TIMEOUT
115
115
 
116
- @metadata = @persistence_provider.get_hashish("metadata")
117
116
  @db = @persistence_provider.get_cached_hashish("db")
118
117
  end
119
118
 
@@ -185,6 +184,7 @@ module Archipelago
185
184
  attr_accessor :transaction_id
186
185
  def initialize(transaction)
187
186
  @manager = transaction.manager
187
+ @manager_id = transaction.manager.service_id
188
188
  @transaction_id = transaction.transaction_id
189
189
  @state = :unknown
190
190
  end
@@ -222,7 +222,21 @@ module Archipelago
222
222
  # returnvalue if necessary.
223
223
  #
224
224
  def method_missing(meth, *args) #:nodoc:
225
- rval = @manager.call_instance_method(@transaction_id, meth, *args)
225
+ rval = nil
226
+ begin
227
+ rval = @manager.call_instance_method(@transaction_id, meth, *args)
228
+ rescue DRb::DRbConnError => e
229
+ if defined?(Archipelago::Disco::MC)
230
+ possible_replacements = Archipelago::Disco::MC.lookup(Archipelago::Disco::Query.new({:service_id => @manager_id}))
231
+ raise e if possible_replacements.empty?
232
+
233
+ @manager = possible_replacements[@manager_id][:service]
234
+
235
+ retry
236
+ else
237
+ raise e
238
+ end
239
+ end
226
240
  case meth
227
241
  when :abort!
228
242
  @state = :aborted
@@ -346,7 +360,7 @@ module Archipelago
346
360
  #
347
361
  # We have a manager!
348
362
  #
349
- @manager = DRbObject.new(manager)
363
+ @manager = manager
350
364
  #
351
365
  # We have a proxy to send forth into the world!
352
366
  #
@@ -16,14 +16,14 @@
16
16
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
 
18
18
  require 'drb'
19
- require 'disco'
20
19
  require 'bdb'
21
20
  require 'pathname'
22
21
  require 'digest/sha1'
23
22
  require 'pp'
24
23
  require 'set'
25
- require 'hashish'
26
- require 'tranny'
24
+ require 'archipelago/hashish'
25
+ require 'archipelago/tranny'
26
+ require 'archipelago/disco'
27
27
 
28
28
  module Archipelago
29
29
 
@@ -35,6 +35,12 @@ module Archipelago
35
35
  #
36
36
  TRANSACTION_RECOVERY_INTERVAL = 30
37
37
 
38
+ #
39
+ # The known chests by service id to speed up
40
+ # recovery by Dubloons having lost their Chest.
41
+ #
42
+ CHESTS_BY_SERVICE_ID = {}
43
+
38
44
  #
39
45
  # Raised whenever the optimistic locking of the serializable transaction isolation level
40
46
  # was proved wrong.
@@ -104,6 +110,36 @@ module Archipelago
104
110
  @public_methods = public_methods
105
111
  end
106
112
  #
113
+ # A more or less normal dump of all our instance variables.
114
+ #
115
+ def _dump(dummy_levels)
116
+ Marshal.dump([
117
+ @key,
118
+ @chest,
119
+ @transaction,
120
+ @chest_id,
121
+ @public_methods
122
+ ])
123
+ end
124
+ #
125
+ # Load some instance variables and replace @chest if we know that
126
+ # it actually is not correct.
127
+ #
128
+ def self._load(s)
129
+ key, chest, transaction, chest_id, public_methods = Marshal.load(s)
130
+ instance = self.allocate
131
+ instance.instance_variable_set(:@key, key)
132
+ instance.instance_variable_set(:@transaction, transaction)
133
+ instance.instance_variable_set(:@chest_id, chest_id)
134
+ instance.instance_variable_set(:@public_methods, public_methods)
135
+ if CHEST_BY_SERVICE_ID.include?(chest_id)
136
+ instance.instance_variable_set(:@chest, CHEST_BY_SERVICE_ID[chest_id])
137
+ else
138
+ instance.instance_variable_set(:@chest, chest)
139
+ end
140
+ return instance
141
+ end
142
+ #
107
143
  # The public_methods of our target.
108
144
  #
109
145
  def public_methods
@@ -144,7 +180,21 @@ module Archipelago
144
180
  #
145
181
  def method_missing(meth, *args, &block)
146
182
  if respond_to?(meth)
147
- return @chest.call_instance_method(@key, meth, @transaction, *args, &block)
183
+ begin
184
+ return @chest.call_instance_method(@key, meth, @transaction, *args, &block)
185
+ rescue DRb::DRbConnError => e
186
+ if defined?(Archipelago::Disco::MC)
187
+ possible_replacements = Archipelago::Disco::MC.lookup(Archipelago::Disco::Query.new({:service_id => @chest_id}))
188
+ raise e if possible_replacements.empty?
189
+
190
+ @chest = possible_replacements[@chest_id][:service]
191
+ CHESTS_BY_SERVICE_ID[@chest_id] = @chest
192
+
193
+ retry
194
+ else
195
+ raise e
196
+ end
197
+ end
148
198
  else
149
199
  return super(meth, *args)
150
200
  end
@@ -158,15 +208,8 @@ module Archipelago
158
208
  #
159
209
  # Has support for optimistically locked distributed serializable transactions.
160
210
  #
161
- # TODO: Test the transaction recovery mechanism.
162
- #
163
211
  class Chest
164
212
 
165
- #
166
- # The Chest never leaves its host.
167
- #
168
- include DRb::DRbUndumped
169
-
170
213
  #
171
214
  # The Chest can be published.
172
215
  #
@@ -215,6 +258,8 @@ module Archipelago
215
258
  #
216
259
  @crashed = Set.new
217
260
 
261
+ initialize_seen_data
262
+
218
263
  #
219
264
  # The magical persistent map that defines how we actually
220
265
  # store our data.
@@ -223,6 +268,7 @@ module Archipelago
223
268
 
224
269
  initialize_prepared(options[:transaction_recovery_interval] || TRANSACTION_RECOVERY_INTERVAL)
225
270
 
271
+ CHESTS_BY_SERVICE_ID[self.service_id] = self
226
272
  end
227
273
 
228
274
  #
@@ -232,6 +278,32 @@ module Archipelago
232
278
  @snapshot_by_transaction.keys.clone
233
279
  end
234
280
 
281
+ #
282
+ # Evaluate +data+ if we have not already seen +label+ or if we have an earlier +timestamp+ than the one given.
283
+ #
284
+ def evaluate!(label, timestamp, data)
285
+ serialized_label = Marshal.dump(label)
286
+ go = false
287
+
288
+ if @seen_data.include?(serialized_label)
289
+ last_timestamp, last_data = Marshal.load(@seen_data[serialized_label])
290
+ go = true if timestamp > last_timestamp
291
+ else
292
+ go = true
293
+ end
294
+
295
+ if go
296
+ begin
297
+ Object.class_eval(data)
298
+ @seen_data[serialized_label] = Marshal.dump([timestamp, data])
299
+ rescue Exception => e
300
+ @seen_data[serialized_label] = Marshal.load([timestamp, nil])
301
+ puts e
302
+ pp e.backtrace
303
+ end
304
+ end
305
+ end
306
+
235
307
  #
236
308
  # Return the contents of this chest using a given +key+ and +transaction+.
237
309
  #
@@ -244,7 +316,7 @@ module Archipelago
244
316
  if Dubloon === instance
245
317
  return instance.join(transaction)
246
318
  else
247
- return Dubloon.new(key, DRbObject.new(self), transaction, self.service_id, instance.public_methods)
319
+ return Dubloon.new(key, self, transaction, self.service_id, instance.public_methods)
248
320
  end
249
321
  end
250
322
 
@@ -365,11 +437,6 @@ module Archipelago
365
437
  # this transaction to block until it is either aborted
366
438
  # or commited!
367
439
  #
368
- # TODO: Make us aware about whether transactions have affected us
369
- # 'for real' ie check whether the instance before the call
370
- # differs from the instance after the call. Preferably
371
- # without incurring performance lossage.
372
- #
373
440
  def prepare!(transaction)
374
441
  assert_transaction(transaction)
375
442
 
@@ -457,6 +524,29 @@ module Archipelago
457
524
 
458
525
  private
459
526
 
527
+ #
528
+ # Evaluates all data we have been told to evaluate in earlier runs.
529
+ #
530
+ def initialize_seen_data
531
+ #
532
+ # [label => [timestamp, data]]
533
+ # To remember what and when we have evaluated and be able to evaluate it again.
534
+ #
535
+ @seen_data = @persistence_provider.get_hashish("seen_data")
536
+ @seen_data.each do |serialized_label, serialized_pair|
537
+ timestamp, data = Marshal.load(serialized_pair)
538
+
539
+ if data
540
+ begin
541
+ Object.class_eval(data)
542
+ rescue Exception => e
543
+ puts e
544
+ pp e.backtrace
545
+ end
546
+ end
547
+ end
548
+ end
549
+
460
550
  #
461
551
  # Allocates space for this +transaction+.
462
552
  #
@@ -471,7 +561,7 @@ module Archipelago
471
561
  @snapshot_by_transaction[transaction] = {}
472
562
  @snapshot_by_transaction[transaction].extend(Archipelago::Current::Synchronized)
473
563
  @timestamp_by_key_by_transaction[transaction] = {}
474
- transaction.join(DRbObject.new(self))
564
+ transaction.join(self)
475
565
  end
476
566
  end
477
567
  else
@@ -631,7 +721,7 @@ module Archipelago
631
721
 
632
722
  return value if Dubloon === value
633
723
 
634
- return Dubloon.new(key, DRbObject.new(self), transaction, service_id, value.public_methods)
724
+ return Dubloon.new(key, self, transaction, service_id, value.public_methods)
635
725
  end
636
726
 
637
727
  #
data/lib/archipelago.rb CHANGED
@@ -17,8 +17,8 @@
17
17
 
18
18
  $: << File.dirname(File.expand_path(__FILE__))
19
19
 
20
- require 'disco'
21
- require 'current'
22
- require 'tranny'
23
- require 'treasure'
24
- require 'pirate'
20
+ require 'archipelago/disco'
21
+ require 'archipelago/current'
22
+ require 'archipelago/tranny'
23
+ require 'archipelago/treasure'
24
+ require 'archipelago/pirate'
data/scripts/chest.rb CHANGED
@@ -7,7 +7,7 @@ end
7
7
 
8
8
  $: << File.join(File.dirname(__FILE__), "..", "lib")
9
9
 
10
- require 'treasure'
10
+ require 'archipelago/treasure'
11
11
 
12
12
  if ARGV.size > 1
13
13
  DRb.start_service(ARGV[1])
data/scripts/pirate.rb CHANGED
@@ -1,6 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pirate'
3
+ require 'archipelago/pirate'
4
+
5
+ #
6
+ # An overload of Archipelago::Hashish::BerkeleyHashish
7
+ # just to get a nice debugging method.
8
+ #
9
+ class Archipelago::Hashish::BerkeleyHashish
10
+ #
11
+ # Get the serialized value for +key+.
12
+ #
13
+ def get_serialized_value(key)
14
+ @content_db[Marshal.dump(key)]
15
+ end
16
+ end
4
17
 
5
18
  DRb.start_service("druby://localhost:#{rand(1000) + 5000}")
6
19
  @p = Archipelago::Pirate::Captain.new
data/scripts/tranny.rb CHANGED
@@ -7,7 +7,7 @@ end
7
7
 
8
8
  $: << File.join(File.dirname(__FILE__), "..", "lib")
9
9
 
10
- require 'treasure'
10
+ require 'archipelago/treasure'
11
11
 
12
12
  if ARGV.size > 1
13
13
  DRb.start_service(ARGV[1])
@@ -1,6 +1,5 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), 'test_helper')
3
- require 'current'
4
3
 
5
4
  class CurrentTest < Test::Unit::TestCase
6
5
 
data/tests/disco_test.rb CHANGED
@@ -1,10 +1,5 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), 'test_helper')
3
- require 'disco'
4
- require 'drb'
5
- require 'socket'
6
- require 'ipaddr'
7
- require 'thread'
8
3
 
9
4
  class RemoteValidator
10
5
  include DRb::DRbUndumped
@@ -27,8 +22,8 @@ class DiscoTest < Test::Unit::TestCase
27
22
  @d2 = TestJockey.new(:thrifty_publishing => false)
28
23
  @v1 = RemoteValidator.new(true)
29
24
  @p1 = Archipelago::Disco::Record.new(:service_id => 1,
30
- :validator => DRbObject.new(@v1),
31
- :epa => "blar")
25
+ :validator => DRbObject.new(@v1),
26
+ :epa => "blar")
32
27
  @d1.publish(@p1)
33
28
  assert(!@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar")).empty?)
34
29
 
@@ -62,8 +57,8 @@ class DiscoTest < Test::Unit::TestCase
62
57
  end
63
58
 
64
59
  def teardown
65
- @d1.stop
66
- @d2.stop
60
+ @d1.stop!
61
+ @d2.stop!
67
62
  DRb.stop_service
68
63
  @lt.kill
69
64
  @listener.close
@@ -78,8 +73,8 @@ class DiscoTest < Test::Unit::TestCase
78
73
  assert(empty)
79
74
 
80
75
  @d1.publish(Archipelago::Disco::Record.new(:service_id => 1,
81
- :validator => Archipelago::Disco::MockValidator.new,
82
- :epa => "blar2"))
76
+ :validator => Archipelago::Disco::MockValidator.new,
77
+ :epa => "blar2"))
83
78
 
84
79
  assert_within(0.5) do
85
80
  !empty
@@ -94,7 +89,9 @@ class DiscoTest < Test::Unit::TestCase
94
89
  def test_thrifty_publishing
95
90
  @ltq.clear
96
91
 
97
- @d1.publish(Archipelago::Disco::Record.new(:glada => "jaa", :validator => Archipelago::Disco::MockValidator.new, :service_id => 344))
92
+ @d1.publish(Archipelago::Disco::Record.new(:glada => "jaa",
93
+ :validator => Archipelago::Disco::MockValidator.new,
94
+ :service_id => 344))
98
95
  sleep 0.1
99
96
  assert(@ltq.any? do |d|
100
97
  o = Marshal.load(d)
@@ -106,24 +103,28 @@ class DiscoTest < Test::Unit::TestCase
106
103
  end
107
104
  end)
108
105
 
109
- @d1.stop
110
- @d2.stop
106
+ @d1.stop!
107
+ @d2.stop!
111
108
 
112
109
  @ltq.clear
113
110
  c3 = Archipelago::Disco::Jockey.new(:thrifty_publishing => true)
114
- c3.publish(Archipelago::Disco::Record.new(:glad => "ja", :validator => Archipelago::Disco::MockValidator.new, :service_id => 33))
111
+ c3.publish(Archipelago::Disco::Record.new(:glad => "ja",
112
+ :validator => Archipelago::Disco::MockValidator.new,
113
+ :service_id => 33))
115
114
  sleep 0.1
116
115
  assert(@ltq.empty?)
117
116
 
118
117
  c1 = Archipelago::Disco::Jockey.new(:thrifty_publishing => true)
119
118
  assert(!c1.lookup(Archipelago::Disco::Query.new(:glad => "ja")).empty?)
120
119
 
121
- c1.stop
122
- c3.stop
120
+ c1.stop!
121
+ c3.stop!
123
122
  end
124
123
 
125
124
  def test_thrifty_replying
126
- @d1.publish(Archipelago::Disco::Record.new(:gladaa => "jaaa", :validator => Archipelago::Disco::MockValidator.new, :service_id => 3444))
125
+ @d1.publish(Archipelago::Disco::Record.new(:gladaa => "jaaa",
126
+ :validator => Archipelago::Disco::MockValidator.new,
127
+ :service_id => 3444))
127
128
 
128
129
  @ltq.clear
129
130
  assert(!@d2.lookup(Archipelago::Disco::Query.new(:gladaa => "jaaa")).empty?)
@@ -138,10 +139,12 @@ class DiscoTest < Test::Unit::TestCase
138
139
  end)
139
140
 
140
141
 
141
- @d1.stop
142
- @d2.stop
142
+ @d1.stop!
143
+ @d2.stop!
143
144
  c3 = Archipelago::Disco::Jockey.new(:thrifty_replying => true, :thrifty_publishing => true)
144
- c3.publish(Archipelago::Disco::Record.new(:glad2 => "ja2", :validator => Archipelago::Disco::MockValidator.new, :service_id => 34))
145
+ c3.publish(Archipelago::Disco::Record.new(:glad2 => "ja2",
146
+ :validator => Archipelago::Disco::MockValidator.new,
147
+ :service_id => 34))
145
148
 
146
149
  @ltq.clear
147
150
 
@@ -157,19 +160,23 @@ class DiscoTest < Test::Unit::TestCase
157
160
  end
158
161
  end)
159
162
 
160
- c1.stop
161
- c3.stop
163
+ c1.stop!
164
+ c3.stop!
162
165
  end
163
166
 
164
167
  def test_thrifty_caching
165
- @d2.publish(Archipelago::Disco::Record.new(:bojkotta => "jag", :validator => Archipelago::Disco::MockValidator.new, :service_id => 411))
168
+ @d2.publish(Archipelago::Disco::Record.new(:bojkotta => "jag",
169
+ :validator => Archipelago::Disco::MockValidator.new,
170
+ :service_id => 411))
166
171
  sleep 0.1
167
172
  assert(@d1.remote_services.include?(411))
168
173
 
169
174
  c1 = TestJockey.new(:thrifty_caching => true)
170
175
  assert(!c1.local_services.include?(41))
171
176
  assert(!c1.remote_services.include?(41))
172
- @d1.publish(Archipelago::Disco::Record.new(:bojkott => "ja", :validator => Archipelago::Disco::MockValidator.new, :service_id => 41))
177
+ @d1.publish(Archipelago::Disco::Record.new(:bojkott => "ja",
178
+ :validator => Archipelago::Disco::MockValidator.new,
179
+ :service_id => 41))
173
180
  sleep 0.1
174
181
  assert(!c1.local_services.include?(41))
175
182
  assert(!c1.remote_services.include?(41))
data/tests/pirate_test.rb CHANGED
@@ -1,10 +1,5 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), 'test_helper')
3
- require 'treasure'
4
- require 'drb'
5
- require 'tranny'
6
- require 'hashish'
7
- require 'pirate'
8
3
 
9
4
  class PirateTest < Test::Unit::TestCase
10
5
 
@@ -27,12 +22,39 @@ class PirateTest < Test::Unit::TestCase
27
22
  end
28
23
 
29
24
  def teardown
25
+ @p.stop!
30
26
  @c.persistence_provider.unlink
31
27
  @c2.persistence_provider.unlink
32
28
  @tm.persistence_provider.unlink
33
29
  DRb.stop_service
34
30
  end
35
31
 
32
+ def test_evaluate
33
+ assert_raise(NameError) do
34
+ e = Evaltest.new
35
+ end
36
+
37
+ p2 = Archipelago::Pirate::Captain.new(:chest_description => {:class => "TestChest"},
38
+ :tranny_description => {:class => "TestManager"},
39
+ :chest_eval_files => [File.join(File.dirname(__FILE__), 'evaltest')])
40
+
41
+ assert_within(10) do
42
+ !p2.chests.empty?
43
+ end
44
+
45
+ e = Evaltest.new
46
+
47
+ assert_raise(NameError) do
48
+ e = Evaltestmore.new
49
+ end
50
+
51
+ p2.evaluate!(File.join(File.dirname(__FILE__), "evaltestmore"))
52
+
53
+ e = Evaltestmore.new
54
+
55
+ p2.stop!
56
+ end
57
+
36
58
  def test_write_read
37
59
  0.upto(100) do |n|
38
60
  @p["#{n}"] = "#{n}"
data/tests/test_helper.rb CHANGED
@@ -2,11 +2,16 @@
2
2
  home = File.expand_path(File.dirname(__FILE__))
3
3
  $: << File.join(home, "..", "lib")
4
4
 
5
+ MC_DISABLED = true
6
+
5
7
  require 'pp'
8
+ require 'drb'
6
9
  require 'test/unit'
7
- require 'tranny'
8
- require 'treasure'
10
+ require 'archipelago'
9
11
  require 'benchmark'
12
+ require 'socket'
13
+ require 'ipaddr'
14
+ require 'thread'
10
15
 
11
16
  class TestTransaction
12
17
  def join(o)
data/tests/tranny_test.rb CHANGED
@@ -1,7 +1,5 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), 'test_helper')
3
- require 'tranny'
4
- require 'drb'
5
3
 
6
4
  class TrannyTest < Test::Unit::TestCase
7
5
 
@@ -1,9 +1,5 @@
1
1
 
2
2
  require File.join(File.dirname(__FILE__), 'test_helper')
3
- require 'treasure'
4
- require 'drb'
5
- require 'tranny'
6
- require 'hashish'
7
3
 
8
4
  class TreasureTest < Test::Unit::TestCase
9
5
 
@@ -21,6 +17,18 @@ class TreasureTest < Test::Unit::TestCase
21
17
  DRb.stop_service
22
18
  end
23
19
 
20
+ def test_eval
21
+ t = Time.now
22
+ @c.evaluate!("burk", t, "class Burk; end")
23
+ b = Burk.new
24
+ @c.evaluate!("burk", t, "class Bong; end")
25
+ assert_raise(NameError) do
26
+ b = Bong.new
27
+ end
28
+ @c.evaluate!("burk", Time.now + 10, "class Bong; end")
29
+ b = Bong.new
30
+ end
31
+
24
32
  def test_store_load_update
25
33
  s = "hehu"
26
34
  @c["oj"] = "hehu"
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: archipelago
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2006-11-12 00:00:00 +01:00
6
+ version: 0.1.1
7
+ date: 2006-11-14 00:00:00 +01:00
8
8
  summary: A set of tools for distributed computing in ruby.
9
9
  require_paths:
10
10
  - lib
@@ -29,12 +29,12 @@ authors:
29
29
  - Martin Kihlgren
30
30
  files:
31
31
  - lib/archipelago.rb
32
- - lib/current.rb
33
- - lib/disco.rb
34
- - lib/hashish.rb
35
- - lib/pirate.rb
36
- - lib/tranny.rb
37
- - lib/treasure.rb
32
+ - lib/archipelago/current.rb
33
+ - lib/archipelago/disco.rb
34
+ - lib/archipelago/hashish.rb
35
+ - lib/archipelago/pirate.rb
36
+ - lib/archipelago/tranny.rb
37
+ - lib/archipelago/treasure.rb
38
38
  - scripts/chest.rb
39
39
  - scripts/console
40
40
  - scripts/pirate.rb