X-Git-Url: http://git.indexdata.com/?p=simpleserver-moved-to-github.git;a=blobdiff_plain;f=SimpleServer.pm;h=2893c5080edb30dd79802a0bbba9f7b5ccba94b4;hp=b2c27a1ef7d75b817d1daae074fb69ed57e73c7b;hb=657bd74a4d71b1125a3bff1fe99631591ddf1873;hpb=6755a668b35e7ddc4c7ac37fb2550a55fb9858ac diff --git a/SimpleServer.pm b/SimpleServer.pm index b2c27a1..2893c50 100644 --- a/SimpleServer.pm +++ b/SimpleServer.pm @@ -25,6 +25,28 @@ ## ## +## $Log: SimpleServer.pm,v $ +## Revision 1.10 2002-02-28 11:21:57 mike +## Add RPN structure to search-handler argument hash. +## +## 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; @@ -42,7 +64,7 @@ require AutoLoader; @EXPORT = qw( ); -$VERSION = '0.02'; +$VERSION = '0.04'; bootstrap Net::Z3950::SimpleServer $VERSION; @@ -52,18 +74,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,11 +102,31 @@ 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); } +# Register packages that we will use in translated RPNs +package Net::Z3950::APDU::Query; +package Net::Z3950::APDU::OID; +package Net::Z3950::RPN::And; +package Net::Z3950::RPN::Or; +package Net::Z3950::RPN::AndNot; +package Net::Z3950::RPN::Term; +package Net::Z3950::RPN::Attributes; +package Net::Z3950::RPN::Attribute; + +# Must revert to original package for Autoloader's benefit +package Net::Z3950::SimpleServer; + + # Autoload methods go after =cut, and are processed by the autosplit program. 1; @@ -119,7 +159,7 @@ 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; if (number_of_hits() == $args->{OFFSET}) { ## Last record in set? @@ -132,15 +172,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 @@ -170,7 +208,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. @@ -187,16 +227,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 @@ -217,9 +259,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 }; @@ -248,17 +290,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 }; @@ -298,6 +340,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 @@ -312,7 +394,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: @@ -323,7 +405,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 @@ -335,16 +417,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: