1 # $Id: Pod.pm,v 1.7 2006-05-11 15:51:36 mike Exp $
11 # Just register the name
12 ZOOM::Log::mask_str("pod");
13 ZOOM::Log::mask_str("pod_unhandled");
18 ZOOM::Pod - Perl extension for handling pods of concurrent ZOOM connections
24 $pod = new ZOOM::Pod("bagel.indexdata.com/gils",
25 "bagel.indexdata.com/marc");
26 $pod->callback(ZOOM::Event::RECV_SEARCH, \&completed_search);
27 $pod->callback(ZOOM::Event::RECV_RECORD, \&got_record);
28 $pod->search_pqf("the");
30 die "$pod->wait() failed with error $err" if $err;
32 sub completed_search {
33 ($conn, undef, $rs) = @_;
34 print $conn->option("host"), ": found ", $rs->size(), " records\n";
35 $rs->records(0, 1, 0); # Queues a request for the record
40 ($conn, undef, $rs) = @_;
41 $rec = $rs->record(0);
42 print $conn->option("host"), ": got $rec = '", $rec->render(), "'\n";
48 C<ZOOM:Pod> provides an API that simplifies asynchronous programming
49 using ZOOM. A pod is a collection of asynchronous connections that
50 are run simultaneously to achieve broadcast searching and retrieval.
51 When a pod is created, a set of connections (or target-strings to
52 connect to) are specified. Thereafter, they are treated as a unit,
53 and methods for searching, option-setting, etc. that are invoked on
54 the pod are delegated to each of its members.
56 The key method on a pod is C<wait()>, which enters a loop accepting
57 and dispatching events occurring on any of the connections in the pod.
58 Unless interrupted,the loop runs until there are no more events left,
59 i.e. no searches are outstanding and no requested records have still
62 Event dispatching is done by means of callback functions, which can be
63 registered for each event. A registered callback is invoked whenever
64 a corresponding event occurs. A special callback can be nominated to
71 $pod = new ZOOM::Pod($conn1, $conn2, $conn3);
72 $pod = new ZOOM::Pod("bagel.indexdata.com/gils",
73 "bagel.indexdata.com/marc");
76 Creates a new pod containing one or more connections. Each connection
77 may be specified either by an existing C<ZOOM::Connection> object,
78 which I<must> be asynchronous; or by a ZOOM target string, in which
79 case the pod module will make the connection object itself.
89 die "$class with no connections" if @conn == 0;
90 my @state; # Hashrefs with application state associated with connections
91 foreach my $conn (@conn) {
93 $conn = new ZOOM::Connection($conn, 0, async => 1);
94 # The $conn object is always made, even if no there's no
95 # server. Such errors are caught later, by the _check()
111 $oldElemSet = $pod->option("elementSetName");
112 $pod->option(elementSetName => "b");
114 Sets a specified option in all the connections in a pod. Returns the
115 old value that the option had in first of the connections in the pod:
116 be aware that this value was not necessarily shared by all the members
117 of the pod ... but that is true often enough to be useful.
123 my($key, $value) = @_;
125 my $old = $this->{conn}->[0]->option($key);
126 foreach my $conn (@{ $this->{conn} }) {
127 $conn->option($key, $value);
135 $pod->callback(ZOOM::Event::RECV_SEARCH, \&completed_search);
136 $pod->callback("exception", sub { print "never mind: $@\n"; return 0 } );
138 Registers a callback to be invoked by the pod when an event happens.
139 Callback functions are invoked by C<wait()> (q.v.).
141 When registering a callback, the first argument is an event-code - one
142 of those defined in the C<ZOOM::Event> enumeration - and the second is
143 a function reference, or equivalently an inline code-fragment. It is
144 acceptable to nominate the same function as the callback for multiple
145 events, by multiple invocations of C<callback()>.
147 When an event occurs during the execution of C<wait()>, the relevant
148 callback function is passed four arguments: the connection that the
149 event happened on; a state hash-reference associated with the
150 connection; the result-set associated with the connection; and the
151 event-type (so that a single function that handles events of multiple
152 types can switch on the code where necessary). The callback function
153 can handle the event as it wishes, finishing up by returning an
154 integer. If this is zero, then C<wait()> continues as normal; if it
155 is anything else, then that value is immediately returned from
158 So a typical, simple, event-handler might look like this:
161 ($conn, $state, $rs, $event) = @_;
162 print "event $event on connection ", $conn->option("host"), "\n";
163 print "Found ", $rs->size(), " records\n"
164 if $event == ZOOM::Event::RECV_SEARCH;
168 In addition to the event-type callbacks discussed above, there is a
169 special callback, C<"exception">, which is invoked if an exception
170 occurs. This will nearly always be a ZOOM error, but this can be
171 tested using C<ref($@) eq "ZOOM::Exception">. This callback is
172 invoked with the same arguments as described above, except that
173 instead of the event-type, the fourth argument is a copy of the
174 exception, C<$@>. Exception-handling callbacks may of course re-throw
175 the exception using C<die $@>.
177 So a simple error-handler might look like this:
180 ($conn, $state, $rs, $exception) = @_;
181 if ($exception->isa("ZOOM::Exception")) {
182 print "Caught error $exception -- continuing";
194 my($event, $sub) = @_;
196 my $old = $this->{callback}->{$event};
197 $this->{callback}->{$event} = $sub
208 An important simplifying assumption is that each connection can only
209 have one search active on it at a time - this allows the pod to
210 maintain a one-to-one mapping between connections and result-sets.
218 foreach my $i (0..@{ $this->{conn} }-1) {
219 $this->{rs}->[$i] = $this->{conn}->[$i]->search_pqf($pqf);
233 while ((my $i = ZOOM::event($this->{conn})) != 0) {
234 my $conn = $this->{conn}->[$i-1];
235 my $ev = $conn->last_event();
236 my $evstr = ZOOM::event_str($ev);
237 ZOOM::Log::log("pod", "connection ", $i-1, ": $evstr");
242 my $sub = $this->{callback}->{exception};
243 die $@ if !defined $sub;
244 $res = &$sub($conn, $this->{state}->[$i-1],
245 $this->{rs}->[$i-1], $@);
250 my $sub = $this->{callback}->{$ev};
252 $res = &$sub($conn, $this->{state}->[$i-1],
253 $this->{rs}->[$i-1], $ev);
256 ZOOM::Log::log("pod_unhandled", "unhandled event $ev ($evstr)");
274 Mike Taylor, E<lt>mike@indexdata.comE<gt>
276 =head1 COPYRIGHT AND LICENCE
278 Copyright (C) 2006 by Index Data.
280 This library is free software; you can redistribute it and/or modify
281 it under the same terms as Perl itself, either Perl version 5.8.4 or,
282 at your option, any later version of Perl 5 you may have available.