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