.../zprise_1/zserver/src/bin/zserver Main function knows nothing about Z39.50 or any IR application. It invokes zserver functions: - init_zserver(): reads table of databases and set default pdus; - zserver(): loops on incoming msgs from the client (via socket) until terminate - close_zserver(): release resources main.c .../zprise_1/zserver/src/lib/zserver IR application-independent server code which: - initializes database table and defaults - loops reads incoming msg in BER-format from socket translates incoming msg to incoming PDU invokes zservices level (process_PDU()) translates outgoing PDU to BER-format msg writes outgoing msg to socket - releases resources when server closes down zserver.c
.../zprise_1/zserver/src/lib/zservices IR application-independent code to process PDUs and invoke the application-specific functions (e.g. those in /zprise) that in turn invoke the IR application functions proper. Based on the PDU choice id, process_PDU() invokes the routines (init, process, close) defined for the operation in op_table.c databases.c default_pdus.c zservices.c #includes: access.c close.c delete.c extended.c init.c implemented present.c implemented search.c implemented scan.c segment.c sort.c resource.c op_table.c Table of pointers to Z3950 operation functions (e.g., init_search, search,...) indexed by PDU id.
.../zprise_1/zserver/src/lib/zprise This layer bridges any gap between the layer (zservices) above it, which knows about the Z39.50 protocol, and the particular IR application layer below it (e.g. PRISE). This is the layer that may require adjustment when a new IR application is inserted. ap_services.c #includes: ap_initdb.c implemented for PRISE ap_search.c implemented for PRISE ap_present.c implemented for PRISE ap_closedb.c ----------- Extensions to ap_help.c implemented for PRISE Z39.50 search ap_generic.c ap_feedback.c
.../zprise_1/prise-search This is the IR application proper.
See"Adding/substituting your own search engine" for more detailed information on how the zserver interfaces to an IR application.
main() -> init_zserver() -> zserver() Loop awaiting/processing incoming msgs --> process_msg() Handle single message from socket ---> ber2pdu() Translate BER-encoded msg into PDU ---> process_PDU() Take a request PDU; return a response PDU ----> ap_table_entry.init == Initialization by operation > init_search() (no init_init()) > init_present() ----> ap_table_entry.proc == Main processing by operation > init() -----> get_db_list() -----> init_default_pdus( > search() -----> MakeSearchResponse() -----> ap_link() Find ap_service_- entry for IR app. given db. name -----> ap_service_entry.delete == Release result > ap_delete() set resources -----> ap_service_entry.init_search == Get ready to > init_ap_search() search -----> ap_service_entry.search == Perform search > ap_search() -----> get_elementSetType() Get some format info loop-> ap_service_entry.present == Get a database > ap_present() record and turn it into a retrieval recd. > InsertResponseRecord() Add retrieval record or sur- rogate to the response -----> ap_service_entry.close_search == > close_ap_search() > present() -----> MakePresentResponse() -----> ap_service_entry.init_present == > init_ap_present() -----> get_elementSetType() loop-> ap_service_entry.present == See above > ap_present() > InsertResponseRecord() See above -----> ap_service_entry.close_present == > close_ap_present() ----> ap_table_entry.close == Close processing by operation > close_search() > close_present() ---> pdu2ber() Translate out- PDU to BER- encoded msg. ---> FreePDU() ---> FreePDU() -> close_zserver() --> free_dbs()
In general the Zserver has been written to be tolerant of invalid requests. So, for example, the zserver looks for an element set name of F or B but finding G instead or none, it uses its default. If the result set contains 3 records and the client asks for 4 starting with the third, the zserver just returns as many as it can (1).
The zserver always attempts to write a message to the log file
/tmp/zserver.RELEVANT-PID.logwhen it encounters a processing error. It attempts to communicate the situation to the client via the PDU and stay up. However, in the following circumstances the zserver will log a message and exit:
- Errors encountered before the msg-read/write loop in process_msg() is entered
- Errors encountered down in the PRISE search engine
- Memory allocation errors
Note that socket processing takes over standard in, out, and error, so writing to standard error will bring the zserver down.