Fix mistake: fuzzy matching is 5=103, not 5=102
[yaz-moved-to-github.git] / doc / frontend.xml
index 0673c3d..985f4bd 100644 (file)
@@ -1,21 +1,19 @@
-<!-- $Id: frontend.xml,v 1.6 2001-10-24 09:27:59 adam Exp $ -->
- <chapter id="server"><title>Making an IR Server for Your Database</title>
+<!-- $Id: frontend.xml,v 1.29 2006-04-25 11:25:08 marc Exp $ -->
+ <chapter id="server"><title>Generic server</title>
   <sect1><title>Introduction</title>
-
+   
    <para>
     If you aren't into documentation, a good way to learn how the
     back end interface works is to look at the <filename>backend.h</filename>
     file. Then, look at the small dummy-server in
-    <filename>ztest/ztest.c</filename>. Finally, you can have a look at
-    the <filename>seshigh.c</filename> file, which is where most of the
-    logic of the frontend server is located. The <filename>backend.h</filename>
+    <filename>ztest/ztest.c</filename>. The <filename>backend.h</filename>
     file also makes a good reference, once you've chewed your way through
     the prose of this file.
    </para>
 
    <para>
     If you have a database system that you would like to make available by
-    means of Z39.50, &yaz; basically offers your two options. You
+    means of Z39.50, SRW o SRU, &yaz; basically offers your two options. You
     can use the APIs provided by the &asn;, &odr;, and &comstack;
     modules to
     create and decode PDUs, and exchange them with a client.
      too many structural changes in existing applications.
     </para>
    </note>
+
+   <note>
+    <para>
+     The &yaz; server does not support XCQL.
+     </para>
+   </note>
   </sect1>
   
   <sect1 id="server.frontend"><title>The Database Frontend</title>
@@ -54,7 +58,8 @@
     The backend API consists of a small number of function handlers and
     structure definitions. You are required to provide the
     <function>main()</function> routine for the server (which can be
-    quite simple), as well as a set of handlers to match each of the prototypes.
+    quite simple), as well as a set of handlers to match each of the
+    prototypes.
     The interface functions that you write can use any mechanism you like
     to communicate with your database system: You might link the whole
     thing together with your database application and access it by
       Result-Set Sort (optional).
      </para></listitem>
     
+    <listitem><para>
+      Return Explain for SRW/SRU (optional).
+     </para></listitem>
+    
    </itemizedlist>
 
    <para>
   <sect1 id="server.backend"><title>The Backend API</title>
 
    <para>
-    The headers files that you need to use the interface are in the
-    <filename>include/yaz</filename> directory. They are called
-    <filename>statserv.h</filename> and <filename>backend.h</filename>. They
-    will include other files from the <filename>include/yaz</filename>
-    directory, so you'll probably want to use the -I option of your
-    compiler to tell it where to find the files. When you run
+    The header file that you need to use the interface are in the
+    <filename>include/yaz</filename> directory. It's called
+    <filename>backend.h</filename>. It will include other files from
+    the <filename>include/yaz</filename> directory, so you'll
+    probably want to use the -I option of your compiler to tell it
+    where to find the files. When you run
     <literal>make</literal> in the top-level &yaz; directory,
-    everything you need to create your server is put the
-    <filename>lib/libyaz.a</filename> library.
+    everything you need to create your server is to link with the
+    <filename>lib/libyaz.la</filename> library.
    </para>
   </sect1>
 
@@ -219,15 +228,15 @@ statserv_options_block *statserv_getcontrol(void);
 
      <varlistentry><term>
       <literal>enum oid_proto default_proto;</literal></term>
-      <listitem><para>Either <literal>PROTO_SR</literal> or
-       <literal>PROTO_Z3950</literal>.
+      <listitem><para>Either <literal>PROTO_Z3950</literal> or
+       <literal>PROTO_SR</literal>.
        Default is <literal>PROTO_Z39_50</literal>.
        </para></listitem></varlistentry>
      
      <varlistentry><term>
        <literal>int idle_timeout;</literal></term>
-      <listitem><para>Maximum session idletime, in minutes. Zero indicates
-       no (infinite) timeout. Default is 120 minutes.
+      <listitem><para>Maximum session idle-time, in minutes. Zero indicates
+       no (infinite) timeout. Default is 15 minutes.
        </para></listitem></varlistentry>
      
      <varlistentry><term>
@@ -325,6 +334,13 @@ bend_initresult (*bend_init)(bend_initrequest *r);
      <function>bend_init</function> handler is passed in the call to
      <function>statserv_start</function>.
     </para>
+
+    <para>
+     This handler is also called when operating in SRW/SRU mode - when
+     a connection has been made (even though SRW/SRU does not offer
+     this service).
+    </para>
+
     <para>
      Unlike previous versions of YAZ, the <function>bend_init</function> also
      serves as a handler that defines the Z39.50 services that the backend
@@ -344,6 +360,7 @@ typedef struct bend_initrequest
     Z_ReferenceId *referenceId;/* reference ID */
     char *peer_name;           /* dns host of peer (client) */
 
+    char *implementation_id;
     char *implementation_name;
     char *implementation_version;
     int (*bend_sort) (void *handle, bend_sort_rr *rr);
@@ -354,6 +371,13 @@ typedef struct bend_initrequest
     int (*bend_delete)(void *handle, bend_delete_rr *rr);
     int (*bend_scan)(void *handle, bend_scan_rr *rr);
     int (*bend_segment)(void *handle, bend_segment_rr *rr);
+
+    ODR decode;                 /* decoding stream */
+    /* character set and language negotiation - see include/yaz/z-charneg.h */
+    Z_CharSetandLanguageNegotiation *charneg_request;
+    Z_External *charneg_response;
+    int (*bend_srw_explain)(void *handle, bend_explain_rr *rr);
+    int (*bend_srw_scan)(void *handle, bend_scan_rr *rr);
 } bend_initrequest;
 
 typedef struct bend_initresult
@@ -396,8 +420,10 @@ typedef struct bend_initresult
 
     <para>
      The members <literal>peer_name</literal>,
+     <literal>implementation_id</literal>,
      <literal>implementation_name</literal> and
-     <literal>implementation_version</literal> holds DNS of client, name
+     <literal>implementation_version</literal> holds
+     DNS of client, ID of implementor, name
      of client (Z39.50) implementation - and version.
     </para>
 
@@ -438,13 +464,13 @@ typedef struct {
     int hits;                  /* number of hits */
     int errcode;               /* 0==OK */
     char *errstring;           /* system error string or NULL */
+    Z_OtherInformation *search_info;
 } bend_search_rr;
-
     </synopsis>
 
     <para>
      The <function>bend_search</function> handler is a fairly close
-     approximation of a protocol Search Request - and Response PDUs
+     approximation of a protocol Z39.50 Search Request - and Response PDUs
      The <literal>setname</literal> is the resultSetName from the protocol.
      You are required to establish a mapping between the set name and whatever
      your backend database likes to use.
@@ -475,7 +501,24 @@ typedef struct {
      defined error codes, and the suggested uses of the addinfo field.
     </para>
 
+    <para>
+     The <function>bend_search</function> handler is also called when
+     the frontend server receives a SRW/SRU SearchRetrieveRequest.
+     For SRW/SRU, a CQL query is usually provided by the client.
+     The CQL query is available as part of <literal>Z_Query</literal>
+     structure (note that CQL is now part of Z39.50 via an external).
+     To support CQL in existing implementations that only do Type-1,
+     we refer to the CQL-to-PQF tool described
+     <link linkend="tools.cql.pqf">here</link>.
+    </para>
 
+    <para>
+     To maintain backwards compatibility, the frontend server
+     of yaz always assume that error codes are BIB-1 diagnostics.
+     For SRW/SRU operation, a Bib-1 diagnostic code is mapped to
+     SRW/SRU diagnostic.
+    </para>
+    
     <synopsis>
 int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
 
@@ -498,21 +541,22 @@ typedef struct bend_fetch_rr {
     int errcode;               /* 0==success */
     char *errstring;           /* system error string or NULL */
     int surrogate_flag;        /* surrogate diagnostic */
+    char *schema;              /* string record schema input/output */
 } bend_fetch_rr;
     </synopsis>
 
     <para>
      The frontend server calls the <function>bend_fetch</function> handler
-     when it needs database records to fulfill a Search Request or a Present
-     Request.
+     when it needs database records to fulfill a Z39.50 Search Request, a
+     Z39.50 Present Request or a SRW SearchRetrieveRequest.
      The <literal>setname</literal> is simply the name of the result set
      that holds the reference to the desired record.
      The <literal>number</literal> is the offset into the set (with 1
      being the first record in the set). The <literal>format</literal> field
-     is the record format requested by the client (See section
-     <link linkend="oid">Object Identifiers</link>). The value
-     <literal>VAL_NONE</literal> indicates that the client did not
-     request a specific format. The <literal>stream</literal> argument
+     is the record format requested by the client (See
+     <xref linkend="asn.oid"/>).
+     The value <literal>VAL_NONE</literal> indicates that the client did
+     not request a specific format. The <literal>stream</literal> argument
      is an &odr; stream which should be used for
      allocating space for structured data records.
      The stream will be reset when all records have been assembled, and
@@ -522,11 +566,21 @@ typedef struct bend_fetch_rr {
     </para>
 
     <para>
+     If a SRW/SRU SearchRetrieveRequest is received by the frontend server,
+     the <literal>referenceId</literal> is NULL and the
+     <literal>request_format</literal> (transfer syntax) is XML (OID name 
+     <literal>VAL_TEXT_XML</literal>).
+     The schema for SRW/SRU is stored in both the
+     <literal>Z_RecordComposition</literal>
+     structure and <literal>schema</literal> (simple string).
+    </para>
+
+    <para>
      In the structure, the <literal>basename</literal> is the name of the
      database that holds the
      record. <literal>len</literal> is the length of the record returned, in
      bytes, and <literal>record</literal> is a pointer to the record.
-     <literal>Last_in_set</literal> should be nonzero only if the record
+     <literal>last_in_set</literal> should be nonzero only if the record
      returned is the last one in the given result set.
      <literal>errcode</literal> and <literal>errstring</literal>, if
      given, will be interpreted as a global error pertaining to the
@@ -586,7 +640,8 @@ typedef struct {
 
     <para>
      The <function>bend_present</function> handler is called when
-     the server receives a Present Request. The <literal>setname</literal>,
+     the server receives a Z39.50 Present Request.
+     The <literal>setname</literal>,
      <literal>start</literal> and <literal>number</literal> is the
      name of the result set - start position - and number of records to
      be retrieved respectively. <literal>format</literal> and
@@ -651,7 +706,7 @@ typedef enum {
 } bend_scan_status;
 
 typedef struct bend_scan_rr {
-    int num_bases;      /* number of elements in databaselist */
+    int num_bases;      /* number of elements in database list */
     char **basenames;   /* databases to search */
     oid_value attributeset;
     Z_ReferenceId *referenceId; /* reference ID */
@@ -667,8 +722,22 @@ typedef struct bend_scan_rr {
     bend_scan_status status;
     int errcode;
     char *errstring;
+    char *scanClause;   /* CQL scan clause */
 } bend_scan_rr;
     </synopsis>
+   <para>
+    This backend server handles both Z39.50 scan 
+    and SRW/SRU scan. In order for a
+    handler to distinguish between SRW/SRU (CQL) scan 
+    Z39.50 Scan , it must check for a non-NULL value of 
+    <literal>scanClause</literal>.
+   </para>
+   <note>
+    <para>
+     if designed today, it would be a choice using a union or similar,
+     but that would break binary compatibility with existing servers.
+    </para>
+    </note>
    </sect2>
   </sect1>
 
@@ -679,166 +748,98 @@ typedef struct bend_scan_rr {
     invocation syntax (by way of <function>statserv_main()</function>):
    </para>
 
-   <synopsis>
-    <replaceable>appname</replaceable> &lsqb;-szSiTu -a <replaceable>apdufile</replaceable> -l <replaceable>logfile</replaceable> -v <replaceable>loglevel</replaceable> -c <replaceable>config</replaceable>&rsqb;
-    &lsqb;listener ...&rsqb;
-   </synopsis>
-
+   &gfs-synopsis;
+   
    <para>
-    The options are
-
-    <variablelist>
-
-     <varlistentry><term>-a <replaceable>file</replaceable></term>
-      <listitem><para>
-       Specify a file for dumping PDUs (for diagnostic purposes).
-       The special name &quot;-&quot; sends output to
-       <literal>stderr</literal>.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-S</term>
-      <listitem><para>
-       Don't fork or make threads on connection requests. This is good for
-       debugging, but not recommended for real operation: Although the
-       server is asynchronous and non-blocking, it can be nice to keep
-       a software malfunction (okay then, a crash) from affecting all
-       current users.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-T</term>
-      <listitem><para>
-       Operate the server in threaded mode. The server creates a thread
-       for each connection rather than a fork a process. Only available
-       on UNIX systems that offers POSIX threads.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-s</term>
-      <listitem><para>
-       Use the SR protocol (obsolete).
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-z</term>
-      <listitem><para>
-       Use the Z39.50 protocol (default). These two options complement
-       each other. You can use both multiple times on the same command
-       line, between listener-specifications (see below). This way, you
-       can set up the server to listen for connections in both protocols
-       concurrently, on different local ports.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-l <replaceable>file</replaceable></term>
-      <listitem><para>The logfile.
-       </para></listitem></varlistentry>
+    The options are:
 
-     <varlistentry><term>-c <replaceable>config</replaceable></term>
-      <listitem><para>A user option that serves as a specifier for some
-       sort of configuration, e.g. a filename.
-       The argument to this option is transferred to member
-       <literal>configname</literal>of the
-       <literal>statserv_options_block</literal>.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-v <replaceable>level</replaceable></term>
-      <listitem><para>
-       The log level. Use a comma-separated list of members of the set
-       {fatal,debug,warn,log,all,none}.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-u <replaceable>userid</replaceable></term>
-      <listitem><para>
-       Set user ID. Sets the real UID of the server process to that of the
-       given user. It's useful if you aren't comfortable with having the
-       server run as root, but you need to start it as such to bind a
-       privileged port.
-       </para></listitem></varlistentry>
+    &gfs-options;
 
-     <varlistentry><term>-w <replaceable>dir</replaceable></term>
-      <listitem><para>
-       Working directory.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-i</term>
-      <listitem><para>
-       Use this when running from the <application>inetd</application> server.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-t <replaceable>minutes</replaceable></term>
-      <listitem><para>
-       Idle session timeout, in minutes.
-       </para></listitem></varlistentry>
-
-     <varlistentry><term>-k <replaceable>size</replaceable></term>
-      <listitem><para>
-       Maximum record size/message size, in kilobytes.
-       </para></listitem></varlistentry>
-
-    </variablelist>
    </para>
-
+   
    <para>
     A listener specification consists of a transport mode followed by a
     colon (:) followed by a listener address. The transport mode is
-    either <literal>osi</literal> or <literal>tcp</literal>.
+    either <literal>tcp</literal>, <literal>unix:</literal> or
+    <literal>ssl</literal>.
    </para>
-
+   
    <para>
-    For TCP, an address has the form
+    For TCP and SSL, an address has the form
    </para>
 
    <synopsis>
     hostname | IP-number &lsqb;: portnumber&rsqb;
    </synopsis>
-
+   
    <para>
     The port number defaults to 210 (standard Z39.50 port).
    </para>
 
    <para>
-    For osi, the address form is
+    For UNIX, the address is the filename of socket.
    </para>
 
-   <synopsis>
-    &lsqb;t-selector /&rsqb; hostname | IP-number &lsqb;: portnumber&rsqb;
-   </synopsis>
-
-   <para>
-    The transport selector is given as a string of hex digits (with an even
-    number of digits). The default port number is 102 (RFC1006 port).
-   </para>
-
-   <para>
-    Examples
-   </para>
-
-   <screen>
-    tcp:dranet.dra.com
-
-    osi:0402/dbserver.osiworld.com:3000
-   </screen>
-
-   <para>
-    In both cases, the special hostname &quot;@&quot; is mapped to
-    the address INADDR_ANY, which causes the server to listen on any local
-    interface. To start the server listening on the registered ports for
-    Z39.50 and SR over OSI/RFC1006, and to drop root privileges once the
-    ports are bound, execute the server like this (from a root shell):
-   </para>
-
-   <screen>
-    my-server -u daemon tcp:@ -s osi:@
-   </screen>
-
    <para>
-    You can replace <literal>daemon</literal> with another user, eg. your
-    own account, or a dedicated IR server account.
-    <literal>my-server</literal> should be the name of your
-    server application. You can test the procedure with the
-    <application>yaz-ztest</application> application.
+    For TCP/IP and SSL, the special hostname <literal>@</literal> 
+    (at sign) is mapped to the address <literal>INADDR_ANY</literal>,
+    which causes the server to listen on any local interface. 
    </para>
 
+   <example><title>Running the GFS on Unix</title>
+    <para>
+     Assuming the server application <replaceable>appname</replaceable> is
+     started as root, the following will make it listen on port 210.
+     The server will change identity to <literal>nobody</literal>
+     and write its log to <filename>/var/log/app.log</filename>.
+     <screen>
+      <replaceable>appname</replaceable> -l /var/log/app.log -u nobody tcp:@:210
+     </screen>
+    </para>
+    <para>
+     The server will accept Z39.50 requests and offer SRW/SRU service
+     on port 210.
+    </para>
+   </example>
+   <example><title>Setting up Apache as SRW/SRU Frontend</title>
+    <para>
+     If you use <ulink url="&url.apache;">Apache</ulink>
+     as your public web server and want to offer HTTP port 80
+     access to the YAZ server on 210, you can use the
+     <ulink url="&url.apache.directive.proxypass;">
+      <literal>ProxyPass</literal></ulink> 
+     directive.
+     If you have virtual host
+     <literal>srw.mydomain</literal> you can use the following directives
+     in Apache's httpd.conf:
+     <screen>
+      &lt;VirtualHost *>
+       ErrorLog /home/srw/logs/error_log
+       TransferLog /home/srw/logs/access_log
+       ProxyPass / http://srw.mydomain:210/
+      &lt;/VirtualHost>
+     </screen>
+    </para>
+    <para>
+     The above for the Apache 1.3 series.
+    </para>
+   </example>
+   <example><title>Running a server with local access only</title>
+    <para>
+     Servers that is only being accessed from the local host should listen
+     on UNIX file socket rather than a Internet socket. To listen on
+     <filename>/tmp/mysocket</filename> start the server as follows:
+     <screen>
+      <replaceable>appname</replaceable> tcp:/tmp/mysocket
+     </screen>
+    </para>
+   </example>
+  </sect1>
+  <sect1 id="server.vhosts"><title>Virtual Hosts</title>
+   &gfs-virtual;
   </sect1>
  </chapter>
-
  <!-- Keep this comment at the end of the file
  Local variables:
  mode: sgml
@@ -849,7 +850,7 @@ typedef struct bend_scan_rr {
  sgml-indent-step:1
  sgml-indent-data:t
  sgml-parent-document: "yaz.xml"
- sgml-local-catalogs: "../../docbook/docbook.cat"
+ sgml-local-catalogs: nil
  sgml-namecase-general:t
  End:
  -->