7.2 Adding Notifications for New Events
Rinda has some additional features that don’t exist in Linda. notify
is a function to send a notification event when a tuple you’re interested in is deleted or added. You can use it to monitor when some tuples are deleted, or you can use it for debugging purposes.
There are three different events: write
, take
, and delete
.
-
write
-
Sends an event when a tuple is added to the tuplespace via a
write
operation -
take
-
Sends an event when a tuple is deleted from the tuplespace via a
take
operation -
delete
-
Sends an event when a tuple is deleted from the tuplespace, either when the tuple is deleted on expiration or by a
cancel
operation
Events are represented as a tuple in combination with the event name and the tuple itself. When the following tuple is written...
ts.write(["Hello", "World"]) |
then the following event gets notified:
["write", ["Hello", "World"]] |
When the following tuple is taken...
ts.take(["Hello", nil]) |
then the following event gets notified:
["take", ["Hello", "World"]] |
So, how do you write a script to actually receive these events? Use a notify
event for this purpose. notify
is a method to request event notifications, and you can specify an event name and tuple pattern.
-
notify(event, pattern, sec=nil)
-
Requests to receive events in the tuplespace and receives events about tuples that match the pattern you specified.
event
is the type of event you are interested in. The element of a tuple is the same as normal tuple matching rules, so it notifies all tuples ifnil
is specified. Thenotify
object returns aNotifyTemplateEntry
object. When the time period specified insec
has passed, then the event notification terminates. When the termination happens, it generates aclose
event as the last event.
NotifyTemplateEntry
is an object to retrieve the event you received from notify
methods.
Here are the major methods NotifyTemplateEntry
provides:
-
each
-
Calls a block when an event happens. The event tuples are passed to the block as follows:
["write", ["foo", "bar"]]
-
pop
-
Takes out one event. Blocks if an event hasn’t arrived yet.
-
cancel
-
Cancels event notification requests. Once this is called, new events stop arriving.
If you call
cancel
after certain events have arrived, you can access them viapop
. Once all events have arrived, it sends aclose
event to indicate the end of events.
The following is the code sequence to handle events:
# Request an event notification |
|
notifier = ts.notify(nil, ['test', nil]) |
|
|
|
# Retrieve events |
|
notifier.each do |event, tuple| |
|
... |
|
end |
A NotifyTemplateEntry
object is generated for each tuple pattern that the notify
method requests. This means that multiple streams of event notifications are separated into their own queues and there is no way to guarantee the order among different queues.
For example, if there are events for the [’test’, nil]
pattern and the [’name’, ’rwiki’,nil]
pattern, they belong to different queues, and there are no methods to observe them at the same time. You could combine multiple queues to make them look like one by using a Queue
object, but it doesn’t guarantee the order in which they arrive. Here is a class to combine two notify events into one:
multiplenotify.rb | |
require 'drb/drb' |
|
require 'rinda/rinda' |
|
require 'rinda/tuplespace' |
|
class MultipleNotify |
|
def initialize(ts, event, ary) |
|
@queue = Queue.new |
|
@entry = [] |
|
ary.each do |pattern| |
|
make_listener(ts, event, pattern) |
|
end |
|
end |
|
def pop |
|
@queue.pop |
|
end |
|
def make_listener(ts, event, pattern) |
|
entry = ts.notify(event, pattern) |
|
@entry.push(entry) |
|
Thread.new do |
|
entry.each do |ev| |
|
@queue.push(ev) |
|
end |
|
end |
|
end |
|
end |
To use this class, try the following:
mn = MultipleNotify.new(ts, nil, [['test', nil], ['name', 'rwiki', nil]]) |
|
while true |
|
p mn.pop |
|
end |
The preceding example listens to two events and displays the tuples when notified.