dbd210475e456ca992fe589b03318cd5f5036921
[yaz-moved-to-github.git] / doc / frontend.xml
1 <!-- $Id: frontend.xml,v 1.16 2003-02-23 20:40:01 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 provide full SRW functionality.
48      However, it provides an adapter for SRW (to Z39.50).
49      </para>
50    </note>
51   </sect1>
52   
53   <sect1 id="server.frontend"><title>The Database Frontend</title>
54
55    <para>
56     We refer to this software as a generic database frontend. Your
57     database system is the <emphasis>backend database</emphasis>, and the
58     interface between the two is called the <emphasis>backend API</emphasis>.
59     The backend API consists of a small number of function handlers and
60     structure definitions. You are required to provide the
61     <function>main()</function> routine for the server (which can be
62     quite simple), as well as a set of handlers to match each of the
63     prototypes.
64     The interface functions that you write can use any mechanism you like
65     to communicate with your database system: You might link the whole
66     thing together with your database application and access it by
67     function calls; you might use IPC to talk to a database server
68     somewhere; or you might link with third-party software that handles
69     the communication for you (like a commercial database client library).
70     At any rate, the handlers will perform the tasks of:
71    </para>
72
73    <itemizedlist>
74
75     <listitem><para>
76       Initialization.
77      </para></listitem>
78
79     <listitem><para>
80       Searching.
81      </para></listitem>
82
83     <listitem><para>
84       Fetching records.
85      </para></listitem>
86
87     <listitem><para>
88       Scanning the database index (optional - if you wish to implement SCAN).
89      </para></listitem>
90
91     <listitem><para>
92       Extended Services (optional).
93      </para></listitem>
94     
95     <listitem><para>
96       Result-Set Delete (optional).
97      </para></listitem>
98
99     <listitem><para>
100       Result-Set Sort (optional).
101      </para></listitem>
102     
103    </itemizedlist>
104
105    <para>
106     (more functions will be added in time to support as much of
107     Z39.50-1995 as possible).
108    </para>
109
110   </sect1>
111   <sect1 id="server.backend"><title>The Backend API</title>
112
113    <para>
114     The header file that you need to use the interface are in the
115     <filename>include/yaz</filename> directory. It's called
116     <filename>backend.h</filename>. It will include other files from
117     the <filename>include/yaz</filename> directory, so you'll
118     probably want to use the -I option of your compiler to tell it
119     where to find the files. When you run
120     <literal>make</literal> in the top-level &yaz; directory,
121     everything you need to create your server is to link with the
122     <filename>lib/libyaz.la</filename> library.
123    </para>
124   </sect1>
125
126   <sect1 id="server.main"><title>Your main() Routine</title>
127
128    <para>
129     As mentioned, your <function>main()</function> routine can be quite brief.
130     If you want to initialize global parameters, or read global configuration
131     tables, this is the place to do it. At the end of the routine, you should
132     call the function
133    </para>
134
135    <synopsis>
136 int statserv_main(int argc, char **argv,
137                   bend_initresult *(*bend_init)(bend_initrequest *r),
138                   void (*bend_close)(void *handle));
139    </synopsis>
140
141    <para>
142     The third and fourth arguments are pointers to handlers. Handler
143     <function>bend_init</function> is called whenever the server receives
144     an Initialize Request, so it serves as a Z39.50 session initializer. The
145     <function>bend_close</function> handler is called when the session is
146     closed.
147    </para>
148
149    <para>
150     <function>statserv_main</function> will establish listening sockets
151     according to the parameters given. When connection requests are received,
152     the event handler will typically <function>fork()</function> and
153     create a sub-process to handle a new connection.
154     Alternatively the server may be setup to create threads for each
155     connection.
156     If you do use global variables and forking, you should be aware, then,
157     that these cannot be shared between associations, unless you explicitly
158     disable forking by command line parameters. 
159    </para>
160    
161    <para>
162     The server provides a mechanism for controlling some of its behavior
163     without using command-line options. The function
164    </para>
165
166    <synopsis>
167 statserv_options_block *statserv_getcontrol(void);
168    </synopsis>
169
170    <para>
171     will return a pointer to a <literal>struct statserv_options_block</literal>
172     describing the current default settings of the server. The structure
173     contains these elements:
174     
175     <variablelist>
176      <varlistentry><term>
177        <literal>int dynamic</literal></term><listitem><para>
178         A boolean value, which determines whether the server
179         will fork on each incoming request (TRUE), or not (FALSE). Default is
180         TRUE. This flag is only read by UNIX-based servers (WIN32 based servers
181         doesn't fork).
182        </para></listitem></varlistentry>
183      
184      <varlistentry><term>
185        <literal>int threads</literal></term><listitem><para>
186         A boolean value, which determines whether the server
187         will create a thread on each incoming request (TRUE), or not (FALSE).
188         Default is FALSE. This flag is only read by UNIX-based servers
189         that offer POSIX Threads support.
190         WIN32-based servers always operate in threaded mode.
191        </para></listitem></varlistentry>
192      
193      <varlistentry><term>
194        <literal>int inetd</literal></term><listitem><para>
195         A boolean value, which determines whether the server
196         will operates under a UNIX INET daemon (inetd). Default is FALSE.
197        </para></listitem></varlistentry>
198      
199      <varlistentry><term>
200        <literal>int loglevel</literal></term><listitem><para>
201         Set this by ORing the constants defined in
202         <filename>include/yaz/yaz-log.h</filename>.
203        </para></listitem></varlistentry>
204      
205      <varlistentry><term>
206        <literal>char logfile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
207       <listitem><para>File for diagnostic output (&quot;&quot;: stderr).
208        </para></listitem></varlistentry>
209      
210      <varlistentry><term>
211        <literal>char apdufile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
212       <listitem><para>
213         Name of file for logging incoming and outgoing APDUs
214         (&quot;&quot;: don't log APDUs, &quot;-&quot;:
215         <literal>stderr</literal>).
216        </para></listitem></varlistentry>
217
218      <varlistentry><term>
219       <literal>char default_listen&lsqb;1024&rsqb;</literal></term>
220       <listitem><para>Same form as the command-line specification of
221         listener address. &quot;&quot;: no default listener address.
222         Default is to listen at &quot;tcp:@:9999&quot;. You can only
223         specify one default listener address in this fashion.
224        </para></listitem></varlistentry>
225
226      <varlistentry><term>
227       <literal>enum oid_proto default_proto;</literal></term>
228       <listitem><para>Either <literal>PROTO_Z3950</literal> or
229         <literal>PROTO_SR</literal>.
230         Default is <literal>PROTO_Z39_50</literal>.
231        </para></listitem></varlistentry>
232      
233      <varlistentry><term>
234        <literal>int idle_timeout;</literal></term>
235       <listitem><para>Maximum session idle-time, in minutes. Zero indicates
236         no (infinite) timeout. Default is 120 minutes.
237        </para></listitem></varlistentry>
238      
239      <varlistentry><term>
240        <literal>int maxrecordsize;</literal></term>
241       <listitem><para>Maximum permissible record (message) size. Default
242         is 1Mb. This amount of memory will only be allocated if a
243         client requests a very large amount of records in one operation
244         (or a big record).
245         Set it to a lower number if you are worried about resource
246         consumption on your host system.
247        </para></listitem></varlistentry>
248
249      <varlistentry><term>
250        <literal>char configname&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
251       <listitem><para>Passed to the backend when a new connection is received.
252        </para></listitem></varlistentry>
253
254      <varlistentry><term>
255        <literal>char setuid&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
256       <listitem><para>Set user id to the user specified, after binding
257         the listener addresses.
258        </para></listitem></varlistentry>
259      
260      <varlistentry><term>
261        <literal>void (*bend_start)(struct statserv_options_block *p)</literal>
262       </term>
263       <listitem><para>Pointer to function which is called after the
264         command line options have been parsed - but before the server
265         starts listening.
266         For forked UNIX servers this handler is called in the mother
267         process; for threaded servers this handler is called in the
268         main thread.
269         The default value of this pointer is NULL in which case it
270         isn't invoked by the frontend server.
271         When the server operates as an NT service this handler is called
272         whenever the service is started. 
273        </para></listitem></varlistentry>
274      
275      <varlistentry><term>
276        <literal>void (*bend_stop)(struct statserv_options_block *p)</literal>
277       </term>
278       <listitem><para>Pointer to function which is called whenever the server
279         has stopped listening for incoming connections. This function pointer
280         has a default value of NULL in which case it isn't called.
281         When the server operates as an NT service this handler is called
282         whenever the service is stopped.
283        </para></listitem></varlistentry>
284
285      <varlistentry><term>
286        <literal>void *handle</literal></term>
287       <listitem><para>User defined pointer (default value NULL).
288         This is a per-server handle that can be used to specify "user-data".
289         Do not confuse this with the session-handle as returned by bend_init.
290        </para></listitem></varlistentry>
291
292     </variablelist>
293    </para>
294
295    <para>
296     The pointer returned by <literal>statserv_getcontrol</literal> points to
297     a static area. You are allowed to change the contents of the structure,
298     but the changes will not take effect before you call
299    </para>
300    
301    <synopsis>
302 void statserv_setcontrol(statserv_options_block *block);
303    </synopsis>
304
305    <note>
306     <para>
307      that you should generally update this structure before calling
308      <function>statserv_main()</function>.
309     </para>
310    </note>
311   </sect1>
312
313   <sect1 id="server.backendfunctions"><title>The Backend Functions</title>
314
315    <para>
316     For each service of the protocol, the backend interface declares one or
317     two functions. You are required to provide implementations of the
318     functions representing the services that you wish to implement.
319    </para>
320
321    <sect2><title>Init</title>
322
323     <synopsis>
324 bend_initresult (*bend_init)(bend_initrequest *r);
325     </synopsis>
326
327     <para>
328      This handler is called once for each new connection request, after
329      a new process/thread has been created, and an Initialize Request has
330      been received from the client. The pointer to the
331      <function>bend_init</function> handler is passed in the call to
332      <function>statserv_start</function>.
333     </para>
334
335     <para>
336      This handler is also called when operating in SRW mode - when
337      a connection has been made (even though SRW does not offer
338      this service).
339     </para>
340
341     <para>
342      Unlike previous versions of YAZ, the <function>bend_init</function> also
343      serves as a handler that defines the Z39.50 services that the backend
344      wish to support. Pointers to <emphasis>all</emphasis> service handlers,
345      including search - and fetch must be specified here in this handler.
346     </para>
347     <para>
348      The request  - and result structures are defined as
349     </para>
350
351     <synopsis>
352 typedef struct bend_initrequest
353 {
354     Z_IdAuthentication *auth;
355     ODR stream;                /* encoding stream */
356     ODR print;                 /* printing stream */
357     Z_ReferenceId *referenceId;/* reference ID */
358     char *peer_name;           /* dns host of peer (client) */
359
360     char *implementation_id;
361     char *implementation_name;
362     char *implementation_version;
363     int (*bend_sort) (void *handle, bend_sort_rr *rr);
364     int (*bend_search) (void *handle, bend_search_rr *rr);
365     int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
366     int (*bend_present) (void *handle, bend_present_rr *rr);
367     int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
368     int (*bend_delete)(void *handle, bend_delete_rr *rr);
369     int (*bend_scan)(void *handle, bend_scan_rr *rr);
370     int (*bend_segment)(void *handle, bend_segment_rr *rr);
371
372     ODR decode;                 /* decoding stream */
373     /* character set and language negotiation - see include/yaz/z-charneg.h */
374     Z_CharSetandLanguageNegotiation *charneg_request;
375     Z_External *charneg_response;
376 } bend_initrequest;
377
378 typedef struct bend_initresult
379 {
380     int errcode;       /* 0==OK */
381     char *errstring;   /* system error string or NULL */
382     void *handle;      /* private handle to the backend module */
383 } bend_initresult;
384     </synopsis>
385
386     <para>
387      In general, the server frontend expects that the
388      <literal>bend_*result</literal> pointer that you return is valid at
389      least until the next call to a <literal>bend_* function</literal>.
390      This applies to all of the functions described herein. The parameter
391      structure passed to you in the call belongs to the server frontend, and
392      you should not make assumptions about its contents after the current
393      function call has completed. In other words, if you want to retain any
394      of the contents of a request structure, you should copy them.
395     </para>
396
397     <para>
398      The <literal>errcode</literal> should be zero if the initialization of
399      the backend went well. Any other value will be interpreted as an error.
400      The <literal>errstring</literal> isn't used in the current version, but
401      one option would be to stick it in the initResponse as a VisibleString.
402      The <literal>handle</literal> is the most important parameter. It should
403      be set to some value that uniquely identifies the current session to
404      the backend implementation. It is used by the frontend server in any
405      future calls to a backend function.
406      The typical use is to set it to point to a dynamically allocated state
407      structure that is private to your backend module.
408     </para>
409
410     <para>
411      The <literal>auth</literal> member holds the authentication information
412      part of the Z39.50 Initialize Request. Interpret this if your serves
413      requires authentication. 
414     </para>
415
416     <para>
417      The members <literal>peer_name</literal>,
418      <literal>implementation_id</literal>,
419      <literal>implementation_name</literal> and
420      <literal>implementation_version</literal> holds
421      DNS of client, ID of implementor, name
422      of client (Z39.50) implementation - and version.
423     </para>
424
425     <para>
426      The <literal>bend_</literal> - members are set to NULL when
427      <function>bend_init</function> is called. Modify the pointers by
428      setting them to point to backend functions.
429     </para>
430
431    </sect2>
432
433    <sect2><title>Search and retrieve</title>
434
435     <para>We now describe the handlers that are required to support search -
436      and retrieve. You must support two functions - one for search - and one
437      for fetch (retrieval of one record). If desirable you can provide a
438      third handler which is called when a present request is received which
439      allows you to optimize retrieval of multiple-records.
440     </para>
441
442     <synopsis>
443 int (*bend_search) (void *handle, bend_search_rr *rr);
444
445 typedef struct {
446     char *setname;             /* name to give to this set */
447     int replace_set;           /* replace set, if it already exists */
448     int num_bases;             /* number of databases in list */
449     char **basenames;          /* databases to search */
450     Z_ReferenceId *referenceId;/* reference ID */
451     Z_Query *query;            /* query structure */
452     ODR stream;                /* encode stream */
453     ODR decode;                /* decode stream */
454     ODR print;                 /* print stream */
455
456     bend_request request;
457     bend_association association;
458     int *fd;
459     int hits;                  /* number of hits */
460     int errcode;               /* 0==OK */
461     char *errstring;           /* system error string or NULL */
462 } bend_search_rr;
463     </synopsis>
464
465     <para>
466      The <function>bend_search</function> handler is a fairly close
467      approximation of a protocol Z39.50 Search Request - and Response PDUs
468      The <literal>setname</literal> is the resultSetName from the protocol.
469      You are required to establish a mapping between the set name and whatever
470      your backend database likes to use.
471      Similarly, the <literal>replace_set</literal> is a boolean value
472      corresponding to the resultSetIndicator field in the protocol.
473      <literal>num_bases/basenames</literal> is a length of/array of character
474      pointers to the database names provided by the client.
475      The <literal>query</literal> is the full query structure as defined in
476      the protocol ASN.1 specification.
477      It can be either of the possible query types, and it's up to you to
478      determine if you can handle the provided query type.
479      Rather than reproduce the C interface here, we'll refer you to the
480      structure definitions in the file
481      <filename>include/yaz/z-core.h</filename>. If you want to look at the
482      attributeSetId OID of the RPN query, you can either match it against
483      your own internal tables, or you can use the
484      <literal>oid_getentbyoid</literal> function provided by &yaz;.
485     </para>
486
487     <para>
488      The structure contains a number of hits, and an
489      <literal>errcode/errstring</literal> pair. If an error occurs
490      during the search, or if you're unhappy with the request, you should
491      set the errcode to a value from the BIB-1 diagnostic set. The value
492      will then be returned to the user in a nonsurrogate diagnostic record
493      in the response. The <literal>errstring</literal>, if provided, will
494      go in the addinfo field. Look at the protocol definition for the
495      defined error codes, and the suggested uses of the addinfo field.
496     </para>
497
498     <para>
499      The <function>bend_search</function> handler is also called when
500      the frontend server receives a SRW SearchRetrieveRequest.
501      For SRW, a CQL query is usually provided by the client.
502      The CQL query is available as part of <literal>Z_Query</literal>
503      structure (note that CQL is now part of Z39.50 via an external).
504      To support CQL in existing implementations that only do Type-1,
505      we refer to the CQL-to-PQF tool described
506      <link linkend="tools.cql.pqf">here</link>.
507     </para>
508
509     <para>
510      To maintain backwards compatibility, the frontend server
511      of yaz always assume that error codes are BIB-1 diagnostics.
512      For SRW operation, a Bib-1 diagnostic code is mapped to
513      SRW diagnostic.
514     </para>
515     
516     <synopsis>
517 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
518
519 typedef struct bend_fetch_rr {
520     char *setname;             /* set name */
521     int number;                /* record number */
522     Z_ReferenceId *referenceId;/* reference ID */
523     oid_value request_format;  /* One of the CLASS_RECSYN members */
524     int *request_format_raw;   /* same as above (raw OID) */
525     Z_RecordComposition *comp; /* Formatting instructions */
526     ODR stream;                /* encoding stream - memory source if req */
527     ODR print;                 /* printing stream */
528
529     char *basename;            /* name of database that provided record */
530     int len;                   /* length of record or -1 if structured */
531     char *record;              /* record */
532     int last_in_set;           /* is it?  */
533     oid_value output_format;   /* format */
534     int *output_format_raw;    /* used instead of above if not-null */
535     int errcode;               /* 0==success */
536     char *errstring;           /* system error string or NULL */
537     int surrogate_flag;        /* surrogate diagnostic */
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 SearchRetrieveRequest is received by the frontend server,
563      the <literal>referenceId</literal> is NULL, the <literal>request_format
564      </literal> (transfer syntax) is XML (OID name 
565      <literal>VAL_TEXT_XML</literal>).
566      The schema for SRW is stored in the
567      <literal>Z_RecordComposition</literal>
568      structure.
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  -->