archipelago 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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