Document handlers.
[irspy-moved-to-github.git] / lib / ZOOM / Pod.pm
index 1907d9b..1c292c8 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Pod.pm,v 1.4 2006-05-10 15:51:10 mike Exp $
+# $Id: Pod.pm,v 1.7 2006-05-11 15:51:36 mike Exp $
 
 package ZOOM::Pod;
 
@@ -30,14 +30,14 @@ ZOOM::Pod - Perl extension for handling pods of concurrent ZOOM connections
  die "$pod->wait() failed with error $err" if $err;
 
  sub completed_search {
-     ($conn, $rs) = @_;
+     ($conn, undef, $rs) = @_;
      print $conn->option("host"), ": found ", $rs->size(), " records\n";
-     $rs->record(0); # Queues a request for the record
+     $rs->records(0, 1, 0); # Queues a request for the record
      return 0;
  }
 
  sub got_record {
-     ($conn, $rs) = @_;
+     ($conn, undef, $rs) = @_;
      $rec = $rs->record(0);
      print $conn->option("host"), ": got $rec = '", $rec->render(), "'\n";
      return 0;
@@ -45,10 +45,41 @@ ZOOM::Pod - Perl extension for handling pods of concurrent ZOOM connections
 
 =head1 DESCRIPTION
 
-I<###>
+C<ZOOM:Pod> provides an API that simplifies asynchronous programming
+using ZOOM.  A pod is a collection of asynchronous connections that
+are run simultaneously to achieve broadcast searching and retrieval.
+When a pod is created, a set of connections (or target-strings to
+connect to) are specified.  Thereafter, they are treated as a unit,
+and methods for searching, option-setting, etc. that are invoked on
+the pod are delegated to each of its members.
+
+The key method on a pod is C<wait()>, which enters a loop accepting
+and dispatching events occurring on any of the connections in the pod.
+Unless interrupted,the loop runs until there are no more events left,
+i.e. no searches are outstanding and no requested records have still
+to be received.
+
+Event dispatching is done by means of callback functions, which can be
+registered for each event.  A registered callback is invoked whenever
+a corresponding event occurs.  A special callback can be nominated to
+handle errors.
 
 =head1 METHODS
 
+=head2 new()
+
+ $pod = new ZOOM::Pod($conn1, $conn2, $conn3);
+ $pod = new ZOOM::Pod("bagel.indexdata.com/gils",
+                      "bagel.indexdata.com/marc");
+
+
+Creates a new pod containing one or more connections.  Each connection
+may be specified either by an existing C<ZOOM::Connection> object,
+which I<must> be asynchronous; or by a ZOOM target string, in which
+case the pod module will make the connection object itself.
+
+Returns the new pod.
+
 =cut
 
 sub new {
@@ -75,15 +106,89 @@ sub new {
     }, $class;
 }
 
+=head2 option()
+
+ $oldElemSet = $pod->option("elementSetName");
+ $pod->option(elementSetName => "b");
+
+Sets a specified option in all the connections in a pod.  Returns the
+old value that the option had in first of the connections in the pod:
+be aware that this value was not necessarily shared by all the members
+of the pod ... but that is true often enough to be useful.
+
+=cut
+
 sub option {
     my $this = shift();
     my($key, $value) = @_;
 
+    my $old = $this->{conn}->[0]->option($key);
     foreach my $conn (@{ $this->{conn} }) {
        $conn->option($key, $value);
     }
+
+    return $old;
 }
 
+=head2 callback()
+
+ $pod->callback(ZOOM::Event::RECV_SEARCH, \&completed_search);
+ $pod->callback("exception", sub { print "never mind: $@\n"; return 0 } );
+
+Registers a callback to be invoked by the pod when an event happens.
+Callback functions are invoked by C<wait()> (q.v.).
+
+When registering a callback, the first argument is an event-code - one
+of those defined in the C<ZOOM::Event> enumeration - and the second is
+a function reference, or equivalently an inline code-fragment.  It is
+acceptable to nominate the same function as the callback for multiple
+events, by multiple invocations of C<callback()>.
+
+When an event occurs during the execution of C<wait()>, the relevant
+callback function is passed four arguments: the connection that the
+event happened on; a state hash-reference associated with the
+connection; the result-set associated with the connection; and the
+event-type (so that a single function that handles events of multiple
+types can switch on the code where necessary).  The callback function
+can handle the event as it wishes, finishing up by returning an
+integer.  If this is zero, then C<wait()> continues as normal; if it
+is anything else, then that value is immediately returned from
+C<wait()>.
+
+So a typical, simple, event-handler might look like this:
+
+ sub got_event {
+      ($conn, $state, $rs, $event) = @_;
+      print "event $event on connection ", $conn->option("host"), "\n";
+      print "Found ", $rs->size(), " records\n"
+         if $event == ZOOM::Event::RECV_SEARCH;
+      return 0;
+ }
+
+In addition to the event-type callbacks discussed above, there is a
+special callback, C<"exception">, which is invoked if an exception
+occurs.  This will nearly always be a ZOOM error, but this can be
+tested using C<ref($@) eq "ZOOM::Exception">.  This callback is
+invoked with the same arguments as described above, except that
+instead of the event-type, the fourth argument is a copy of the
+exception, C<$@>.  Exception-handling callbacks may of course re-throw
+the exception using C<die $@>.
+
+So a simple error-handler might look like this:
+
+ sub got_error {
+      ($conn, $state, $rs, $exception) = @_;
+      if ($exception->isa("ZOOM::Exception")) {
+          print "Caught error $exception -- continuing";
+          return 0;
+      }
+      die $exception;
+ }
+
+I<### state>
+
+=cut
+
 sub callback {
     my $this = shift();
     my($event, $sub) = @_;
@@ -95,6 +200,17 @@ sub callback {
     return $old;
 }
 
+=head2 search_pqf()
+
+I<###>
+
+B<WARNING!>
+An important simplifying assumption is that each connection can only
+have one search active on it at a time - this allows the pod to
+maintain a one-to-one mapping between connections and result-sets.  
+
+=cut
+
 sub search_pqf {
     my $this = shift();
     my($pqf) = @_;
@@ -104,6 +220,12 @@ sub search_pqf {
     }
 }
 
+=head2 wait()
+
+I<###>
+
+=cut
+
 sub wait {
     my $this = shift();
     my $res = 0;