The ZServer accepts requests for information retrieval (IR) services encoded according to the Z39.50 protocol (and Basic Encoding Rules - BER). It decodes these requests and passes them on to an IR application for execution, encodes the IR application's response, and returns it to the client which made the request.
The ZServer is designed in 4 layers described in more detail below:
The ZServer design is based on the assumption that a new instantiation of the server will be started for each client by the inet demon when contacted by a client at the agreed-upon port.
Main function knows nothing about Z39.50 or any IR application. It invokes ZServer functions:
IR application-independent server code which:
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
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.
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.
sets timeout interval (60 mins)
process_msg() handles single message from socket
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).
When the ZServer comes up it opens a file named according to it's PID
zserver.RELEVANT-PID.login the directory indicated in the zservlog.spec file in its defaultdir, or by default in /tmp. The pointer to this file is kept in two global locations (logfp and err_fp). Logfp is used for trace information if the ZServer has been compiled with the WRITE_TRACE option. Logfp may be set to NULL at runtime to stop such logging and restored from err_fp to start such logging again. Err_fp must remain as initially set.
When ZServer 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 (still working on this)
- Memory allocation errors
The ZServer manages memory directly via calls to the C library routines malloc, calloc, and free as well as indirectly for the encoding and decoding of the Z39.50 protocol data (PDUs) via routines generated by the SNACC ASN.1 compiler. A SNACC routine allocates an initial memory buffer (so-called "nibble memory") when the ZServer begins execution. Later, the PDU decoding and encoding code calls other SNACC routines to parcel out pieces of the nibble memory buffer. If the request for a piece can't be filled in the current buffer, a new one is allocated and added to the buffer chain.
The ZServer contains calls to SNACC-generated Free... routines to free the pieces of nibble memory it uses, but these routines do not currently do anything. They are there to support the option of changing from the use of nibble memory management to direct calls to C library routines. The ZServer frees nibble memory by reseting the memory buffer chain each time it sends a PDU back to the the client. When the chain is reset, all the nibble memory buffers except the first are freed. The first buffer contains default PDU information which we preserve for the life of the ZServer. See ..../zserver/src/lib/zserver/zserver.c for the calls to the nibble memory intialization and reset routines.