An Overview of Gazelle
Architecture
In order to develop the code which connects Gazelle to your data, it
is important to understand Gazelle's architectural core. This core
consists of modules which communicate with a Z39.50 client and
translate its requests and queries into callbacks in the target API,
for which you provide an implementation. Here's a schematic of this
architecture:
The Z39.50 client interacts with Gazelle through a client handler,
which responds to client requests by making calls to the target API.
Client queries are translated into the desired target syntax by the
query translator, which is driven by templates specified in the
configuration file. The client handler also manages the target
implementation's state information. The target implementation is
responsible for executing the translated query against a data source,
and providing random access to result records.
Query Translation
One of the most unique and powerful features of Gazelle is its query
translator. The query translator uses templates specified in the
configuration file to translate Z39.50 queries into arbitrary target
syntaxes. It does this first by matching templates against the
combinations of attributes associated with each term in the Z39.50
query. These attributes, which are members of Z39.50 Attribute Sets,
represent search parameters such as which field to match the term
against, or what kind of matching is to be performed. The query
translator then expands the matched template by substituting the term
value for a placeholder. Complex Z39.50 queries (i.e. queries which
combine pairs of terms with the operators OR, AND, and AND NOT) are
matched against the appropriate complex query template, into which the
expanded term templates for the left and right hand side of the
operator are substituted. The resulting query string is then returned
from the query translator and passed to the target API.
The Target API
Gazelle's Target API forms the bridge between Gazelle and your data.
It is a simple interface consisting of four routines:
target_connect
target_search
target_present
target_disconnect
Gazelle calls these routines when the corresponding events occur in
its interaction with the Z39.50 client. The connect and disconnect
routines are called at the beginning and end of the client
interaction, respectively. When the client issues a query, it is
translated by the Query Translator and passed to the search routine.
Finally, when the search has been executed and the client is
requesting records, the present routine is called for each record the
client requests.
In addition to these four core routines, the Target API also
provides a "result record" data structure for associating
record data with a Z39.50 record syntax. These record syntaxes are
analogous to MIME types, and indeed Z39.50 provides a set of mappings
between MIME types and record syntax identifiers, several of which are
defined as constants in Gazelle. Several routines are provided for
constructing result records out of binary data and null-terminated
strings.
libemerge Utilities
Gazebo and Gazelle are both built around a core library called
"libemerge", which contains
support for Z39.50, portable socket I/O, MARC record formatting (used
by some Z39.50 services), and a set of convenient data structures and
routines to manipulate them. When writing targets, it's important to
understand the "Dict" module; it is also convenient to
understand the "Plist" module as well.
Dict
The "Dict" module provides a facility for creating
dictionaries of objects, whose keys are strings. It provides routines
for adding, retrieving, and removing entries from a dictionary. The
most important routine used in Gazelle is dict_get, which you can use
in your implementation of target_connect and target_search to retrieve
values of configuration file parameters passed to those routines.
For more details, see the target API tutorial, and the code-level
documentation in the source code for libemerge.
PList
The "Plist" module provides a facility for creating
doubly-linked lists of objects. It contains functions for adding,
retrieving, and removing elements from lists, as well as a macro for
iteration.
Z39.50 Support
libemerge contains many modules for Z39.50 support.
These include a set of utilities for constructing
and parsing Z39.50 Protocol Data Units (PDU's), as well as low-level
binary formatting routines and some utilities for managing the Marc21
format, a popular record format for bibliographic Z39.50 services.
Unisock
Gazelle's network I/O is performed with the Unisock library, a
simplified socket library which is portable across UNIX and Windows
platforms.