Ignore program tstxmalloc
[yaz-moved-to-github.git] / doc / frontend.xml
index 2ff6ed9..18a4f27 100644 (file)
@@ -1,6 +1,5 @@
-<!-- $Id: frontend.xml,v 1.23 2004-06-15 09:33:12 adam Exp $ -->
  <chapter id="server"><title>Generic server</title>
-  <sect1><title>Introduction</title>
+  <sect1 id="server.introduction"><title>Introduction</title>
    
    <para>
     If you aren't into documentation, a good way to learn how the
@@ -13,7 +12,7 @@
 
    <para>
     If you have a database system that you would like to make available by
-    means of Z39.50, SRW o SRU, &yaz; basically offers your two options. You
+    means of Z39.50 or 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.
       Result-Set Sort (optional).
      </para></listitem>
     
+    <listitem><para>
+      Return Explain for SRU (optional).
+     </para></listitem>
+    
    </itemizedlist>
 
    <para>
@@ -163,7 +166,7 @@ int statserv_main(int argc, char **argv,
    </para>
 
    <synopsis>
-statserv_options_block *statserv_getcontrol(void);
+    statserv_options_block *statserv_getcontrol(void);
    </synopsis>
 
    <para>
@@ -196,18 +199,12 @@ statserv_options_block *statserv_getcontrol(void);
        </para></listitem></varlistentry>
      
      <varlistentry><term>
-       <literal>int loglevel</literal></term><listitem><para>
-       Set this by ORing the constants defined in
-       <filename>include/yaz/yaz-log.h</filename>.
-       </para></listitem></varlistentry>
-     
-     <varlistentry><term>
-       <literal>char logfile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
+       <literal>char logfile[ODR_MAXNAME+1]</literal></term>
       <listitem><para>File for diagnostic output (&quot;&quot;: stderr).
        </para></listitem></varlistentry>
      
      <varlistentry><term>
-       <literal>char apdufile&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
+       <literal>char apdufile[ODR_MAXNAME+1]</literal></term>
       <listitem><para>
        Name of file for logging incoming and outgoing APDUs
        (&quot;&quot;: don't log APDUs, &quot;-&quot;:
@@ -215,7 +212,7 @@ statserv_options_block *statserv_getcontrol(void);
        </para></listitem></varlistentry>
 
      <varlistentry><term>
-      <literal>char default_listen&lsqb;1024&rsqb;</literal></term>
+      <literal>char default_listen[1024]</literal></term>
       <listitem><para>Same form as the command-line specification of
        listener address. &quot;&quot;: no default listener address.
        Default is to listen at &quot;tcp:@:9999&quot;. You can only
@@ -246,12 +243,12 @@ statserv_options_block *statserv_getcontrol(void);
        </para></listitem></varlistentry>
 
      <varlistentry><term>
-       <literal>char configname&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
+       <literal>char configname[ODR_MAXNAME+1]</literal></term>
       <listitem><para>Passed to the backend when a new connection is received.
        </para></listitem></varlistentry>
 
      <varlistentry><term>
-       <literal>char setuid&lsqb;ODR_MAXNAME+1&rsqb;</literal></term>
+       <literal>char setuid[ODR_MAXNAME+1]</literal></term>
       <listitem><para>Set user id to the user specified, after binding
        the listener addresses.
        </para></listitem></varlistentry>
@@ -317,7 +314,7 @@ void statserv_setcontrol(statserv_options_block *block);
     functions representing the services that you wish to implement.
    </para>
 
-   <sect2><title>Init</title>
+   <sect2 id="server.init"><title>Init</title>
 
     <synopsis>
 bend_initresult (*bend_init)(bend_initrequest *r);
@@ -332,8 +329,8 @@ bend_initresult (*bend_init)(bend_initrequest *r);
     </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 handler is also called when operating in SRU mode - when
+     a connection has been made (even though SRU does not offer
      this service).
     </para>
 
@@ -350,35 +347,77 @@ bend_initresult (*bend_init)(bend_initrequest *r);
     <synopsis>
 typedef struct bend_initrequest
 {
-    Z_IdAuthentication *auth;
-    ODR stream;                /* encoding stream */
-    ODR print;                 /* printing stream */
-    Z_ReferenceId *referenceId;/* reference ID */
-    char *peer_name;           /* dns host of peer (client) */
+    /** \brief user/name/password to be read */
+    Z_IdAuthentication *auth; 
+    /** \brief encoding stream (for results) */
+    ODR stream;
+    /** \brief printing stream */
+    ODR print;
+    /** \brief decoding stream (use stream for results) */
+    ODR decode; 
+    /** \brief reference ID */
+    Z_ReferenceId *referenceId;
+    /** \brief peer address of client */
+    char *peer_name;           
+    
+    /** \brief character set and language negotiation 
+
+    see include/yaz/z-charneg.h 
+    */
+    Z_CharSetandLanguageNegotiation *charneg_request;
+
+    /** \brief character negotiation response */
+    Z_External *charneg_response;
+
+    /** \brief character set (encoding) for query terms 
+        
+    This is NULL by default. It should be set to the native character
+    set that the backend assumes for query terms */
+    char *query_charset;      
+
+    /** \brief whehter query_charset also applies to recors 
+    
+    Is 0 (No) by default. Set to 1 (yes) if records is in the same
+    character set as queries. If in doubt, use 0 (No).
+    */
+    int records_in_same_charset;
 
     char *implementation_id;
     char *implementation_name;
     char *implementation_version;
-    int (*bend_sort) (void *handle, bend_sort_rr *rr);
-    int (*bend_search) (void *handle, bend_search_rr *rr);
-    int (*bend_fetch) (void *handle, bend_fetch_rr *rr);
-    int (*bend_present) (void *handle, bend_present_rr *rr);
+
+    /** \brief Z39.50 sort handler */
+    int (*bend_sort)(void *handle, bend_sort_rr *rr);
+    /** \brief SRU/Z39.50 search handler */
+    int (*bend_search)(void *handle, bend_search_rr *rr);
+    /** \brief SRU/Z39.50 fetch handler */
+    int (*bend_fetch)(void *handle, bend_fetch_rr *rr);
+    /** \brief SRU/Z39.50 present handler */
+    int (*bend_present)(void *handle, bend_present_rr *rr);
+    /** \brief Z39.50 extended services handler */
     int (*bend_esrequest) (void *handle, bend_esrequest_rr *rr);
+    /** \brief Z39.50 delete result set handler */
     int (*bend_delete)(void *handle, bend_delete_rr *rr);
+    /** \brief Z39.50 scan handler */
     int (*bend_scan)(void *handle, bend_scan_rr *rr);
+    /** \brief Z39.50 segment facility handler */
     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;
+    /** \brief SRU explain handler */
+    int (*bend_explain)(void *handle, bend_explain_rr *rr);
+    /** \brief SRU scan handler */
+    int (*bend_srw_scan)(void *handle, bend_scan_rr *rr);
+    /** \brief SRU record update handler */
+    int (*bend_srw_update)(void *handle, bend_update_rr *rr);
+
+    /** \brief whether named result sets are supported (0=disable, 1=enable) */
+    int named_result_sets;
 } bend_initrequest;
 
 typedef struct bend_initresult
 {
-    int errcode;       /* 0==OK */
-    char *errstring;   /* system error string or NULL */
-    void *handle;      /* private handle to the backend module */
+    int errcode;               /* 0==OK */
+    char *errstring;           /* system error string or NULL */
+    void *handle;              /* private handle to the backend module */
 } bend_initresult;
     </synopsis>
 
@@ -429,7 +468,7 @@ typedef struct bend_initresult
 
    </sect2>
 
-   <sect2><title>Search and retrieve</title>
+   <sect2 id="server.search.retrieve"><title>Search and Retrieve</title>
 
     <para>We now describe the handlers that are required to support search -
      and retrieve. You must support two functions - one for search - and one
@@ -458,6 +497,12 @@ typedef struct {
     int hits;                  /* number of hits */
     int errcode;               /* 0==OK */
     char *errstring;           /* system error string or NULL */
+    Z_OtherInformation *search_info; /* additional search info */
+    char *srw_sortKeys;        /* holds SRU/SRW sortKeys info */
+    char *srw_setname;         /* holds SRU/SRW generated resultsetID */
+    int *srw_setnameIdleTime;  /* holds SRU/SRW life-time */
+    int estimated_hit_count;   /* if hit count is estimated */
+    int partial_resultset;     /* if result set is partial */
 } bend_search_rr;
     </synopsis>
 
@@ -479,8 +524,8 @@ typedef struct {
      structure definitions in the file
      <filename>include/yaz/z-core.h</filename>. If you want to look at the
      attributeSetId OID of the RPN query, you can either match it against
-     your own internal tables, or you can use the
-     <literal>oid_getentbyoid</literal> function provided by &yaz;.
+     your own internal tables, or you can use the <link linkend="tools.oid">
+     OID tools</link>.
     </para>
 
     <para>
@@ -496,20 +541,20 @@ typedef struct {
 
     <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 frontend server receives a SRU SearchRetrieveRequest.
+     For 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>.
+     <link linkend="cql.to.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.
+     For SRU operation, a Bib-1 diagnostic code is mapped to
+     SRU diagnostic.
     </para>
     
     <synopsis>
@@ -519,8 +564,7 @@ typedef struct bend_fetch_rr {
     char *setname;             /* set name */
     int number;                /* record number */
     Z_ReferenceId *referenceId;/* reference ID */
-    oid_value request_format;  /* One of the CLASS_RECSYN members */
-    int *request_format_raw;   /* same as above (raw OID) */
+    Odr_oid *request_format;        /* format, transfer syntax (OID) */
     Z_RecordComposition *comp; /* Formatting instructions */
     ODR stream;                /* encoding stream - memory source if req */
     ODR print;                 /* printing stream */
@@ -529,8 +573,7 @@ typedef struct bend_fetch_rr {
     int len;                   /* length of record or -1 if structured */
     char *record;              /* record */
     int last_in_set;           /* is it?  */
-    oid_value output_format;   /* format */
-    int *output_format_raw;    /* used instead of above if not-null */
+    Odr_oid *output_format;        /* response format/syntax (OID) */
     int errcode;               /* 0==success */
     char *errstring;           /* system error string or NULL */
     int surrogate_flag;        /* surrogate diagnostic */
@@ -541,17 +584,17 @@ typedef struct bend_fetch_rr {
     <para>
      The frontend server calls the <function>bend_fetch</function> handler
      when it needs database records to fulfill a Z39.50 Search Request, a
-     Z39.50 Present Request or a SRW SearchRetrieveRequest.
+     Z39.50 Present Request or a SRU 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
-     <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.
+     <xref linkend="tools.oid"/>).
+     A value of NULL for <literal>format</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
      the response package has been transmitted.
      For unstructured data, the backend is responsible for maintaining a
@@ -559,11 +602,10 @@ typedef struct bend_fetch_rr {
     </para>
 
     <para>
-     If a SRW/SRU SearchRetrieveRequest is received by the frontend server,
+     If a 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>format</literal> (transfer syntax) is the OID for XML.
+     The schema for SRU is stored in both the
      <literal>Z_RecordComposition</literal>
      structure and <literal>schema</literal> (simple string).
     </para>
@@ -617,10 +659,10 @@ typedef struct {
     char *setname;             /* set name */
     int start;
     int number;                /* record number */
-    oid_value format;          /* One of the CLASS_RECSYN members */
+    Odr_oid *format;           /* format, transfer syntax (OID) */
     Z_ReferenceId *referenceId;/* reference ID */
     Z_RecordComposition *comp; /* Formatting instructions */
-    ODR stream;                /* encoding stream */
+    ODR stream;                /* encoding stream - memory source if required */
     ODR print;                 /* printing stream */
     bend_request request;
     bend_association association;
@@ -649,7 +691,7 @@ typedef struct {
 
    </sect2>
 
-   <sect2><title>Delete</title>
+   <sect2 id="server.delete"><title>Delete</title>
 
     <para>
      For back-ends that supports delete of a result set only one handler
@@ -683,7 +725,7 @@ typedef struct bend_delete_rr {
 
    </sect2>
 
-   <sect2><title>scan</title>
+   <sect2 id="server.scan"><title>Scan</title>
 
     <para>
      For servers that wish to offer the scan service one handler
@@ -691,7 +733,7 @@ typedef struct bend_delete_rr {
     </para>
 
     <synopsis>
-int (*bend_delete)(void *handle, bend_delete_rr *rr);
+int (*bend_scan)(void *handle, bend_scan_rr *rr);
 
 typedef enum {
     BEND_SCAN_SUCCESS,  /* ok */
@@ -699,9 +741,9 @@ typedef enum {
 } bend_scan_status;
 
 typedef struct bend_scan_rr {
-    int num_bases;      /* number of elements in database list */
+    int num_bases;      /* number of elements in databaselist */
     char **basenames;   /* databases to search */
-    oid_value attributeset;
+    Odr_oid *attributeset;
     Z_ReferenceId *referenceId; /* reference ID */
     Z_AttributesPlusTerm *term;
     ODR stream;         /* encoding stream - memory source if required */
@@ -711,12 +753,28 @@ typedef struct bend_scan_rr {
     int term_position;  /* desired index of term in result list/returned */
     int num_entries;    /* number of entries requested/returned */
 
+    /* scan term entries. The called handler does not have
+       to allocate this. Size of entries is num_entries (see above) */
     struct scan_entry *entries;
     bend_scan_status status;
     int errcode;
     char *errstring;
+    char *scanClause;   /* CQL scan clause */
+    char *setname;      /* Scan in result set (NULL if omitted) */
 } bend_scan_rr;
     </synopsis>
+   <para>
+    This backend server handles both Z39.50 scan 
+    and SRU scan. In order for a handler to distinguish between 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>
 
@@ -726,31 +784,13 @@ typedef struct bend_scan_rr {
     The finished application has the following
     invocation syntax (by way of <function>statserv_main()</function>):
    </para>
-   
-   <cmdsynopsis>
-    <command>appname</command>
-    <arg choice="opt"><option>-install</option></arg>
-    <arg choice="opt"><option>-installa</option></arg>
-    <arg choice="opt"><option>-remove</option></arg>
-    <arg choice="opt"><option>-a <replaceable>file</replaceable></option></arg>
-    <arg choice="opt"><option>-v <replaceable>level</replaceable></option></arg>
-    <arg choice="opt"><option>-l <replaceable>file</replaceable></option></arg>
-    <arg choice="opt"><option>-u <replaceable>uid</replaceable></option></arg>
-    <arg choice="opt"><option>-c <replaceable>config</replaceable></option></arg>
-    <arg choice="opt"><option>-t <replaceable>minutes</replaceable></option></arg>
-    <sbr/>
-    <arg choice="opt"><option>-k <replaceable>kilobytes</replaceable></option></arg>
-    <arg choice="opt"><option>-d <replaceable>daemon</replaceable></option></arg>
-    <arg choice="opt"><option>-w <replaceable>dir</replaceable></option></arg>
-    <arg choice="opt"><option>-p <replaceable>pidfile</replaceable></option></arg>
-    <arg choice="opt"><option>-ziDST1</option></arg>
-    <arg choice="opt" rep="repeat">listener-spec</arg>
-   </cmdsynopsis>
+
+   &gfs-synopsis;
    
    <para>
     The options are:
 
-    &ztest-options;
+    &gfs-options;
 
    </para>
    
@@ -766,7 +806,7 @@ typedef struct bend_scan_rr {
    </para>
 
    <synopsis>
-    hostname | IP-number &lsqb;: portnumber&rsqb;
+    hostname | IP-number [: portnumber]
    </synopsis>
    
    <para>
@@ -783,27 +823,26 @@ typedef struct bend_scan_rr {
     which causes the server to listen on any local interface. 
    </para>
 
-   <example><title>Running the GFS on Unix</title>
+   <example id="server.example.running.unix"><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
+      application -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.
+     The server will accept Z39.50 requests and offer SRU service on port 210.
     </para>
    </example>
-   <example><title>Setting up Apache as SRW/SRU Frontend</title>
+   <example id="server.example.apache.sru"><title>Setting up Apache as SRU Frontend</title>
     <para>
-     If you use <ulink url="http://httpd.apache.org/">Apache</ulink>
+     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="http://httpd.apache.org/docs/mod/mod_proxy.html#proxypass">
+     <ulink url="&url.apache.directive.proxypass;">
       <literal>ProxyPass</literal></ulink> 
      directive.
      If you have virtual host
@@ -814,24 +853,28 @@ typedef struct bend_scan_rr {
        ErrorLog /home/srw/logs/error_log
        TransferLog /home/srw/logs/access_log
        ProxyPass / http://srw.mydomain:210/
-      &lt;/VirualHost>
+      &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>
+   <example id="server.example.local.access">
+    <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
+      application unix:/tmp/mysocket
      </screen>
     </para>
    </example>
   </sect1>
+  <sect1 id="server.vhosts"><title>GFS Configuration and Virtual Hosts</title>
+   &gfs-virtual;
+  </sect1>
  </chapter>
  
  <!-- Keep this comment at the end of the file