Added routines
[simpleserver-moved-to-github.git] / SimpleServer.pm
index 9dcfe5e..3dc3d2c 100644 (file)
 ##
 ##
 
+## $Log: SimpleServer.pm,v $
+## Revision 1.9  2001-08-29 11:48:36  sondberg
+## Added routines
+##
+##     Net::Z3950::SimpleServer::ScanSuccess
+##     Net::Z3950::SimpleServer::ScanPartial
+##
+## and a bit of documentation.
+##
+## Revision 1.8  2001/08/29 10:29:51  sondberg
+## Added some documentation of scan.
+##
+## Revision 1.7  2001/08/24 14:00:20  sondberg
+## Added support for scan.
+##
+## Revision 1.6  2001/03/13 14:17:15  sondberg
+## Added support for GRS-1.
+##
+
 package Net::Z3950::SimpleServer;
 
 use strict;
@@ -52,18 +71,16 @@ my $count = 0;
 
 sub new {
        my $class = shift;
-       my $args = shift || croak "SimpleServer::new: Usage new(argument hash)";
-       my $self = {};
+       my %args = @_;
+       my $self = \%args;
 
        if ($count) {
                carp "SimpleServer.pm: WARNING: Multithreaded server unsupported";
        }
        $count = 1;
 
-       $self->{INIT} = $args->{INIT};
-       $self->{SEARCH} = $args->{SEARCH} || croak "SimpleServer.pm: ERROR: Unspecified search handler";
-       $self->{FETCH} = $args->{FETCH} || croak "SimpleServer.pm: ERROR: Unspecified fetch handler";
-       $self->{CLOSE} = $args->{CLOSE};
+       croak "SimpleServer.pm: ERROR: Unspecified search handler" unless defined($self->{SEARCH});
+       croak "SimpleServer.pm: ERROR: Unspecified fetch handler" unless defined($self->{FETCH});
 
        bless $self, $class;
        return $self;
@@ -82,6 +99,12 @@ sub launch_server {
        if (defined($self->{CLOSE})) {
                set_close_handler($self->{CLOSE});
        }
+       if (defined($self->{PRESENT})) {
+               set_present_handler($self->{PRESENT});
+       }
+       if (defined($self->{SCAN})) {
+               set_scan_handler($self->{SCAN});
+       }
 
        start_server(@args);
 }
@@ -119,10 +142,9 @@ Net::Z3950::SimpleServer - Simple Perl API for building Z39.50 servers.
 
        my $set_id = $args->{SETNAME};
 
-       my $record = fetch_a_record($args->{OFFSET);
+       my $record = fetch_a_record($args->{OFFSET});
 
        $args->{RECORD} = $record;
-       $args->{LEN} = length($record);
        if (number_of_hits() == $args->{OFFSET}) {      ## Last record in set?
                $args->{LAST} = 1;
        } else {
@@ -133,15 +155,13 @@ Net::Z3950::SimpleServer - Simple Perl API for building Z39.50 servers.
 
   ## Register custom event handlers:
 
-  my $handle = Net::Z3950::SimpleServer->new({
-                                               INIT   =>  \&my_init_handler,
+  my $z = new Net::Z3950::SimpleServer(                INIT   =>  \&my_init_handler,
                                                CLOSE  =>  \&my_close_handler,
                                                SEARCH =>  \&my_search_handler,
-                                               FETCH  =>  \&my_fetch_handler
-                                            });
+                                               FETCH  =>  \&my_fetch_handler);
   ## Launch server:
 
-  $handle->launch_server("ztest.pl", @ARGV);
+  $z->launch_server("ztest.pl", @ARGV);
 
 =head1 DESCRIPTION
 
@@ -171,7 +191,9 @@ of events:
 
   - Initialize request
   - Search request
+  - Present request
   - Fetching of records
+  - Scan request (browsing) 
   - Closing down connection
 
 Note that only the Search and Fetch handler functions are required.
@@ -188,16 +210,18 @@ output parameters.
 The Perl programmer specifies the event handles for the server by
 means of the the SimpleServer object constructor
 
-  my $handle = Net::Z3950::SimpleServer->new({
-               INIT    =>      \&my_init_handler,
-               CLOSE   =>      \&my_close_handler,
-               SEARCH  =>      \&my_search_handler,
-               FETCH   =>      \&my_fetch_handler });
+  my $z = new Net::Z3950::SimpleServer(
+                       INIT    =>      \&my_init_handler,
+                       CLOSE   =>      \&my_close_handler,
+                       SEARCH  =>      \&my_search_handler,
+                       PRESENT =>      \&my_present_handler,
+                       SCAN    =>      \&my_scan_handler,
+                       FETCH   =>      \&my_fetch_handler);
 
 After the custom event handles are declared, the server is launched
 by means of the method
 
-  $handle->launch_server("MyServer.pl", @ARGV);
+  $z->launch_server("MyServer.pl", @ARGV);
 
 Notice, the first argument should be the name of your server
 script (for logging purposes), while the rest of the arguments
@@ -218,9 +242,9 @@ The argument hash passed to the init handler has the form
   $args = {
                                    ## Response parameters:
 
-            IMP_NAME  =>  ""       ## Z39.50 Implementation name
-            IMP_VER   =>  ""       ## Z39.50 Implementation version
-            ERR_CODE  =>  0        ## Error code, cnf. Z39.50 manual
+            IMP_NAME  =>  "",      ## Z39.50 Implementation name
+            IMP_VER   =>  "",      ## Z39.50 Implementation version
+            ERR_CODE  =>  0,       ## Error code, cnf. Z39.50 manual
             HANDLE    =>  undef    ## Handler of Perl data structure
          };
 
@@ -249,17 +273,17 @@ mous hash. The structure is the following:
   $args = {
                                    ## Request parameters:
 
-            HANDLE    =>  ref      ## Your session reference.
-            SETNAME   =>  "id"     ## ID of the result set
-            REPL_SET  =>  0        ## Replace set if already existing?
-            DATABASES =>  ["xxx"]  ## Reference to a list of data-
+            HANDLE    =>  ref,     ## Your session reference.
+            SETNAME   =>  "id",    ## ID of the result set
+            REPL_SET  =>  0,       ## Replace set if already existing?
+            DATABASES =>  ["xxx"], ## Reference to a list of data-
                                    ## bases to search
-            QUERY     =>  "query"  ## The query expression
+            QUERY     =>  "query", ## The query expression
 
                                    ## Response parameters:
 
-            ERR_CODE  =>  0        ## Error code (0=Succesful search)
-            ERR_STR   =>  ""       ## Error string
+            ERR_CODE  =>  0,       ## Error code (0=Succesful search)
+            ERR_STR   =>  "",      ## Error string
             HITS      =>  0        ## Number of matches
          };
 
@@ -299,6 +323,46 @@ it is perfectly legal to not accept boolean operators, but you SHOULD
 try to return good error codes if you run into something you can't or
 won't support.
 
+=head2 Present handler
+
+The presence of a present handler in a SimpleServer front-end is optional.
+Each time a client wishes to retrieve records, the present service is
+called. The present service allows the origin to request a certain number
+of records retrieved from a given result set.
+When the present handler is called, the front-end server should prepare a
+result set for fetching. In practice, this means to get access to the
+data from the backend database and store the data in a temporary fashion
+for fast and efficient fetching. The present handler does *not* fetch
+anything. This task is taken care of by the fetch handler, which will be
+called the correct number of times by the YAZ library. More about this
+below.
+If no present handler is implemented in the front-end, the YAZ toolkit
+will take care of a minimum of preparations itself. This default present
+handler is sufficient in many situations, where only a small amount of
+records are expected to be retrieved. If on the other hand, large result
+sets are likely to occur, the implementation of a reasonable present
+handler can gain performance significantly.
+
+The informations exchanged between client and present handle are:
+
+  $args = {
+                                   ## Client/server request:
+
+            HANDLE    =>  ref,     ## Reference to datastructure
+            SETNAME   =>  "id",    ## Result set ID
+            START     =>  xxx,     ## Start position
+            COMP      =>  "",      ## Desired record composition
+            NUMBER    =>  yyy,     ## Number of requested records
+
+
+                                   ## Respons parameters:
+
+            HITS      =>  zzz,     ## Number of returned records
+            ERR_CODE  =>  0,       ## Error code
+            ERR_STR   =>  ""       ## Error message
+          };
+
+
 =head2 Fetch handler
 
 The fetch handler is asked to retrieve a SINGLE record from a given
@@ -313,7 +377,7 @@ The parameters exchanged between the server and the fetch handler are
             HANDLE    =>  ref      ## Reference to data structure
             SETNAME   =>  "id"     ## ID of the requested result set
             OFFSET    =>  nnn      ## Record offset number
-            REQ_FORM  =>  "USMARC" ## Client requested record format
+            REQ_FORM  =>  "n.m.k.l"## Client requested format OID
             COMP      =>  "xyz"    ## Formatting instructions
 
                                    ## Handler response:
@@ -324,7 +388,7 @@ The parameters exchanged between the server and the fetch handler are
             ERR_CODE  =>  0        ## Error code
             ERR_STR   =>  ""       ## Error string
             SUR_FLAG  =>  0        ## Surrogate diagnostic flag
-            REP_FORM  =>  "USMARC" ## Provided record format
+            REP_FORM  =>  "n.m.k.l"## Provided format OID
          };
 
 The REP_FORM value has by default the REQ_FORM value but can be set to
@@ -336,16 +400,68 @@ indicate whether the error condition pertains to the record currently
 being retrieved, or whether it pertains to the operation as a whole
 (eg. the client has specified a result set which does not exist.)
 
-Record formats are currently carried as strings (eg. USMARC, TEXT_XML,
-SUTRS), but this will probably change to proper OID strings in the
-future (not to worry, though, the module will supply constant values
-for the common OIDs). If you need to return USMARC records, you might
-want to have a look at the MARC module on CPAN, if you don't already
-have a way of generating these.
+If you need to return USMARC records, you might want to have a look at
+the MARC module on CPAN, if you don't already have a way of generating
+these.
 
 NOTE: The record offset is 1-indexed - 1 is the offset of the first
 record in the set.
 
+=head2 Scan handler
+
+A full featured Z39.50 server should support scan (or in some literature
+browse). The client specifies a starting term of the scan, and the server
+should return an ordered list of specified length consisting of terms
+actually occurring in the data base. Each of these terms should be close
+to or equal to the term originally specified. The quality of scan compared
+to simple search is a guarantee of hits. It is simply like browsing through
+an index of a book, you always find something! The parameters exchanged are
+
+  $args = {
+                                               ## Client request
+
+               HANDLE          => $ref         ## Reference to data structure
+               TERM            => 'start',     ## The start term
+               NUMBER          => xx,          ## Number of requested terms
+               POS             => yy,          ## Position of starting point
+                                               ## within returned list
+               STEP            => 0,           ## Step size
+
+                                               ## Server response
+
+               ERR_CODE        => 0,           ## Error code
+               ERR_STR         => '',          ## Diagnostic message
+               NUMBER          => zz,          ## Number of returned terms
+               STATUS          => $status,     ## ScanSuccess/ScanFailure
+               ENTRIES         => $entries     ## Referenced list of terms
+       };
+
+where the term list is returned by reference in the scalar $entries, which
+should point at a data structure of this kind,
+
+  my $entries = [
+                       {       TERM            => 'energy',
+                               OCCURRENCE      => 5            },
+
+                       {       TERM            => 'energy density',
+                               OCCURRENCE      => 6,           },
+
+                       {       TERM            => 'energy flow',
+                               OCCURRENCE      => 3            },
+
+                               ...
+
+                               ...
+       ];
+
+The $status flag should be assigned one of two values:
+
+  Net::Z3950::SimpleServer::ScanSuccess  On success (default)
+  Net::Z3950::SimpleServer::ScanPartial  Less terms returned than requested
+
+The STEP member contains the requested number of entries in the term-list
+between two adjacent entries in the response.
+
 =head2 Close handler
 
 The argument hash recieved by the close handler has one element only: