Update headers and omit CVS Ids.
[yaz-moved-to-github.git] / doc / frontend.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 1Mb. 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 } bend_initrequest;
413
414 typedef struct bend_initresult
415 {
416     int errcode;               /* 0==OK */
417     char *errstring;           /* system error string or NULL */
418     void *handle;              /* private handle to the backend module */
419 } bend_initresult;
420     </synopsis>
421
422     <para>
423      In general, the server frontend expects that the
424      <literal>bend_*result</literal> pointer that you return is valid at
425      least until the next call to a <literal>bend_* function</literal>.
426      This applies to all of the functions described herein. The parameter
427      structure passed to you in the call belongs to the server frontend, and
428      you should not make assumptions about its contents after the current
429      function call has completed. In other words, if you want to retain any
430      of the contents of a request structure, you should copy them.
431     </para>
432
433     <para>
434      The <literal>errcode</literal> should be zero if the initialization of
435      the backend went well. Any other value will be interpreted as an error.
436      The <literal>errstring</literal> isn't used in the current version, but
437      one option would be to stick it in the initResponse as a VisibleString.
438      The <literal>handle</literal> is the most important parameter. It should
439      be set to some value that uniquely identifies the current session to
440      the backend implementation. It is used by the frontend server in any
441      future calls to a backend function.
442      The typical use is to set it to point to a dynamically allocated state
443      structure that is private to your backend module.
444     </para>
445
446     <para>
447      The <literal>auth</literal> member holds the authentication information
448      part of the Z39.50 Initialize Request. Interpret this if your serves
449      requires authentication. 
450     </para>
451
452     <para>
453      The members <literal>peer_name</literal>,
454      <literal>implementation_id</literal>,
455      <literal>implementation_name</literal> and
456      <literal>implementation_version</literal> holds
457      DNS of client, ID of implementor, name
458      of client (Z39.50) implementation - and version.
459     </para>
460
461     <para>
462      The <literal>bend_</literal> - members are set to NULL when
463      <function>bend_init</function> is called. Modify the pointers by
464      setting them to point to backend functions.
465     </para>
466
467    </sect2>
468
469    <sect2 id="server.search.retrieve"><title>Search and Retrieve</title>
470
471     <para>We now describe the handlers that are required to support search -
472      and retrieve. You must support two functions - one for search - and one
473      for fetch (retrieval of one record). If desirable you can provide a
474      third handler which is called when a present request is received which
475      allows you to optimize retrieval of multiple-records.
476     </para>
477
478     <synopsis>
479 int (*bend_search) (void *handle, bend_search_rr *rr);
480
481 typedef struct {
482     char *setname;             /* name to give to this set */
483     int replace_set;           /* replace set, if it already exists */
484     int num_bases;             /* number of databases in list */
485     char **basenames;          /* databases to search */
486     Z_ReferenceId *referenceId;/* reference ID */
487     Z_Query *query;            /* query structure */
488     ODR stream;                /* encode stream */
489     ODR decode;                /* decode stream */
490     ODR print;                 /* print stream */
491
492     bend_request request;
493     bend_association association;
494     int *fd;
495     int hits;                  /* number of hits */
496     int errcode;               /* 0==OK */
497     char *errstring;           /* system error string or NULL */
498     Z_OtherInformation *search_info; /* additional search info */
499     char *srw_sortKeys;        /* holds SRU/SRW sortKeys info */
500     char *srw_setname;         /* holds SRU/SRW generated resultsetID */
501     int *srw_setnameIdleTime;  /* holds SRU/SRW life-time */
502     int estimated_hit_count;   /* if hit count is estimated */
503     int partial_resultset;     /* if result set is partial */
504 } bend_search_rr;
505     </synopsis>
506
507     <para>
508      The <function>bend_search</function> handler is a fairly close
509      approximation of a protocol Z39.50 Search Request - and Response PDUs
510      The <literal>setname</literal> is the resultSetName from the protocol.
511      You are required to establish a mapping between the set name and whatever
512      your backend database likes to use.
513      Similarly, the <literal>replace_set</literal> is a boolean value
514      corresponding to the resultSetIndicator field in the protocol.
515      <literal>num_bases/basenames</literal> is a length of/array of character
516      pointers to the database names provided by the client.
517      The <literal>query</literal> is the full query structure as defined in
518      the protocol ASN.1 specification.
519      It can be either of the possible query types, and it's up to you to
520      determine if you can handle the provided query type.
521      Rather than reproduce the C interface here, we'll refer you to the
522      structure definitions in the file
523      <filename>include/yaz/z-core.h</filename>. If you want to look at the
524      attributeSetId OID of the RPN query, you can either match it against
525      your own internal tables, or you can use the <link linkend="tools.oid">
526      OID tools</link>.
527     </para>
528
529     <para>
530      The structure contains a number of hits, and an
531      <literal>errcode/errstring</literal> pair. If an error occurs
532      during the search, or if you're unhappy with the request, you should
533      set the errcode to a value from the BIB-1 diagnostic set. The value
534      will then be returned to the user in a nonsurrogate diagnostic record
535      in the response. The <literal>errstring</literal>, if provided, will
536      go in the addinfo field. Look at the protocol definition for the
537      defined error codes, and the suggested uses of the addinfo field.
538     </para>
539
540     <para>
541      The <function>bend_search</function> handler is also called when
542      the frontend server receives a SRU SearchRetrieveRequest.
543      For SRU, a CQL query is usually provided by the client.
544      The CQL query is available as part of <literal>Z_Query</literal>
545      structure (note that CQL is now part of Z39.50 via an external).
546      To support CQL in existing implementations that only do Type-1,
547      we refer to the CQL-to-PQF tool described
548      <link linkend="cql.to.pqf">here</link>.
549     </para>
550
551     <para>
552      To maintain backwards compatibility, the frontend server
553      of yaz always assume that error codes are BIB-1 diagnostics.
554      For SRU operation, a Bib-1 diagnostic code is mapped to
555      SRU diagnostic.
556     </para>
557     
558     <synopsis>
559 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
560
561 typedef struct bend_fetch_rr {
562     char *setname;             /* set name */
563     int number;                /* record number */
564     Z_ReferenceId *referenceId;/* reference ID */
565     Odr_oid *request_format;        /* format, transfer syntax (OID) */
566     Z_RecordComposition *comp; /* Formatting instructions */
567     ODR stream;                /* encoding stream - memory source if req */
568     ODR print;                 /* printing stream */
569
570     char *basename;            /* name of database that provided record */
571     int len;                   /* length of record or -1 if structured */
572     char *record;              /* record */
573     int last_in_set;           /* is it?  */
574     Odr_oid *output_format;        /* response format/syntax (OID) */
575     int errcode;               /* 0==success */
576     char *errstring;           /* system error string or NULL */
577     int surrogate_flag;        /* surrogate diagnostic */
578     char *schema;              /* string record schema input/output */
579 } bend_fetch_rr;
580     </synopsis>
581
582     <para>
583      The frontend server calls the <function>bend_fetch</function> handler
584      when it needs database records to fulfill a Z39.50 Search Request, a
585      Z39.50 Present Request or a SRU SearchRetrieveRequest.
586      The <literal>setname</literal> is simply the name of the result set
587      that holds the reference to the desired record.
588      The <literal>number</literal> is the offset into the set (with 1
589      being the first record in the set). The <literal>format</literal> field
590      is the record format requested by the client (See
591      <xref linkend="tools.oid"/>).
592      A value of NULL for <literal>format</literal> indicates that the
593      client did not request a specific format.
594      The <literal>stream</literal> argument is an &odr; stream which
595      should be used for allocating space for structured data records.
596      The stream will be reset when all records have been assembled, and
597      the response package has been transmitted.
598      For unstructured data, the backend is responsible for maintaining a
599      static or dynamic buffer for the record between calls.
600     </para>
601
602     <para>
603      If a SRU SearchRetrieveRequest is received by the frontend server,
604      the <literal>referenceId</literal> is NULL and the
605      <literal>format</literal> (transfer syntax) is the OID for XML.
606      The schema for SRU is stored in both the
607      <literal>Z_RecordComposition</literal>
608      structure and <literal>schema</literal> (simple string).
609     </para>
610
611     <para>
612      In the structure, the <literal>basename</literal> is the name of the
613      database that holds the
614      record. <literal>len</literal> is the length of the record returned, in
615      bytes, and <literal>record</literal> is a pointer to the record.
616      <literal>last_in_set</literal> should be nonzero only if the record
617      returned is the last one in the given result set.
618      <literal>errcode</literal> and <literal>errstring</literal>, if
619      given, will be interpreted as a global error pertaining to the
620      set, and will be returned in a non-surrogate-diagnostic.
621      If you wish to return the error as a surrogate-diagnostic
622      (local error) you can do this by setting
623      <literal>surrogate_flag</literal> to 1 also.
624     </para>
625
626     <para>
627      If the <literal>len</literal> field has the value -1, then
628      <literal>record</literal> is assumed to point to a constructed data
629      type. The <literal>format</literal> field will be used to determine
630      which encoder should be used to serialize the data.
631     </para>
632
633     <note>
634      <para>
635       If your backend generates structured records, it should use
636       <function>odr_malloc()</function> on the provided stream for allocating
637       data: This allows the frontend server to keep track of the record sizes.
638      </para>
639     </note>
640
641     <para>
642      The <literal>format</literal> field is mapped to an object identifier
643      in the direct reference of the resulting EXTERNAL representation
644      of the record.
645     </para>
646
647     <note>
648      <para>
649       The current version of &yaz; only supports the direct reference mode.
650      </para>
651     </note>
652
653     <synopsis>
654 int (*bend_present) (void *handle, bend_present_rr *rr);
655
656 typedef struct {
657     char *setname;             /* set name */
658     int start;
659     int number;                /* record number */
660     Odr_oid *format;           /* format, transfer syntax (OID) */
661     Z_ReferenceId *referenceId;/* reference ID */
662     Z_RecordComposition *comp; /* Formatting instructions */
663     ODR stream;                /* encoding stream - memory source if required */
664     ODR print;                 /* printing stream */
665     bend_request request;
666     bend_association association;
667
668     int hits;                  /* number of hits */
669     int errcode;               /* 0==OK */
670     char *errstring;           /* system error string or NULL */
671 } bend_present_rr;
672     </synopsis>
673
674     <para>
675      The <function>bend_present</function> handler is called when
676      the server receives a Z39.50 Present Request.
677      The <literal>setname</literal>,
678      <literal>start</literal> and <literal>number</literal> is the
679      name of the result set - start position - and number of records to
680      be retrieved respectively. <literal>format</literal> and
681      <literal>comp</literal> is the preferred transfer syntax and element
682      specifications of the present request.
683     </para>
684     <para>
685      Note that this is handler serves as a supplement for
686      <function>bend_fetch</function> and need not to be defined in order to
687      support search - and retrieve. 
688     </para>
689
690    </sect2>
691
692    <sect2 id="server.delete"><title>Delete</title>
693
694     <para>
695      For back-ends that supports delete of a result set only one handler
696      must be defined.
697     </para>
698
699     <synopsis>
700 int (*bend_delete)(void *handle, bend_delete_rr *rr);
701
702 typedef struct bend_delete_rr {
703     int function;
704     int num_setnames;
705     char **setnames;
706     Z_ReferenceId *referenceId;
707     int delete_status;      /* status for the whole operation */
708     int *statuses;          /* status each set - indexed as setnames */
709     ODR stream;
710     ODR print; 
711 } bend_delete_rr;
712     </synopsis>
713
714     <note>
715      <para>
716       The delete set function definition is rather primitive, mostly because
717       we have had no practical need for it as of yet. If someone wants
718       to provide a full delete service, we'd be happy to add the
719       extra parameters that are required. Are there clients out there
720       that will actually delete sets they no longer need?
721      </para>
722     </note>
723
724    </sect2>
725
726    <sect2 id="server.scan"><title>Scan</title>
727
728     <para>
729      For servers that wish to offer the scan service one handler
730      must be defined.
731     </para>
732
733     <synopsis>
734 int (*bend_scan)(void *handle, bend_scan_rr *rr);
735
736 typedef enum {
737     BEND_SCAN_SUCCESS,  /* ok */
738     BEND_SCAN_PARTIAL   /* not all entries could be found */
739 } bend_scan_status;
740
741 typedef struct bend_scan_rr {
742     int num_bases;      /* number of elements in databaselist */
743     char **basenames;   /* databases to search */
744     Odr_oid *attributeset;
745     Z_ReferenceId *referenceId; /* reference ID */
746     Z_AttributesPlusTerm *term;
747     ODR stream;         /* encoding stream - memory source if required */
748     ODR print;          /* printing stream */
749
750     int *step_size;     /* step size */
751     int term_position;  /* desired index of term in result list/returned */
752     int num_entries;    /* number of entries requested/returned */
753
754     /* scan term entries. The called handler does not have
755        to allocate this. Size of entries is num_entries (see above) */
756     struct scan_entry *entries;
757     bend_scan_status status;
758     int errcode;
759     char *errstring;
760     char *scanClause;   /* CQL scan clause */
761     char *setname;      /* Scan in result set (NULL if omitted) */
762 } bend_scan_rr;
763     </synopsis>
764    <para>
765     This backend server handles both Z39.50 scan 
766     and SRU scan. In order for a handler to distinguish between SRU (CQL) scan 
767     Z39.50 Scan , it must check for a non-NULL value of 
768     <literal>scanClause</literal>.
769    </para>
770    <note>
771     <para>
772      if designed today, it would be a choice using a union or similar,
773      but that would break binary compatibility with existing servers.
774     </para>
775     </note>
776    </sect2>
777   </sect1>
778
779   <sect1 id="server.invocation"><title>Application Invocation</title>
780
781    <para>
782     The finished application has the following
783     invocation syntax (by way of <function>statserv_main()</function>):
784    </para>
785
786    &gfs-synopsis;
787    
788    <para>
789     The options are:
790
791     &gfs-options;
792
793    </para>
794    
795    <para>
796     A listener specification consists of a transport mode followed by a
797     colon (:) followed by a listener address. The transport mode is
798     either <literal>tcp</literal>, <literal>unix:</literal> or
799     <literal>ssl</literal>.
800    </para>
801    
802    <para>
803     For TCP and SSL, an address has the form
804    </para>
805
806    <synopsis>
807     hostname | IP-number [: portnumber]
808    </synopsis>
809    
810    <para>
811     The port number defaults to 210 (standard Z39.50 port).
812    </para>
813
814    <para>
815     For UNIX, the address is the filename of socket.
816    </para>
817
818    <para>
819     For TCP/IP and SSL, the special hostname <literal>@</literal> 
820     (at sign) is mapped to the address <literal>INADDR_ANY</literal>,
821     which causes the server to listen on any local interface. 
822    </para>
823
824    <example id="server.example.running.unix"><title>Running the GFS on Unix</title>
825     <para>
826      Assuming the server application <replaceable>appname</replaceable> is
827      started as root, the following will make it listen on port 210.
828      The server will change identity to <literal>nobody</literal>
829      and write its log to <filename>/var/log/app.log</filename>.
830      <screen>
831       <replaceable>appname</replaceable> -l /var/log/app.log -u nobody tcp:@:210
832      </screen>
833     </para>
834     <para>
835      The server will accept Z39.50 requests and offer SRU service on port 210.
836     </para>
837    </example>
838    <example id="server.example.apache.sru"><title>Setting up Apache as SRU Frontend</title>
839     <para>
840      If you use <ulink url="&url.apache;">Apache</ulink>
841      as your public web server and want to offer HTTP port 80
842      access to the YAZ server on 210, you can use the
843      <ulink url="&url.apache.directive.proxypass;">
844       <literal>ProxyPass</literal></ulink> 
845      directive.
846      If you have virtual host
847      <literal>srw.mydomain</literal> you can use the following directives
848      in Apache's httpd.conf:
849      <screen>
850       &lt;VirtualHost *>
851        ErrorLog /home/srw/logs/error_log
852        TransferLog /home/srw/logs/access_log
853        ProxyPass / http://srw.mydomain:210/
854       &lt;/VirtualHost>
855      </screen>
856     </para>
857     <para>
858      The above for the Apache 1.3 series.
859     </para>
860    </example>
861    <example id="server.example.local.access">
862     <title>Running a server with local access only</title>
863     <para>
864      Servers that is only being accessed from the local host should listen
865      on UNIX file socket rather than a Internet socket. To listen on
866      <filename>/tmp/mysocket</filename> start the server as follows:
867      <screen>
868       <replaceable>appname</replaceable> tcp:/tmp/mysocket
869      </screen>
870     </para>
871    </example>
872   </sect1>
873   <sect1 id="server.vhosts"><title>GFS Configuration and Virtual Hosts</title>
874    &gfs-virtual;
875   </sect1>
876  </chapter>
877  
878  <!-- Keep this comment at the end of the file
879  Local variables:
880  mode: sgml
881  sgml-omittag:t
882  sgml-shorttag:t
883  sgml-minimize-attributes:nil
884  sgml-always-quote-attributes:t
885  sgml-indent-step:1
886  sgml-indent-data:t
887  sgml-parent-document: "yaz.xml"
888  sgml-local-catalogs: nil
889  sgml-namecase-general:t
890  End:
891  -->