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
writeoperation -
take -
Sends an event when a tuple is deleted from the tuplespace via a
takeoperation -
delete -
Sends an event when a tuple is deleted from the tuplespace, either when the tuple is deleted on expiration or by a
canceloperation
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.
eventis 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 ifnilis specified. Thenotifyobject returns aNotifyTemplateEntryobject. When the time period specified insechas passed, then the event notification terminates. When the termination happens, it generates acloseevent 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
cancelafter certain events have arrived, you can access them viapop. Once all events have arrived, it sends acloseevent 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.