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