archipelago 0.2.7 → 0.3.0
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/lib/archipelago.rb +2 -0
- data/lib/archipelago/client.rb +9 -3
- data/lib/archipelago/current.rb +0 -35
- data/lib/archipelago/disco.rb +39 -17
- data/lib/archipelago/dump.rb +1 -0
- data/lib/archipelago/hashish.rb +1 -0
- data/lib/archipelago/pirate.rb +1 -2
- data/lib/archipelago/sanitation.rb +5 -2
- data/lib/archipelago/treasure.rb +28 -7
- data/script/pirate.rb +1 -1
- data/tests/current_test.rb +0 -35
- data/tests/disco_benchmark.rb +2 -2
- data/tests/disco_test.rb +39 -6
- data/tests/pirate_test.rb +8 -4
- data/tests/sanitation_test.rb +24 -4
- metadata +38 -29
data/lib/archipelago.rb
CHANGED
data/lib/archipelago/client.rb
CHANGED
@@ -35,11 +35,13 @@ module Archipelago
|
|
35
35
|
# The timeout that will be used in the first lookup to ensure that we actually
|
36
36
|
# have any services.
|
37
37
|
#
|
38
|
-
INITIAL_LOOKUP_TIMEOUT =
|
38
|
+
INITIAL_LOOKUP_TIMEOUT = 0
|
39
39
|
|
40
40
|
class Base
|
41
41
|
include Archipelago::Disco::Camel
|
42
|
+
|
42
43
|
attr_reader :jockey, :services, :service_descriptions
|
44
|
+
attr_accessor :debug_callable
|
43
45
|
|
44
46
|
#
|
45
47
|
# Initialize a Client using Archipelago::Disco::MC or <i>:jockey</i> if given,
|
@@ -55,6 +57,7 @@ module Archipelago
|
|
55
57
|
@maximum_service_update_interval = options[:maximum_service_update_interval] || MAXIMUM_SERVICE_UPDATE_INTERVAL
|
56
58
|
@service_descriptions = options[:service_descriptions]
|
57
59
|
@initial_lookup_timeout = options[:initial_lookup_timeout] || INITIAL_LOOKUP_TIMEOUT
|
60
|
+
@debug_callable = options[:debug_callable]
|
58
61
|
@services = {}
|
59
62
|
@service_descriptions.each do |name, description|
|
60
63
|
@services[name] = Archipelago::Disco::ServiceLocker.new
|
@@ -101,6 +104,8 @@ module Archipelago
|
|
101
104
|
#
|
102
105
|
def update_services!(options = {})
|
103
106
|
timeout = options[:timeout] || 0
|
107
|
+
silent = options[:silent] || false
|
108
|
+
|
104
109
|
validate = options[:validate] || false
|
105
110
|
around_update_services do
|
106
111
|
@service_descriptions.each do |name, description|
|
@@ -117,10 +122,11 @@ module Archipelago
|
|
117
122
|
# more than on average once every MAXIMUM_SERVICE_UPDATE_INTERVAL, so that MAY make it worthwhile to do
|
118
123
|
# the RBTree song and dance in here. Hopefully.
|
119
124
|
#
|
120
|
-
new_services = @jockey.lookup(Archipelago::Disco::Query.new(description), timeout)
|
125
|
+
new_services = @jockey.lookup(Archipelago::Disco::Query.new(description), :timeout => timeout, :silent => silent)
|
121
126
|
new_services.convert_to_tree!
|
122
127
|
new_services.validate! if validate
|
123
128
|
@services[name] = new_services
|
129
|
+
@debug_callable.call("#{self}.service[#{name.inspect}]: #{PP.pp(@services[name].keys, "")}") if @debug_callable
|
124
130
|
end
|
125
131
|
end
|
126
132
|
end
|
@@ -214,7 +220,7 @@ module Archipelago
|
|
214
220
|
def start_service_updater
|
215
221
|
update_services!(:timeout => @initial_lookup_timeout, :validate => true)
|
216
222
|
@service_update_thread.kill if defined?(@service_update_thread)
|
217
|
-
@service_update_thread = Thread.
|
223
|
+
@service_update_thread = Thread.new do
|
218
224
|
standoff = @initial_service_update_interval
|
219
225
|
loop do
|
220
226
|
begin
|
data/lib/archipelago/current.rb
CHANGED
@@ -33,41 +33,6 @@ module Archipelago
|
|
33
33
|
|
34
34
|
module Current
|
35
35
|
|
36
|
-
class Queue
|
37
|
-
def initialize
|
38
|
-
@lock = Monitor.new
|
39
|
-
@flag = MonitorMixin::ConditionVariable.new(@lock)
|
40
|
-
@ary = []
|
41
|
-
end
|
42
|
-
def <<(e)
|
43
|
-
@lock.synchronize do
|
44
|
-
@ary << e
|
45
|
-
@flag.broadcast
|
46
|
-
end
|
47
|
-
end
|
48
|
-
def empty?(wait = false)
|
49
|
-
@lock.synchronize do
|
50
|
-
if wait
|
51
|
-
@flag.wait_until do
|
52
|
-
@ary.empty?
|
53
|
-
end unless @ary.empty?
|
54
|
-
return @ary.empty?
|
55
|
-
else
|
56
|
-
return @ary.empty?
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
def shift
|
61
|
-
@lock.synchronize do
|
62
|
-
@flag.wait_while do
|
63
|
-
@ary.empty?
|
64
|
-
end if @ary.empty?
|
65
|
-
@flag.broadcast
|
66
|
-
return @ary.shift
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
36
|
#
|
72
37
|
# Adds a few threaded methods to the normal ruby collections.
|
73
38
|
#
|
data/lib/archipelago/disco.rb
CHANGED
@@ -46,7 +46,7 @@ module Archipelago
|
|
46
46
|
#
|
47
47
|
# Default lookup timeout.
|
48
48
|
#
|
49
|
-
LOOKUP_TIMEOUT =
|
49
|
+
LOOKUP_TIMEOUT = 0
|
50
50
|
#
|
51
51
|
# Default initial pause between resending lookup queries.
|
52
52
|
# Will be doubled for each resend.
|
@@ -80,6 +80,7 @@ module Archipelago
|
|
80
80
|
# can include this for simplicity.
|
81
81
|
#
|
82
82
|
module Camel
|
83
|
+
attr_reader :jockey
|
83
84
|
private
|
84
85
|
#
|
85
86
|
# Setup our @jockey as a Archipelago::Disco::Jockey with given options.
|
@@ -311,11 +312,20 @@ module Archipelago
|
|
311
312
|
@attributes = hash
|
312
313
|
end
|
313
314
|
#
|
315
|
+
# To make it Hash and Set friendly.
|
316
|
+
#
|
317
|
+
def hash
|
318
|
+
@attributes.inject(0) do |sum, pair|
|
319
|
+
sum + pair.first.hash + pair.last.hash
|
320
|
+
end
|
321
|
+
end
|
322
|
+
#
|
314
323
|
# Returns whether our @attributes are equal to that of +o+.
|
315
324
|
#
|
316
325
|
def eql?(o)
|
317
326
|
ServiceDescription === o && @attributes == o.attributes
|
318
327
|
end
|
328
|
+
alias :== :eql?
|
319
329
|
#
|
320
330
|
# Returns whether this ServiceDescription matches the given +match+.
|
321
331
|
#
|
@@ -433,7 +443,7 @@ module Archipelago
|
|
433
443
|
#
|
434
444
|
def get_services(match)
|
435
445
|
rval = ServiceLocker.new
|
436
|
-
self.
|
446
|
+
self.each do |service_id, service_data|
|
437
447
|
if service_data.matches?(match)
|
438
448
|
rval[service_id] = service_data
|
439
449
|
end
|
@@ -486,8 +496,8 @@ module Archipelago
|
|
486
496
|
@local_services = ServiceLocker.new(:jockey => self)
|
487
497
|
@subscribed_services = Set.new
|
488
498
|
|
489
|
-
@incoming =
|
490
|
-
@outgoing =
|
499
|
+
@incoming = Queue.new
|
500
|
+
@outgoing = Queue.new
|
491
501
|
|
492
502
|
@new_service_semaphore = MonitorMixin::ConditionVariable.new(Archipelago::Current::Lock.new)
|
493
503
|
@service_change_subscribers_by_event_type = {:found => {}, :lost => {}}
|
@@ -503,6 +513,9 @@ module Archipelago
|
|
503
513
|
# Will listen for +event_type+s matching the Query +match+
|
504
514
|
# and do +block+.call with the matching Record.
|
505
515
|
#
|
516
|
+
# +identity+ is used to determine what subscription to remove
|
517
|
+
# when doing unsubscribe.
|
518
|
+
#
|
506
519
|
# Recognized +event_types+: :found, :lost
|
507
520
|
#
|
508
521
|
def subscribe(event_type, match, identity, &block)
|
@@ -510,7 +523,7 @@ module Archipelago
|
|
510
523
|
end
|
511
524
|
|
512
525
|
#
|
513
|
-
# Will stop listening for +event_type+ and +match+.
|
526
|
+
# Will stop listening for +event_type+ and +match+ with +identity+.
|
514
527
|
#
|
515
528
|
def unsubscribe(event_type, match, identity)
|
516
529
|
@service_change_subscribers_by_event_type[event_type].delete([match, identity])
|
@@ -588,12 +601,16 @@ module Archipelago
|
|
588
601
|
@listener_thread.kill
|
589
602
|
@unilistener_thread.kill
|
590
603
|
|
591
|
-
@incoming.empty?(true)
|
592
|
-
@picker_thread.kill
|
593
604
|
@listener.close
|
594
605
|
@unilistener.close
|
595
|
-
|
596
|
-
|
606
|
+
while !@incoming.empty?
|
607
|
+
sleep 0.1
|
608
|
+
end
|
609
|
+
@picker_thread.kill
|
610
|
+
|
611
|
+
while !@outgoing.empty?
|
612
|
+
sleep 0.1
|
613
|
+
end
|
597
614
|
@shouter_thread.kill
|
598
615
|
@sender.close
|
599
616
|
@unisender.close
|
@@ -603,36 +620,41 @@ module Archipelago
|
|
603
620
|
end
|
604
621
|
|
605
622
|
#
|
606
|
-
# Lookup any services matching +match+, optionally
|
623
|
+
# Lookup any services matching +match+, optionally
|
624
|
+
# with a +:timeout+ and optionally +:silent+.
|
607
625
|
#
|
608
626
|
# Will immediately return if we know of matching and valid services,
|
609
627
|
# will otherwise send out regular Queries and return as soon as
|
610
628
|
# matching services are found, or when the +timeout+ runs out.
|
611
629
|
#
|
612
|
-
def lookup(match,
|
630
|
+
def lookup(match, options = {})
|
631
|
+
timeout = options[:timeout] || @lookup_timeout
|
632
|
+
silent = options[:silent] || false
|
633
|
+
|
613
634
|
match[:unicast_reply] = @unicast_address
|
614
635
|
@subscribed_services << match if @thrifty_caching
|
615
636
|
standoff = @initial_lookup_standoff
|
616
637
|
|
617
|
-
@outgoing << [nil, match]
|
638
|
+
@outgoing << [nil, match] unless silent
|
618
639
|
known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
|
619
640
|
return known_services if timeout == 0 || !known_services.empty?
|
620
641
|
|
621
642
|
t = Time.new
|
622
643
|
@new_service_semaphore.wait([standoff, timeout].min)
|
623
644
|
standoff *= 2
|
624
|
-
|
645
|
+
|
625
646
|
while Time.new < t + timeout
|
626
647
|
known_services = @remote_services.get_services(match).merge(@local_services.get_services(match))
|
627
648
|
return known_services unless known_services.empty?
|
628
649
|
|
629
|
-
|
650
|
+
wait_time = [standoff, (t + timeout) - Time.new].min
|
651
|
+
@new_service_semaphore.wait(wait_time)
|
630
652
|
standoff *= 2
|
631
653
|
|
632
|
-
@outgoing << [nil, match]
|
654
|
+
@outgoing << [nil, match] unless silent
|
633
655
|
end
|
634
656
|
|
635
|
-
ServiceLocker.new
|
657
|
+
return ServiceLocker.new
|
636
658
|
end
|
637
659
|
|
638
660
|
#
|
@@ -786,7 +808,7 @@ module Archipelago
|
|
786
808
|
@picker_thread = Thread.new do
|
787
809
|
loop do
|
788
810
|
begin
|
789
|
-
data = @incoming.
|
811
|
+
data = @incoming.pop
|
790
812
|
if Archipelago::Disco::Query === data
|
791
813
|
@local_services.get_services(data).each do |service_id, service_data|
|
792
814
|
if @thrifty_replying
|
data/lib/archipelago/dump.rb
CHANGED
@@ -85,6 +85,7 @@ module Archipelago
|
|
85
85
|
# Any values with a different timestamp will be deleted.
|
86
86
|
#
|
87
87
|
def insert!(key, values, timestamp = "\000\000\000\000")
|
88
|
+
@debug_callable.call("#{self.service_id}.insert!(#{key}, #{values.inspect}, #{timestamp.inspect}) called") if @debug_callable
|
88
89
|
if (duplicates = @db.duplicates(key)).empty?
|
89
90
|
values.each do |value|
|
90
91
|
@db[key] = timestamp + value
|
data/lib/archipelago/hashish.rb
CHANGED
data/lib/archipelago/pirate.rb
CHANGED
@@ -21,7 +21,6 @@ require 'archipelago/treasure'
|
|
21
21
|
require 'archipelago/client'
|
22
22
|
require 'pp'
|
23
23
|
require 'drb'
|
24
|
-
require 'digest/sha1'
|
25
24
|
|
26
25
|
module Archipelago
|
27
26
|
|
@@ -251,7 +250,7 @@ module Archipelago
|
|
251
250
|
def responsible_chest(key)
|
252
251
|
raise NoRemoteDatabaseAvailableException.new(self) if self.chests.empty?
|
253
252
|
|
254
|
-
return get_least_greater_than(:chests,
|
253
|
+
return get_least_greater_than(:chests, key, 1).first
|
255
254
|
end
|
256
255
|
|
257
256
|
#
|
@@ -17,6 +17,8 @@
|
|
17
17
|
|
18
18
|
require 'archipelago/client'
|
19
19
|
require 'archipelago/dump'
|
20
|
+
require 'rubygems'
|
21
|
+
require 'oneliner'
|
20
22
|
require 'monitor'
|
21
23
|
require 'drb'
|
22
24
|
|
@@ -93,7 +95,7 @@ module Archipelago
|
|
93
95
|
|
94
96
|
options.merge!({
|
95
97
|
:service_descriptions => {
|
96
|
-
:sites =>
|
98
|
+
:sites => SITE_DESCRIPTION.merge(options[:site_description] || {})
|
97
99
|
}
|
98
100
|
})
|
99
101
|
setup_client(options)
|
@@ -115,6 +117,7 @@ module Archipelago
|
|
115
117
|
dump_hash = responsible_sites(key)
|
116
118
|
super_string.encode(8)
|
117
119
|
dump_hash.t_each do |dump_id, nr_of_chunks_needed|
|
120
|
+
@debug_callable.call("calling #{dump_id}.insert!(#{key}, ..., #{t})") if @debug_callable
|
118
121
|
self.sites[dump_id][:service].insert!(key,
|
119
122
|
(0...nr_of_chunks_needed).collect do |nr_of_chunks_needed|
|
120
123
|
super_string.encode(chunk_size)
|
@@ -243,7 +246,7 @@ module Archipelago
|
|
243
246
|
end
|
244
247
|
end
|
245
248
|
|
246
|
-
if rval.
|
249
|
+
if rval.done?
|
247
250
|
return [rval.to_s, newest_timestamp]
|
248
251
|
else
|
249
252
|
raise NotEnoughDataException.new(self, key) if newest_timestamp != "\000\000\000\000"
|
data/lib/archipelago/treasure.rb
CHANGED
@@ -57,7 +57,7 @@ module Archipelago
|
|
57
57
|
#
|
58
58
|
class WrongChestException < RuntimeError
|
59
59
|
def initialize(chest_id, predecessor_id, key)
|
60
|
-
super("#{key.inspect} is not between #{predecessor_id} and #{chest_id}, and should not be here")
|
60
|
+
super("#{key.inspect} is not between my predecessor (#{predecessor_id}) and me (#{chest_id}), and should not be here")
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -118,6 +118,17 @@ module Archipelago
|
|
118
118
|
# method call itself within the home Chest of the proxied object.
|
119
119
|
#
|
120
120
|
class Dubloon
|
121
|
+
@@debug_callable = nil
|
122
|
+
def self.debug_callable=(c)
|
123
|
+
@@debug_callable = c
|
124
|
+
end
|
125
|
+
#
|
126
|
+
# Will return whether +o+ is an instance of Dubloon or one
|
127
|
+
# of its subclasses.
|
128
|
+
#
|
129
|
+
def self.dubloon?(o)
|
130
|
+
return o.respond_to?(:dubloon?) && o.dubloon?
|
131
|
+
end
|
121
132
|
#
|
122
133
|
# Remove all methods so that we look like our target.
|
123
134
|
#
|
@@ -138,12 +149,18 @@ module Archipelago
|
|
138
149
|
self.==(o)
|
139
150
|
end
|
140
151
|
#
|
141
|
-
#
|
152
|
+
# Will return that this is a Dubloon.
|
153
|
+
#
|
154
|
+
def dubloon?
|
155
|
+
true
|
156
|
+
end
|
157
|
+
#
|
158
|
+
# If +o+ is a Dubloon, will return true if it has the same Dubloon#object_id.
|
142
159
|
#
|
143
160
|
# Otherwise will defer to Dubloon#method_missing.
|
144
161
|
#
|
145
162
|
def ==(o)
|
146
|
-
if Dubloon
|
163
|
+
if Dubloon.dubloon?(o)
|
147
164
|
return true if self.object_id == o.object_id
|
148
165
|
end
|
149
166
|
return self.method_missing(:==, o)
|
@@ -202,7 +219,7 @@ module Archipelago
|
|
202
219
|
# @chest_id, @key and possibly @transaction.
|
203
220
|
#
|
204
221
|
def object_id
|
205
|
-
id = "
|
222
|
+
id = "Archipelago::Treasure::Dubloon:#{@key}@#{@chest_id}"
|
206
223
|
id << ":#{@transaction.transaction_id}" if @transaction
|
207
224
|
return id
|
208
225
|
end
|
@@ -222,6 +239,7 @@ module Archipelago
|
|
222
239
|
begin
|
223
240
|
return @chest.call_instance_method(@key, meth, @transaction, *args, &block)
|
224
241
|
rescue WrongChestException => e
|
242
|
+
@@debug_callable.call("#{self.object_id} got #{e} when trying to call #{meth}.#{args}") if @@debug_callable
|
225
243
|
#
|
226
244
|
# We just have to find the new chest we belong at now...
|
227
245
|
#
|
@@ -237,6 +255,7 @@ module Archipelago
|
|
237
255
|
|
238
256
|
retry
|
239
257
|
rescue DRb::DRbConnError => e
|
258
|
+
@@debug_callable.call("#{self.object_id} got #{e} when trying to call #{meth}.#{args}") if @@debug_callable
|
240
259
|
#
|
241
260
|
# Here is some fancy rescuing being done.
|
242
261
|
#
|
@@ -289,6 +308,8 @@ module Archipelago
|
|
289
308
|
#
|
290
309
|
include Archipelago::Disco::Publishable
|
291
310
|
|
311
|
+
attr_reader :captain
|
312
|
+
|
292
313
|
#
|
293
314
|
# Initialize a Chest
|
294
315
|
#
|
@@ -438,7 +459,7 @@ module Archipelago
|
|
438
459
|
instance = ensure_instance_with_transaction(key, transaction)
|
439
460
|
return nil unless instance
|
440
461
|
|
441
|
-
if Dubloon
|
462
|
+
if Dubloon.dubloon?(instance)
|
442
463
|
return instance.join(transaction)
|
443
464
|
else
|
444
465
|
return Dubloon.new(key, self, transaction, self.service_id)
|
@@ -890,7 +911,7 @@ module Archipelago
|
|
890
911
|
#
|
891
912
|
def set(key, value, transaction)
|
892
913
|
join!(transaction)
|
893
|
-
if Dubloon
|
914
|
+
if Dubloon.dubloon?(value)
|
894
915
|
value.assert_transaction(transaction)
|
895
916
|
#
|
896
917
|
# Return the value if the value is in fact a proxy to what we are trying overwrite.
|
@@ -920,7 +941,7 @@ module Archipelago
|
|
920
941
|
@db[key] = value
|
921
942
|
end
|
922
943
|
|
923
|
-
return value if Dubloon
|
944
|
+
return value if Dubloon.dubloon?(value)
|
924
945
|
|
925
946
|
return Dubloon.new(key, self, transaction, service_id)
|
926
947
|
end
|
data/script/pirate.rb
CHANGED
data/tests/current_test.rb
CHANGED
@@ -19,41 +19,6 @@ end
|
|
19
19
|
|
20
20
|
class CurrentTest < Test::Unit::TestCase
|
21
21
|
|
22
|
-
def test_queue
|
23
|
-
q = Archipelago::Current::Queue.new
|
24
|
-
assert(q.empty?)
|
25
|
-
t = true
|
26
|
-
Thread.new do
|
27
|
-
e = q.shift
|
28
|
-
t = false
|
29
|
-
end
|
30
|
-
Thread.pass
|
31
|
-
assert(t)
|
32
|
-
q << "blar"
|
33
|
-
Thread.pass
|
34
|
-
sleep(0.1)
|
35
|
-
assert(!t)
|
36
|
-
|
37
|
-
q << "bunke"
|
38
|
-
assert(!q.empty?)
|
39
|
-
q.shift
|
40
|
-
assert(q.empty?)
|
41
|
-
|
42
|
-
assert(q.empty?)
|
43
|
-
q << "hehu"
|
44
|
-
assert(!q.empty?)
|
45
|
-
Thread.new do
|
46
|
-
q.empty?(true)
|
47
|
-
t = true
|
48
|
-
end
|
49
|
-
Thread.pass
|
50
|
-
assert(!t)
|
51
|
-
q.shift
|
52
|
-
Thread.pass
|
53
|
-
assert(t)
|
54
|
-
assert(q.empty?)
|
55
|
-
end
|
56
|
-
|
57
22
|
def test_synchronized
|
58
23
|
t = true
|
59
24
|
|
data/tests/disco_benchmark.rb
CHANGED
@@ -9,12 +9,12 @@ class DiscoBenchmark < Test::Unit::TestCase
|
|
9
9
|
x = 0
|
10
10
|
bm("Jockey#publish/lookup", :n => 10) do
|
11
11
|
dj1.publish(Archipelago::Disco::Record.new({:service_id => x.to_s, :validator => Archipelago::Disco::MockValidator.new}))
|
12
|
-
assert(!dj2.lookup(Archipelago::Disco::Query.new({:service_id => x.to_s})).empty?)
|
12
|
+
assert(!dj2.lookup(Archipelago::Disco::Query.new({:service_id => x.to_s}), :timeout => 2).empty?)
|
13
13
|
x += 1
|
14
14
|
end
|
15
15
|
dj1.publish(Archipelago::Disco::Record.new({:service_id => "brappa", :validator => Archipelago::Disco::MockValidator.new}))
|
16
16
|
bm("Jockey#lookup", :n => 10) do
|
17
|
-
assert(!dj2.lookup(Archipelago::Disco::Query.new({:service_id => "brappa"})).empty?)
|
17
|
+
assert(!dj2.lookup(Archipelago::Disco::Query.new({:service_id => "brappa"}), :timeout => 2).empty?)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/tests/disco_test.rb
CHANGED
@@ -24,7 +24,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
24
24
|
:validator => DRbObject.new(@v1),
|
25
25
|
:epa => "blar")
|
26
26
|
@d1.publish(@p1)
|
27
|
-
assert(!@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar")).empty?)
|
27
|
+
assert(!@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), :timeout => 2).empty?)
|
28
28
|
|
29
29
|
@listener = UDPSocket.new
|
30
30
|
@listener.setsockopt(Socket::IPPROTO_IP,
|
@@ -76,7 +76,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
76
76
|
|
77
77
|
empty = true
|
78
78
|
Thread.new do
|
79
|
-
empty = @d2.lookup(Archipelago::Disco::Query.new(:epa => "blar2")).empty?
|
79
|
+
empty = @d2.lookup(Archipelago::Disco::Query.new(:epa => "blar2"), :timeout => 2).empty?
|
80
80
|
end
|
81
81
|
|
82
82
|
assert(empty)
|
@@ -93,6 +93,39 @@ class DiscoTest < Test::Unit::TestCase
|
|
93
93
|
assert(!found_wrong)
|
94
94
|
end
|
95
95
|
|
96
|
+
def test_unsubscribe
|
97
|
+
@v1.valid = false
|
98
|
+
|
99
|
+
lost_it = false
|
100
|
+
|
101
|
+
@d2.subscribe(:lost, Archipelago::Disco::Query.new(:epa => "blar"), 1) do
|
102
|
+
lost_it = true
|
103
|
+
end
|
104
|
+
@d2.unsubscribe(:lost, Archipelago::Disco::Query.new(:epa => "blar"), 1)
|
105
|
+
|
106
|
+
assert(@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), :timeout => 0).validate!.empty?)
|
107
|
+
|
108
|
+
@d2.validate!
|
109
|
+
|
110
|
+
assert(!lost_it)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_subscribe
|
114
|
+
@v1.valid = false
|
115
|
+
|
116
|
+
lost_it = false
|
117
|
+
|
118
|
+
@d2.subscribe(:lost, Archipelago::Disco::Query.new(:epa => "blar"), 1) do
|
119
|
+
lost_it = true
|
120
|
+
end
|
121
|
+
|
122
|
+
assert(@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), :timeout => 0).validate!.empty?)
|
123
|
+
|
124
|
+
@d2.validate!
|
125
|
+
|
126
|
+
assert(lost_it)
|
127
|
+
end
|
128
|
+
|
96
129
|
def test_publish_invalidate
|
97
130
|
@v1.valid = false
|
98
131
|
|
@@ -110,7 +143,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
110
143
|
end
|
111
144
|
@d2.unsubscribe(:lost, Archipelago::Disco::Query.new(:epa => "blarx"), 2)
|
112
145
|
|
113
|
-
assert(@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), 0).validate!.empty?)
|
146
|
+
assert(@d2.lookup(Archipelago::Disco::Query.new(:epa => "blar"), :timeout => 0).validate!.empty?)
|
114
147
|
|
115
148
|
@d2.validate!
|
116
149
|
|
@@ -147,7 +180,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
147
180
|
assert(@ltq.empty?, "we got messages while we shouldnt: #{@ltq.inspect}")
|
148
181
|
|
149
182
|
c1 = Archipelago::Disco::Jockey.new(:thrifty_publishing => true)
|
150
|
-
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad => "ja")).empty?)
|
183
|
+
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad => "ja"), :timeout => 2).empty?)
|
151
184
|
|
152
185
|
c1.stop!
|
153
186
|
c3.stop!
|
@@ -159,7 +192,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
159
192
|
:service_id => 3444))
|
160
193
|
|
161
194
|
@ltq.clear
|
162
|
-
assert(!@d2.lookup(Archipelago::Disco::Query.new(:gladaa => "jaaa")).empty?)
|
195
|
+
assert(!@d2.lookup(Archipelago::Disco::Query.new(:gladaa => "jaaa"), :timeout => 2).empty?)
|
163
196
|
assert(@ltq.any? do |d|
|
164
197
|
o = Marshal.load(d)
|
165
198
|
case o
|
@@ -181,7 +214,7 @@ class DiscoTest < Test::Unit::TestCase
|
|
181
214
|
@ltq.clear
|
182
215
|
|
183
216
|
c1 = Archipelago::Disco::Jockey.new
|
184
|
-
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad2 => "ja2"), 2).empty?)
|
217
|
+
assert(!c1.lookup(Archipelago::Disco::Query.new(:glad2 => "ja2"), :timeout => 2).empty?)
|
185
218
|
|
186
219
|
assert(!@ltq.any? do |data|
|
187
220
|
o = Marshal.load(data)
|
data/tests/pirate_test.rb
CHANGED
@@ -111,6 +111,7 @@ class PirateTest < Test::Unit::TestCase
|
|
111
111
|
|
112
112
|
p2 = Archipelago::Pirate::Captain.new(:chest_description => {:class => "TestChest"},
|
113
113
|
:tranny_description => {:class => "TestManager"},
|
114
|
+
:initial_lookup_timeout => 5,
|
114
115
|
:chest_eval_files => [File.join(File.dirname(__FILE__), 'evaltest')])
|
115
116
|
|
116
117
|
assert_within(10) do
|
@@ -185,13 +186,16 @@ class PirateTest < Test::Unit::TestCase
|
|
185
186
|
end
|
186
187
|
|
187
188
|
def test_wrong_chest_exception
|
188
|
-
|
189
|
-
|
190
|
-
|
189
|
+
k = Digest::SHA1.hexdigest("hehu")
|
190
|
+
resp_ch = @p.responsible_chest(k)[:service]
|
191
|
+
irresp_ch = resp_ch == @c2 ? @c : @c2
|
191
192
|
begin
|
192
193
|
$DO_ASSERT_MINE = true
|
193
194
|
assert_raise(Archipelago::Treasure::WrongChestException) do
|
194
|
-
|
195
|
+
irresp_ch.call_instance_method(k, :bruhuf, nil)
|
196
|
+
end
|
197
|
+
assert_raise(Archipelago::Treasure::UnknownObjectException) do
|
198
|
+
resp_ch.call_instance_method(k, :bruff, nil)
|
195
199
|
end
|
196
200
|
ensure
|
197
201
|
$DO_ASSERT_MINE = false
|
data/tests/sanitation_test.rb
CHANGED
@@ -74,6 +74,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
74
74
|
dumps = []
|
75
75
|
cleaner2 = Archipelago::Sanitation::Officer.new(:minimum_nr_of_chunks => 3,
|
76
76
|
:initial_lookup_timeout => 0)
|
77
|
+
print "(setup cleaner)"
|
78
|
+
STDOUT.flush
|
77
79
|
begin
|
78
80
|
10.times do |n|
|
79
81
|
dumps[n] = Archipelago::Dump::Site.new(:officer => cleaner2,
|
@@ -81,6 +83,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
81
83
|
:persistence_directory => Pathname.new(__FILE__).parent.join("master_test_#{n}.db"))
|
82
84
|
dumps[n].publish!
|
83
85
|
end
|
86
|
+
print "(created dumps)"
|
87
|
+
STDOUT.flush
|
84
88
|
#
|
85
89
|
# Wait until it is alive
|
86
90
|
#
|
@@ -88,6 +92,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
88
92
|
cleaner2.update_services!
|
89
93
|
dumps.collect do |d| d.service_id end.sort == cleaner2.sites.keys.sort
|
90
94
|
end
|
95
|
+
print "(updated services)"
|
96
|
+
STDOUT.flush
|
91
97
|
#
|
92
98
|
# Perform checks on all dumps
|
93
99
|
#
|
@@ -109,6 +115,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
109
115
|
assert_equal(dumps[9].service_id, cleaner2.predecessor(dumps[0].service_id))
|
110
116
|
end
|
111
117
|
end
|
118
|
+
print "(tested relations)"
|
119
|
+
STDOUT.flush
|
112
120
|
#
|
113
121
|
# Check that only fresh data is returned
|
114
122
|
#
|
@@ -121,6 +129,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
121
129
|
assert(cleaner2.responsible_sites("a").include?(dumps[0].service_id))
|
122
130
|
assert(cleaner2.responsible_sites("a").include?(dumps[1].service_id))
|
123
131
|
assert_equal(s2.to_s, cleaner2["a"])
|
132
|
+
print "(tested timestamps)"
|
133
|
+
STDOUT.flush
|
124
134
|
#
|
125
135
|
# Check the utility methods of sanitation
|
126
136
|
#
|
@@ -136,6 +146,8 @@ class SanitationTest < Test::Unit::TestCase
|
|
136
146
|
cleaner2.second_master_to(dumps[4].service_id))
|
137
147
|
assert_equal(dumps[9].service_id,
|
138
148
|
cleaner2.second_master_to(dumps[0].service_id))
|
149
|
+
print "(tested recovery relations)"
|
150
|
+
STDOUT.flush
|
139
151
|
#
|
140
152
|
# Check the recovery methods
|
141
153
|
#
|
@@ -167,41 +179,49 @@ class SanitationTest < Test::Unit::TestCase
|
|
167
179
|
}
|
168
180
|
assert_equal(healthy_chunks,
|
169
181
|
chunks_by_id(cleaner2, "a"))
|
182
|
+
print "(tested basic recovery)"
|
183
|
+
STDOUT.flush
|
170
184
|
dumps[1].close!
|
171
185
|
cleaner2.update_services!(:validate => true)
|
172
186
|
dumps[0].instance_eval do lost_peer({:service_id => dumps[1].service_id}) end
|
173
187
|
dumps[2].instance_eval do lost_peer({:service_id => dumps[1].service_id}) end
|
174
188
|
assert_equal({"6"=>0, "7"=>0, "8"=>0, "9"=>0, "0"=>1, "2"=>1, "3"=>1, "4"=>0, "5"=>0},
|
175
189
|
chunks_by_id(cleaner2, "a"))
|
176
|
-
|
190
|
+
print "(tore down service)"
|
177
191
|
dumps[1] = Archipelago::Dump::Site.new(:officer => cleaner2,
|
178
192
|
:service_description => {:service_id => "1"},
|
179
193
|
:persistence_directory => Pathname.new(__FILE__).parent.join("master_test_1.db"))
|
180
194
|
dumps[1].publish!
|
181
195
|
begin
|
182
196
|
assert_within(20) do
|
183
|
-
cleaner2.update_services!
|
197
|
+
cleaner2.update_services!(:validate => true)
|
184
198
|
["0","1","2","3","4","5","6","7","8","9"].sort == cleaner2.sites.keys.sort
|
185
199
|
end
|
186
200
|
rescue Test::Unit::AssertionFailedError => e
|
187
201
|
pp chunks_by_id(cleaner2, "a")
|
188
202
|
raise e
|
189
203
|
end
|
204
|
+
print "(restarted service)"
|
205
|
+
STDOUT.flush
|
190
206
|
assert_equal({"0"=>1, "1"=>1, "2"=>1},
|
191
207
|
cleaner2.responsible_sites("a"))
|
208
|
+
|
192
209
|
dumps[3].instance_eval do @edge_check_thread.wakeup end
|
193
|
-
|
210
|
+
|
194
211
|
begin
|
195
212
|
assert_within(20) do
|
213
|
+
cleaner2.update_services!(:validate => true)
|
196
214
|
chunks_by_id(cleaner2, "a") == healthy_chunks
|
197
215
|
end
|
198
216
|
rescue Test::Unit::AssertionFailedError => e
|
199
217
|
pp chunks_by_id(cleaner2, "a")
|
200
218
|
raise e
|
201
219
|
end
|
220
|
+
print "(asserted auto recovery)"
|
221
|
+
STDOUT.flush
|
202
222
|
ensure
|
203
223
|
dumps.extend(Archipelago::Current::ThreadedCollection)
|
204
|
-
dumps.
|
224
|
+
dumps.each do |dump|
|
205
225
|
dump.close!
|
206
226
|
dump.instance_eval do @persistence_provider.unlink! end
|
207
227
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: archipelago
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-06-07 00:00:00 +02:00
|
8
8
|
summary: A set of tools for distributed computing in ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,46 +29,46 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Martin Kihlgren
|
31
31
|
files:
|
32
|
-
- lib/archipelago/
|
33
|
-
- lib/archipelago/current.rb
|
34
|
-
- lib/archipelago/disco.rb
|
35
|
-
- lib/archipelago/dump.rb
|
32
|
+
- lib/archipelago/tranny.rb
|
36
33
|
- lib/archipelago/hashish.rb
|
34
|
+
- lib/archipelago/dump.rb
|
35
|
+
- lib/archipelago/current.rb
|
36
|
+
- lib/archipelago/treasure.rb
|
37
|
+
- lib/archipelago/client.rb
|
37
38
|
- lib/archipelago/pirate.rb
|
39
|
+
- lib/archipelago/disco.rb
|
38
40
|
- lib/archipelago/sanitation.rb
|
39
|
-
- lib/archipelago/tranny.rb
|
40
|
-
- lib/archipelago/treasure.rb
|
41
41
|
- lib/archipelago.rb
|
42
|
-
- tests/
|
43
|
-
- tests/
|
44
|
-
- tests/disco_benchmark.rb
|
45
|
-
- tests/disco_test.rb
|
46
|
-
- tests/dump_test.rb
|
42
|
+
- tests/test_helper.rb
|
43
|
+
- tests/treasure_benchmark.rb
|
47
44
|
- tests/evaltest
|
48
45
|
- tests/evaltestmore
|
49
|
-
- tests/
|
46
|
+
- tests/treasure_test.rb
|
47
|
+
- tests/tranny_test.rb
|
48
|
+
- tests/current_benchmark.rb
|
50
49
|
- tests/sanitation_benchmark.rb
|
50
|
+
- tests/dump_test.rb
|
51
51
|
- tests/sanitation_test.rb
|
52
|
-
- tests/
|
53
|
-
- tests/
|
54
|
-
- tests/
|
55
|
-
- tests/
|
56
|
-
- script/console.rb
|
57
|
-
- script/officer.rb
|
52
|
+
- tests/current_test.rb
|
53
|
+
- tests/pirate_test.rb
|
54
|
+
- tests/disco_test.rb
|
55
|
+
- tests/disco_benchmark.rb
|
58
56
|
- script/overloads.rb
|
59
|
-
- script/pirate.rb
|
60
57
|
- script/services.rb
|
58
|
+
- script/officer.rb
|
59
|
+
- script/console.rb
|
60
|
+
- script/pirate.rb
|
61
61
|
- GPL-2
|
62
62
|
- TODO
|
63
63
|
- README
|
64
64
|
test_files:
|
65
|
-
- tests/
|
66
|
-
- tests/
|
65
|
+
- tests/treasure_test.rb
|
66
|
+
- tests/tranny_test.rb
|
67
67
|
- tests/dump_test.rb
|
68
|
-
- tests/pirate_test.rb
|
69
68
|
- tests/sanitation_test.rb
|
70
|
-
- tests/
|
71
|
-
- tests/
|
69
|
+
- tests/current_test.rb
|
70
|
+
- tests/pirate_test.rb
|
71
|
+
- tests/disco_test.rb
|
72
72
|
- tests/test_helper.rb
|
73
73
|
rdoc_options:
|
74
74
|
- --line-numbers
|
@@ -89,7 +89,16 @@ dependencies:
|
|
89
89
|
requirements:
|
90
90
|
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
|
-
version: 0.
|
92
|
+
version: 0.3.0
|
93
|
+
version:
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: fastthread
|
96
|
+
version_requirement:
|
97
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.0.0
|
93
102
|
version:
|
94
103
|
- !ruby/object:Gem::Dependency
|
95
104
|
name: archipelago_rbtree
|
@@ -98,5 +107,5 @@ dependencies:
|
|
98
107
|
requirements:
|
99
108
|
- - ">="
|
100
109
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.
|
110
|
+
version: 0.3.0
|
102
111
|
version:
|