Towards 2.0.2
[yaz-moved-to-github.git] / doc / frontend.xml
1 <!-- $Id: frontend.xml,v 1.17 2003-04-28 21:02:16 adam Exp $ -->
2  <chapter id="server"><title>Generic server</title>
3   <sect1><title>Introduction</title>
4    
5    <para>
6     If you aren't into documentation, a good way to learn how the
7     back end interface works is to look at the <filename>backend.h</filename>
8     file. Then, look at the small dummy-server in
9     <filename>ztest/ztest.c</filename>. The <filename>backend.h</filename>
10     file also makes a good reference, once you've chewed your way through
11     the prose of this file.
12    </para>
13
14    <para>
15     If you have a database system that you would like to make available by
16     means of Z39.50 or SRW, &yaz; basically offers your two options. You
17     can use the APIs provided by the &asn;, &odr;, and &comstack;
18     modules to
19     create and decode PDUs, and exchange them with a client.
20     Using this low-level interface gives you access to all fields and
21     options of the protocol, and you can construct your server as close
22     to your existing database as you like.
23     It is also a fairly involved process, requiring
24     you to set up an event-handling mechanism, protocol state machine,
25     etc. To simplify server implementation, we have implemented a compact
26     and simple, but reasonably full-functioned server-frontend that will
27     handle most of the protocol mechanics, while leaving you to
28     concentrate on your database interface.
29    </para>
30
31    <note>
32     <para>
33      The backend interface was designed in anticipation of a specific
34      integration task, while still attempting to achieve some degree of
35      generality. We realize fully that there are points where the
36      interface can be improved significantly. If you have specific
37      functions or parameters that you think could be useful, send us a
38      mail (or better, sign on to the mailing list referred to in the
39      top-level README file). We will try to fit good suggestions into future
40      releases, to the extent that it can be done without requiring
41      too many structural changes in existing applications.
42     </para>
43    </note>
44
45    <note>
46     <para>
47      The &yaz; server does not support XCQL.
48      </para>
49    </note>
50   </sect1>
51   
52   <sect1 id="server.frontend"><title>The Database Frontend</title>
53
54    <para>
55     We refer to this software as a generic database frontend. Your
56     database system is the <emphasis>backend database</emphasis>, and the
57     interface between the two is called the <emphasis>backend API</emphasis>.
58     The backend API consists of a small number of function handlers and
59     structure definitions. You are required to provide the
60     <function>main()</function> routine for the server (which can be
61     quite simple), as well as a set of handlers to match each of the
62     prototypes.
63     The interface functions that you write can use any mechanism you like
64     to communicate with your database system: You might link the whole
65     thing together with your database application and access it by
66     function calls; you might use IPC to talk to a database server
67     somewhere; or you might link with third-party software that handles
68     the communication for you (like a commercial database client library).
69     At any rate, the handlers will perform the tasks of:
70    </para>
71
72    <itemizedlist>
73
74     <listitem><para>
75       Initialization.
76      </para></listitem>
77
78     <listitem><para>
79       Searching.
80      </para></listitem>
81
82     <listitem><para>
83       Fetching records.
84      </para></listitem>
85
86     <listitem><para>
87       Scanning the database index (optional - if you wish to implement SCAN).
88      </para></listitem>
89
90     <listitem><para>
91       Extended Services (optional).
92      </para></listitem>
93     
94     <listitem><para>
95       Result-Set Delete (optional).
96      </para></listitem>
97
98     <listitem><para>
99       Result-Set Sort (optional).
100      </para></listitem>
101     
102    </itemizedlist>
103
104    <para>
105     (more functions will be added in time to support as much of
106     Z39.50-1995 as possible).
107    </para>
108
109   </sect1>
110   <sect1 id="server.backend"><title>The Backend API</title>
111
112    <para>
113     The header file that you need to use the interface are in the
114     <filename>include/yaz</filename> directory. It's called
115     <filename>backend.h</filename>. It will include other files from
116     the <filename>include/yaz</filename> directory, so you'll
117     probably want to use the -I option of your compiler to tell it
118     where to find the files. When you run
119     <literal>make</literal> in the top-level &yaz; directory,
120     everything you need to create your server is to link with the
121     <filename>lib/libyaz.la</filename> library.
122    </para>
123   </sect1>
124
125   <sect1 id="server.main"><title>Your main() Routine</title>
126
127    <para>
128     As mentioned, your <function>main()</function> routine can be quite brief.
129     If you want to initialize global parameters, or read global configuration
130     tables, this is the place to do it. At the end of the routine, you should
131     call the function
132    </para>
133
134    <synopsis>
135 int statserv_main(int argc, char **argv,
136                   bend_initresult *(*bend_init)(bend_initrequest *r),
137                   void (*bend_close)(void *handle));
138    </synopsis>
139
140    <para>
141     The third and fourth arguments are pointers to handlers. Handler
142     <function>bend_init</function> is called whenever the server receives
143     an Initialize Request, so it serves as a Z39.50 session initializer. The
144     <function>bend_close</function> handler is called when the session is
145     closed.
146    </para>
147
148    <para>
149     <function>statserv_main</function> will establish listening sockets
150     according to the parameters given. When connection requests are received,
151     the event handler will typically <function>fork()</function> and
152     create a sub-process to handle a new connection.
153     Alternatively the server may be setup to create threads for each
154     connection.
155     If you do use global variables and forking, you should be aware, then,
156     that these cannot be shared between associations, unless you explicitly
157     disable forking by command line parameters. 
158    </para>
159    
160    <para>
161     The server provides a mechanism for controlling some of its behavior
162     without using command-line options. The function
163    </para>
164
165    <synopsis>
166 statserv_options_block *statserv_getcontrol(void);
167    </synopsis>
168
169    <para>
170     will return a pointer to a <literal>struct statserv_options_block</literal>
171     describing the current default settings of the server. The structure
172     contains these elements:
173     
174     <variablelist>
175      <varlistentry><term>
176        <literal>int dynamic</literal></term><listitem><para>
177         A boolean value, which determines whether the server
178         will fork on each incoming request (TRUE), or not (FALSE). Default is
179         TRUE. This flag is only read by UNIX-based servers (WIN32 based servers
180         doesn't fork).
181        </para></listitem></varlistentry>
182      
183      <varlistentry><term>
184        <literal>int threads</literal></term><listitem><para>
185         A boolean value, which determines whether the server
186         will create a thread on each incoming request (TRUE), or not (FALSE).
187         Default is FALSE. This flag is only read by UNIX-based servers
188         that offer POSIX Threads support.
189         WIN32-based servers always operate in threaded mode.
190        </para></listitem></varlistentry>
191      
192      <varlistentry><term>
193        <literal>int inetd</literal></term><listitem><para>
194         A boolean value, which determines whether the server
195         will operates under a UNIX INET daemon (inetd). Default is FALSE.
196        </para></listitem></varlistentry>
197      
198      <varlistentry><term>
199        <literal>int loglevel</literal></term><listitem><para>
200         Set this by ORing the constants defined in
201         <filename>include/yaz/yaz-log.h</filename>.
202        </para></listitem></varlistentry>
203      
204      <varlistentry><term>
205        <literal>char logfile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
206       <listitem><para>File for diagnostic output (&quot;&quot;: stderr).
207        </para></listitem></varlistentry>
208      
209      <varlistentry><term>
210        <literal>char apdufile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
211       <listitem><para>
212         Name of file for logging incoming and outgoing APDUs
213         (&quot;&quot;: don't log APDUs, &quot;-&quot;:
214         <literal>stderr</literal>).
215        </para></listitem></varlistentry>
216
217      <varlistentry><term>
218       <literal>char default_listen&lsqb;1024&rsqb;</literal></term>
219       <listitem><para>Same form as the command-line specification of
220         listener address. &quot;&quot;: no default listener address.
221         Default is to listen at &quot;tcp:@:9999&quot;. You can only
222         specify one default listener address in this fashion.
223        </para></listitem></varlistentry>
224
225      <varlistentry><term>
226       <literal>enum oid_proto default_proto;</literal></term>
227       <listitem><para>Either <literal>PROTO_Z3950</literal> or
228         <literal>PROTO_SR</literal>.
229         Default is <literal>PROTO_Z39_50</literal>.
230        </para></listitem></varlistentry>
231      
232      <varlistentry><term>
233        <literal>int idle_timeout;</literal></term>
234       <listitem><para>Maximum session idle-time, in minutes. Zero indicates
235         no (infinite) timeout. Default is 120 minutes.
236        </para></listitem></varlistentry>
237      
238      <varlistentry><term>
239        <literal>int maxrecordsize;</literal></term>
240       <listitem><para>Maximum permissible record (message) size. Default
241         is 1Mb. This amount of memory will only be allocated if a
242         client requests a very large amount of records in one operation
243         (or a big record).
244         Set it to a lower number if you are worried about resource
245         consumption on your host system.
246        </para></listitem></varlistentry>
247
248      <varlistentry><term>
249        <literal>char configname&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
250       <listitem><para>Passed to the backend when a new connection is received.
251        </para></listitem></varlistentry>
252
253      <varlistentry><term>
254        <literal>char setuid&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
255       <listitem><para>Set user id to the user specified, after binding
256         the listener addresses.
257        </para></listitem></varlistentry>
258      
259      <varlistentry><term>
260        <literal>void (*bend_start)(struct statserv_options_block *p)</literal>
261       </term>
262       <listitem><para>Pointer to function which is called after the
263         command line options have been parsed - but before the server
264         starts listening.
265         For forked UNIX servers this handler is called in the mother
266         process; for threaded servers this handler is called in the
267         main thread.
268         The default value of this pointer is NULL in which case it
269         isn't invoked by the frontend server.
270         When the server operates as an NT service this handler is called
271         whenever the service is started. 
272        </para></listitem></varlistentry>
273      
274      <varlistentry><term>
275        <literal>void (*bend_stop)(struct statserv_options_block *p)</literal>
276       </term>
277       <listitem><para>Pointer to function which is called whenever the server
278         has stopped listening for incoming connections. This function pointer
279         has a default value of NULL in which case it isn't called.
280         When the server operates as an NT service this handler is called
281         whenever the service is stopped.
282        </para></listitem></varlistentry>
283
284      <varlistentry><term>
285        <literal>void *handle</literal></term>
286       <listitem><para>User defined pointer (default value NULL).
287         This is a per-server handle that can be used to specify "user-data".
288         Do not confuse this with the session-handle as returned by bend_init.
289        </para></listitem></varlistentry>
290
291     </variablelist>
292    </para>
293
294    <para>
295     The pointer returned by <literal>statserv_getcontrol</literal> points to
296     a static area. You are allowed to change the contents of the structure,
297     but the changes will not take effect before you call
298    </para>
299    
300    <synopsis>
301 void statserv_setcontrol(statserv_options_block *block);
302    </synopsis>
303
304    <note>
305     <para>
306      that you should generally update this structure before calling
307      <function>statserv_main()</function>.
308     </para>
309    </note>
310   </sect1>
311
312   <sect1 id="server.backendfunctions"><title>The Backend Functions</title>
313
314    <para>
315     For each service of the protocol, the backend interface declares one or
316     two functions. You are required to provide implementations of the
317     functions representing the services that you wish to implement.
318    </para>
319
320    <sect2><title>Init</title>
321
322     <synopsis>
323 bend_initresult (*bend_init)(bend_initrequest *r);
324     </synopsis>
325
326     <para>
327      This handler is called once for each new connection request, after
328      a new process/thread has been created, and an Initialize Request has
329      been received from the client. The pointer to the
330      <function>bend_init</function> handler is passed in the call to
331      <function>statserv_start</function>.
332     </para>
333
334     <para>
335      This handler is also called when operating in SRW/SRU mode - when
336      a connection has been made (even though SRW/SRU does not offer
337      this service).
338     </para>
339
340     <para>
341      Unlike previous versions of YAZ, the <function>bend_init</function> also
342      serves as a handler that defines the Z39.50 services that the backend
343      wish to support. Pointers to <emphasis>all</emphasis> service handlers,
344      including search - and fetch must be specified here in this handler.
345     </para>
346     <para>
347      The request  - and result structures are defined as
348     </para>
349
350     <synopsis>
351 typedef struct bend_initrequest
352 {
353     Z_IdAuthentication *auth;
354     ODR stream;                /* encoding stream */
355     ODR print;                 /* printing stream */
356     Z_ReferenceId *referenceId;/* reference ID */
357     char *peer_name;           /* dns host of peer (client) */
358
359     char *implementation_id;
360     char *implementation_name;
361     char *implementation_version;
362     int (*bend_sort) (void *handle, bend_sort_rr *rr);
363     int (*bend_search) (void *handle, bend_search_rr *rr);
364     int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
365     int (*bend_present) (void *handle, bend_present_rr *rr);
366     int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
367     int (*bend_delete)(void *handle, bend_delete_rr *rr);
368     int (*bend_scan)(void *handle, bend_scan_rr *rr);
369     int (*bend_segment)(void *handle, bend_segment_rr *rr);
370
371     ODR decode;                 /* decoding stream */
372     /* character set and language negotiation - see include/yaz/z-charneg.h */
373     Z_CharSetandLanguageNegotiation *charneg_request;
374     Z_External *charneg_response;
375 } bend_initrequest;
376
377 typedef struct bend_initresult
378 {
379     int errcode;       /* 0==OK */
380     char *errstring;   /* system error string or NULL */
381     void *handle;      /* private handle to the backend module */
382 } bend_initresult;
383     </synopsis>
384
385     <para>
386      In general, the server frontend expects that the
387      <literal>bend_*result</literal> pointer that you return is valid at
388      least until the next call to a <literal>bend_* function</literal>.
389      This applies to all of the functions described herein. The parameter
390      structure passed to you in the call belongs to the server frontend, and
391      you should not make assumptions about its contents after the current
392      function call has completed. In other words, if you want to retain any
393      of the contents of a request structure, you should copy them.
394     </para>
395
396     <para>
397      The <literal>errcode</literal> should be zero if the initialization of
398      the backend went well. Any other value will be interpreted as an error.
399      The <literal>errstring</literal> isn't used in the current version, but
400      one option would be to stick it in the initResponse as a VisibleString.
401      The <literal>handle</literal> is the most important parameter. It should
402      be set to some value that uniquely identifies the current session to
403      the backend implementation. It is used by the frontend server in any
404      future calls to a backend function.
405      The typical use is to set it to point to a dynamically allocated state
406      structure that is private to your backend module.
407     </para>
408
409     <para>
410      The <literal>auth</literal> member holds the authentication information
411      part of the Z39.50 Initialize Request. Interpret this if your serves
412      requires authentication. 
413     </para>
414
415     <para>
416      The members <literal>peer_name</literal>,
417      <literal>implementation_id</literal>,
418      <literal>implementation_name</literal> and
419      <literal>implementation_version</literal> holds
420      DNS of client, ID of implementor, name
421      of client (Z39.50) implementation - and version.
422     </para>
423
424     <para>
425      The <literal>bend_</literal> - members are set to NULL when
426      <function>bend_init</function> is called. Modify the pointers by
427      setting them to point to backend functions.
428     </para>
429
430    </sect2>
431
432    <sect2><title>Search and retrieve</title>
433
434     <para>We now describe the handlers that are required to support search -
435      and retrieve. You must support two functions - one for search - and one
436      for fetch (retrieval of one record). If desirable you can provide a
437      third handler which is called when a present request is received which
438      allows you to optimize retrieval of multiple-records.
439     </para>
440
441     <synopsis>
442 int (*bend_search) (void *handle, bend_search_rr *rr);
443
444 typedef struct {
445     char *setname;             /* name to give to this set */
446     int replace_set;           /* replace set, if it already exists */
447     int num_bases;             /* number of databases in list */
448     char **basenames;          /* databases to search */
449     Z_ReferenceId *referenceId;/* reference ID */
450     Z_Query *query;            /* query structure */
451     ODR stream;                /* encode stream */
452     ODR decode;                /* decode stream */
453     ODR print;                 /* print stream */
454
455     bend_request request;
456     bend_association association;
457     int *fd;
458     int hits;                  /* number of hits */
459     int errcode;               /* 0==OK */
460     char *errstring;           /* system error string or NULL */
461 } bend_search_rr;
462     </synopsis>
463
464     <para>
465      The <function>bend_search</function> handler is a fairly close
466      approximation of a protocol Z39.50 Search Request - and Response PDUs
467      The <literal>setname</literal> is the resultSetName from the protocol.
468      You are required to establish a mapping between the set name and whatever
469      your backend database likes to use.
470      Similarly, the <literal>replace_set</literal> is a boolean value
471      corresponding to the resultSetIndicator field in the protocol.
472      <literal>num_bases/basenames</literal> is a length of/array of character
473      pointers to the database names provided by the client.
474      The <literal>query</literal> is the full query structure as defined in
475      the protocol ASN.1 specification.
476      It can be either of the possible query types, and it's up to you to
477      determine if you can handle the provided query type.
478      Rather than reproduce the C interface here, we'll refer you to the
479      structure definitions in the file
480      <filename>include/yaz/z-core.h</filename>. If you want to look at the
481      attributeSetId OID of the RPN query, you can either match it against
482      your own internal tables, or you can use the
483      <literal>oid_getentbyoid</literal> function provided by &yaz;.
484     </para>
485
486     <para>
487      The structure contains a number of hits, and an
488      <literal>errcode/errstring</literal> pair. If an error occurs
489      during the search, or if you're unhappy with the request, you should
490      set the errcode to a value from the BIB-1 diagnostic set. The value
491      will then be returned to the user in a nonsurrogate diagnostic record
492      in the response. The <literal>errstring</literal>, if provided, will
493      go in the addinfo field. Look at the protocol definition for the
494      defined error codes, and the suggested uses of the addinfo field.
495     </para>
496
497     <para>
498      The <function>bend_search</function> handler is also called when
499      the frontend server receives a SRW/SRU SearchRetrieveRequest.
500      For SRW/SRU, a CQL query is usually provided by the client.
501      The CQL query is available as part of <literal>Z_Query</literal>
502      structure (note that CQL is now part of Z39.50 via an external).
503      To support CQL in existing implementations that only do Type-1,
504      we refer to the CQL-to-PQF tool described
505      <link linkend="tools.cql.pqf">here</link>.
506     </para>
507
508     <para>
509      To maintain backwards compatibility, the frontend server
510      of yaz always assume that error codes are BIB-1 diagnostics.
511      For SRW/SRU operation, a Bib-1 diagnostic code is mapped to
512      SRW/SRU diagnostic.
513     </para>
514     
515     <synopsis>
516 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
517
518 typedef struct bend_fetch_rr {
519     char *setname;             /* set name */
520     int number;                /* record number */
521     Z_ReferenceId *referenceId;/* reference ID */
522     oid_value request_format;  /* One of the CLASS_RECSYN members */
523     int *request_format_raw;   /* same as above (raw OID) */
524     Z_RecordComposition *comp; /* Formatting instructions */
525     ODR stream;                /* encoding stream - memory source if req */
526     ODR print;                 /* printing stream */
527
528     char *basename;            /* name of database that provided record */
529     int len;                   /* length of record or -1 if structured */
530     char *record;              /* record */
531     int last_in_set;           /* is it?  */
532     oid_value output_format;   /* format */
533     int *output_format_raw;    /* used instead of above if not-null */
534     int errcode;               /* 0==success */
535     char *errstring;           /* system error string or NULL */
536     int surrogate_flag;        /* surrogate diagnostic */
537     char *schema;              /* string record schema input/output */
538 } bend_fetch_rr;
539     </synopsis>
540
541     <para>
542      The frontend server calls the <function>bend_fetch</function> handler
543      when it needs database records to fulfill a Z39.50 Search Request, a
544      Z39.50 Present Request or a SRW SearchRetrieveRequest.
545      The <literal>setname</literal> is simply the name of the result set
546      that holds the reference to the desired record.
547      The <literal>number</literal> is the offset into the set (with 1
548      being the first record in the set). The <literal>format</literal> field
549      is the record format requested by the client (See section
550      <link linkend="oid">Object Identifiers</link>). The value
551      <literal>VAL_NONE</literal> indicates that the client did not
552      request a specific format. The <literal>stream</literal> argument
553      is an &odr; stream which should be used for
554      allocating space for structured data records.
555      The stream will be reset when all records have been assembled, and
556      the response package has been transmitted.
557      For unstructured data, the backend is responsible for maintaining a
558      static or dynamic buffer for the record between calls.
559     </para>
560
561     <para>
562      If a SRW/SRU SearchRetrieveRequest is received by the frontend server,
563      the <literal>referenceId</literal> is NULL and the
564      <literal>request_format</literal> (transfer syntax) is XML (OID name 
565      <literal>VAL_TEXT_XML</literal>).
566      The schema for SRW/SRU is stored in both the
567      <literal>Z_RecordComposition</literal>
568      structure and <literal>schema</literal> (simple string).
569     </para>
570
571     <para>
572      In the structure, the <literal>basename</literal> is the name of the
573      database that holds the
574      record. <literal>len</literal> is the length of the record returned, in
575      bytes, and <literal>record</literal> is a pointer to the record.
576      <literal>last_in_set</literal> should be nonzero only if the record
577      returned is the last one in the given result set.
578      <literal>errcode</literal> and <literal>errstring</literal>, if
579      given, will be interpreted as a global error pertaining to the
580      set, and will be returned in a non-surrogate-diagnostic.
581      If you wish to return the error as a surrogate-diagnostic
582      (local error) you can do this by setting
583      <literal>surrogate_flag</literal> to 1 also.
584     </para>
585
586     <para>
587      If the <literal>len</literal> field has the value -1, then
588      <literal>record</literal> is assumed to point to a constructed data
589      type. The <literal>format</literal> field will be used to determine
590      which encoder should be used to serialize the data.
591     </para>
592
593     <note>
594      <para>
595       If your backend generates structured records, it should use
596       <function>odr_malloc()</function> on the provided stream for allocating
597       data: This allows the frontend server to keep track of the record sizes.
598      </para>
599     </note>
600
601     <para>
602      The <literal>format</literal> field is mapped to an object identifier
603      in the direct reference of the resulting EXTERNAL representation
604      of the record.
605     </para>
606
607     <note>
608      <para>
609       The current version of &yaz; only supports the direct reference mode.
610      </para>
611     </note>
612
613     <synopsis>
614 int (*bend_present) (void *handle, bend_present_rr *rr);
615
616 typedef struct {
617     char *setname;             /* set name */
618     int start;
619     int number;                /* record number */
620     oid_value format;          /* One of the CLASS_RECSYN members */
621     Z_ReferenceId *referenceId;/* reference ID */
622     Z_RecordComposition *comp; /* Formatting instructions */
623     ODR stream;                /* encoding stream */
624     ODR print;                 /* printing stream */
625     bend_request request;
626     bend_association association;
627
628     int hits;                  /* number of hits */
629     int errcode;               /* 0==OK */
630     char *errstring;           /* system error string or NULL */
631 } bend_present_rr;
632     </synopsis>
633
634     <para>
635      The <function>bend_present</function> handler is called when
636      the server receives a Z39.50 Present Request.
637      The <literal>setname</literal>,
638      <literal>start</literal> and <literal>number</literal> is the
639      name of the result set - start position - and number of records to
640      be retrieved respectively. <literal>format</literal> and
641      <literal>comp</literal> is the preferred transfer syntax and element
642      specifications of the present request.
643     </para>
644     <para>
645      Note that this is handler serves as a supplement for
646      <function>bend_fetch</function> and need not to be defined in order to
647      support search - and retrieve. 
648     </para>
649
650    </sect2>
651
652    <sect2><title>Delete</title>
653
654     <para>
655      For back-ends that supports delete of a result set only one handler
656      must be defined.
657     </para>
658
659     <synopsis>
660 int (*bend_delete)(void *handle, bend_delete_rr *rr);
661
662 typedef struct bend_delete_rr {
663     int function;
664     int num_setnames;
665     char **setnames;
666     Z_ReferenceId *referenceId;
667     int delete_status;      /* status for the whole operation */
668     int *statuses;          /* status each set - indexed as setnames */
669     ODR stream;
670     ODR print; 
671 } bend_delete_rr;
672     </synopsis>
673
674     <note>
675      <para>
676       The delete set function definition is rather primitive, mostly because
677       we have had no practical need for it as of yet. If someone wants
678       to provide a full delete service, we'd be happy to add the
679       extra parameters that are required. Are there clients out there
680       that will actually delete sets they no longer need?
681      </para>
682     </note>
683
684    </sect2>
685
686    <sect2><title>scan</title>
687
688     <para>
689      For servers that wish to offer the scan service one handler
690      must be defined.
691     </para>
692
693     <synopsis>
694 int (*bend_delete)(void *handle, bend_delete_rr *rr);
695
696 typedef enum {
697     BEND_SCAN_SUCCESS,  /* ok */
698     BEND_SCAN_PARTIAL   /* not all entries could be found */
699 } bend_scan_status;
700
701 typedef struct bend_scan_rr {
702     int num_bases;      /* number of elements in database list */
703     char **basenames;   /* databases to search */
704     oid_value attributeset;
705     Z_ReferenceId *referenceId; /* reference ID */
706     Z_AttributesPlusTerm *term;
707     ODR stream;         /* encoding stream - memory source if required */
708     ODR print;          /* printing stream */
709
710     int *step_size;     /* step size */
711     int term_position;  /* desired index of term in result list/returned */
712     int num_entries;    /* number of entries requested/returned */
713
714     struct scan_entry *entries;
715     bend_scan_status status;
716     int errcode;
717     char *errstring;
718 } bend_scan_rr;
719     </synopsis>
720    </sect2>
721   </sect1>
722
723   <sect1 id="server.invocation"><title>Application Invocation</title>
724
725    <para>
726     The finished application has the following
727     invocation syntax (by way of <function>statserv_main()</function>):
728    </para>
729    
730    <cmdsynopsis>
731     <command>appname</command>
732     <arg choice="opt"><option>-a <replaceable>file</replaceable></option></arg>
733     <arg choice="opt"><option>-v <replaceable>level</replaceable></option></arg>
734     <arg choice="opt"><option>-l <replaceable>file</replaceable></option></arg>
735     <arg choice="opt"><option>-u <replaceable>uid</replaceable></option></arg>
736     <arg choice="opt"><option>-c <replaceable>config</replaceable></option></arg>
737     <arg choice="opt"><option>-t <replaceable>minutes</replaceable></option></arg>
738     <sbr/>
739     <arg choice="opt"><option>-k <replaceable>kilobytes</replaceable></option></arg>
740     <arg choice="opt"><option>-d <replaceable>daemon</replaceable></option></arg>
741     <arg choice="opt"><option>-w <replaceable>dir</replaceable></option></arg>
742     <arg choice="opt"><option>-ziST1</option></arg>
743     <arg choice="opt" rep="repeat">listener-spec</arg>
744    </cmdsynopsis>
745    
746    <para>
747     The options are:
748
749     &ztest-options;
750
751    </para>
752    
753    <para>
754     A listener specification consists of a transport mode followed by a
755     colon (:) followed by a listener address. The transport mode is
756     either <literal>tcp</literal>, <literal>unix:</literal> or
757     <literal>ssl</literal>.
758    </para>
759    
760    <para>
761     For TCP and SSL, an address has the form
762    </para>
763
764    <synopsis>
765     hostname | IP-number &lsqb;: portnumber&rsqb;
766    </synopsis>
767
768    <para>
769     The port number defaults to 210 (standard Z39.50 port).
770    </para>
771
772    <para>
773     For UNIX, the address is the filename of socket.
774    </para>
775
776    <para>
777     For TCP/IP and SSL, the special hostname &quot;@&quot; is mapped to
778     the address <literal>INADDR_ANY</literal>, which causes the
779     server to listen on any local interface. 
780    </para>
781    
782    <para>
783     Examples:
784    <screen>
785     tcp:@:210
786
787     ssl:@:3000
788
789     unix:/tmp/yaz
790    </screen>
791    </para>
792
793   </sect1>
794  </chapter>
795  
796  <!-- Keep this comment at the end of the file
797  Local variables:
798  mode: sgml
799  sgml-omittag:t
800  sgml-shorttag:t
801  sgml-minimize-attributes:nil
802  sgml-always-quote-attributes:t
803  sgml-indent-step:1
804  sgml-indent-data:t
805  sgml-parent-document: "yaz.xml"
806  sgml-local-catalogs: nil
807  sgml-namecase-general:t
808  End:
809  -->