Doc: Update to Docbook 4.4
[metaproxy-moved-to-github.git] / doc / book.xml
1 <?xml version="1.0" standalone="no"?>
2 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3     "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" 
4 [
5      <!ENTITY % local SYSTEM "local.ent">
6      %local;
7      <!ENTITY manref SYSTEM "manref.xml">
8      <!ENTITY progref SYSTEM "progref.xml">
9      <!ENTITY gpl2 SYSTEM "gpl-2.0.xml">
10      <!ENTITY % idcommon SYSTEM "common/common.ent">
11      %idcommon;
12 ]>
13 <book>
14  <bookinfo>
15   <title>Metaproxy - User's Guide and Reference</title>
16   <authorgroup>
17    <author>
18     <firstname>Adam</firstname><surname>Dickmeiss</surname>
19    </author>
20    <author>
21     <firstname>Marc</firstname><surname>Cromme</surname>
22    </author>
23    <author>
24     <firstname>Mike</firstname><surname>Taylor</surname>
25    </author>
26   </authorgroup>
27   <releaseinfo>&version;</releaseinfo>
28   <copyright>
29    <year>2005-2010</year>
30    <holder>Index Data</holder>
31   </copyright>
32   <abstract>
33    <simpara>
34     This manual is part of Metaproxy version &version;.
35     </simpara>
36    <simpara>
37     Metaproxy is a universal router, proxy and encapsulated
38     metasearcher for information retrieval protocols.  It accepts,
39     processes, interprets and redirects requests from IR clients using
40     standard protocols such as the binary
41     <ulink url="&url.z39.50;">ANSI/NISO Z39.50</ulink>
42     and  the information search and retrieval 
43     web service <ulink url="&url.sru;">SRU</ulink>
44     as well as functioning as a limited
45     <ulink url="&url.http;">HTTP</ulink> server. 
46    </simpara>
47    <simpara>
48     Metaproxy is configured by an XML file which
49     specifies how the software should function in terms of routes that
50     the request packets can take through the proxy, each step on a
51     route being an instantiation of a filter.  Filters come in many
52     types, one for each operation: accepting Z39.50 packets, logging,
53     query transformation, multiplexing, etc.  Further filter-types can
54     be added as loadable modules to extend Metaproxy functionality,
55     using the filter API.
56    </simpara>
57    <simpara>
58     Metaproxy is covered by the GNU General Public License version 2.
59    </simpara>
60    <simpara>
61     <inlinemediaobject>
62      <imageobject>
63       <imagedata fileref="common/id.png" format="PNG"/>
64      </imageobject>
65      <imageobject>
66       <imagedata fileref="common/id.eps" format="EPS"/>
67      </imageobject>
68     </inlinemediaobject>
69    </simpara>
70   </abstract>
71  </bookinfo>
72
73  <chapter id="introduction">
74   <title>Introduction</title>
75   
76   <para>
77    <ulink url="&url.metaproxy;">Metaproxy</ulink>
78    is a stand alone program that acts as a universal router, proxy and
79    encapsulated metasearcher for information retrieval protocols such
80    as <ulink url="&url.z39.50;">Z39.50</ulink> and
81    <ulink url="&url.sru;">SRU</ulink>.
82    To clients, it acts as a server of these protocols: it can be searched,
83    records can be retrieved from it, etc. 
84    To servers, it acts as a client: it searches in them,
85    retrieves records from them, etc.  it satisfies its clients'
86    requests by transforming them, multiplexing them, forwarding them
87    on to zero or more servers, merging the results, transforming
88    them, and delivering them back to the client.  In addition, it
89    acts as a simple <ulink url="&url.http;">HTTP</ulink> server; support
90    for further protocols can be added in a modular fashion, through the
91    creation of new filters.
92   </para>
93   <screen>
94    Anything goes in!
95    Anything goes out!
96    Fish, bananas, cold pyjamas,
97    Mutton, beef and trout!
98         - attributed to Cole Porter.
99   </screen>
100   <para>
101    Metaproxy is a more capable alternative to
102    <ulink url="&url.yazproxy;">YAZ Proxy</ulink>,
103    being more powerful, flexible, configurable and extensible.  Among
104    its many advantages over the older, more pedestrian work are
105    support for multiplexing (encapsulated metasearching), routing by
106    database name, authentication and authorization and serving local
107    files via HTTP.  Equally significant, its modular architecture
108    facilitites the creation of pluggable modules implementing further
109    functionality.
110   </para>
111   <para>
112    This manual will describe how to install Metaproxy
113    before giving an overview of its architecture, then discussing the
114    key concept of a filter in some depth and giving an overview of
115    the various filter types, then discussing the configuration file
116    format.  After this come several optional chapters which may be
117    freely skipped: a detailed discussion of virtual databases and
118    multi-database searching, some notes on writing extensions
119    (additional filter types) and a high-level description of the
120    source code.  Finally comes the reference guide, which contains
121    instructions for invoking the <command>metaproxy</command>
122    program, and detailed information on each type of filter,
123    including examples.
124   </para>
125  </chapter>
126  
127  <chapter id="installation">
128   <title>Installation</title>
129   <para>
130    Metaproxy depends on the following tools/libraries:
131    <variablelist>
132     <varlistentry><term><ulink url="&url.yazplusplus;">YAZ++</ulink></term>
133      <listitem>
134       <para>
135        This is a C++ library based on <ulink url="&url.yaz;">YAZ</ulink>.
136       </para>
137      </listitem>
138     </varlistentry>
139     <varlistentry><term><ulink url="&url.libxslt;">Libxslt</ulink></term>
140      <listitem>
141       <para>This is an XSLT processor - based on 
142        <ulink url="&url.libxml2;">Libxml2</ulink>. Both Libxml2 and
143        Libxslt must be installed with the development components
144        (header files, etc.) as well as the run-time libraries.
145       </para>
146      </listitem>
147     </varlistentry>
148     <varlistentry><term><ulink url="&url.boost;">Boost</ulink></term>
149      <listitem>
150       <para>
151        The popular C++ library. Initial versions of Metaproxy
152        was built with 1.32 but this is no longer supported.
153        Metaproxy is known to work with Boost version 1.33 through 1.38.
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 successfully built Metaproxy 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    <section id="libxml2.fromsource">
182     <title>Libxml2/libxslt</title>
183     <para>
184      Libxml2/libxslt:
185     </para>
186     <screen>
187      gunzip -c libxml2-version.tar.gz|tar xf -
188      cd libxml2-version
189      ./configure
190      make
191      su
192      make install
193     </screen>
194     <screen>
195      gunzip -c libxslt-version.tar.gz|tar xf -
196      cd libxslt-version
197      ./configure
198      make
199      su
200      make install
201     </screen>
202    </section>
203    <section id="yaz.fromsource">
204     <title>YAZ/YAZ++</title>
205     <screen>
206      gunzip -c yaz-version.tar.gz|tar xf -
207      cd yaz-version
208      ./configure
209      make
210      su
211      make install
212     </screen>
213     <screen>
214      gunzip -c yazpp-version.tar.gz|tar xf -
215      cd yazpp-version
216      ./configure
217      make
218      su
219      make install
220     </screen>
221    </section>
222    <section>
223     <title id="boost.fromsource">Boost</title>
224     <para>
225      Metaproxy needs components thread and test from
226      Boost.
227     </para>
228     <screen>
229      gunzip -c boost-version.tar.gz|tar xf -
230      cd boost-version
231      ./configure --with-libraries=thread,test --with-toolset=gcc
232      make
233      su
234      make install
235     </screen>
236     <para>
237      However, under the hood bjam is used. You can invoke that with
238     </para>
239     <screen>
240      ./bjam --toolset=gcc --with-thread --with-test stage
241     </screen>
242     <para>
243      Replace <literal>stage</literal> with <literal>clean</literal> /
244      <literal>install</literal> to perform clean and install respectively.
245     </para>
246     <para>
247      Add <literal>--prefix=DIR</literal> to install Boost in other
248      prefix than <literal>/usr/local</literal>.
249     </para>
250    </section>
251    <section id="metaproxy.fromsource">
252     <title>Metaproxy</title>
253     <screen>
254      gunzip -c metaproxy-version.tar.gz|tar xf -
255      cd metaproxy-version
256      ./configure
257      make
258      su
259      make install
260     </screen>
261     <para>
262      You may have to tell configure where Boost is installed by supplying
263      options <literal>--with-boost</literal> and <literal>--with-boost-toolset</literal>.
264      The former sets the PREFIX for Boost (same as --prefix for Boost above).
265      The latter the compiler toolset (eg. gcc34).
266     </para>
267     <para>
268      Pass <literal>--help</literal> to configure to get a list of 
269      available options.
270     </para>
271    </section>
272   </section>
273
274   <section id="installation.debian">
275    <title>Installation on Debian GNU/Linux</title>
276    <para>
277     All dependencies for Metaproxy are available as 
278     <ulink url="&url.debian;">Debian</ulink>
279     packages for the sarge (stable in 2005) and etch (testing in 2005)
280     distributions.
281    </para>
282    <para>
283     The procedures for Debian based systems, such as
284     <ulink url="&url.ubuntu;">Ubuntu</ulink> is probably similar
285    </para>
286    <para>
287     There is currently no official Debian package for YAZ++.
288     And the official Debian package for YAZ is probably too old.
289     But Index Data bulds "new" versions of those for Debian (i386 only).
290    </para>
291    <para>
292     Update the <filename>/etc/apt/sources.list</filename>
293     to include the Index Data repository.
294     See YAZ' <ulink url="&url.yaz.download.debian;">Download Debian</ulink>
295     for more information.
296    </para>
297    <screen>
298     apt-get install libxslt1-dev
299     apt-get install libyazpp2-dev
300     apt-get install libboost-dev
301     apt-get install libboost-thread-dev
302     apt-get install libboost-test-dev
303    </screen>
304    <para>
305     With these packages installed, the usual configure + make
306     procedure can be used for Metaproxy as outlined in
307     <xref linkend="installation.unix"/>.
308    </para>
309   </section>
310
311   <section id="installation.rpm">
312    <title>Installation on RPM based Linux Systems</title>
313    <para>
314     All external dependencies for Metaproxy are available as 
315     RPM packages, either from your distribution site, or from the 
316     <ulink url="http://fr.rpmfind.net/">RPMfind</ulink> site.
317    </para>
318    <para>
319     For example, an installation of the requires Boost C++ development 
320     libraries on RedHat Fedora C4 and C5 can be done like this:
321     <screen> 
322     wget ftp://fr.rpmfind.net/wlinux/fedora/core/updates/testing/4/SRPMS/boost-1.33.0-3.fc4.src.rpm
323     sudo rpmbuild --buildroot src/ --rebuild -p fc4/boost-1.33.0-3.fc4.src.rpm
324     sudo rpm -U /usr/src/redhat/RPMS/i386/boost-*rpm
325     </screen>
326    </para>
327    <para>
328     The  <ulink url="&url.yaz;">YAZ</ulink> library is needed to
329     compile &metaproxy;, see there
330     for more information on available RPM packages.
331    </para>
332    <para>
333     There is currently no official RPM package for YAZ++.
334     See the <ulink url="&url.yazplusplus;">YAZ++</ulink> pages 
335     for more information on a Unix tarball install.
336    </para>
337    <para>
338     With these packages installed, the usual configure + make
339     procedure can be used for Metaproxy as outlined in
340     <xref linkend="installation.unix"/>.
341    </para>
342   </section>
343
344   <section id="installation.windows">
345    <title>Installation on Windows</title>
346    <para>
347     Metaproxy can be compiled with Microsoft
348     <ulink url="&url.vstudio;">Visual Studio</ulink>.
349     Versions 2003 (C 7.1), 2005 (C 8.0) and 2008 (C 9.0) is known to work.
350    </para>
351    <section id="installation.windows.boost">
352     <title>Boost</title>
353     <para>
354      For Windows, it's easiest to get the precompiled Boost
355      package from <ulink url="&url.boost.windows.download;">here</ulink>.
356      Several versions of the Boost libraries may be selected when
357      installing Boost for windows. Please choose at least the
358      <emphasis>multithreaded</emphasis> (non-DLL) version because
359      the Metaproxy makefile uses that.
360     </para>
361     <para>
362      For more information about installing Boost refer to the
363      <ulink url="&url.boost.getting.started;">getting started</ulink>
364      pages.
365     </para>
366    </section>
367
368    <section id="installation.windows.libxslt">
369     <title>Libxslt</title>
370     <para>
371      <ulink url="&url.libxslt;">Libxslt</ulink> can be downloaded
372      for Windows from
373      <ulink url="&url.libxml2.download.win32;">here</ulink>.
374     </para>
375     <para>
376      Libxslt has other dependencies, but these can all be downloaded
377      from the same site. Get the following package:
378      iconv, zlib, libxml2, libxslt.
379     </para>
380    </section>
381
382    <section id="installation.windows.yaz">
383     <title>YAZ</title>
384     <para>
385      <ulink url="&url.yaz;">YAZ</ulink> can be downloaded
386      for Windows from
387      <ulink url="&url.yaz.download.win32;">here</ulink>.
388     </para>
389    </section>
390
391    <section id="installation.windows.yazplusplus">
392     <title>YAZ++</title>
393     <para>
394      Get <ulink url="&url.yazplusplus;">YAZ++</ulink> as well.
395      Version 1.1.0 or later is required.
396     </para>
397     <para>
398      YAZ++ includes NMAKE makefiles, similar to those found in the
399      YAZ package.
400     </para>
401    </section>
402
403    <section id="installation.windows.metaproxy">
404     <title>Metaproxy</title>
405     <para>
406      Metaproxy is shipped with NMAKE makefiles as well - similar
407      to those found in the YAZ++/YAZ packages. Adjust this Makefile
408      to point to the proper locations of Boost, Libxslt, Libxml2,
409      zlib, iconv, yaz and yazpp.
410     </para>
411
412     <variablelist>
413      <varlistentry><term><literal>DEBUG</literal></term>
414       <listitem><para>
415         If set to 1, the software is
416         compiled with debugging libraries (code generation is
417         multi-threaded debug DLL).
418         If set to 0, the software is compiled with release libraries
419         (code generation is multi-threaded DLL).
420        </para></listitem>
421      </varlistentry>
422
423      <varlistentry>
424       <term><literal>BOOST</literal></term>
425       <listitem>
426        <para>
427         Boost install location
428        </para>
429       </listitem>
430      </varlistentry>
431
432      <varlistentry>
433       <term><literal>BOOST_VERSION</literal></term>
434       <listitem>
435        <para>
436         Boost version (replace . with _).
437        </para>
438       </listitem>
439      </varlistentry>
440
441      <varlistentry>
442       <term><literal>BOOST_TOOLSET</literal></term>
443       <listitem>
444        <para>
445         Boost toolset.
446        </para>
447       </listitem>
448      </varlistentry>
449
450      <varlistentry>
451       <term><literal>LIBXSLT_DIR</literal>,
452        <literal>LIBXML2_DIR</literal> ..</term>
453       <listitem>
454        <para>
455         Specify the locations of Libxslt, libiconv, libxml2 and
456         libxslt.
457        </para>
458       </listitem>
459      </varlistentry>
460       
461     </variablelist>
462     
463     <para>
464      After successful compilation you'll find
465      <literal>metaproxy.exe</literal> in the
466      <literal>bin</literal> directory.
467     </para>
468    </section>
469
470
471   </section>
472  </chapter>
473  
474 <chapter id="yazproxy-comparison">
475  <title>YAZ Proxy Comparison</title>
476  <para>
477   The table below lists facilities either supported by either
478    <ulink url="&url.yazproxy;">YAZ Proxy</ulink> or Metaproxy.
479  </para>
480 <table id="yazproxy-comparison-table">
481  <title>Metaproxy / YAZ Proxy comparison</title>
482  <tgroup cols="3">
483   <thead>
484    <row>
485     <entry>Facility</entry>
486     <entry>Metaproxy</entry>
487     <entry>YAZ Proxy</entry>
488    </row>
489   </thead>
490   <tbody>
491    <row>
492     <entry>Z39.50 server</entry>
493     <entry>Using filter <literal>frontend_net</literal></entry>
494     <entry>Supported</entry>
495    </row>
496    <row>
497     <entry>SRU server</entry>
498     <entry>Supported with filter <literal>sru_z3950</literal></entry>
499     <entry>Supported</entry>
500    </row>
501    <row>
502     <entry>Z39.50 client</entry>
503     <entry>Supported with filter <literal>z3950_client</literal></entry>
504     <entry>Supported</entry>
505    </row>
506    <row>
507     <entry>SRU client</entry>
508     <entry>Unsupported</entry>
509     <entry>Unsupported</entry>
510    </row>
511    <row>
512     <entry>Connection reuse</entry>
513     <entry>Supported with filter <literal>session_shared</literal></entry>
514     <entry>Supported</entry>
515    </row>
516    <row>
517     <entry>Connection share</entry>
518     <entry>Supported with filter <literal>session_shared</literal></entry>
519     <entry>Unsupported</entry>
520    </row>
521    <row>
522     <entry>Result set reuse</entry>
523     <entry>Supported with filter <literal>session_shared</literal></entry>
524     <entry>Within one Z39.50 session / HTTP keep-alive</entry>
525    </row>
526    <row>
527     <entry>Record cache</entry>
528     <entry>Supported by filter <literal>session_shared</literal></entry>
529     <entry>Supported for last result set within one Z39.50/HTTP-keep alive session</entry>
530    </row>
531    <row>
532     <entry>Z39.50 Virtual database, i.e. select any Z39.50 target for database</entry>
533     <entry>Supported with filter <literal>virt_db</literal></entry>
534     <entry>Unsupported</entry>
535    </row>
536    <row>
537     <entry>SRU Virtual database, i.e. select any Z39.50 target for path</entry>
538     <entry>Supported with filter <literal>virt_db</literal>, 
539      <literal>sru_z3950</literal></entry>
540     <entry>Supported</entry>
541    </row>
542    <row>
543     <entry>Multi target search</entry>
544     <entry>Supported with filter <literal>multi</literal> (round-robin)</entry>
545     <entry>Unsupported</entry>
546    </row>
547    <row>
548     <entry>Retrieval and search limits</entry>
549     <entry>Supported using filter <literal>limit</literal></entry>
550     <entry>Supported</entry>
551    </row>
552    <row>
553     <entry>Bandwidth limits</entry>
554     <entry>Supported using filter <literal>limit</literal></entry>
555     <entry>Supported</entry>
556    </row>
557    <row>
558     <entry>Connect limits</entry>
559     <entry>Supported by filter <literal>frontend_net</literal> (connect-max)</entry>
560     <entry>Supported</entry>
561    </row>
562    <row>
563     <entry>Retrieval sanity check and conversions</entry>
564     <entry>Supported using filter <literal>record_transform</literal></entry>
565     <entry>Supported</entry>
566    </row>
567    <row>
568     <entry>Query check</entry>
569     <entry>
570       Supported by <literal>query_rewrite</literal> which may be check
571       a query and throw diagnostics (errors)
572     </entry>
573     <entry>Supported</entry>
574    </row>
575    <row>
576     <entry>Query rewrite</entry>
577     <entry>Supported with <literal>query_rewrite</literal></entry>
578     <entry>Unsupported</entry>
579    </row>
580    <row>
581     <entry>Session invalidate for -1 hits</entry>
582     <entry>Unsupported</entry>
583     <entry>Supported</entry>
584    </row>
585    <row>
586     <entry>Architecture</entry>
587     <entry>Multi-threaded + select for networked modules such as
588       <literal>frontend_net</literal>)</entry>
589     <entry>Single-threaded using select</entry>
590    </row>
591
592    <row>
593     <entry>Extensability</entry>
594     <entry>Most functionality implemented as loadable modules</entry>
595     <entry>Unsupported and experimental</entry>
596    </row>
597
598    <row>
599     <entry><ulink url="&url.usemarcon;">USEMARCON</ulink></entry>
600     <entry>Unsupported</entry>
601     <entry>Supported</entry>
602    </row>
603
604    <row>
605     <entry>Portability</entry>
606     <entry>
607      Requires YAZ, YAZ++ and modern C++ compiler supporting
608      <ulink url="&url.boost;">Boost</ulink>.
609     </entry>
610     <entry>
611      Requires YAZ and YAZ++.
612      STL is not required so pretty much any C++ compiler out there should work.
613     </entry>
614    </row>
615
616   </tbody>
617  </tgroup>
618 </table>
619 </chapter>
620
621  <chapter id="architecture">
622   <title>The Metaproxy Architecture</title>
623   <para>
624    The Metaproxy architecture is based on three concepts:
625    the <emphasis>package</emphasis>,
626    the <emphasis>route</emphasis>
627    and the <emphasis>filter</emphasis>.
628   </para>
629   <variablelist>
630    <varlistentry>
631     <term>Packages</term>
632     <listitem>
633      <para>
634       A package is request or response, encoded in some protocol,
635       issued by a client, making its way through Metaproxy, send to or
636       received from a server, or sent back to the client.
637      </para>
638      <para>
639       The core of a package is the protocol unit - for example, a
640       Z39.50 Init Request or Search Response, or an SRU searchRetrieve
641       URL or Explain Response.  In addition to this core, a package
642       also carries some extra information added and used by Metaproxy
643       itself.
644      </para>
645      <para>
646       In general, packages are doctored as they pass through
647       Metaproxy.  For example, when the proxy performs authentication
648       and authorization on a Z39.50 Init request, it removes the
649       authentication credentials from the package so that they are not
650       passed onto the back-end server; and when search-response
651       packages are obtained from multiple servers, they are merged
652       into a single unified package that makes its way back to the
653       client.
654      </para>
655     </listitem>
656    </varlistentry>
657    <varlistentry>
658     <term>Routes</term>
659     <listitem>
660      <para>
661       Packages make their way through routes, which can be thought of
662       as programs that operate on the package data-type.  Each
663       incoming package initially makes its way through a default
664       route, but may be switched to a different route based on various
665       considerations.  Routes are made up of sequences of filters (see
666       below).
667      </para>
668     </listitem>
669    </varlistentry>
670    <varlistentry>
671     <term>Filters</term>
672     <listitem>
673      <para>
674       Filters provide the individual instructions within a route, and
675       effect the necessary transformations on packages.  A particular
676       configuration of Metaproxy is essentially a set of filters,
677       described by configuration details and arranged in order in one
678       or more routes.  There are many kinds of filter - about a dozen
679       at the time of writing with more appearing all the time - each
680       performing a specific function and configured by different
681       information.
682      </para>
683      <para>
684       The word ``filter'' is sometimes used rather loosely, in two
685       different ways: it may be used to mean a particular
686       <emphasis>type</emphasis> of filter, as when we speak of ``the
687       auth_simple filter'' or ``the multi filter''; or it may be used
688       to be a specific <emphasis>instance</emphasis> of a filter
689       within a Metaproxy configuration.  For example, a single
690       configuration will often contain multiple instances of the
691       <literal>z3950_client</literal> filter.  In
692       operational terms, of these is a separate filter.  In practice,
693       context always make it clear which sense of the word ``filter''
694       is being used.
695      </para>
696      <para>
697       Extensibility of Metaproxy is primarily through the creation of
698       plugins that provide new filters.  The filter API is small and
699       conceptually simple, but there are many details to master.  See
700       the section below on
701       <link linkend="filters">Filters</link>.
702      </para>
703     </listitem>
704    </varlistentry>
705   </variablelist>
706   <para>
707    Since packages are created and handled by the system itself, and
708    routes are conceptually simple, most of the remainder of this
709    document concentrates on filters.  After a brief overview of the
710    filter types follows, along with some thoughts on possible future
711    directions.
712   </para>
713  </chapter>
714
715
716
717  <chapter id="filters">
718   <title>Filters</title>
719   
720   
721   <section id="filters-introductory-notes">
722    <title>Introductory notes</title>
723    <para>
724     It's useful to think of Metaproxy as an interpreter providing a small
725     number of primitives and operations, but operating on a very
726     complex data type, namely the ``package''.
727    </para>
728    <para>
729     A package represents a Z39.50 or SRU/W request (whether for Init,
730     Search, Scan, etc.)  together with information about where it came
731     from.  Packages are created by front-end filters such as
732     <literal>frontend_net</literal> (see below), which reads them from
733     the network; other front-end filters are possible.  They then pass
734     along a route consisting of a sequence of filters, each of which
735     transforms the package and may also have side-effects such as
736     generating logging.  Eventually, the route will yield a response,
737     which is sent back to the origin.
738    </para>
739    <para>
740     There are many kinds of filter: some that are defined statically
741     as part of Metaproxy, and others may be provided by third parties
742     and dynamically loaded.  They all conform to the same simple API
743     of essentially two methods: <function>configure()</function> is
744     called at startup time, and is passed an XML DOM tree representing that
745     part of the configuration file that pertains to this filter
746     instance: it is expected to walk that tree extracting relevant
747     information; and <function>process()</function> is called every
748     time the filter has to processes a package.
749    </para>
750    <para>
751     While all filters provide the same API, there are different modes
752     of functionality.  Some filters are sources: they create
753     packages
754     (<literal>frontend_net</literal>);
755     others are sinks: they consume packages and return a result
756     (<literal>backend_test</literal>,
757     <literal>bounce</literal>,
758     <literal>http_file</literal>, 
759     <literal>z3950_client</literal>);
760     the others are true filters, that read, process and pass on the
761     packages they are fed
762     (<literal>auth_simple</literal>,
763     <literal>log</literal>,
764     <literal>multi</literal>,
765     <literal>query_rewrite</literal>,
766     <literal>record_transform</literal>,
767     <literal>session_shared</literal>,
768     <literal>sru_z3950</literal>,
769     <literal>template</literal>,
770     <literal>virt_db</literal>).
771    </para>
772  </section>
773   
774   
775   <section id="overview.filter.types">
776    <title>Overview of filter types</title>
777    <para>
778     We now briefly consider each of the types of filter supported by
779     the core Metaproxy binary.  This overview is intended to give a
780     flavor of the available functionality; more detailed information
781     about each type of filter is included below in
782     <xref linkend="reference"/>.
783    </para>
784    <para>
785     The filters are here named by the string that is used as the
786     <literal>type</literal> attribute of a
787     <literal>&lt;filter&gt;</literal> element in the configuration
788     file to request them, with the name of the class that implements
789     them in parentheses.  (The classname is not needed for normal
790     configuration and use of Metaproxy; it is useful only to
791     developers.)
792    </para>
793    <para>
794     The filters are here listed in alphabetical order:
795    </para>
796    
797 <!--
798
799 ### New filters:
800
801 New virt_db-alike that does inteligent peer choice, explain merging,
802 adds FD&N to explain.  Keeps init responses (like "virt_db Classic"),
803 makes routing choices based on local explain knowledge.  Ref IDDI
804 paper.
805
806 Filter to convert Explain Classic to ZeeRex.
807
808 CQL2PQF (which needs augmented ZeeRex) - MARC for Talis.
809
810 SRU2Z39.50 (ditto).
811
812 Figure out what additional information we need in:
813         ZeeRex (check against D3.1)
814         Init request (e.g. loop detection)
815         Query package (e.g. number of hops)
816         Query response (e.g. record source)
817
818 -->
819
820    <section id="auth_simple">
821     <title><literal>auth_simple</literal>
822      (mp::filter::AuthSimple)</title>
823     <para>
824      Simple authentication and authorization.  The configuration
825      specifies the name of a file that is the user register, which
826      lists <varname>username</varname>:<varname>password</varname>
827      pairs, one per line, colon separated. When a session begins, it
828      is rejected unless username and passsword are supplied, and match
829      a pair in the register.  The configuration file may also specific
830      the name of another file that is the target register: this lists
831      lists <varname>username</varname>:<varname>dbname</varname>,<varname>dbname</varname>...
832      sets, one per line, with multiple database names separated by
833      commas.  When a search is processed, it is rejected unless the
834      database to be searched is one of those listed as available to
835      the user.
836     </para>
837    </section>
838    
839    <section id="backend_test">
840     <title><literal>backend_test</literal>
841     (mp::filter::Backend_test)</title>
842     <para>
843      A partial sink that provides dummy responses in the manner of the
844      <literal>yaz-ztest</literal> Z39.50 server.  This is useful only
845      for testing.  Seriously, you don't need this.  Pretend you didn't
846      even read this section.
847     </para>
848    </section>
849    
850    <section id="bounce">
851     <title><literal>bounce</literal>
852     (mp::filter::Bounce)</title>
853     <para>
854      A sink that swallows <emphasis>all packages</emphasis>, 
855      and returns them almost unprocessed.
856      It never sends any package of any type further down the row, but
857      sets Z39.50 packages to Z_Close, and HTTP_Request packages to
858      HTTP_Response err code 400 packages, and adds a suitable bounce
859      message. 
860      The bounce filter is usually added at end of each filter chain route
861      to prevent infinite hanging of for example HTTP
862      requests packages when only the Z39.50 client partial sink 
863      filter is found in the
864      route.  
865     </para>
866    </section>
867    
868    <section id="cql_rpn">
869     <title><literal>cql_rpn</literal>
870     (mp::filter::CQLtoRPN)</title>
871     <para>
872      A query language transforming filter which catches Z39.50 
873      <literal>searchRequest</literal>
874      packages containing <literal>CQL</literal> queries, transforms
875      those to <literal>RPN</literal> queries,
876      and sends the <literal>searchRequests</literal> on to the next
877      filters. It is among other things useful in a SRU context. 
878     </para>
879    </section>
880    
881    <section id="frontend_net">
882     <title><literal>frontend_net</literal>
883      (mp::filter::FrontendNet)</title>
884     <para>
885      A source that accepts Z39.50 connections from a port
886      specified in the configuration, reads protocol units, and
887      feeds them into the next filter in the route.  When the result is
888      received, it is returned to the original origin.
889     </para>
890    </section>
891
892    <section id="http_file">
893     <title><literal>http_file</literal>
894      (mp::filter::HttpFile)</title>
895     <para>
896      A partial sink which swallows only 
897      <literal>HTTP_Request</literal> packages, and 
898      returns the contents of files from the local
899      filesystem in response to HTTP requests.  
900      It lets Z39.50 packages and all other forthcoming package types
901      pass untouched. 
902      (Yes, Virginia, this
903      does mean that Metaproxy is also a Web-server in its spare time.  So
904      far it does not contain either an email-reader or a Lisp
905      interpreter, but that day is surely coming.)
906     </para>
907    </section>
908    
909    <section id="load_balance">
910     <title><literal>load_balance</literal>
911      (mp::filter::LoadBalance)</title>
912     <para>
913      Performs load balancing for incoming Z39.50 init requests.
914      It is used together with the <literal>virt_db</literal> filter,
915      but unlike the <literal>multi</literal> filter it does send an
916      entire session to only one of the virtual backends. The 
917      <literal>load_balance</literal> filter is assuming that
918      all backend targets have equal content, and chooses the backend
919      with least load cost for a new session.
920     <warning>
921      <para>
922       This filter is experimental and yet not mature for heavy load
923       production sites.
924      </para>
925     </warning>
926    </para>
927    </section>
928       
929    <section id="log">
930     <title><literal>log</literal>
931      (mp::filter::Log)</title>
932     <para>
933      Writes logging information to standard output, and passes on
934      the package unchanged. A log file name can be specified, as well
935      as multiple different logging formats.
936    </para>
937    </section>
938
939    <section id="multi">
940    <title><literal>multi</literal>
941      (mp::filter::Multi)</title>
942     <para>
943      Performs multi-database searching.
944      See
945      <link linkend="multidb">the extended discussion</link>
946      of virtual databases and multi-database searching below.
947     </para>
948    </section>
949    
950    <section id="query_rewrite">
951    <title><literal>query_rewrite</literal>
952      (mp::filter::QueryRewrite)</title>
953     <para>
954      Rewrites Z39.50 <literal>Type-1</literal> 
955      and <literal>Type-101</literal> (``<literal>RPN</literal>'') 
956      queries by a
957      three-step process: the query is transliterated from Z39.50
958      packet structures into an XML representation; that XML
959      representation is transformed by an XSLT stylesheet; and the
960      resulting XML is transliterated back into the Z39.50 packet
961      structure.
962     </para>
963    </section>
964    
965    
966    <section id="record_transform">
967     <title><literal>record_transform</literal>
968     (mp::filter::RecordTransform)</title>
969     <para>
970      This filter acts only on Z3950 present requests, and let all
971      other types of packages and requests pass untouched. It's use is
972      twofold: blocking Z3950  present requests, which the backend
973      server does not understand and can not honor, and transforming
974      the present syntax and elementset name according to the rules
975      specified, to fetch only existing record formats, and transform
976      them on the fly to requested record syntaxes.
977     </para>
978    </section>
979
980    <section id="session_shared">
981     <title><literal>session_shared</literal>
982      (mp::filter::SessionShared)</title>
983     <para>
984      This filter implements global sharing of
985      result sets (i.e. between threads and therefore between
986      clients), yielding performance improvements by clever resource
987      pooling. 
988     </para>
989    </section>
990
991    <section id="sru_z3950">
992     <title><literal>sru_z3950</literal>
993     (mp::filter::SRUtoZ3950)</title>
994     <para>
995      This filter transforms valid
996      SRU GET/POST/SOAP searchRetrieve requests to Z3950 init, search,
997      and present requests, and wraps the
998      received hit counts and XML records into suitable SRU response
999      messages.
1000      The <literal>sru_z3950</literal> filter  processes also  SRU
1001      GET/POST/SOAP explain requests, returning
1002      either the absolute minimum required by the standard, or a  full 
1003      pre-defined ZeeReX explain record.
1004      See the 
1005      <ulink url="&url.zeerex.explain;">ZeeReX Explain</ulink>
1006      standard pages and the 
1007      <ulink url="&url.sru.explain;">SRU Explain</ulink> pages
1008      for more information on the correct explain syntax.
1009      SRU scan requests are not supported yet.
1010     </para>
1011    </section>
1012    
1013    <section id="template">
1014     <title><literal>template</literal>
1015      (mp::filter::Template)</title>
1016     <para>
1017      Does nothing at all, merely passing the packet on.  (Maybe it
1018      should be called <literal>nop</literal> or
1019      <literal>passthrough</literal>?)  This exists not to be used, but
1020      to be copied - to become the skeleton of new filters as they are
1021      written.  As with <literal>backend_test</literal>, this is not
1022      intended for civilians.
1023     </para>
1024    </section>
1025    
1026    <section id="virt_db">
1027     <title><literal>virt_db</literal>
1028      (mp::filter::VirtualDB)</title>
1029     <para>
1030      Performs virtual database selection: based on the name of the
1031      database in the search request, a server is selected, and its
1032      address added to the request in a <literal>VAL_PROXY</literal>
1033      otherInfo packet.  It will subsequently be used by a
1034      <literal>z3950_client</literal> filter.
1035      See
1036      <link linkend="multidb">the extended discussion</link>
1037      of virtual databases and multi-database searching below.
1038     </para>
1039    </section>
1040    
1041    <section id="z3950_client">
1042     <title><literal>z3950_client</literal>
1043      (mp::filter::Z3950Client)</title>
1044     <para>
1045      A partial sink which swallows only Z39.50 packages.
1046      It performs Z39.50 searching and retrieval by proxying the
1047      packages that are passed to it.  Init requests are sent to the
1048      address specified in the <literal>VAL_PROXY</literal> otherInfo
1049      attached to the request: this may have been specified by client,
1050      or generated by a <literal>virt_db</literal> filter earlier in
1051      the route.  Subsequent requests are sent to the same address,
1052      which is remembered at Init time in a Session object.
1053      HTTP_Request packages and all other forthcoming package types
1054      are passed untouched. 
1055     </para>
1056   </section>
1057
1058
1059    <section id="zeerex_explain">
1060     <title><literal>zeerex_explain</literal>
1061      (mp::filter::ZeerexExplain)</title>
1062     <para>
1063      This filter acts as a sink for
1064      Z39.50 explain requests, returning a static ZeeReX
1065      Explain XML record from the config section. All other packages
1066      are passed through.
1067      See the 
1068      <ulink url="&url.zeerex.explain;">ZeeReX Explain</ulink>
1069      standard pages
1070      for more information on the correct explain syntax.
1071     </para>
1072     <warning>
1073      <para>
1074       This filter is not yet completed.
1075      </para>
1076     </warning>
1077    </section>
1078    
1079
1080   </section>
1081   
1082   
1083   <section id="future.directions">
1084    <title>Future directions</title>
1085   <para>
1086     Some other filters that do not yet exist, but which would be
1087     useful, are briefly described.  These may be added in future
1088     releases (or may be created by third parties, as loadable
1089     modules).
1090    </para>
1091
1092    <variablelist>
1093     <varlistentry>
1094      <term><literal>frontend_cli</literal> (source)</term>
1095     <listitem>
1096       <para>
1097        Command-line interface for generating requests.
1098       </para>
1099      </listitem>
1100     </varlistentry>
1101     <varlistentry>
1102      <term><literal>sru_client</literal> (sink)</term>
1103      <listitem>
1104       <para>
1105        SRU/GET and SRU/SOAP searching and retrieval.
1106       </para>
1107      </listitem>
1108     </varlistentry>
1109     <varlistentry>
1110      <term><literal>opensearch_client</literal> (sink)</term>
1111      <listitem>
1112       <para>
1113        A9 OpenSearch searching and retrieval.
1114       </para>
1115      </listitem>
1116     </varlistentry>
1117    </variablelist>
1118   </section>
1119  </chapter>
1120  
1121  
1122  
1123  <chapter id="configuration">
1124   <title>Configuration: the Metaproxy configuration file format</title>
1125   
1126   
1127   <section id="configuration-introductory-notes">
1128    <title>Introductory notes</title>
1129    <para>
1130     If Metaproxy is an interpreter providing operations on packages, then
1131     its configuration file can be thought of as a program for that
1132     interpreter.  Configuration is by means of a single XML file, the name
1133     of which is supplied as the sole command-line argument to the
1134     <command>metaproxy</command> program.  (See
1135     <xref linkend="reference"/> below for more information on invoking
1136     Metaproxy.)
1137    </para>
1138   </section>
1139   
1140   <section id="overview.xml.structure">
1141    <title>Overview of the config file XML structure</title>
1142    <para>
1143     All elements and attributes are in the namespace
1144     <ulink url="http://indexdata.com/metaproxy"/>.
1145      This is most easily achieved by setting the default namespace on
1146      the top-level element, as here:
1147    </para>
1148    <screen>
1149     &lt;metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0"&gt;
1150    </screen>
1151    <para>
1152     The top-level element is &lt;metaproxy&gt;.  This contains
1153     a &lt;dlpath&gt; element,
1154     a &lt;start&gt; element,
1155     a &lt;filters&gt; element and
1156     a &lt;routes&gt; element, in that order.  &lt;dlpath&gt; and
1157     &lt;filters&gt; are optional; the other two are mandatory.
1158     All four are non-repeatable.
1159    </para>
1160    <para>
1161      The &lt;dlpath;&gt; element contains a text element which 
1162      specifies the location of filter modules. This is only needed
1163      if Metaproxy must load 3rd party filters (most filters with Metaproxy
1164      are built into the Metaproxy application).
1165    </para>
1166   <para>
1167     The &lt;start&gt; element is empty, but carries a
1168     <literal>route</literal> attribute, whose value is the name of
1169     route at which to start running - analogous to the name of the
1170     start production in a formal grammar.
1171    </para>
1172   <para>
1173     If present, &lt;filters&gt; contains zero or more &lt;filter&gt;
1174     elements.  Each filter carries a <literal>type</literal> attribute
1175     which specifies what kind of filter is being defined
1176     (<literal>frontend_net</literal>, <literal>log</literal>, etc.)
1177     and contain various elements that provide suitable configuration
1178     for a filter of its type.  The filter-specific elements are
1179     described in
1180     <xref linkend="reference"/>.
1181     Filters defined in this part of the file must carry an
1182     <literal>id</literal> attribute so that they can be referenced
1183     from elsewhere.
1184    </para>
1185    <para>
1186     &lt;routes&gt; contains one or more &lt;route&gt; elements, each
1187     of which must carry an <literal>id</literal> element.  One of the
1188     routes must have the ID value that was specified as the start
1189     route in the &lt;start&gt; element's <literal>route</literal>
1190     attribute.  Each route contains zero or more &lt;filter&gt;
1191     elements.  These are of two types.  They may be empty, but carry a
1192     <literal>refid</literal> attribute whose value is the same as the
1193     <literal>id</literal> of a filter previously defined in the
1194     &lt;filters&gt; section.  Alternatively, a route within a filter
1195     may omit the <literal>refid</literal> attribute, but contain
1196     configuration elements similar to those used for filters defined
1197     in the &lt;filters&gt; section.  (In other words, each filter in a
1198     route may be included either by reference or by physical
1199     inclusion.)
1200    </para>
1201   </section>
1202
1203
1204   <section id="example.configuration">
1205    <title>An example configuration</title>
1206    <para>
1207     The following is a small, but complete, Metaproxy configuration
1208     file (included in the distribution as
1209     <literal>metaproxy/etc/config1.xml</literal>).
1210     This file defines a very simple configuration that simply proxies
1211     to whatever back-end server the client requests, but logs each
1212     request and response.  This can be useful for debugging complex
1213     client-server dialogues.
1214    </para>
1215    <screen><![CDATA[<?xml version="1.0"?>
1216 <metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0">
1217   <dlpath>/usr/lib/metaproxy/modules</dlpath>
1218   <start route="start"/>
1219   <filters>
1220     <filter id="frontend" type="frontend_net">
1221       <port>@:9000</port>
1222     </filter>
1223     <filter id="backend" type="z3950_client">
1224     </filter>
1225   </filters>
1226   <routes>  
1227     <route id="start">
1228       <filter refid="frontend"/>
1229       <filter type="log"/>
1230       <filter refid="backend"/>
1231       <filter type="bounce"/>
1232     </route>
1233   </routes>
1234 </metaproxy>
1235 ]]></screen>
1236    <para>
1237     It works by defining a single route, called
1238     <literal>start</literal>, which consists of a sequence of four
1239     filters.  The first and last of these are included by reference:
1240     their <literal>&lt;filter&gt;</literal> elements have
1241     <literal>refid</literal> attributes that refer to filters defined
1242     within the prior <literal>&lt;filters&gt;</literal> section.  The
1243     middle filter is included inline in the route.
1244    </para>
1245    <para>
1246     The four filters in the route are as follows: first, a
1247     <literal>frontend_net</literal> filter accepts Z39.50 requests
1248     from any host on port 9000; then these requests are passed through
1249     a <literal>log</literal> filter that emits a message for each
1250     request; they are then fed into a <literal>z3950_client</literal>
1251     filter, which forwards all Z39.50 requests to the client-specified
1252     back-end Z39.509 server. Those Z39.50 packages are returned by the
1253     <literal>z3950_client</literal> filter, with the response data
1254     filled by the external Z39.50 server targeted.
1255     All non-Z39.50 packages are passed through to the
1256     <literal>bounce</literal> filter, which definitely bounces
1257     everything, including fish, bananas, cold pyjamas,
1258     mutton, beef and trout packages.
1259     When the response arrives, it is handed
1260     back to the <literal>log</literal> filter, which emits another
1261     message; and then to the <literal>frontend_net</literal> filter, 
1262     which returns the response to the client.
1263    </para>
1264   </section>
1265
1266   <section id="config-file-modularity">
1267    <title>Config file modularity</title>
1268    <para>
1269     Metaproxy XML configuration snippets can be reused by other
1270     filters using the <literal>XInclude</literal> standard, as seen in
1271     the <literal>/etc/config-sru-to-z3950.xml</literal> example SRU 
1272     configuration.
1273    <screen><![CDATA[
1274     <filter id="sru" type="sru_z3950">
1275       <database name="Default">
1276        <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
1277                     href="explain.xml"/>
1278       </database>
1279     </filter>
1280 ]]></screen>
1281     </para>
1282   </section>
1283
1284   <section id="config-file-syntax-check">
1285    <title>Config file syntax checking</title>
1286    <para>
1287     The distribution contains RelaxNG Compact and XML syntax checking
1288     files, as well as XML Schema files. These are found in the
1289     distribution paths 
1290    <screen>
1291     xml/schema/metaproxy.rnc
1292     xml/schema/metaproxy.rng
1293     xml/schema/metaproxy.xsd
1294    </screen>
1295     and can be used to verify or debug the XML structure of
1296     configuration files. For example, using the utility
1297     <filename>xmllint</filename>, syntax checking is done like this:
1298    <screen>
1299     xmllint --noout --schema xml/schema/metaproxy.xsd etc/config-local.xml 
1300     xmllint --noout --relaxng xml/schema/metaproxy.rng etc/config-local.xml 
1301    </screen>
1302     (A recent version of <literal>libxml2</literal> is required, as
1303     support for XML Schemas is a relatively recent addition.)
1304    </para>
1305    <para>
1306     You can of course use any other RelaxNG or XML Schema compliant tool
1307     you wish.
1308    </para>
1309    </section>
1310  </chapter>
1311
1312
1313
1314  <chapter id="multidb">
1315   <title>Virtual databases and multi-database searching</title>
1316
1317
1318   <section id="multidb-introductory-notes">
1319    <title>Introductory notes</title>
1320    <para>
1321     Two of Metaproxy's filters are concerned with multiple-database
1322     operations.  Of these, <literal>virt_db</literal> can work alone
1323     to control the routing of searches to one of a number of servers,
1324     while <literal>multi</literal> can work together with
1325     <literal>virt_db</literal> to perform multi-database searching, merging
1326     the results into a unified result-set - ``metasearch in a box''.
1327    </para>
1328    <para>
1329     The interaction between
1330     these two filters is necessarily complex: it reflects the real,
1331     irreducible complexity of multi-database searching in a protocol such
1332     as Z39.50 that separates initialization from searching, and in
1333     which the database to be searched is not known at initialization
1334     time.
1335    </para>
1336    <para>
1337     It's possible to use these filters without understanding the
1338     details of their functioning and the interaction between them; the
1339     next two sections of this chapter are ``HOW-TO'' guides for doing
1340     just that.  However, debugging complex configurations will require
1341     a deeper understanding, which the last two sections of this
1342     chapters attempt to provide.
1343    </para>
1344   </section>
1345
1346
1347   <section id="multidb.virt_db">
1348    <title>Virtual databases with the <literal>virt_db</literal> filter</title>
1349    <para>
1350     Working alone, the purpose of the
1351     <literal>virt_db</literal>
1352     filter is to route search requests to one of a selection of
1353     back-end databases.  In this way, a single Z39.50 endpoint
1354     (running Metaproxy) can provide access to several different
1355     underlying services, including those that would otherwise be
1356     inaccessible due to firewalls.  In many useful configurations, the
1357     back-end databases are local to the Metaproxy installation, but
1358     the software does not enforce this, and any valid Z39.50 servers
1359     may be used as back-ends.
1360    </para>
1361    <para>
1362     For example, a <literal>virt_db</literal>
1363     filter could be set up so that searches in the virtual database
1364     ``lc'' are forwarded to the Library of Congress bibliographic
1365     catalogue server, and searches in the virtual database ``marc''
1366     are forwarded to the toy database of MARC records that Index Data
1367     hosts for testing purposes.  A <literal>virt_db</literal>
1368     configuration to make this switch would look like this:
1369    </para>
1370    <screen><![CDATA[<filter type="virt_db">
1371   <virtual>
1372     <database>lc</database>
1373     <target>z3950.loc.gov:7090/voyager</target>
1374   </virtual>
1375   <virtual>
1376     <database>marc</database>
1377     <target>indexdata.com/marc</target>
1378   </virtual>
1379 </filter>]]></screen>
1380    <para>
1381     As well as being useful in it own right, this filter also provides
1382     the foundation for multi-database searching.
1383    </para>
1384   </section>
1385
1386
1387   <section id="multidb.multi">
1388    <title>Multi-database search with the <literal>multi</literal> filter</title>
1389    <para>
1390     To arrange for Metaproxy to broadcast searches to multiple back-end
1391     servers, the configuration needs to include two components: a
1392     <literal>virt_db</literal>
1393     filter that specifies multiple
1394     <literal>&lt;target&gt;</literal>
1395     elements, and a subsequent
1396     <literal>multi</literal>
1397     filter.  Here, for example, is a complete configuration that
1398     broadcasts searches to both the Library of Congress catalogue and
1399     Index Data's tiny testing database of MARC records:
1400    </para>
1401    <screen><![CDATA[<?xml version="1.0"?>
1402 <metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0">
1403   <start route="start"/>
1404   <routes>
1405     <route id="start">
1406       <filter type="frontend_net">
1407         <threads>10</threads>
1408         <port>@:9000</port>
1409       </filter>
1410       <filter type="virt_db">
1411         <virtual>
1412           <database>lc</database>
1413           <target>z3950.loc.gov:7090/voyager</target>
1414         </virtual>
1415         <virtual>
1416           <database>marc</database>
1417           <target>indexdata.com/marc</target>
1418         </virtual>
1419         <virtual>
1420           <database>all</database>
1421           <target>z3950.loc.gov:7090/voyager</target>
1422           <target>indexdata.com/marc</target>
1423         </virtual>
1424       </filter>
1425       <filter type="multi"/>
1426       <filter type="z3950_client">
1427         <timeout>30</timeout>
1428       </filter>
1429       <filter type="bounce"/>
1430     </route>
1431   </routes>
1432 </metaproxy>]]></screen>
1433    <para>
1434     (Using a
1435     <literal>virt_db</literal>
1436     filter that specifies multiple
1437     <literal>&lt;target&gt;</literal>
1438     elements but without a subsequent
1439     <literal>multi</literal>
1440     filter yields surprising and undesirable results, as will be
1441     described below.  Don't do that.)
1442    </para>
1443    <para>
1444     Metaproxy can be invoked with this configuration as follows:
1445    </para>
1446    <screen>../src/metaproxy --config config-simple-multi.xml</screen>
1447    <para>
1448     And thereafter, Z39.50 clients can connect to the running server
1449     (on port 9000, as specified in the configuration) and search in
1450     any of the databases
1451     <literal>lc</literal> (the Library of Congress catalogue),
1452     <literal>marc</literal> (Index Data's test database of MARC records)
1453     or
1454     <literal>all</literal> (both of these).  As an example, a session
1455     using the YAZ command-line client <literal>yaz-client</literal> is
1456     here included (edited for brevity and clarity):
1457    </para>
1458    <screen><![CDATA[$ yaz-client @:9000
1459 Connecting...OK.
1460 Z> base lc
1461 Z> find computer
1462 Search was a success.
1463 Number of hits: 10000, setno 1
1464 Elapsed: 5.521070
1465 Z> base marc
1466 Z> find computer
1467 Search was a success.
1468 Number of hits: 10, setno 3
1469 Elapsed: 0.060187
1470 Z> base all
1471 Z> find computer
1472 Search was a success.
1473 Number of hits: 10010, setno 4
1474 Elapsed: 2.237648
1475 Z> show 1
1476 [marc]Record type: USmarc
1477 001    11224466
1478 003 DLC
1479 005 00000000000000.0
1480 008 910710c19910701nju           00010 eng
1481 010    $a 11224466
1482 040    $a DLC $c DLC
1483 050 00 $a 123-xyz
1484 100 10 $a Jack Collins
1485 245 10 $a How to program a computer
1486 260 1  $a Penguin
1487 263    $a 8710
1488 300    $a p. cm.
1489 Elapsed: 0.119612
1490 Z> show 2
1491 [VOYAGER]Record type: USmarc
1492 001 13339105
1493 005 20041229102447.0
1494 008 030910s2004    caua          000 0 eng
1495 035    $a (DLC)  2003112666
1496 906    $a 7 $b cbc $c orignew $d 4 $e epcn $f 20 $g y-gencatlg
1497 925 0  $a acquire $b 1 shelf copy $x policy default
1498 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.
1499 010    $a   2003112666
1500 020    $a 0761542892
1501 040    $a DLC $c DLC $d DLC
1502 050 00 $a MLCM 2004/03312 (G)
1503 245 10 $a 007, everything or nothing : $b Prima's official strategy guide / $c created by Kaizen Media Group.
1504 246 3  $a Double-O-seven, everything or nothing
1505 246 30 $a Prima's official strategy guide
1506 260    $a Roseville, CA : $b Prima Games, $c c2004.
1507 300    $a 161 p. : $b col. ill. ; $c 28 cm.
1508 500    $a "Platforms: Nintendo GameCube, Macintosh, PC, PlayStation 2 computer entertainment system, Xbox"--P. [4] of cover.
1509 650  0 $a Video games.
1510 710 2  $a Kaizen Media Group.
1511 856 42 $3 Publisher description $u http://www.loc.gov/catdir/description/random052/2003112666.html
1512 Elapsed: 0.150623
1513 Z>
1514 ]]></screen>
1515    <para>
1516     As can be seen, the first record in the result set is from the
1517     Index Data test database, and the second from the Library of
1518     Congress database.  The result-set continues alternating records
1519     round-robin style until the point where one of the databases'
1520     records are exhausted.
1521    </para>
1522    <para>
1523     This example uses only two back-end databases; more may be used.
1524     There is no limitation imposed on the number of databases that may
1525     be metasearched in this way: issues of resource usage and
1526     administrative complexity dictate the practical limits.
1527    </para>
1528    <para>
1529     What happens when one of the databases doesn't respond?  By default,
1530     the entire multi-database search fails, and the appropriate
1531     diagnostic is returned to the client.  This is usually appropriate
1532     during development, when technicians need maximum information, but
1533     can be inconvenient in deployment, when users typically don't want
1534     to be bothered with problems of this kind and prefer just to get
1535     the records from the databases that are available.  To obtain this
1536     latter behavior add an empty
1537     <literal>&lt;hideunavailable&gt;</literal>
1538     element inside the
1539     <literal>multi</literal> filter:
1540    </para>
1541    <screen><![CDATA[      <filter type="multi">
1542         <hideunavailable/>
1543       </filter>]]></screen>
1544    <para>
1545     Under this regime, an error is reported to the client only if
1546     <emphasis>all</emphasis> the databases in a multi-database search
1547     are unavailable.
1548    </para>
1549   </section>
1550
1551
1552   <section id="multidb.what">
1553    <title>What's going on?</title>
1554    <warning>
1555     <title>Lark's vomit</title>
1556     <para>
1557      This section goes into a level of technical detail that is
1558      probably not necessary in order to configure and use Metaproxy.
1559      It is provided only for those who like to know how things work.
1560      You should feel free to skip on to the next section if this one
1561      doesn't seem like fun.
1562     </para>
1563    </warning>
1564    <para>
1565     Hold on tight - this may get a little hairy.
1566    </para>
1567    <para>
1568     In the general course of things, a Z39.50 Init request may carry
1569     with it an otherInfo packet of type <literal>VAL_PROXY</literal>,
1570     whose value indicates the address of a Z39.50 server to which the
1571     ultimate connection is to be made.  (This otherInfo packet is
1572     supported by YAZ-based Z39.50 clients and servers, but has not yet
1573     been ratified by the Maintenance Agency and so is not widely used
1574     in non-Index Data software.  We're working on it.)
1575     The <literal>VAL_PROXY</literal> packet functions
1576     analogously to the absoluteURI-style Request-URI used with the GET
1577     method when a web browser asks a proxy to forward its request: see
1578     the
1579     <ulink url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2"
1580            >Request-URI</ulink>
1581     section of
1582     <ulink url="http://www.w3.org/Protocols/rfc2616/rfc2616.html"
1583            >the HTTP 1.1 specification</ulink>.
1584    </para>
1585    <para>
1586     Within Metaproxy, Search requests that are part of the same
1587     session as an Init request that carries a
1588     <literal>VAL_PROXY</literal> otherInfo are also annotated with the
1589     same information.  The role of the <literal>virt_db</literal>
1590     filter is to rewrite this otherInfo packet dependent on the
1591     virtual database that the client wants to search.
1592    </para>
1593    <para>
1594     When Metaproxy receives a Z39.50 Init request from a client, it
1595     doesn't immediately forward that request to the back-end server.
1596     Why not?  Because it doesn't know <emphasis>which</emphasis>
1597     back-end server to forward it to until the client sends a Search
1598     request that specifies the database that it wants to search in.
1599     Instead, it just treasures the Init request up in its heart; and,
1600     later, the first time the client does a search on one of the
1601     specified virtual databases, a connection is forged to the
1602     appropriate server and the Init request is forwarded to it.  If,
1603     later in the session, the same client searches in a different
1604     virtual database, then a connection is forged to the server that
1605     hosts it, and the same cached Init request is forwarded there,
1606     too.
1607    </para>
1608    <para>
1609     All of this clever Init-delaying is done by the
1610     <literal>frontend_net</literal> filter.  The
1611     <literal>virt_db</literal> filter knows nothing about it; in
1612     fact, because the Init request that is received from the client
1613     doesn't get forwarded until a Search request is received, the
1614     <literal>virt_db</literal> filter (and the
1615     <literal>z3950_client</literal> filter behind it) doesn't even get
1616     invoked at Init time.  The <emphasis>only</emphasis> thing that a
1617     <literal>virt_db</literal> filter ever does is rewrite the
1618     <literal>VAL_PROXY</literal> otherInfo in the requests that pass
1619     through it.
1620    </para>
1621    <para>
1622     It is possible for a <literal>virt_db</literal> filter to contain
1623     multiple
1624     <literal>&lt;target&gt;</literal>
1625     elements.  What does this mean?  Only that the filter will add
1626     multiple <literal>VAL_PROXY</literal> otherInfo packets to the
1627     Search requests that pass through it.  That's because the virtual
1628     DB filter is dumb, and does exactly what it's told - no more, no
1629     less.
1630     If a Search request with multiple <literal>VAL_PROXY</literal>
1631     otherInfo packets reaches a <literal>z3950_client</literal>
1632     filter, this is an error.  That filter doesn't know how to deal
1633     with multiple targets, so it will either just pick one and search
1634     in it, or (better) fail with an error message.
1635    </para>
1636    <para>
1637     The <literal>multi</literal> filter comes to the rescue!  This is
1638     the only filter that knows how to deal with multiple
1639     <literal>VAL_PROXY</literal> otherInfo packets, and it does so by
1640     making multiple copies of the entire Search request: one for each
1641     <literal>VAL_PROXY</literal>.  Each of these new copies is then
1642     passed down through the remaining filters in the route.  (The
1643     copies are handled in parallel though the
1644     spawning of new threads.)  Since the copies each have only one
1645     <literal>VAL_PROXY</literal> otherInfo, they can be handled by the
1646     <literal>z3950_client</literal> filter, which happily deals with
1647     each one individually.  When the results of the individual
1648     searches come back up to the <literal>multi</literal> filter, it
1649     merges them into a single Search response, which is what
1650     eventually makes it back to the client.
1651    </para>
1652
1653     <mediaobject>
1654      <imageobject>
1655       <imagedata fileref="multi.pdf" format="PDF" scale="50"/>
1656      </imageobject>
1657      <imageobject>
1658       <imagedata fileref="multi.png" format="PNG"/>
1659      </imageobject>
1660      <textobject>
1661       <!-- Fall back if none of the images can be used -->
1662       <phrase>
1663        [Here there should be a diagram showing the progress of
1664        packages through the filters during a simple virtual-database
1665        search and a multi-database search, but is seems that your
1666        tool chain has not been able to include the diagram in this
1667        document.]
1668       </phrase>
1669      </textobject>
1670      <caption>
1671       <para>A picture is worth a thousand words (but only five hundred on 64-bit architectures)</para>
1672      </caption>
1673     </mediaobject>
1674   </section>
1675  </chapter>
1676
1677
1678  <chapter id="sru-server">
1679   <title>Combined SRU webservice and Z39.50 server configuration</title>
1680   <para>
1681    Metaproxy can act as 
1682    <ulink url="&url.sru;">SRU</ulink> and 
1683    web service server, which translates web service requests to 
1684    <ulink url="&url.z39.50;">ANSI/NISO Z39.50</ulink> packages and
1685    sends them off to common available targets.
1686   </para>
1687   <para>
1688   A typical setup for this operation needs a filter route including the
1689   following modules: 
1690   </para>
1691    
1692   <table id="sru-server-table-config" frame="top">
1693    <title>SRU/Z39.50 Server Filter Route Configuration</title>
1694    <tgroup cols="3">
1695     <thead>
1696      <row>
1697       <entry>Filter</entry>
1698       <entry>Importance</entry>
1699       <entry>Purpose</entry>
1700      </row>
1701     </thead>
1702     
1703     <tbody>
1704      <row>
1705       <entry><literal>frontend_net</literal></entry>
1706       <entry>required</entry>
1707       <entry>Accepting HTTP connections and passing them to following
1708       filters. Since this filter also accepts Z39.50 connections, the
1709       server works as SRU and Z39.50 server on the same port.</entry>
1710      </row>
1711      <row>
1712       <entry><literal>sru_z3950</literal></entry>
1713       <entry>required</entry>
1714       <entry>Accepting SRU GET/POST/SOAP explain and
1715        searchRetrieve requests for the the configured databases.
1716        Explain requests are directly served from the static XML configuration.
1717        SearchRetrieve requests are
1718        transformed  to Z39.50 search and present packages.
1719        All other HTTP and Z39.50 packages are passed unaltered.</entry>
1720      </row>
1721      <row>
1722       <entry><literal>http_file</literal></entry>
1723       <entry>optional</entry>
1724       <entry>Serving HTTP requests from the filesystem. This is only
1725       needed if the server should serve XSLT stylesheets, static HTML
1726       files or Java Script for thin browser based clients.
1727        Z39.50 packages are passed unaltered.</entry>
1728      </row>
1729      <row>
1730       <entry><literal>cql_rpn</literal></entry>
1731       <entry>required</entry>
1732       <entry>Usually, Z39.50 servers do not talk CQL, hence the
1733       translation of the CQL query language to RPN is mandatory in
1734       most cases. Affects only  Z39.50 search packages.</entry>
1735      </row>
1736      <row>
1737       <entry><literal>record_transform</literal></entry>
1738       <entry>optional</entry>
1739       <entry>Some Z39.50 backend targets can not present XML record
1740       syntaxes in common wanted element sets. using this filter, one
1741       can transform binary MARC records to MARCXML records, and
1742       further transform those to any needed XML schema/format by XSLT
1743       transformations. Changes only  Z39.50 present packages.</entry>
1744      </row>
1745      <row>
1746       <entry><literal>session_shared</literal></entry>
1747       <entry>optional</entry>
1748       <entry>The stateless nature of web services requires frequent
1749       re-searching of the same targets for display of paged result set
1750       records. This might be an unacceptable burden for the accessed
1751       backend Z39.50 targets, and this mosule can be added for
1752       efficient backend target resource pooling.</entry>
1753      </row>
1754      <row>
1755       <entry><literal>z3950_client</literal></entry>
1756       <entry>required</entry>
1757       <entry>Finally, a Z39.50 package sink is needed in the filter
1758       chain to provide the response packages. The Z39.50 client module
1759       is used to access external targets over the network, but any
1760       coming local Z39.50 package sink could be used instead of.</entry>
1761      </row>
1762      <row>
1763       <entry><literal>bounce</literal></entry>
1764       <entry>required</entry>
1765       <entry>Any Metaproxy package arriving here did not do so by
1766       purpose, and is bounced back with connection closure. this
1767       prevents inifinite package hanging inside the SRU server.</entry>
1768      </row>
1769     </tbody>
1770    </tgroup>
1771   </table>
1772   <para> 
1773    A typical minimal example <ulink url="&url.sru;">SRU</ulink>
1774    server configuration file is found in the tarball distribution at 
1775    <literal>etc/config-sru-to-z3950.xml</literal>.
1776   </para> 
1777   <para>
1778    Off course, any other metaproxy modules can be integrated into a
1779    SRU server solution, including, but not limited to, load balancing, 
1780    multiple target querying 
1781    (see  <xref linkend="multidb"/>), and complex RPN query rewrites. 
1782   </para>
1783
1784
1785  </chapter>
1786
1787  <!--
1788  <chapter id="extensions">
1789   <title>Writing extensions for Metaproxy</title>
1790   <para>### To be written</para>
1791  </chapter>
1792  -->
1793
1794
1795
1796  <chapter id="classes">
1797   <title>Classes in the Metaproxy source code</title>
1798
1799
1800   <section id="classes-introductory-notes">
1801    <title>Introductory notes</title>
1802    <para>
1803     <emphasis>Stop!  Do not read this!</emphasis>
1804     You won't enjoy it at all.  You should just skip ahead to
1805     <xref linkend="reference"/>,
1806     which tells
1807     <!-- The remainder of this paragraph is lifted verbatim from
1808     Douglas Adams' _Hitch Hiker's Guide to the Galaxy_, chapter 8 -->
1809     you things you really need to know, like the fact that the
1810     fabulously beautiful planet Bethselamin is now so worried about
1811     the cumulative erosion by ten billion visiting tourists a year
1812     that any net imbalance between the amount you eat and the amount
1813     you excrete whilst on the planet is surgically removed from your
1814     bodyweight when you leave: so every time you go to the lavatory it
1815     is vitally important to get a receipt.
1816    </para>
1817    <para>
1818     This chapter contains documentation of the Metaproxy source code, and is
1819     of interest only to maintainers and developers.  If you need to
1820     change Metaproxy's behavior or write a new filter, then you will most
1821     likely find this chapter helpful.  Otherwise it's a waste of your
1822     good time.  Seriously: go and watch a film or something.
1823     <citetitle>This is Spinal Tap</citetitle> is particularly good.
1824    </para>
1825    <para>
1826     Still here?  OK, let's continue.
1827    </para>
1828    <para>
1829     In general, classes seem to be named big-endianly, so that
1830     <literal>FactoryFilter</literal> is not a filter that filters
1831     factories, but a factory that produces filters; and
1832     <literal>FactoryStatic</literal> is a factory for the statically
1833     registered filters (as opposed to those that are dynamically
1834     loaded).
1835    </para>
1836   </section>
1837
1838   <section id="individual.classes">
1839    <title>Individual classes</title>
1840    <para>
1841     The classes making up the Metaproxy application are here listed by
1842     class-name, with the names of the source files that define them in
1843     parentheses.
1844    </para>
1845
1846    <section id="class-FactoryFilter">
1847     <title><literal>mp::FactoryFilter</literal>
1848      (<filename>factory_filter.cpp</filename>)</title>
1849     <para>
1850      A factory class that exists primarily to provide the
1851      <literal>create()</literal> method, which takes the name of a
1852      filter class as its argument and returns a new filter of that
1853      type.  To enable this, the factory must first be populated by
1854      calling <literal>add_creator()</literal> for static filters (this
1855      is done by the <literal>FactoryStatic</literal> class, see below)
1856      and <literal>add_creator_dyn()</literal> for filters loaded
1857      dynamically.
1858     </para>
1859    </section>
1860
1861    <section id="class-FactoryStatic">
1862     <title><literal>mp::FactoryStatic</literal>
1863      (<filename>factory_static.cpp</filename>)</title>
1864     <para>
1865      A subclass of <literal>FactoryFilter</literal> which is
1866      responsible for registering all the statically defined filter
1867      types.  It does this by knowing about all those filters'
1868      structures, which are listed in its constructor.  Merely
1869      instantiating this class registers all the static classes.  It is
1870      for the benefit of this class that <literal>struct
1871       metaproxy_1_filter_struct</literal> exists, and that all the filter
1872      classes provide a static object of that type.
1873     </para>
1874    </section>
1875
1876    <section id="class-filter-Base">
1877     <title><literal>mp::filter::Base</literal>
1878      (<filename>filter.cpp</filename>)</title>
1879     <para>
1880      The virtual base class of all filters.  The filter API is, on the
1881      surface at least, extremely simple: two methods.
1882      <literal>configure()</literal> is passed an XML DOM tree representing
1883      that part of the configuration file that pertains to this filter
1884      instance, and is expected to walk that tree extracting relevant
1885      information.  And <literal>process()</literal> processes a
1886      package (see below).  That surface simplicity is a bit
1887      misleading, as <literal>process()</literal> needs to know a lot
1888      about the <literal>Package</literal> class in order to do
1889      anything useful.
1890     </para>
1891    </section>
1892
1893    <section id="class-AuthSimple">
1894     <title><literal>mp::filter::AuthSimple</literal>,
1895      <literal>Backend_test</literal>, etc.
1896      (<filename>filter_auth_simple.cpp</filename>,
1897      <filename>filter_backend_test.cpp</filename>, etc.)</title>
1898     <para>
1899      Individual filters.  Each of these is implemented by a header and
1900      a source file, named <filename>filter_*.hpp</filename> and
1901      <filename>filter_*.cpp</filename> respectively.  All the header
1902      files should be pretty much identical, in that they declare the
1903      class, including a private <literal>Rep</literal> class and a
1904      member pointer to it, and the two public methods.
1905     </para>
1906     <para>
1907      The source file for each filter needs to supply:
1908     </para>
1909     <itemizedlist>
1910      <listitem>
1911       <para>
1912        A definition of the private <literal>Rep</literal> class.
1913       </para>
1914      </listitem>
1915      <listitem>
1916       <para>
1917        Some boilerplate constructors and destructors.
1918       </para>
1919      </listitem>
1920      <listitem>
1921       <para>
1922        A <literal>configure()</literal> method that uses the
1923        appropriate XML fragment.
1924       </para>
1925      </listitem>
1926      <listitem>
1927       <para>
1928        Most important, the <literal>process()</literal> method that
1929        does all the actual work.
1930       </para>
1931      </listitem>
1932     </itemizedlist>
1933    </section>
1934
1935    <section id="class-Package">
1936     <title><literal>mp::Package</literal>
1937      (<filename>package.cpp</filename>)</title>
1938     <para>
1939      Represents a package on its way through the series of filters
1940      that make up a route.  This is essentially a Z39.50 or SRU APDU
1941      together with information about where it came from, which is
1942      modified as it passes through the various filters.
1943     </para>
1944    </section>
1945
1946    <section id="class-Pipe">
1947     <title><literal>mp::Pipe</literal>
1948      (<filename>pipe.cpp</filename>)</title>
1949     <para>
1950      This class provides a compatibility layer so that we have an IPC
1951      mechanism that works the same under Unix and Windows.  It's not
1952      particularly exciting.
1953     </para>
1954    </section>
1955
1956    <section id="class-RouterChain">
1957     <title><literal>mp::RouterChain</literal>
1958      (<filename>router_chain.cpp</filename>)</title>
1959     <para>
1960      ### to be written
1961     </para>
1962    </section>
1963
1964    <section id="class-RouterFleXML">
1965     <title><literal>mp::RouterFleXML</literal>
1966      (<filename>router_flexml.cpp</filename>)</title>
1967     <para>
1968      ### to be written
1969     </para>
1970    </section>
1971
1972    <section id="class-Session">
1973     <title><literal>mp::Session</literal>
1974      (<filename>session.cpp</filename>)</title>
1975     <para>
1976      ### to be written
1977     </para>
1978    </section>
1979
1980    <section id="class-ThreadPoolSocketObserver">
1981     <title><literal>mp::ThreadPoolSocketObserver</literal>
1982      (<filename>thread_pool_observer.cpp</filename>)</title>
1983     <para>
1984      ### to be written
1985     </para>
1986    </section>
1987
1988    <section id="class-util">
1989     <title><literal>mp::util</literal>
1990      (<filename>util.cpp</filename>)</title>
1991     <para>
1992      A namespace of various small utility functions and classes,
1993      collected together for convenience.  Most importantly, includes
1994      the <literal>mp::util::odr</literal> class, a wrapper for YAZ's
1995      ODR facilities.
1996     </para>
1997    </section>
1998
1999    <section id="class-xml">
2000     <title><literal>mp::xml</literal>
2001      (<filename>xmlutil.cpp</filename>)</title>
2002     <para>
2003      A namespace of various XML utility functions and classes,
2004      collected together for convenience.
2005     </para>
2006    </section>
2007   </section>
2008
2009
2010   <section id="other.source.files">
2011    <title>Other Source Files</title>
2012    <para>
2013     In addition to the Metaproxy source files that define the classes
2014     described above, there are a few additional files which are
2015     briefly described here:
2016    </para>
2017    <variablelist>
2018     <varlistentry>
2019      <term><literal>metaproxy_prog.cpp</literal></term>
2020      <listitem>
2021       <para>
2022        The main function of the <command>metaproxy</command> program.
2023       </para>
2024      </listitem>
2025     </varlistentry>
2026     <varlistentry>
2027      <term><literal>ex_router_flexml.cpp</literal></term>
2028      <listitem>
2029       <para>
2030        Identical to <literal>metaproxy_prog.cpp</literal>: it's not clear why.
2031       </para>
2032      </listitem>
2033     </varlistentry>
2034     <varlistentry>
2035      <term><literal>test_*.cpp</literal></term>
2036      <listitem>
2037       <para>
2038        Unit-tests for various modules.
2039       </para>
2040      </listitem>
2041     </varlistentry>
2042    </variablelist>
2043    <para>
2044     ### Still to be described:
2045     <literal>ex_filter_frontend_net.cpp</literal>,
2046     <literal>filter_dl.cpp</literal>,
2047     <literal>plainfile.cpp</literal>,
2048     <literal>tstdl.cpp</literal>.
2049    </para>
2050   </section>
2051  </chapter>
2052  
2053  
2054  <reference id="reference">
2055   <title>Reference</title>
2056    <partintro id="reference-introduction">
2057     <para>
2058      The material in this chapter is drawn directly from the individual
2059      manual entries.  In particular, the Metaproxy invocation section is
2060      available using <command>man metaproxy</command>, and the section
2061      on each individual filter is available using the name of the filter
2062      as the argument to the <command>man</command> command.
2063     </para>
2064    </partintro>
2065    &manref;
2066  </reference>
2067
2068 <appendix id="license">
2069  <title>License</title>
2070
2071   <para>
2072    Metaproxy, Copyright &copy; 1995-2010 Index Data.
2073  </para>
2074
2075   <para>
2076    Metaproxy is free software; you can redistribute it and/or modify it under
2077    the terms of the GNU General Public License as published by the Free
2078    Software Foundation; either version 2, or (at your option) any later
2079    version.
2080    </para>
2081
2082   <para>
2083    Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
2084    WARRANTY; without even the implied warranty of MERCHANTABILITY or
2085    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
2086    for more details.
2087   </para>
2088   
2089   <para>
2090    You should have received a copy of the GNU General Public License
2091    along with Metaproxy; see the file LICENSE.  If not, write to the
2092    Free Software Foundation, 
2093    51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2094    </para>
2095   
2096  </appendix>
2097
2098  &gpl2;
2099 </book>
2100
2101  <!-- Keep this comment at the end of the file
2102  Local variables:
2103  mode: sgml
2104  sgml-omittag:t
2105  sgml-shorttag:t
2106  sgml-minimize-attributes:nil
2107  sgml-always-quote-attributes:t
2108  sgml-indent-step:1
2109  sgml-indent-data:t
2110  sgml-parent-document: nil
2111  sgml-local-catalogs: nil
2112  sgml-namecase-general:t
2113  End:
2114  -->