From nobody at rubyforge.org Sun Sep 30 08:36:56 2007
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 30 Sep 2007 08:36:56 -0400 (EDT)
Subject: [Archipelago-submits] [325] trunk/archipelago: created a simplified
queue class for disco to use.
Message-ID: <20070930123657.06FB95240A22@rubyforge.org>
Revision: 325
Author: zond
Date: 2007-09-30 08:36:56 -0400 (Sun, 30 Sep 2007)
Log Message:
-----------
created a simplified queue class for disco to use. greatly improved the running of tests.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/current.rb
trunk/archipelago/lib/archipelago/disco.rb
trunk/archipelago/tests/current_test.rb
Modified: trunk/archipelago/lib/archipelago/current.rb
===================================================================
--- trunk/archipelago/lib/archipelago/current.rb 2007-06-06 22:33:09 UTC (rev 324)
+++ trunk/archipelago/lib/archipelago/current.rb 2007-09-30 12:36:56 UTC (rev 325)
@@ -222,6 +222,47 @@
attr_reader :mon_entering_queue
end
+ class Queue
+ def initialize
+ @ary = []
+ @lock = Archipelago::Current::Lock.new
+ @shift_semaphore = MonitorMixin::ConditionVariable.new(@lock)
+ @push_semaphore = MonitorMixin::ConditionVariable.new(@lock)
+ end
+ def <<(o)
+ @lock.synchronize do
+ @ary << o
+ @push_semaphore.broadcast
+ end
+ end
+ def shift
+ @lock.synchronize do
+ @ary.shift
+ @shift_semaphore.broadcast
+ end
+ end
+ def empty?
+ @lock.synchronize do
+ @ary.empty?
+ end
+ end
+ def wait_for_emptiness
+ @lock.synchronize do
+ while !@ary.empty?
+ @shift_semaphore.wait
+ end
+ end
+ end
+ def wait_for_shift
+ @lock.synchronize do
+ @push_semaphore.wait while @ary.empty?
+ rval = @ary.shift
+ @shift_semaphore.broadcast
+ return rval
+ end
+ end
+ end
+
end
-
+
end
Modified: trunk/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2007-06-06 22:33:09 UTC (rev 324)
+++ trunk/archipelago/lib/archipelago/disco.rb 2007-09-30 12:36:56 UTC (rev 325)
@@ -496,8 +496,8 @@
@local_services = ServiceLocker.new(:jockey => self)
@subscribed_services = Set.new
- @incoming = Queue.new
- @outgoing = Queue.new
+ @incoming = Archipelago::Current::Queue.new
+ @outgoing = Archipelago::Current::Queue.new
@new_service_semaphore = MonitorMixin::ConditionVariable.new(Archipelago::Current::Lock.new)
@service_change_subscribers_by_event_type = {:found => {}, :lost => {}}
@@ -603,14 +603,10 @@
@listener.close
@unilistener.close
- while !@incoming.empty?
- sleep 0.1
- end
+ @incoming.wait_for_emptiness
@picker_thread.kill
- while !@outgoing.empty?
- sleep 0.1
- end
+ @outgoing.wait_for_emptiness
@shouter_thread.kill
@sender.close
@unisender.close
@@ -745,7 +741,7 @@
@shouter_thread = Thread.new do
loop do
begin
- recipient, data = @outgoing.shift
+ recipient, data = @outgoing.wait_for_shift
if recipient
address, port = recipient.split(/:/)
@unisender.send(Marshal.dump(data), 0, address, port.to_i)
@@ -808,7 +804,7 @@
@picker_thread = Thread.new do
loop do
begin
- data = @incoming.pop
+ data = @incoming.wait_for_shift
if Archipelago::Disco::Query === data
@local_services.get_services(data).each do |service_id, service_data|
if @thrifty_replying
Modified: trunk/archipelago/tests/current_test.rb
===================================================================
--- trunk/archipelago/tests/current_test.rb 2007-06-06 22:33:09 UTC (rev 324)
+++ trunk/archipelago/tests/current_test.rb 2007-09-30 12:36:56 UTC (rev 325)
@@ -58,14 +58,50 @@
end
end
+ def test_queue
+ q = Archipelago::Current::Queue.new
+ x = false
+ Thread.new do
+ x = q.wait_for_shift
+ end
+ Thread.pass
+ assert(!x)
+ q << true
+ Thread.pass
+ sleep 0.1
+ assert(x)
+
+ q << true
+ Thread.new do
+ q.wait_for_emptiness
+ x = false
+ end
+ Thread.pass
+ assert(x)
+ q.shift
+ Thread.pass
+ sleep 0.1
+ assert(!x)
+
+ y = false
+ q << "plur"
+ Thread.new do
+ q.wait_for_emptiness
+ y = true
+ end
+ q.wait_for_shift
+ sleep 0.1
+ assert(y)
+ end
+
def test_threaded_collection
a = Array(10)
a.extend(Archipelago::Current::ThreadedCollection)
- assert_equal(a.select do |e| e == nil end,
- a.t_select do |e| e == nil end)
- assert_equal(a.reject do |e| e == nil end,
- a.t_reject do |e| e == nil end)
+ assert_equal(a.select do |e| e == nil end.sort,
+ a.t_select do |e| e == nil end.sort)
+ assert_equal(a.reject do |e| e == nil end.sort,
+ a.t_reject do |e| e == nil end.sort)
assert_equal(a.collect do |e| e == nil end,
a.t_collect do |e| e == nil end)
b = []
@@ -75,10 +111,10 @@
a = {1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5}
a.extend(Archipelago::Current::ThreadedCollection)
- assert_equal(a.select do |k,v| k == nil end,
- a.t_select do |k,v| k == nil end)
- assert_equal(a.to_a.reject do |k,v| k == nil end,
- a.t_reject do |k,v| k == nil end)
+ assert_equal(a.select do |k,v| k == nil end.sort,
+ a.t_select do |k,v| k == nil end.sort)
+ assert_equal(a.to_a.reject do |k,v| k == nil end.sort,
+ a.t_reject do |k,v| k == nil end.sort)
assert_equal(a.collect do |k,v| k == nil end,
a.t_collect do |k,c| k == nil end)
From nobody at rubyforge.org Sun Sep 30 14:58:52 2007
From: nobody at rubyforge.org (nobody at rubyforge.org)
Date: Sun, 30 Sep 2007 14:58:52 -0400 (EDT)
Subject: [Archipelago-submits] [326] trunk/archipelago/lib/archipelago: made
the notify_successor! more failsafe by updating the captain
before asking it for the successor.
Message-ID: <20070930185852.A8C575240C28@rubyforge.org>
Revision: 326
Author: zond
Date: 2007-09-30 14:58:52 -0400 (Sun, 30 Sep 2007)
Log Message:
-----------
made the notify_successor! more failsafe by updating the captain before asking it for the successor. made monitormixin not try to wake the dead. made the notification subscribers synchronized to avoid nil problems there.
Modified Paths:
--------------
trunk/archipelago/lib/archipelago/client.rb
trunk/archipelago/lib/archipelago/current.rb
trunk/archipelago/lib/archipelago/disco.rb
trunk/archipelago/lib/archipelago/treasure.rb
Modified: trunk/archipelago/lib/archipelago/client.rb
===================================================================
--- trunk/archipelago/lib/archipelago/client.rb 2007-09-30 12:36:56 UTC (rev 325)
+++ trunk/archipelago/lib/archipelago/client.rb 2007-09-30 18:58:52 UTC (rev 326)
@@ -102,6 +102,11 @@
#
# Make our @jockey lookup all our services.
#
+ # Arguments:
+ # :timeout => The timeout for the disco lookup
+ # :silent => Whether the lookup shall be silent
+ # :validate => Whether the result of the lookup shall be immediately validated
+ #
def update_services!(options = {})
timeout = options[:timeout] || 0
silent = options[:silent] || false
Modified: trunk/archipelago/lib/archipelago/current.rb
===================================================================
--- trunk/archipelago/lib/archipelago/current.rb 2007-09-30 12:36:56 UTC (rev 325)
+++ trunk/archipelago/lib/archipelago/current.rb 2007-09-30 18:58:52 UTC (rev 326)
@@ -29,6 +29,15 @@
end
end
+module MonitorMixin
+ def mon_release
+ @mon_owner = nil
+ t = @mon_waiting_queue.shift
+ t = @mon_entering_queue.shift unless t
+ t.wakeup if t && t.alive?
+ end
+end
+
module Archipelago
module Current
Modified: trunk/archipelago/lib/archipelago/disco.rb
===================================================================
--- trunk/archipelago/lib/archipelago/disco.rb 2007-09-30 12:36:56 UTC (rev 325)
+++ trunk/archipelago/lib/archipelago/disco.rb 2007-09-30 18:58:52 UTC (rev 326)
@@ -467,7 +467,6 @@
# The main discovery class used to both publish and lookup services.
#
class Jockey
-
#
# Will create a Jockey service running on :address and :port or
# ADDRESS and PORT if none are given.
@@ -501,6 +500,7 @@
@new_service_semaphore = MonitorMixin::ConditionVariable.new(Archipelago::Current::Lock.new)
@service_change_subscribers_by_event_type = {:found => {}, :lost => {}}
+ @service_change_subscribers_by_event_type.extend(Archipelago::Current::Synchronized)
@validation_interval = options[:validation_interval] || VALIDATION_INTERVAL
@@ -519,14 +519,18 @@
# Recognized +event_types+: :found, :lost
#
def subscribe(event_type, match, identity, &block)
- @service_change_subscribers_by_event_type[event_type][[match, identity]] = block
+ @service_change_subscribers_by_event_type.synchronize do
+ @service_change_subscribers_by_event_type[event_type][[match, identity]] = block
+ end
end
#
# Will stop listening for +event_type+ and +match+ with +identity+.
#
def unsubscribe(event_type, match, identity)
- @service_change_subscribers_by_event_type[event_type].delete([match, identity])
+ @service_change_subscribers_by_event_type.synchronize do
+ @service_change_subscribers_by_event_type[event_type].delete([match, identity])
+ end
end
#
@@ -703,17 +707,19 @@
# Will notify all subscribers to +event_type+ looking for +record+.
#
def notify_subscribers(event_type, record)
- @service_change_subscribers_by_event_type[event_type].clone.each do |query_and_identity, proc|
- query = query_and_identity.first
- Thread.new do
- begin
- proc.call(record)
- rescue Exception => e
- @service_change_subscribers_by_event_type[event_type].delete(query_and_identity)
- puts e
- pp e.backtrace
- end
- end if record.matches?(query)
+ @service_change_subscribers_by_event_type.synchronize do
+ @service_change_subscribers_by_event_type[event_type].clone.each do |query_and_identity, proc|
+ query = query_and_identity.first
+ Thread.new do
+ begin
+ proc.call(record)
+ rescue Exception => e
+ @service_change_subscribers_by_event_type[event_type].delete(query_and_identity)
+ puts e
+ pp e.backtrace
+ end
+ end if record.matches?(query)
+ end
end
end
Modified: trunk/archipelago/lib/archipelago/treasure.rb
===================================================================
--- trunk/archipelago/lib/archipelago/treasure.rb 2007-09-30 12:36:56 UTC (rev 325)
+++ trunk/archipelago/lib/archipelago/treasure.rb 2007-09-30 18:58:52 UTC (rev 326)
@@ -696,9 +696,11 @@
def around_publish(&block)
notify_successor!
@jockey.subscribe(:lost, @captain.service_descriptions[:chests], service_id) do |record|
+ @captain.chests.delete(record[:service_id])
notify_successor!
end
@jockey.subscribe(:found, @captain.service_descriptions[:chests], service_id) do |record|
+ @captain.chests[record[:service_id]] = record
notify_successor!
end
yield