X-Git-Url: http://git.indexdata.com/?p=simpleserver-moved-to-github.git;a=blobdiff_plain;f=SimpleServer.pm;h=a29563434a3392389072499d78bcc18ae6be2ddb;hp=cc6c7d00081111116ad453d3e8e60000b3d7f1e9;hb=5b833f1b8ce65bd8c7a1d1afb57dc329f7693a9d;hpb=03aac9fd7958d065157b3c5878bf5a7c76420a0f diff --git a/SimpleServer.pm b/SimpleServer.pm index cc6c7d0..a295634 100644 --- a/SimpleServer.pm +++ b/SimpleServer.pm @@ -1,5 +1,5 @@ ## -## Copyright (c) 2000, Index Data. +## Copyright (c) 2000-2004, Index Data. ## ## Permission to use, copy, modify, distribute, and sell this software and ## its documentation, in whole or in part, for any purpose, is hereby granted, @@ -25,16 +25,7 @@ ## ## -## $Log: SimpleServer.pm,v $ -## 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. -## +## $Id: SimpleServer.pm,v 1.21 2004-06-04 09:57:00 sondberg Exp $ package Net::Z3950::SimpleServer; @@ -47,13 +38,8 @@ require DynaLoader; require AutoLoader; @ISA = qw(Exporter AutoLoader DynaLoader); -# Items to export into callers namespace by default. Note: do not export -# names by default without a very good reason. Use EXPORT_OK instead. -# Do not simply export all your public functions/methods/constants. -@EXPORT = qw( - -); -$VERSION = '0.02'; +@EXPORT = qw( ); +$VERSION = '0.08'; bootstrap Net::Z3950::SimpleServer $VERSION; @@ -102,6 +88,20 @@ sub launch_server { } +# 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; @@ -195,12 +195,12 @@ After the launching of the server, all control is given away from the Perl script to the server. The server calls the registered subroutines to field incoming requests from Z39.50 clients. -A reference to an anonymous hash is passed to each handle. Some of +A reference to an anonymous hash is passed to each handler. Some of the entries of these hashes are to be considered input and others output parameters. -The Perl programmer specifies the event handles for the server by -means of the the SimpleServer object constructor +The Perl programmer specifies the event handlers for the server by +means of the SimpleServer object constructor my $z = new Net::Z3950::SimpleServer( INIT => \&my_init_handler, @@ -210,7 +210,22 @@ means of the the SimpleServer object constructor SCAN => \&my_scan_handler, FETCH => \&my_fetch_handler); -After the custom event handles are declared, the server is launched +If you want your SimpleServer to start a thread (threaded mode) to +handle each incoming Z39.50 request instead of forking a process +(forking mode), you need to register the handlers by symbol rather +than by code reference. Thus, in threaded mode, you will need to +register your handlers this way: + + my $z = new Net::Z3950::SimpleServer( + INIT => "my_package::my_init_handler", + CLOSE => "my_package::my_close_handler", + .... + .... ); + +where my_package is the Perl package in which your handler is +located. + +After the custom event handlers are declared, the server is launched by means of the method $z->launch_server("MyServer.pl", @ARGV); @@ -220,6 +235,9 @@ script (for logging purposes), while the rest of the arguments are documented in the YAZ toolkit manual: The section on application invocation: +In particular, you need to use the -T switch to start your SimpleServer +in threaded mode. + =head2 Init handler The init handler is called whenever a Z39.50 client is attempting @@ -234,9 +252,15 @@ The argument hash passed to the init handler has the form $args = { ## Response parameters: + IMP_ID => "", ## Z39.50 Implementation ID IMP_NAME => "", ## Z39.50 Implementation name IMP_VER => "", ## Z39.50 Implementation version ERR_CODE => 0, ## Error code, cnf. Z39.50 manual + ERR_STR => "", ## Error string (additional info.) + USER => "xxx" ## If Z39.50 authentication is used, + ## this member contains user name + PASS => "yyy" ## Under same conditions, this member + ## contains the password in clear text HANDLE => undef ## Handler of Perl data structure }; @@ -249,13 +273,14 @@ result sets or a handle to a back-end search engine of some sort), it is always best to store them in a private session structure - rather than leaving them in global variables in your script. -The Implementation name and version are only really used by Z39.50 +The Implementation ID, name and version are only really used by Z39.50 client developers to see what kind of server they're dealing with. Filling these in is optional. The ERR_CODE should be left at 0 (the default value) if you wish to accept the connection. Any other value is interpreted as a failure -and the client will be shown the door. +and the client will be shown the door, with the code and the +associated additional information, ERR_STR returned. =head2 Search handler @@ -271,6 +296,7 @@ mous hash. The structure is the following: DATABASES => ["xxx"], ## Reference to a list of data- ## bases to search QUERY => "query", ## The query expression + RPN => $obj, ## Reference to a Net::Z3950::APDU::Query ## Response parameters: @@ -315,6 +341,134 @@ 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. +A more convenient alternative to the QUERY member may be the RPN +member, which is a reference to a Net::Z3950::APDU::Query object +representing the RPN query tree. The structure of that object is +supposed to be self-documenting, but here's a brief summary of what +you get: + +=over 4 + +=item * + +C is a hash with two fields: + +Z<> + +=over 4 + +=item C + +Optional. If present, it is a reference to a +C. This is a string of dot-separated integers +representing the OID of the query's top-level attribute set. + +=item C + +Mandatory: a refererence to the RPN tree itself. + +=back + +=item * + +Each node of the tree is an object of one of the following types: + +Z<> + +=over 4 + +=item C + +=item C + +=item C + +These three classes are all arrays of two elements, each of which is a +node of one of the above types. + +=item C + +See below for details. + +=back + +(I guess I should make a superclass C and make +all of these subclasses of it. Not done that yet, but will do soon.) + +=back + +=over 4 + +=item * + +C is a hash with two fields: + +Z<> + +=over 4 + +=item C + +A string containing the search term itself. + +=item C + +A reference to a C object. + +=back + +=item * + +C is an array of references to +C objects. (Note the plural/singular +distinction.) + +=item * + +C is a hash with three elements: + +Z<> + +=over 4 + +=item C + +Optional. If present, it is dot-separated OID string, as above. + +=item C + +An integer indicating the type of the attribute - for example, under +the BIB-1 attribute set, type 1 indicates a ``use'' attribute, type 2 +a ``relation'' attribute, etc. + +=item C + +An integer indicating the value of the attribute - for example, under +BIB-1, if the attribute type is 1, then value 4 indictates a title +search and 7 indictates an ISBN search; but if the attribute type is +2, then value 4 indicates a ``greater than or equal'' search, and 102 +indicates a relevance match. + +=back + +=back + +Note that, at the moment, none of these classes have any methods at +all: the blessing into classes is largely just a documentation thing +so that, for example, if you do + + { use Data::Dumper; print Dumper($args->{RPN}) } + +you get something fairly human-readable. But of course, the type +distinction between the three different kinds of boolean node is +important. + +By adding your own methods to these classes (building what I call +``augmented classes''), you can easily build code that walks the tree +of the incoming RPN. Take a look at C for a +sample implementation of such an augmented classes technique. + + =head2 Present handler The presence of a present handler in a SimpleServer front-end is optional. @@ -424,7 +578,7 @@ an index of a book, you always find something! The parameters exchanged are ERR_CODE => 0, ## Error code ERR_STR => '', ## Diagnostic message NUMBER => zz, ## Number of returned terms - STATUS => ScanSuccess, ## ScanSuccess/ScanFailure + STATUS => $status, ## ScanSuccess/ScanFailure ENTRIES => $entries ## Referenced list of terms }; @@ -445,7 +599,14 @@ should point at a data structure of this kind, ... ]; - + +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 @@ -463,15 +624,12 @@ or something similar, this is the place to do it. =head1 AUTHORS Anders Sønderberg (sondberg@indexdata.dk) and Sebastian Hammer -(quinn@indexdata.dk). +(quinn@indexdata.dk). Substantial contributions made by Mike Taylor +(mike@miketaylor.org.uk). =head1 SEE ALSO -perl(1). - Any Perl module which is useful for accessing the database of your choice. =cut - -