Much more on virtual databases and multi-database searching.
[metaproxy-moved-to-github.git] / doc / book.xml
1 <!-- $Id: book.xml,v 1.24 2006-04-27 16:16:28 mike Exp $ -->
2  <bookinfo>
3   <title>Metaproxy - User's Guide and Reference</title>
4   <author>
5    <firstname>Mike</firstname><surname>Taylor</surname>
6   </author>
7   <author>
8    <firstname>Adam</firstname><surname>Dickmeiss</surname>
9   </author>
10   <copyright>
11    <year>2006</year>
12    <holder>Index Data ApS</holder>
13   </copyright>
14   <abstract>
15    <simpara>
16     Metaproxy is a universal router, proxy and encapsulated
17     metasearcher for information retrieval protocols.  It accepts,
18     processes, interprets and redirects requests from IR clients using
19     standard protocols such as
20     <ulink url="&url.z39.50;">ANSI/NISO Z39.50</ulink>
21     (and in the future <ulink url="&url.sru;">SRU</ulink>
22     and <ulink url="&url.srw;">SRW</ulink>), as
23     well as functioning as a limited
24     <ulink url="&url.http;">HTTP</ulink> server. 
25     Metaproxy is configured by an XML file which
26     specifies how the software should function in terms of routes that
27     the request packets can take through the proxy, each step on a
28     route being an instantiation of a filter.  Filters come in many
29     types, one for each operation: accepting Z39.50 packets, logging,
30     query transformation, multiplexing, etc.  Further filter-types can
31     be added as loadable modules to extend Metaproxy functionality,
32     using the filter API.
33    </simpara>
34    <simpara>
35     The terms under which Metaproxy will be distributed have yet to be
36     established, but it will not necessarily be open source; so users
37     should not at this stage redistribute the code without explicit
38     written permission from the copyright holders, Index Data ApS.
39    </simpara>
40    <simpara>
41     <inlinemediaobject>
42      <imageobject>
43       <imagedata fileref="common/id.png" format="PNG"/>
44      </imageobject>
45      <imageobject>
46       <imagedata fileref="common/id.eps" format="EPS"/>
47      </imageobject>
48     </inlinemediaobject>
49    </simpara>
50   </abstract>
51  </bookinfo>
52
53  <chapter id="introduction">
54   <title>Introduction</title>
55   
56   
57   <para>
58    <ulink url="&url.metaproxy;">Metaproxy</ulink>
59    is a standalone program that acts as a universal router, proxy and
60    encapsulated metasearcher for information retrieval protocols such
61    as <ulink url="&url.z39.50;">Z39.50</ulink>, and in the future
62    <ulink url="&url.sru;">SRU</ulink> and <ulink url="&url.srw;">SRW</ulink>.
63    To clients, it acts as a server of these protocols: it can be searched,
64    records can be retrieved from it, etc. 
65    To servers, it acts as a client: it searches in them,
66    retrieves records from them, etc.  it satisfies its clients'
67    requests by transforming them, multiplexing them, forwarding them
68    on to zero or more servers, merging the results, transforming
69    them, and delivering them back to the client.  In addition, it
70    acts as a simple <ulink url="&url.http;">HTTP</ulink> server; support
71    for further protocols can be added in a modular fashion, through the
72    creation of new filters.
73   </para>
74   <screen>
75    Anything goes in!
76    Anything goes out!
77    Fish, bananas, cold pyjamas,
78    Mutton, beef and trout!
79         - attributed to Cole Porter.
80   </screen>
81   <para>
82    Metaproxy is a more capable alternative to
83    <ulink url="&url.yazproxy;">YAZ Proxy</ulink>,
84    being more powerful, flexible, configurable and extensible.  Among
85    its many advantages over the older, more pedestrian work are
86    support for multiplexing (encapsulated metasearching), routing by
87    database name, authentication and authorisation and serving local
88    files via HTTP.  Equally significant, its modular architecture
89    facilitites the creation of pluggable modules implementing further
90    functionality.
91   </para>
92   <para>
93    This manual will briefly describe Metaproxy's licensing situation
94    before giving an overview of its architecture, then discussing the
95    key concept of a filter in some depth and giving an overview of
96    the various filter types, then discussing the configuration file
97    format.  After this come several optional chapters which may be
98    freely skipped: a detailed discussion of virtual databases and
99    multi-database searching, some notes on writing extensions
100    (additional filter types) and a high-level description of the
101    source code.  Finally comes the reference guide, which contains
102    instructions for invoking the <command>metaproxy</command>
103    program, and detailed information on each type of filter,
104    including examples.
105   </para>
106  </chapter>
107
108
109
110  <chapter id="licence">
111   <title>The Metaproxy Licence</title>
112   <para>
113    <emphasis role="strong">
114     No decision has yet been made on the terms under which
115     Metaproxy will be distributed.
116    </emphasis>
117    It is possible that, unlike
118    other Index Data products, metaproxy may not be released under a
119    free-software licence such as the GNU GPL.  Until a decision is
120    made and a public statement made, then, and unless it has been
121    delivered to you other specific terms, please treat Metaproxy as
122    though it were proprietary software.
123    The code should not be redistributed without explicit
124    written permission from the copyright holders, Index Data ApS.
125   </para>
126  </chapter>
127
128  <chapter id="installation">
129   <title>Installation</title>
130   <para>
131    Metaproxy depends on the following tools/libraries:
132    <variablelist>
133     <varlistentry><term><ulink url="&url.yazplusplus;">YAZ++</ulink></term>
134      <listitem>
135       <para>
136        This is a C++ library based on <ulink url="&url.yaz;">YAZ</ulink>.
137       </para>
138      </listitem>
139     </varlistentry>
140     <varlistentry><term><ulink url="&url.libxslt;">Libxslt</ulink></term>
141      <listitem>
142       <para>This is an XSLT processor - based on 
143        <ulink url="&url.libxml2;">Libxml2</ulink>. Both Libxml2 and
144        Libxslt must be installed with the development components
145        (header files, etc.) as well as the run-time libraries.
146       </para>
147      </listitem>
148     </varlistentry>
149     <varlistentry><term><ulink url="&url.boost;">Boost</ulink></term>
150      <listitem>
151       <para>
152        The popular C++ library. Initial versions of Metaproxy
153        was built with 1.33.0. Version 1.33.1 works too.
154       </para>
155      </listitem>
156     </varlistentry>
157    </variablelist>
158   </para>
159   <para>
160    In order to compile Metaproxy a modern C++ compiler is
161    required. Boost, in particular, requires the C++ compiler
162    to facilitate the newest features. Refer to Boost
163    <ulink url="&url.boost.compilers.status;">Compiler Status</ulink>
164    for more information.
165   </para>
166   <para>
167    We have succesfully used Metaproxy with Boost using the compilers
168    <ulink url="&url.gcc;">GCC</ulink> version 4.0 and
169    <ulink url="&url.vstudio;">Microsoft Visual Studio</ulink> 2003/2005.
170   </para>
171
172   <section id="installation.unix">
173    <title>Installation on Unix (from Source)</title>
174    <para>
175     Here is a quick step-by-step guide on how to compile all the
176     tools that Metaproxy uses. Only few systems have none of the required
177     tools binary packages. If, for example, Libxml2/libxslt are already
178     installed as development packages use those (and omit compilation).
179    </para>
180    
181    <para>
182     Libxml2/libxslt:
183    </para>
184    <screen>
185     gunzip -c libxml2-version.tar.gz|tar xf -
186     cd libxml2-version
187     ./configure
188     make
189     su
190     make install
191    </screen>
192    <screen>
193     gunzip -c libxslt-version.tar.gz|tar xf -
194     cd libxslt-version
195     ./configure
196     make
197     su
198     make install
199    </screen>
200    <para>
201     YAZ/YAZ++:
202    </para>
203    <screen>
204     gunzip -c yaz-version.tar.gz|tar xf -
205     cd yaz-version
206     ./configure
207     make
208     su
209     make install
210    </screen>
211    <screen>
212     gunzip -c yazpp-version.tar.gz|tar xf -
213     cd yazpp-version
214     ./configure
215     make
216     su
217     make install
218    </screen>
219    <para>
220     Boost:
221    </para>
222    <screen>
223     gunzip -c boost-version.tar.gz|tar xf -
224     cd boost-version
225     ./configure
226     make
227     su
228     make install
229    </screen>
230    <para>
231     Metaproxy:
232    </para>
233    <screen>
234     gunzip -c metaproxy-version.tar.gz|tar xf -
235     cd metaproxy-version
236     ./configure
237     make
238     su
239     make install
240    </screen>
241   </section>
242
243   <section id="installation.debian">
244    <title>Installation on Debian</title>
245    <para>
246     ### To be written
247    </para>
248    </section>
249
250   <section id="installation.windows">
251    <title>Installation on Windows</title>
252    <para>
253     Compilation of Metaproxy can be done using
254     Microsoft <ulink url="&url.vstudio;">Visual Studio</ulink>.
255     We know Version 2003 works. We expect Version 2005 to
256     work as well.
257    </para>
258    <section id="installation.windows.boost">
259     <title>Boost</title>
260     <para>
261      Get Boost from its <ulink url="&url.boost;">home page</ulink>.
262      You also need Boost Jam (an alternative to make).
263      That's also available from this
264      home page. The files download are called something like:
265      <literal>boost_1_33-1.exe</literal>
266      and
267      <literal>boost-jam-3.1.12-1-ntx86.zip</literal>.
268      Unpack Boost Jam first. Put <literal>bjam.exe</literal>
269      in your system path. Make a command prompt and ensure
270      it can be found automatically. If not check the PATH.
271      The Boost .exe is a self-extracting exe with
272      complete source for Boost. Compile that source with
273      Boost Jam (An alternative to Make).
274      The compilation takes a while.
275      By default, the Boost build process puts the resulting
276      libraries + header files in
277      <literal>\boost\lib</literal>, <literal>\boost\include</literal>.
278     </para>
279     <para>
280      For more informatation about installing Boost refer to the
281      <ulink url="&url.boost.getting.started;">getting started</ulink>
282      pages.
283     </para>
284    </section>
285
286    <section id="installation.windows.libxslt">
287     <title>Libxslt</title>
288     <para>
289      <ulink url="&url.libxslt;">Libxslt</ulink> can be downloaded
290      for Windows from
291      <ulink url="&url.libxml2.download.win32;">here</ulink>.
292     </para>
293     <para>
294      Libxslt has other dependencies, but thes can all be downloaded
295      from the same site. Get the following:
296      iconv, zlib, libxml2, libxslt.
297     </para>
298    </section>
299
300    <section id="installation.windows.yaz">
301     <title>YAZ</title>
302     <para>
303      <ulink url="&url.yaz;">YAZ</ulink> can be downloaded
304      for Windows from
305      <ulink url="&url.yaz.download.win32;">here</ulink>.
306     </para>
307    </section>
308
309    <section id="installation.windows.yazplusplus">
310     <title>YAZ++</title>
311     <para>
312      Get <ulink url="&url.yazplusplus;">YAZ++</ulink> as well.
313      Version 1.0 or later is required. For now get it from
314      Index Data's
315      <ulink url="&url.snapshot.download;">Snapshot area</ulink>.
316     </para>
317     <para>
318      YAZ++ includes NMAKE makefiles, similar to those found in the
319      YAZ package.
320     </para>
321    </section>
322
323    <section id="installation.windows.metaproxy">
324     <title>Metaproxy</title>
325     <para>
326      Metaproxy is shipped with NMAKE makfiles as well - similar
327      to those found in the YAZ++/YAZ packages. Adjust this Makefile
328      to point to the proper locations of Boost, Libxslt, Libxml2,
329      zlib, iconv, yaz and yazpp.
330     </para>
331     <para>
332      After succesful compilation you'll find
333      <literal>metaproxy.exe</literal> in the
334      <literal>bin</literal> directory.
335     </para>
336    </section>
337
338   </section>
339  </chapter>
340  
341  <chapter id="architecture">
342   <title>The Metaproxy Architecture</title>
343   <para>
344    The Metaproxy architecture is based on three concepts:
345    the <emphasis>package</emphasis>,
346    the <emphasis>route</emphasis>
347    and the <emphasis>filter</emphasis>.
348   </para>
349   <variablelist>
350    <varlistentry>
351     <term>Packages</term>
352     <listitem>
353      <para>
354       A package is request or response, encoded in some protocol,
355       issued by a client, making its way through Metaproxy, send to or
356       received from a server, or sent back to the client.
357      </para>
358      <para>
359       The core of a package is the protocol unit - for example, a
360       Z39.50 Init Request or Search Response, or an SRU searchRetrieve
361       URL or Explain Response.  In addition to this core, a package
362       also carries some extra information added and used by Metaproxy
363       itself.
364      </para>
365      <para>
366       In general, packages are doctored as they pass through
367       Metaproxy.  For example, when the proxy performs authentication
368       and authorisation on a Z39.50 Init request, it removes the
369       authentication credentials from the package so that they are not
370       passed onto the back-end server; and when search-response
371       packages are obtained from multiple servers, they are merged
372       into a single unified package that makes its way back to the
373       client.
374      </para>
375     </listitem>
376    </varlistentry>
377    <varlistentry>
378     <term>Routes</term>
379     <listitem>
380      <para>
381       Packages make their way through routes, which can be thought of
382       as programs that operate on the package data-type.  Each
383       incoming package initially makes its way through a default
384       route, but may be switched to a different route based on various
385       considerations.  Routes are made up of sequences of filters (see
386       below).
387      </para>
388     </listitem>
389    </varlistentry>
390    <varlistentry>
391     <term>Filters</term>
392     <listitem>
393      <para>
394       Filters provide the individual instructions within a route, and
395       effect the necessary transformations on packages.  A particular
396       configuration of Metaproxy is essentially a set of filters,
397       described by configuration details and arranged in order in one
398       or more routes.  There are many kinds of filter - about a dozen
399       at the time of writing with more appearing all the time - each
400       performing a specific function and configured by different
401       information.
402      </para>
403      <para>
404       The word ``filter'' is sometimes used rather loosely, in two
405       different ways: it may be used to mean a particular
406       <emphasis>type</emphasis> of filter, as when we speak of ``the
407       auth_simplefilter'' or ``the multi filter''; or it may be used
408       to be a specific <emphasis>instance</emphasis> of a filter
409       within a Metaproxy configuration.  For example, a single
410       configuration will often contain multiple instances of the
411       <literal>z3950_client</literal> filter.  In
412       operational terms, of these is a separate filter.  In practice,
413       context always make it clear which sense of the word ``filter''
414       is being used.
415      </para>
416      <para>
417       Extensibility of Metaproxy is primarily through the creation of
418       plugins that provide new filters.  The filter API is small and
419       conceptually simple, but there are many details to master.  See
420       the section below on
421       <link linkend="extensions">extensions</link>.
422      </para>
423     </listitem>
424    </varlistentry>
425   </variablelist>
426   <para>
427    Since packages are created and handled by the system itself, and
428    routes are conceptually simple, most of the remainder of this
429    document concentrates on filters.  After a brief overview of the
430    filter types follows, along with some thoughts on possible future
431    directions.
432   </para>
433  </chapter>
434
435
436
437  <chapter id="filters">
438   <title>Filters</title>
439   
440   
441   <section>
442    <title>Introductory notes</title>
443    <para>
444     It's useful to think of Metaproxy as an interpreter providing a small
445     number of primitives and operations, but operating on a very
446     complex data type, namely the ``package''.
447    </para>
448    <para>
449     A package represents a Z39.50 or SRU/W request (whether for Init,
450     Search, Scan, etc.)  together with information about where it came
451     from.  Packages are created by front-end filters such as
452     <literal>frontend_net</literal> (see below), which reads them from
453     the network; other front-end filters are possible.  They then pass
454     along a route consisting of a sequence of filters, each of which
455     transforms the package and may also have side-effects such as
456     generating logging.  Eventually, the route will yield a response,
457     which is sent back to the origin.
458    </para>
459    <para>
460     There are many kinds of filter: some that are defined statically
461     as part of Metaproxy, and others may be provided by third parties
462     and dynamically loaded.  They all conform to the same simple API
463     of essentially two methods: <function>configure()</function> is
464     called at startup time, and is passed a DOM tree representing that
465     part of the configuration file that pertains to this filter
466     instance: it is expected to walk that tree extracting relevant
467     information; and <function>process()</function> is called every
468     time the filter has to processes a package.
469    </para>
470    <para>
471     While all filters provide the same API, there are different modes
472     of functionality.  Some filters are sources: they create
473     packages
474     (<literal>frontend_net</literal>);
475     others are sinks: they consume packages and return a result
476     (<literal>z3950_client</literal>,
477     <literal>backend_test</literal>,
478     <literal>http_file</literal>);
479     the others are true filters, that read, process and pass on the
480     packages they are fed
481     (<literal>auth_simple</literal>,
482     <literal>log</literal>,
483     <literal>multi</literal>,
484     <literal>query_rewrite</literal>,
485     <literal>session_shared</literal>,
486     <literal>template</literal>,
487     <literal>virt_db</literal>).
488    </para>
489  </section>
490   
491   
492   <section id="overview.filter.types">
493    <title>Overview of filter types</title>
494    <para>
495     We now briefly consider each of the types of filter supported by
496     the core Metaproxy binary.  This overview is intended to give a
497     flavour of the available functionality; more detailed information
498     about each type of filter is included below in
499     <link linkend="filterref"
500           >the reference guide to Metaproxy filters</link>.
501    </para>
502    <para>
503     The filters are here named by the string that is used as the
504     <literal>type</literal> attribute of a
505     <literal>&lt;filter&gt;</literal> element in the configuration
506     file to request them, with the name of the class that implements
507     them in parentheses.  (The classname is not needed for normal
508     configuration and use of Metaproxy; it is useful only to
509     developers.)
510    </para>
511    <para>
512     The filters are here listed in alphabetical order:
513    </para>
514    
515    <section>
516     <title><literal>auth_simple</literal>
517      (mp::filter::AuthSimple)</title>
518     <para>
519      Simple authentication and authorisation.  The configuration
520      specifies the name of a file that is the user register, which
521      lists <varname>username</varname>:<varname>password</varname>
522      pairs, one per line, colon separated. When a session begins, it
523      is rejected unless username and passsword are supplied, and match
524      a pair in the register.  The configuration file may also specific
525      the name of another file that is the target register: this lists
526      lists <varname>username</varname>:<varname>dbname</varname>,<varname>dbname</varname>...
527      sets, one per line, with multiple database names separated by
528      commas.  When a search is processed, it is rejected unless the
529      database to be searched is one of those listed as available to
530      the user.
531     </para>
532    </section>
533    
534    <section>
535     <title><literal>backend_test</literal>
536     (mp::filter::Backend_test)</title>
537     <para>
538      A sink that provides dummy responses in the manner of the
539      <literal>yaz-ztest</literal> Z39.50 server.  This is useful only
540      for testing.  Seriously, you don't need this.  Pretend you didn't
541      even read this section.
542     </para>
543    </section>
544    
545    <section>
546     <title><literal>frontend_net</literal>
547      (mp::filter::FrontendNet)</title>
548     <para>
549      A source that accepts Z39.50 connections from a port
550      specified in the configuration, reads protocol units, and
551      feeds them into the next filter in the route.  When the result is
552      revceived, it is returned to the original origin.
553     </para>
554    </section>
555
556    <section>
557     <title><literal>http_file</literal>
558      (mp::filter::HttpFile)</title>
559     <para>
560      A sink that returns the contents of files from the local
561      filesystem in response to HTTP requests.  (Yes, Virginia, this
562      does mean that Metaproxy is also a Web-server in its spare time.  So
563      far it does not contain either an email-reader or a Lisp
564      interpreter, but that day is surely coming.)
565     </para>
566    </section>
567    
568    <section>
569     <title><literal>log</literal>
570      (mp::filter::Log)</title>
571     <para>
572      Writes logging information to standard output, and passes on
573      the package unchanged.
574    </para>
575    </section>
576    
577    <section>
578    <title><literal>multi</literal>
579      (mp::filter::Multi)</title>
580     <para>
581      Performs multi-database searching.
582      See
583      <link linkend="multidb">the extended discussion</link>
584      of virtual databases and multi-database searching below.
585     </para>
586    </section>
587    
588    <section>
589    <title><literal>query_rewrite</literal>
590      (mp::filter::QueryRewrite)</title>
591     <para>
592      Rewrites Z39.50 Type-1 and Type-101 (``RPN'') queries by a
593      three-step process: the query is transliterated from Z39.50
594      packet structures into an XML representation; that XML
595      representation is transformed by an XSLT stylesheet; and the
596      resulting XML is transliterated back into the Z39.50 packet
597      structure.
598     </para>
599    </section>
600    
601    <section>
602     <title><literal>session_shared</literal>
603      (mp::filter::SessionShared)</title>
604     <para>
605      When this is finished, it will implement global sharing of
606      result sets (i.e. between threads and therefore between
607      clients), yielding performance improvements especially when
608      incoming requests are from a stateless environment such as a
609      web-server, in which the client process representing a session
610      might be any one of many.  However:
611     </para>
612     <warning>
613      <para>
614       This filter is not yet completed.
615      </para>
616     </warning>
617    </section>
618    
619    <section>
620     <title><literal>template</literal>
621      (mp::filter::Template)</title>
622     <para>
623      Does nothing at all, merely passing the packet on.  (Maybe it
624      should be called <literal>nop</literal> or
625      <literal>passthrough</literal>?)  This exists not to be used, but
626      to be copied - to become the skeleton of new filters as they are
627      written.  As with <literal>backend_test</literal>, this is not
628      intended for civilians.
629     </para>
630    </section>
631    
632    <section>
633     <title><literal>virt_db</literal>
634      (mp::filter::Virt_db)</title>
635     <para>
636      Performs virtual database selection: based on the name of the
637      database in the search request, a server is selected, and its
638      address added to the request in a <literal>VAL_PROXY</literal>
639      otherInfo packet.  It will subsequently be used by a
640      <literal>z3950_client</literal> filter.
641      See
642      <link linkend="multidb">the extended discussion</link>
643      of virtual databases and multi-database searching below.
644     </para>
645    </section>
646    
647    <section>
648     <title><literal>z3950_client</literal>
649      (mp::filter::Z3950Client)</title>
650     <para>
651      Performs Z39.50 searching and retrieval by proxying the
652      packages that are passed to it.  Init requests are sent to the
653      address specified in the <literal>VAL_PROXY</literal> otherInfo
654      attached to the request: this may have been specified by client,
655      or generated by a <literal>virt_db</literal> filter earlier in
656      the route.  Subsequent requests are sent to the same address,
657      which is remembered at Init time in a Session object.
658     </para>
659   </section>
660   </section>
661   
662   
663   <section id="future.directions">
664    <title>Future directions</title>
665   <para>
666     Some other filters that do not yet exist, but which would be
667     useful, are briefly described.  These may be added in future
668     releases (or may be created by third parties, as loadable
669     modules).
670    </para>
671
672    <variablelist>
673     <varlistentry>
674      <term><literal>frontend_cli</literal> (source)</term>
675     <listitem>
676       <para>
677        Command-line interface for generating requests.
678       </para>
679      </listitem>
680     </varlistentry>
681     <varlistentry>
682      <term><literal>frontend_sru</literal> (source)</term>
683      <listitem>
684       <para>
685        Receive SRU (and perhaps SRW) requests.
686      </para>
687      </listitem>
688     </varlistentry>
689     <varlistentry>
690      <term><literal>sru2z3950</literal> (filter)</term>
691      <listitem>
692       <para>
693        Translate SRU requests into Z39.50 requests.
694      </para>
695      </listitem>
696     </varlistentry>
697     <varlistentry>
698      <term><literal>sru_client</literal> (sink)</term>
699      <listitem>
700       <para>
701        SRU searching and retrieval.
702       </para>
703      </listitem>
704     </varlistentry>
705     <varlistentry>
706      <term><literal>srw_client</literal> (sink)</term>
707      <listitem>
708       <para>
709        SRW searching and retrieval.
710       </para>
711      </listitem>
712     </varlistentry>
713     <varlistentry>
714      <term><literal>opensearch_client</literal> (sink)</term>
715      <listitem>
716       <para>
717        A9 OpenSearch searching and retrieval.
718       </para>
719      </listitem>
720     </varlistentry>
721    </variablelist>
722   </section>
723  </chapter>
724  
725  
726  
727  <chapter id="configuration">
728   <title>Configuration: the Metaproxy configuration file format</title>
729   
730   
731   <section>
732    <title>Introductory notes</title>
733    <para>
734     If Metaproxy is an interpreter providing operations on packages, then
735     its configuration file can be thought of as a program for that
736     interpreter.  Configuration is by means of a single file, the name
737     of which is supplied as the sole command-line argument to the
738     <command>metaproxy</command> program.  (See
739     <link linkend="progref">the reference guide</link>
740     below for more information on invoking Metaproxy.)
741    </para>
742    <para>
743     The configuration files are written in XML.  (But that's just an
744     implementation detail - they could just as well have been written
745     in YAML or Lisp-like S-expressions, or in a custom syntax.)
746    </para>
747    <para>
748     Since XML has been chosen, an XML schema,
749     <filename>config.xsd</filename>, is provided for validating
750     configuration files.  This file is supplied in the
751     <filename>etc</filename> directory of the Metaproxy distribution.  It
752     can be used by (among other tools) the <command>xmllint</command>
753     program supplied as part of the <literal>libxml2</literal>
754     distribution:
755    </para>
756    <screen>
757     xmllint --noout --schema etc/config.xsd my-config-file.xml
758    </screen>
759    <para>
760     (A recent version of <literal>libxml2</literal> is required, as
761     support for XML Schemas is a relatively recent addition.)
762    </para>
763   </section>
764   
765   <section id="overview.xml.structure">
766    <title>Overview of XML structure</title>
767    <para>
768     All elements and attributes are in the namespace
769     <ulink url="http://indexdata.dk/yp2/config/1"/>.
770      This is most easily achieved by setting the default namespace on
771      the top-level element, as here:
772    </para>
773    <screen>
774     &lt;yp2 xmlns="http://indexdata.dk/yp2/config/1"&gt;
775    </screen>
776    <para>
777     The top-level element is &lt;yp2&gt;.  This contains a
778     &lt;start&gt; element, a &lt;filters&gt; element and a
779     &lt;routes&gt; element, in that order.  &lt;filters&gt; is
780     optional; the other two are mandatory.  All three are
781     non-repeatable.
782    </para>
783   <para>
784     The &lt;start&gt; element is empty, but carries a
785     <literal>route</literal> attribute, whose value is the name of
786     route at which to start running - analogous to the name of the
787     start production in a formal grammar.
788    </para>
789   <para>
790     If present, &lt;filters&gt; contains zero or more &lt;filter&gt;
791     elements.  Each filter carries a <literal>type</literal> attribute
792     which specifies what kind of filter is being defined
793     (<literal>frontend_net</literal>, <literal>log</literal>, etc.)
794     and contain various elements that provide suitable configuration
795     for a filter of its type.  The filter-specific elements are
796     described in
797     <link linkend="filterref">the reference guide below</link>.
798     Filters defined in this part of the file must carry an
799     <literal>id</literal> attribute so that they can be referenced
800     from elsewhere.
801    </para>
802    <para>
803     &lt;routes&gt; contains one or more &lt;route&gt; elements, each
804     of which must carry an <literal>id</literal> element.  One of the
805     routes must have the ID value that was specified as the start
806     route in the &lt;start&gt; element's <literal>route</literal>
807     attribute.  Each route contains zero or more &lt;filter&gt;
808     elements.  These are of two types.  They may be empty, but carry a
809     <literal>refid</literal> attribute whose value is the same as the
810     <literal>id</literal> of a filter previously defined in the
811     &lt;filters&gt; section.  Alternatively, a route within a filter
812     may omit the <literal>refid</literal> attribute, but contain
813     configuration elements similar to those used for filters defined
814     in the &lt;filters&gt; section.  (In other words, each filter in a
815     route may be included either by reference or by physical
816     inclusion.)
817    </para>
818   </section>
819
820
821   <section id="example.configuration">
822    <title>An example configuration</title>
823    <para>
824     The following is a small, but complete, Metaproxy configuration
825     file (included in the distribution as
826     <literal>metaproxy/etc/config0.xml</literal>).
827     This file defines a very simple configuration that simply proxies
828     to whatever back-end server the client requests, but logs each
829     request and response.  This can be useful for debugging complex
830     client-server dialogues.
831    </para>
832    <screen><![CDATA[<?xml version="1.0"?>
833 <yp2 xmlns="http://indexdata.dk/yp2/config/1">
834   <start route="start"/>
835   <filters>
836     <filter id="frontend" type="frontend_net">
837       <port>@:9000</port>
838     </filter>
839     <filter id="backend" type="z3950_client">
840     </filter>
841   </filters>
842   <routes>  
843     <route id="start">
844       <filter refid="frontend"/>
845       <filter type="log"/>
846       <filter refid="backend"/>
847     </route>
848   </routes>
849 </yp2>
850 ]]></screen>
851    <para>
852     It works by defining a single route, called
853     <literal>start</literal>, which consists of a sequence of three
854     filters.  The first and last of these are included by reference:
855     their <literal>&lt;filter&gt;</literal> elements have
856     <literal>refid</literal> attributes that refer to filters defined
857     within the prior <literal>&lt;filters&gt;</literal> section.  The
858     middle filter is included inline in the route.
859    </para>
860    <para>
861     The three filters in the route are as follows: first, a
862     <literal>frontend_net</literal> filter accepts Z39.50 requests
863     from any host on port 9000; then these requests are passed through
864     a <literal>log</literal> filter that emits a message for each
865     request; they are then fed into a <literal>z3950_client</literal>
866     filter, which forwards the requests to the client-specified
867     back-end Z39.509 server.  When the response arrives, it is handed
868     back to the <literal>log</literal> filter, which emits another
869     message; and then to the front-end filter, which returns the
870     response to the client.
871    </para>
872   </section>
873  </chapter>
874
875
876
877  <chapter id="multidb">
878   <title>Virtual databases and multi-database searching</title>
879
880
881   <section>
882    <title>Introductory notes</title>
883    <para>
884     Two of Metaproxy's filters are concerned with multiple-database
885     operations.  Of these, <literal>virt_db</literal> can work alone
886     to control the routing of searches to one of a number of servers,
887     while <literal>multi</literal> can work together with
888     <literal>virt_db</literal> to perform multi-database searching, merging
889     the results into a unified result-set - ``metasearch in a box''.
890    </para>
891    <para>
892     The interaction between
893     these two filters is necessarily complex: it reflects the real,
894     irreducible complexity of multi-database searching in a protocol such
895     as Z39.50 that separates initialisation from searching, and in
896     which the database to be searched is not known at initialisation
897     time.
898    </para>
899    <para>
900     It's possible to use these filters without understanding the
901     details of their functioning and the interaction between them; the
902     next two sections of this chapter are ``HOWTO'' guides for doing
903     just that.  However, debugging complex configurations will require
904     a deeper understanding, which the last two sections of this
905     chapters attempt to provide.
906    </para>
907   </section>
908
909
910   <section id="multidb.virt_db">
911    <title>Virtual databases with the <literal>virt_db</literal> filter</title>
912    <para>
913     Working alone, the purpose of the
914     <literal>virt_db</literal>
915     filter is to route search requests to one of a selection of
916     back-end databases.  In this way, a single Z39.50 endpoint
917     (running Metaproxy) can provide access to several different
918     underlying services, including those that would otherwise be
919     inaccessible due to firewalls.  In many useful configurations, the
920     back-end databases are local to the Metaproxy installation, but
921     the software does not enforce this, and any valid Z39.50 servers
922     may be used as back-ends.
923    </para>
924    <para>
925     For example, a <literal>virt_db</literal>
926     filter could be set up so that searches in the virtual database
927     ``lc'' are forwarded to the Library of Congress bibliographic
928     catalogue server, and searches in the virtual database ``marc''
929     are forwarded to the toy database of MARC records that Index Data
930     hosts for testing purposes.  A <literal>virt_db</literal>
931     configuration to make this switch would look like this:
932    </para>
933    <screen><![CDATA[<filter type="virt_db">
934   <virtual>
935     <database>lc</database>
936     <target>z3950.loc.gov:7090/voyager</target>
937   </virtual>
938   <virtual>
939     <database>marc</database>
940     <target>indexdata.dk/marc</target>
941   </virtual>
942 </filter>]]></screen>
943    <para>
944     As well as being useful in it own right, this filter also provides
945     the foundation for multi-database searching.
946    </para>
947   </section>
948
949
950   <section id="multidb.multi">
951    <title>Multi-database search with the <literal>multi</literal> filter</title>
952    <para>
953     To arrange for Metaproxy to broadcast searches to multiple back-end
954     servers, the configuration needs to include two components: a
955     <literal>virt_db</literal>
956     filter that specifies multiple
957     <literal>&lt;target&gt;</literal>
958     elements, and a subsequent
959     <literal>multi</literal>
960     filter.  Here, for example, is a complete configuration that
961     broadcasts searches to both the Library of Congress catalogue and
962     Index Data's tiny testing database of MARC records:
963    </para>
964    <screen><![CDATA[<?xml version="1.0"?>
965 <yp2 xmlns="http://indexdata.dk/yp2/config/1">
966   <start route="start"/>
967   <routes>
968     <route id="start">
969       <filter type="frontend_net">
970         <threads>10</threads>
971         <port>@:9000</port>
972       </filter>
973       <filter type="virt_db">
974         <virtual>
975           <database>lc</database>
976           <target>z3950.loc.gov:7090/voyager</target>
977         </virtual>
978         <virtual>
979           <database>marc</database>
980           <target>indexdata.dk/marc</target>
981         </virtual>
982         <virtual>
983           <database>all</database>
984           <target>z3950.loc.gov:7090/voyager</target>
985           <target>indexdata.dk/marc</target>
986         </virtual>
987       </filter>
988       <filter type="multi"/>
989       <filter type="z3950_client">
990         <timeout>30</timeout>
991       </filter>
992     </route>
993   </routes>
994 </yp2>]]></screen>
995    <para>
996     (Using a
997     <literal>virt_db</literal>
998     filter that specifies multiple
999     <literal>&lt;target&gt;</literal>
1000     elements but without a subsequent
1001     <literal>multi</literal>
1002     filter yields surprising and undesirable results, as will be
1003     described below.  Don't do that.)
1004    </para>
1005    <para>
1006     Metaproxy can be invoked with this configuration as follows:
1007    </para>
1008    <screen>../src/metaproxy --config config-simple-multi.xml</screen>
1009    <para>
1010     And thereafter, Z39.50 clients can connect to the running server
1011     (on port 9000, as specified in the configuration) and search in
1012     any of the databases
1013     <literal>lc</literal> (the Library of Congress catalogue),
1014     <literal>marc</literal> (Index Data's test database of MARC records)
1015     or
1016     <literal>all</literal> (both of these).  As an example, a session
1017     using the YAZ command-line client <literal>yaz-client</literal> is
1018     here included (edited for brevity and clarity):
1019    </para>
1020    <screen><![CDATA[$ yaz-client @:9000
1021 Connecting...OK.
1022 Z> base lc
1023 Z> find computer
1024 Search was a success.
1025 Number of hits: 10000, setno 1
1026 Elapsed: 5.521070
1027 Z> base marc
1028 Z> find computer
1029 Search was a success.
1030 Number of hits: 10, setno 3
1031 Elapsed: 0.060187
1032 Z> base all
1033 Z> find computer
1034 Search was a success.
1035 Number of hits: 10010, setno 4
1036 Elapsed: 2.237648
1037 Z> show 1
1038 [marc]Record type: USmarc
1039 001    11224466
1040 003 DLC
1041 005 00000000000000.0
1042 008 910710c19910701nju           00010 eng
1043 010    $a 11224466
1044 040    $a DLC $c DLC
1045 050 00 $a 123-xyz
1046 100 10 $a Jack Collins
1047 245 10 $a How to program a computer
1048 260 1  $a Penguin
1049 263    $a 8710
1050 300    $a p. cm.
1051 Elapsed: 0.119612
1052 Z> show 2
1053 [VOYAGER]Record type: USmarc
1054 001 13339105
1055 005 20041229102447.0
1056 008 030910s2004    caua          000 0 eng
1057 035    $a (DLC)  2003112666
1058 906    $a 7 $b cbc $c orignew $d 4 $e epcn $f 20 $g y-gencatlg
1059 925 0  $a acquire $b 1 shelf copy $x policy default
1060 955    $a pc10 2003-09-10 $a pv12 2004-06-23 to SSCD; $h sj05 2004-11-30 $e sj05 2004-11-30 to Shelf.
1061 010    $a   2003112666
1062 020    $a 0761542892
1063 040    $a DLC $c DLC $d DLC
1064 050 00 $a MLCM 2004/03312 (G)
1065 245 10 $a 007, everything or nothing : $b Prima's official strategy guide / $c created by Kaizen Media Group.
1066 246 3  $a Double-O-seven, everything or nothing
1067 246 30 $a Prima's official strategy guide
1068 260    $a Roseville, CA : $b Prima Games, $c c2004.
1069 300    $a 161 p. : $b col. ill. ; $c 28 cm.
1070 500    $a "Platforms: Nintendo GameCube, Macintosh, PC, PlayStation 2 computer entertainment system, Xbox"--P. [4] of cover.
1071 650  0 $a Video games.
1072 710 2  $a Kaizen Media Group.
1073 856 42 $3 Publisher description $u http://www.loc.gov/catdir/description/random052/2003112666.html
1074 Elapsed: 0.150623
1075 Z>
1076 ]]></screen>
1077    <para>
1078     As can be seen, the first record in the result set is from the
1079     Index Data test database, and the second from the Library of
1080     Congress database.  The result-set continues alternating records
1081     round-robin style until the point where one of the databases'
1082     records are exhausted.
1083    </para>
1084    <para>
1085     This example uses only two back-end databases; more may be used.
1086     There is no limitation imposed on the number of databases that may
1087     be metasearched in this way: issues of resource usage and
1088     administrative complexity dictate the practical limits.
1089    </para>
1090   </section>
1091
1092
1093   <section id="multidb.what">
1094    <title>What's going on?</title>
1095    <warning>
1096     <title>Lark's vomit</title>
1097     <para>
1098      This section goes into a level of technical detail that is
1099      probably not necessary in order to configure and use Metaproxy.
1100      It is provided only for those who like to know how things work.
1101      You should feel free to skip on to the next section if this one
1102      doesn't seem like fun.
1103     </para>
1104    </warning>
1105    <para>
1106     Hold on tight - this may get a little hairy.
1107    </para>
1108    <para>
1109     In the general course of things, a Z39.50 Init request may carry
1110     with it an otherInfo packet of type <literal>VAL_PROXY</literal>,
1111     whose value indicates the address of a Z39.50 server to which the
1112     ultimate connection is to be made.  (This otherInfo packet is
1113     supported by YAZ-based Z39.50 clients and servers, but has not yet
1114     been ratified by the Maintenance Agency and so is not widely used
1115     in non-Index Data software.  We're working on it.)
1116     The <literal>VAL_PROXY</literal> packet functions
1117     analogously to the absoluteURI-style Request-URI used with the GET
1118     method when a web browser asks a proxy to forward its request: see
1119     the
1120     <ulink url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2"
1121            >Request-URI</ulink>
1122     section of
1123     <ulink url="http://www.w3.org/Protocols/rfc2616/rfc2616.html"
1124            >the HTTP 1.1 specification</ulink>.
1125    </para>
1126    <para>
1127     The role of the <literal>virt_db</literal> filter is to rewrite
1128     this otherInfo packet dependent on the virtual database that the
1129     client wants to search.  
1130    </para>
1131    <para>
1132     When Metaproxy receives a Z39.50 Init request from a client, it
1133     doesn't immediately forward that request to the back-end server.
1134     Why not?  Because it doesn't know <emphasis>which</emphasis>
1135     back-end server to forward it to until the client sends a search
1136     request that specifies the database that it wants to search in.
1137     Instead, it just treasures the Init request up in its heart; and,
1138     later, the first time the client does a search on one of the
1139     specified virtual databases, a connection is forged to the
1140     appropriate server and the Init request is forwarded to it.  If,
1141     later in the session, the same client searches in a different
1142     virtual database, then a connection is forged to the server that
1143     hosts it, and the same cached Init request is forwarded there,
1144     too.
1145    </para>
1146    <para>
1147     All of this clever Init-delaying is done by the
1148     <literal>frontend_net</literal> filter.  The
1149     <literal>virt_db</literal> filter knows nothing about it; in
1150     fact, because the Init request that is received from the client
1151     doesn't get forwarded until a Search request is received, the
1152     <literal>virt_db</literal> filter (and the
1153     <literal>z3950_client</literal> filter behind it) doesn't even get
1154     invoked at Init time.  The <emphasis>only</emphasis> thing that a
1155     <literal>virt_db</literal> filter ever does is rewrite the
1156     <literal>VAL_PROXY</literal> otherInfo in the requests that pass
1157     through it.
1158    </para>
1159    <para>
1160     ### Describe the use of multiple <literal>VAL_PROXY</literal>
1161     otherInfos, added by <literal>virt_db</literal> and used by
1162     <literal>multi</literal>.
1163    </para>
1164   </section>
1165
1166
1167   <section id="multidb.picture">
1168    <title>A picture is worth a thousand words (but only five hundred on 64-bit architectures)</title>
1169    <simpara>
1170     <inlinemediaobject>
1171      <imageobject>
1172       <imagedata fileref="multi.pdf" format="PDF"/>
1173      </imageobject>
1174      <imageobject>
1175       <imagedata fileref="multi.png" format="PNG"/>
1176      </imageobject>
1177      <textobject>
1178       <!-- Fall back if none of the images can be used -->
1179       <phrase>
1180        [Here there should be a diagram showing the progress of
1181        packages through the filters during a simple virtual-database
1182        search and a multi-database search, but is seems that your
1183        toolchain has not been able to include the diagram in this
1184        document.  This is because of LaTeX suckage.  Time to move to
1185        OpenOffice.  Yes, really.]
1186       </phrase>
1187      </textobject>
1188 <!-- ### This used to work with an older version of DocBook
1189      <caption>
1190       <para>Caption: progress of packages through filters.</para>
1191      </caption>
1192 -->
1193     </inlinemediaobject>
1194    </simpara>
1195   </section>
1196  </chapter>
1197
1198
1199
1200  <chapter id="extensions">
1201   <title>Writing extensions for Metaproxy</title>
1202   <para>### To be written</para>
1203  </chapter>
1204
1205
1206
1207
1208  <chapter id="classes">
1209   <title>Classes in the Metaproxy source code</title>
1210
1211
1212   <section>
1213    <title>Introductory notes</title>
1214    <para>
1215     <emphasis>Stop!  Do not read this!</emphasis>
1216     You won't enjoy it at all.  You should just skip ahead to
1217     <link linkend="refguide">the reference guide</link>,
1218     which tells
1219     <!-- The remainder of this paragraph is lifted verbatim from
1220     Douglas Adams' _Hitch Hiker's Guide to the Galaxy_, chapter 8 -->
1221     you things you really need to know, like the fact that the
1222     fabulously beautiful planet Bethselamin is now so worried about
1223     the cumulative erosion by ten billion visiting tourists a year
1224     that any net imbalance between the amount you eat and the amount
1225     you excrete whilst on the planet is surgically removed from your
1226     bodyweight when you leave: so every time you go to the lavatory it
1227     is vitally important to get a receipt.
1228    </para>
1229    <para>
1230     This chapter contains documentation of the Metaproxy source code, and is
1231     of interest only to maintainers and developers.  If you need to
1232     change Metaproxy's behaviour or write a new filter, then you will most
1233     likely find this chapter helpful.  Otherwise it's a waste of your
1234     good time.  Seriously: go and watch a film or something.
1235     <citetitle>This is Spinal Tap</citetitle> is particularly good.
1236    </para>
1237    <para>
1238     Still here?  OK, let's continue.
1239    </para>
1240    <para>
1241     In general, classes seem to be named big-endianly, so that
1242     <literal>FactoryFilter</literal> is not a filter that filters
1243     factories, but a factory that produces filters; and
1244     <literal>FactoryStatic</literal> is a factory for the statically
1245     registered filters (as opposed to those that are dynamically
1246     loaded).
1247    </para>
1248   </section>
1249
1250   <section id="individual.classes">
1251    <title>Individual classes</title>
1252    <para>
1253     The classes making up the Metaproxy application are here listed by
1254     class-name, with the names of the source files that define them in
1255     parentheses.
1256    </para>
1257
1258    <section>
1259     <title><literal>mp::FactoryFilter</literal>
1260      (<filename>factory_filter.cpp</filename>)</title>
1261     <para>
1262      A factory class that exists primarily to provide the
1263      <literal>create()</literal> method, which takes the name of a
1264      filter class as its argument and returns a new filter of that
1265      type.  To enable this, the factory must first be populated by
1266      calling <literal>add_creator()</literal> for static filters (this
1267      is done by the <literal>FactoryStatic</literal> class, see below)
1268      and <literal>add_creator_dyn()</literal> for filters loaded
1269      dynamically.
1270     </para>
1271    </section>
1272
1273    <section>
1274     <title><literal>mp::FactoryStatic</literal>
1275      (<filename>factory_static.cpp</filename>)</title>
1276     <para>
1277      A subclass of <literal>FactoryFilter</literal> which is
1278      responsible for registering all the statically defined filter
1279      types.  It does this by knowing about all those filters'
1280      structures, which are listed in its constructor.  Merely
1281      instantiating this class registers all the static classes.  It is
1282      for the benefit of this class that <literal>struct
1283       metaproxy_1_filter_struct</literal> exists, and that all the filter
1284      classes provide a static object of that type.
1285     </para>
1286    </section>
1287
1288    <section>
1289     <title><literal>mp::filter::Base</literal>
1290      (<filename>filter.cpp</filename>)</title>
1291     <para>
1292      The virtual base class of all filters.  The filter API is, on the
1293      surface at least, extremely simple: two methods.
1294      <literal>configure()</literal> is passed a DOM tree representing
1295      that part of the configuration file that pertains to this filter
1296      instance, and is expected to walk that tree extracting relevant
1297      information.  And <literal>process()</literal> processes a
1298      package (see below).  That surface simplicitly is a bit
1299      misleading, as <literal>process()</literal> needs to know a lot
1300      about the <literal>Package</literal> class in order to do
1301      anything useful.
1302     </para>
1303    </section>
1304
1305    <section>
1306     <title><literal>mp::filter::AuthSimple</literal>,
1307      <literal>Backend_test</literal>, etc.
1308      (<filename>filter_auth_simple.cpp</filename>,
1309      <filename>filter_backend_test.cpp</filename>, etc.)</title>
1310     <para>
1311      Individual filters.  Each of these is implemented by a header and
1312      a source file, named <filename>filter_*.hpp</filename> and
1313      <filename>filter_*.cpp</filename> respectively.  All the header
1314      files should be pretty much identical, in that they declare the
1315      class, including a private <literal>Rep</literal> class and a
1316      member pointer to it, and the two public methods.  The only extra
1317      information in any filter header is additional private types and
1318      members (which should really all be in the <literal>Rep</literal>
1319      anyway) and private methods (which should also remain known only
1320      to the source file, but C++'s brain-damaged design requires this
1321      dirty laundry to be exhibited in public.  Thanks, Bjarne!)
1322     </para>
1323     <para>
1324      The source file for each filter needs to supply:
1325     </para>
1326     <itemizedlist>
1327      <listitem>
1328       <para>
1329        A definition of the private <literal>Rep</literal> class.
1330       </para>
1331      </listitem>
1332      <listitem>
1333       <para>
1334        Some boilerplate constructors and destructors.
1335       </para>
1336      </listitem>
1337      <listitem>
1338       <para>
1339        A <literal>configure()</literal> method that uses the
1340        appropriate XML fragment.
1341       </para>
1342      </listitem>
1343      <listitem>
1344       <para>
1345        Most important, the <literal>process()</literal> method that
1346        does all the actual work.
1347       </para>
1348      </listitem>
1349     </itemizedlist>
1350    </section>
1351
1352    <section>
1353     <title><literal>mp::Package</literal>
1354      (<filename>package.cpp</filename>)</title>
1355     <para>
1356      Represents a package on its way through the series of filters
1357      that make up a route.  This is essentially a Z39.50 or SRU APDU
1358      together with information about where it came from, which is
1359      modified as it passes through the various filters.
1360     </para>
1361    </section>
1362
1363    <section>
1364     <title><literal>mp::Pipe</literal>
1365      (<filename>pipe.cpp</filename>)</title>
1366     <para>
1367      This class provides a compatibility layer so that we have an IPC
1368      mechanism that works the same under Unix and Windows.  It's not
1369      particularly exciting.
1370     </para>
1371    </section>
1372
1373    <section>
1374     <title><literal>mp::RouterChain</literal>
1375      (<filename>router_chain.cpp</filename>)</title>
1376     <para>
1377      ### to be written
1378     </para>
1379    </section>
1380
1381    <section>
1382     <title><literal>mp::RouterFleXML</literal>
1383      (<filename>router_flexml.cpp</filename>)</title>
1384     <para>
1385      ### to be written
1386     </para>
1387    </section>
1388
1389    <section>
1390     <title><literal>mp::Session</literal>
1391      (<filename>session.cpp</filename>)</title>
1392     <para>
1393      ### to be written
1394     </para>
1395    </section>
1396
1397    <section>
1398     <title><literal>mp::ThreadPoolSocketObserver</literal>
1399      (<filename>thread_pool_observer.cpp</filename>)</title>
1400     <para>
1401      ### to be written
1402     </para>
1403    </section>
1404
1405    <section>
1406     <title><literal>mp::util</literal>
1407      (<filename>util.cpp</filename>)</title>
1408     <para>
1409      A namespace of various small utility functions and classes,
1410      collected together for convenience.  Most importantly, includes
1411      the <literal>mp::util::odr</literal> class, a wrapper for YAZ's
1412      ODR facilities.
1413     </para>
1414    </section>
1415
1416    <section>
1417     <title><literal>mp::xml</literal>
1418      (<filename>xmlutil.cpp</filename>)</title>
1419     <para>
1420      A namespace of various XML utility functions and classes,
1421      collected together for convenience.
1422     </para>
1423    </section>
1424   </section>
1425
1426
1427   <section id="other.source.files">
1428    <title>Other Source Files</title>
1429    <para>
1430     In addition to the Metaproxy source files that define the classes
1431     described above, there are a few additional files which are
1432     briefly described here:
1433    </para>
1434    <variablelist>
1435     <varlistentry>
1436      <term><literal>metaproxy_prog.cpp</literal></term>
1437      <listitem>
1438       <para>
1439        The main function of the <command>metaproxy</command> program.
1440       </para>
1441      </listitem>
1442     </varlistentry>
1443     <varlistentry>
1444      <term><literal>ex_router_flexml.cpp</literal></term>
1445      <listitem>
1446       <para>
1447        Identical to <literal>metaproxy_prog.cpp</literal>: it's not clear why.
1448       </para>
1449      </listitem>
1450     </varlistentry>
1451     <varlistentry>
1452      <term><literal>test_*.cpp</literal></term>
1453      <listitem>
1454       <para>
1455        Unit-tests for various modules.
1456       </para>
1457      </listitem>
1458     </varlistentry>
1459    </variablelist>
1460    <para>
1461     ### Still to be described:
1462     <literal>ex_filter_frontend_net.cpp</literal>,
1463     <literal>filter_dl.cpp</literal>,
1464     <literal>plainfile.cpp</literal>,
1465     <literal>tstdl.cpp</literal>.
1466    </para>
1467   </section>
1468  </chapter>
1469
1470
1471
1472  <chapter id="refguide">
1473   <title>Reference guide</title>
1474   <para>
1475    The material in this chapter is drawn directly from the individual
1476    manual entries.  In particular, the Metaproxy invocation section is
1477    available using <command>man metaproxy</command>, and the section
1478    on each individual filter is available using the name of the filter
1479    as the argument to the <command>man</command> command.
1480   </para>
1481
1482
1483   <section id="progref">
1484    <title>Metaproxy invocation</title>
1485    &progref;
1486   </section>
1487
1488
1489   <section id="filterref">
1490    <title>Reference guide to Metaproxy filters</title>
1491    &manref;
1492   </section>
1493  </chapter>
1494
1495
1496
1497  <!-- Keep this comment at the end of the file
1498  Local variables:
1499  mode: sgml
1500  sgml-omittag:t
1501  sgml-shorttag:t
1502  sgml-minimize-attributes:nil
1503  sgml-always-quote-attributes:t
1504  sgml-indent-step:1
1505  sgml-indent-data:t
1506  sgml-parent-document: "main.xml"
1507  sgml-local-catalogs: nil
1508  sgml-namecase-general:t
1509  End:
1510  -->