+--- 1.3.13 2011/10/26
+
+Fix Origin class assigment method; was removd by mistake in 1.3.12.
+
+--- 1.3.12 2011/10/26
+
+zoom: database args x-name=value are passed through to backend database.
+
+SRU filter: user may specify session ID that is passed to log entries
+that follows. It is specified by using x-session-id in the SRU arguments.
+
+zoom: fix null pointer reference which would occur for bad url parameter
+inside "torus" or if url was not given.
+
+--- 1.3.11 2011/09/09
+Fix bug in filter session_shared where sessions would not expire
+properly (session ttl). This in turn could make the target close the
+connection before expected and session_shared would return diagnostic
+2: system temporarily available.
+
+--- 1.3.10 2011/09/09
+
+zoom: new target profile setting: sortmap_field. If sortmap_field is given
+the field is mapped to the value for the sortmap. Values not matching
+sortmap_field are passed verbatim.
+
+zoom: new target profile setting: sortStrategy. One of: "z3950", "type7",
+"cql", "sru11" or "embed". The "embed" chooses type-7 or CQL sortby
+depending on whether RPN or CQL is actually sent to the target.
+
--- 1.3.9 2011/08/25
zoom: urlRecipe result is stored in <pz:metadata type="generated-url">.
# Autoconf and automake setup
AC_PREREQ([2.60])
-AC_INIT([metaproxy],[1.3.9],[metaproxy-help@indexdata.dk])
+AC_INIT([metaproxy],[1.3.13],[metaproxy-help@indexdata.dk])
AC_CONFIG_HEADERS([src/config.hpp])
if test -z "$YAZPPLIB"; then
AC_MSG_ERROR([YAZ++ development libraries missing])
fi
-YAZ_DOC
CPPFLAGS="$YAZPPINC $CPPFLAGS"
+AC_MSG_CHECKING([if YAZ is version 4.2.14 or later])
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <yaz/yaz-version.h>]],
+ [[
+#if YAZ_VERSIONL < 0x4020e
+#error too old
+#endif
+]])],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([newer version of YAZ required])]
+)
+YAZ_DOC
ID_BOOST([thread test regex],[1.33])
if test -z "${BOOST_THREAD_LIB}"; then
+metaproxy (1.3.13-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Wed, 26 Oct 2011 20:29:14 +0200
+
+metaproxy (1.3.12-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Wed, 26 Oct 2011 14:00:22 +0200
+
+metaproxy (1.3.11-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Fri, 09 Sep 2011 11:06:56 +0200
+
+metaproxy (1.3.10-1indexdata) unstable; urgency=low
+
+ * Upstream.
+
+ -- Adam Dickmeiss <adam@indexdata.dk> Fri, 09 Sep 2011 09:57:00 +0200
+
metaproxy (1.3.9-1indexdata) unstable; urgency=low
* Upstream.
Maintainer: Adam Dickmeiss <adam@indexdata.dk>
Priority: extra
Build-Depends: debhelper (>= 4),
- libyaz4-dev (>= 4.2.8),
+ libyaz4-dev (>= 4.2.14),
libyazpp4-dev (>= 1.2.7),
libxslt1-dev,
libboost-dev,
dh_fixperms
# dh_perl
# dh_python
- dh_makeshlibs -V 'libmetaproxy4 (>= 1.2.9)'
+ dh_makeshlibs -V 'libmetaproxy4 (>= 1.3.12)'
dh_installdeb
dh_shlibdeps -l debian/libmetaproxy4/usr/lib
dh_gencontrol
unset DISPLAY; ${INKSCAPE} --export-png=$@ --export-area=0:0:1050:500 $?
multi.eps: multi.svg
- unset DISPLAY; ${INKSCAPE} --export-eps=$@ --export-bbox-page $?
+ unset DISPLAY; ${INKSCAPE} --export-eps=$@ --export-area-page $?
.eps.pdf:
epstopdf -hires $?
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<para>
The popular C++ library. Initial versions of Metaproxy
was built with 1.32 but this is no longer supported.
- Metaproxy is known to work with Boost version 1.33 through 1.38.
+ Metaproxy is known to work with Boost version 1.33 through 1.46.
</para>
</listitem>
</varlistentry>
<para>
We have successfully built Metaproxy using the compilers
<ulink url="&url.gcc;">GCC</ulink> version 4.0 and
- <ulink url="&url.vstudio;">Microsoft Visual Studio</ulink> 2003/2005.
+ <ulink url="&url.vstudio;">Microsoft Visual Studio</ulink> 2003/2005/2008.
</para>
<section id="installation.unix">
<screen>
gunzip -c boost-version.tar.gz|tar xf -
cd boost-version
- ./configure --with-libraries=thread,test --with-toolset=gcc
+ ./configure --with-libraries=thread,test,regex --with-toolset=gcc
make
su
make install
However, under the hood bjam is used. You can invoke that with
</para>
<screen>
- ./bjam --toolset=gcc --with-thread --with-test stage
+ ./bjam --toolset=gcc --with-thread --with-test --with-regex stage
</screen>
<para>
Replace <literal>stage</literal> with <literal>clean</literal> /
<para>
There is currently no official Debian package for YAZ++.
And the official Debian package for YAZ is probably too old.
- But Index Data bulds "new" versions of those for Debian (i386 only).
+ But Index Data builds "new" versions of those for Debian (i386, amd64 only).
</para>
<para>
Update the <filename>/etc/apt/sources.list</filename>
apt-get install libboost-dev
apt-get install libboost-thread-dev
apt-get install libboost-test-dev
+ apt-get install libboost-regex-dev
</screen>
<para>
With these packages installed, the usual configure + make
<para>
Metaproxy can be compiled with Microsoft
<ulink url="&url.vstudio;">Visual Studio</ulink>.
- Versions 2003 (C 7.1), 2005 (C 8.0) and 2008 (C 9.0) is known to work.
+ Versions 2003 (C 7.1), 2005 (C 8.0) and 2008 (C 9.0) are known to work.
</para>
<section id="installation.windows.boost">
<title>Boost</title>
<title>YAZ++</title>
<para>
Get <ulink url="&url.yazplusplus;">YAZ++</ulink> as well.
- Version 1.1.0 or later is required.
+ Version 1.2.7 or later is required.
</para>
<para>
YAZ++ includes NMAKE makefiles, similar to those found in the
&gpl2;
</book>
- <!-- Keep this comment at the end of the file
- Local variables:
- mode: sgml
- sgml-omittag:t
- sgml-shorttag:t
- sgml-minimize-attributes:nil
- sgml-always-quote-attributes:t
- sgml-indent-step:1
- sgml-indent-data:t
- sgml-parent-document: nil
- sgml-local-catalogs: nil
- sgml-namecase-general:t
- End:
- -->
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: nxml
+nxml-child-indent: 1
+End:
+-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<productname>Metaproxy</productname>
<info><orgname>Index Data</orgname></info>
</refentryinfo>
-
+
<refmeta>
<refentrytitle>zoom</refentrytitle>
<manvolnum>3mp</manvolnum>
<refpurpose>Metaproxy ZOOM Module</refpurpose>
</refnamediv>
- <refsect1><title>DESCRIPTION</title>
+ <refsect1>
+ <title>DESCRIPTION</title>
<para>
This filter implements a generic client based on
<ulink url="&url.yaz.zoom;">ZOOM</ulink> of YAZ.
The client implements the protocols that ZOOM C does: Z39.50, SRU
(GET, POST, SOAP) and SOLR .
</para>
-
+
<para>
This filter only deals with Z39.50 on input. The following services
are supported: init, search, present and close. The backend target
</refsect1>
- <refsect1><title>CONFIGURATION</title>
- <para>
- The configuration consists of four parts: <literal>torus</literal>,
- <literal>fieldmap</literal>, <literal>cclmap</literal>
- and <literal>log</literal>.
- </para>
- <refsect2><title>torus</title>
- <para>
- The <literal>torus</literal> element specifies target profiles
- and takes the following content:
- </para>
- <variablelist>
- <varlistentry>
- <term>attribute <literal>url</literal></term>
- <listitem>
- <para>
- URL of Web service to be used to fetch target profile
- for a given database (udb). The special sequence
- <literal>%db</literal> of the URL is replaced by the
- actual database specified as part of Search.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>attribute <literal>proxy</literal></term>
- <listitem>
- <para>
- HTTP proxy to bse used for fetching target profiles.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>attribute <literal>xsldir</literal></term>
- <listitem>
- <para>
- Directory that is searched for XSL stylesheets. Stylesheets
- are specified in the target profile by the
- <literal>transform</literal> element.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>attribute <literal>element_transform</literal></term>
- <listitem>
- <para>
- Specifies the element that triggers retrieval and transform using
- the parameters elementSet, recordEncoding, requestSyntax, transform
- from the target profile. Default value
- is "pz2", due to the fact that for historical reasons the
- common format is that used in Pazpar2.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>attribute <literal>element_raw</literal></term>
- <listitem>
- <para>
- Specifies an element that triggers retrieval using the
- parameters elementSet, recordEncoding, requestSyntax from the
- target profile. Same actions as for element_transform, but without
- the XSL transform. Useful for debugging.
- The default value is "raw".
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>element <literal>records</literal></term>
- <listitem>
- <para>
- Local target profiles. This element may includes zero or
- more <literal>record</literal> elements (one per target
- profile). See section TARGET PROFILE.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- <refsect2><title>fieldmap</title>
- <para>
- The <literal>fieldmap</literal> may be specified zero or more times and
- specifies the map from CQL fields to CCL fields and takes the
- following content:
- </para>
- <variablelist>
- <varlistentry>
- <term>attribute <literal>cql</literal></term>
- <listitem>
- <para>
- CQL field that we are mapping "from".
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>attribute <literal>ccl</literal></term>
- <listitem>
- <para>
- CCL field that we are mapping "to".
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- <refsect2><title>cclmap</title>
- <para>
- The third part of the configuration consists of zero or more
- <literal>cclmap</literal> elements that specifies
- <emphasis>base</emphasis> CCL profile to be used for all targets.
- This configuration, thus, will be combined with cclmap-definitions
- from the target profile.
- </para>
- </refsect2>
- <refsect2><title>log</title>
- <para>
- The <literal>log</literal> element controls logging for the
- ZOOM filter.
- </para>
- <variablelist>
- <varlistentry>
- <term>attribute <literal>apdu</literal></term>
- <listitem>
- <para>
- If the value of apdu is "true", then protocol packages
- (APDUs and HTTP packages) from the ZOOM filter will be
- logged to the yaz_log system. A value of "false" will
- not perform logging of protocol packages (the default
- behavior).
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
- <refsect1><title>QUERY HANDLING</title>
- <para>
- The ZOOM filter accepts three query types: RPN(Type-1), CCL and
- CQL.
- </para>
- <para>
- Queries are converted in two separate steps. In the first step
- the input query is converted to RPN/Type-1. This is always
- the common internal format between step 1 and step 2.
- In step 2 the query is converted to the native query type of the target.
- </para>
+ <refsect1>
+ <title>CONFIGURATION</title>
+ <para>
+ The configuration consists of five parts: <literal>torus</literal>,
+ <literal>fieldmap</literal>, <literal>cclmap</literal>,
+ <literal>contentProxy</literal> and <literal>log</literal>.
+ </para>
+ <refsect2>
+ <title>torus</title>
<para>
- Step 1: for RPN, the query is passed unmodified to the target.
+ The <literal>torus</literal> element specifies target profiles
+ and takes the following content:
</para>
+ <variablelist>
+ <varlistentry>
+ <term>attribute <literal>url</literal></term>
+ <listitem>
+ <para>
+ URL of Web service to be used to fetch target profile
+ for a given database (udb). The special sequence
+ <literal>%db</literal> of the URL is replaced by the
+ actual database specified as part of Search.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>proxy</literal></term>
+ <listitem>
+ <para>
+ HTTP proxy to bse used for fetching target profiles.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>xsldir</literal></term>
+ <listitem>
+ <para>
+ Directory that is searched for XSL stylesheets. Stylesheets
+ are specified in the target profile by the
+ <literal>transform</literal> element.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>element_transform</literal></term>
+ <listitem>
+ <para>
+ Specifies the element that triggers retrieval and transform using
+ the parameters elementSet, recordEncoding, requestSyntax, transform
+ from the target profile. Default value
+ is "pz2", due to the fact that for historical reasons the
+ common format is that used in Pazpar2.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>element_raw</literal></term>
+ <listitem>
+ <para>
+ Specifies an element that triggers retrieval using the
+ parameters elementSet, recordEncoding, requestSyntax from the
+ target profile. Same actions as for element_transform, but without
+ the XSL transform. Useful for debugging.
+ The default value is "raw".
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>element <literal>records</literal></term>
+ <listitem>
+ <para>
+ Local target profiles. This element may includes zero or
+ more <literal>record</literal> elements (one per target
+ profile). See section TARGET PROFILE.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+ <refsect2 id="fieldmap">
+ <title>fieldmap</title>
<para>
- Step 1: for CCL, the query is converted to RPN via
- <literal>cclmap</literal> elements part of the target profile.
+ The <literal>fieldmap</literal> may be specified zero or more times and
+ specifies the map from CQL fields to CCL fields and takes the
+ following content:
</para>
+ <variablelist>
+ <varlistentry>
+ <term>attribute <literal>cql</literal></term>
+ <listitem>
+ <para>
+ CQL field that we are mapping "from".
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>ccl</literal></term>
+ <listitem>
+ <para>
+ CCL field that we are mapping "to".
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+ <refsect2 id="cclmap_base">
+ <title>cclmap</title>
<para>
- Step 1: For CQL, the query is converted to CCL. The mappings of
- CQL fields to CCL fields are handled by <literal>fieldmap</literal>
- elements as part of the target profile. The resulting query, CCL,
- is the converted to RPN using the schema mentioned earlier (via
- <literal>cclmap</literal>).
+ The third part of the configuration consists of zero or more
+ <literal>cclmap</literal> elements that specifies
+ <emphasis>base</emphasis> CCL profile to be used for all targets.
+ This configuration, thus, will be combined with cclmap-definitions
+ from the target profile.
</para>
+ </refsect2>
+ <refsect2>
+ <title>contentProxy</title>
<para>
- Step 2: If the target is Z39.50-based, it is passed verbatim (RPN).
- If the target is SRU-based, the RPN will be converted to CQL.
- If the target is SOLR-based, the RPN will be converted to SOLR's query
- type.
+ The <literal>contentProxy</literal> element controls content proxy'in.
+ This section
+ is optional and must only be defined if content proxy'ing is enabled.
</para>
- </refsect1>
-
- <refsect1><title>TARGET PROFILE</title>
+ <variablelist>
+ <varlistentry>
+ <term>attribute <literal>server</literal></term>
+ <listitem>
+ <para>
+ Specifies the content proxy host. The host is of the form
+ host[:port]. That is without a method (such as HTTP) and optional
+ port number.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>tmp_file</literal></term>
+ <listitem>
+ <para>
+ Specifies a filename of a session file for content proxy'ing. The
+ file should be an absolute filename that includes
+ <literal>XXXXXX</literal> which is replaced by a unique filename
+ using the mkstemp(3) system call. The default value of this
+ setting is <literal>/tmp/cf.XXXXXX.p</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+ <refsect2>
+ <title>log</title>
<para>
- The following elements are honored by the ZOOM module of Metaproxy.
- Note that unknown elements are silently ignored. There are several
- elements in use that makes no sense to the ZOOM module.
+ The <literal>log</literal> element controls logging for the
+ ZOOM filter.
</para>
<variablelist>
- <varlistentry>
- <term>authentication</term><listitem>
- <para>
- Authentication parameters to be sent to the target. For
- Z39.50 targets, this will be sent as part of the
- Init Request.
- </para>
- <para>
- If this value is omitted or empty, not authentication information
- is simply omitted.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>attribute <literal>apdu</literal></term>
+ <listitem>
+ <para>
+ If the value of apdu is "true", then protocol packages
+ (APDUs and HTTP packages) from the ZOOM filter will be
+ logged to the yaz_log system. A value of "false" will
+ not perform logging of protocol packages (the default
+ behavior).
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+ </refsect1>
+ <refsect1>
+ <title>QUERY HANDLING</title>
+ <para>
+ The ZOOM filter accepts three query types: RPN(Type-1), CCL and
+ CQL.
+ </para>
+ <para>
+ Queries are converted in two separate steps. In the first step
+ the input query is converted to RPN/Type-1. This is always
+ the common internal format between step 1 and step 2.
+ In step 2 the query is converted to the native query type of the target.
+ </para>
+ <para>
+ Step 1: for RPN, the query is passed un-modified to the target.
+ </para>
+ <para>
+ Step 1: for CCL, the query is converted to RPN via
+ <link linkend="cclmap"><literal>cclmap</literal></link> elements part of
+ the target profile as well as
+ <link linkend="cclmap_base">base CCL maps</link>.
+ </para>
+ <para>
+ Step 1: For CQL, the query is converted to CCL. The mappings of
+ CQL fields to CCL fields are handled by
+ <link linkend="fieldmap"><literal>fieldmap</literal></link>
+ elements as part of the target profile. The resulting query, CCL,
+ is the converted to RPN using the schema mentioned earlier (via
+ <literal>cclmap</literal>).
+ </para>
+ <para>
+ Step 2: If the target is Z39.50-based, it is passed verbatim (RPN).
+ If the target is SRU-based, the RPN will be converted to CQL.
+ If the target is SOLR-based, the RPN will be converted to SOLR's query
+ type.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SORTING</title>
+ <para>
+ The ZOOM module actively handle CQL sorting - using the SORTBY parameter
+ which was introduced in SRU version 1.2. The conversion from SORTBY clause
+ to native sort for some target is driven by the two parameters:
+ <link linkend="sortStrategy"><literal>sortStrategy</literal></link>
+ and <link linkend="sortmap"><literal>sortmap_</literal><replaceable>field</replaceable></link>.
+ </para>
+ <para>
+ If a sort field that does not have an equivalent
+ <literal>sortmap_</literal>-mapping is passed un-modified through the
+ conversion. It doesn't throw a diagnostic.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>TARGET PROFILE</title>
+ <para>
+ The ZOOM module is driven by a number of settings that specifies how
+ to handle each target.
+ Note that unknown elements are silently <emphasis>ignored</emphasis>.
+ </para>
+ <para>
+ The elements, in alphabetical order, are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term>authentication</term><listitem>
+ <para>
+ Authentication parameters to be sent to the target. For
+ Z39.50 targets, this will be sent as part of the
+ Init Request.
+ </para>
+ <para>
+ If this value is omitted or empty no authentication information is sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="cclmap">
+ <term>cclmap_<replaceable>field</replaceable></term><listitem>
+ <para>
+ This value specifies CCL field (qualifier) definition for some
+ field. For Z39.50 targets this most likely will specify the
+ mapping to a numeric use attribute + a structure attribute.
+ For SRU targets, the use attribute should be string based, in
+ order to make the RPN to CQL conversion work properly (step 2).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>cfAuth</term><listitem>
+ <para>
+ When cfAuth is defined, its value will be used as authentication
+ to backend target and authentication setting will be specified
+ as part of a database. This is like a "proxy" for authentication and
+ is used for Connector Framework based targets.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>piggyback</term><listitem>
- <para>
- A value of 1/true is a hint to the ZOOM module that this Z39.50
- target supports piggyback searches, ie Search Response with
- records. Any other value (false) will prevent the ZOOM module
- to make use of piggyback (all records part of Present Response).
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>cfProxy</term><listitem>
+ <para>
+ Specifies HTTP proxy for the target in the form
+ <replaceable>host</replaceable>:<replaceable>port</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>queryEncoding</term><listitem>
- <para>
- If this value is defined, all queries will be converted
- to this encoding. This should be used for all Z39.50 targets that
- do not use UTF-8 for query terms.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>cfSubDb</term><listitem>
+ <para>
+ Specifies sub database for a Connector Framework based target.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>udb</term><listitem>
- <para>
- This value is required and specifies the unique database for
- this profile . All target profiles should hold a unique database.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry id="contentConnector">
+ <term>contentConnector</term><listitem>
+ <para>
+ Specifies a database for content-based proxy'ing.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>cclmap_*</term><listitem>
- <para>
- This value specifies CCL field (qualifier) definition for some
- field. For Z39.50 targets this most likely will specify the
- mapping to a numeric use attribute + a structure attribute.
- For SRU targets, the use attribute should be string based, in
- order to make the RPN to CQL conversion work properly (step 2).
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>elementSet</term><listitem>
+ <para>
+ Specifies the elementSet to be sent to the target if record
+ transform is enabled (not to be confused' with the record_transform
+ module). The record transform is enabled only if the client uses
+ record syntax = XML and a element set determined by
+ the <literal>element_transform</literal> /
+ <literal>element_raw</literal> from the configuration.
+ By default that is the element sets <literal>pz2</literal>
+ and <literal>raw</literal>.
+ If record transform is not enabled, this setting is
+ not used and the element set specified by the client
+ is passed verbatim.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>elementSet</term><listitem>
- <para>
- Specifies the elementSet to be sent to the target if record
- transform is enabled (not to be confused' with the record_transform
- module). The record transform is enabled only if the client uses
- record syntax = XML and a element set determined by
- the <literal>element_transform</literal> /
- <literal>element_raw</literal> from the configuration.
- By default that is the element sets <literal>pz2</literal>
- and <literal>raw</literal>.
- If record transform is not enabled, this setting is
- not used and the element set specified by the client
- is passed verbatim.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>literalTransform</term><listitem>
+ <para>
+ Specifies a XSL stylesheet to be used if record
+ transform is anabled; see description of elementSet.
+ The XSL transform is only used if the element set is set to the
+ value of <literal>element_transform</literal> in the configuration.
+ </para>
+ <para>
+ The value of literalTransform is the XSL - string encoded.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>piggyback</term><listitem>
+ <para>
+ A value of 1/true is a hint to the ZOOM module that this Z39.50
+ target supports piggyback searches, ie Search Response with
+ records. Any other value (false) will prevent the ZOOM module
+ to make use of piggyback (all records part of Present Response).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>queryEncoding</term><listitem>
+ <para>
+ If this value is defined, all queries will be converted
+ to this encoding. This should be used for all Z39.50 targets that
+ do not use UTF-8 for query terms.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>recordEncoding</term><listitem>
+ <para>
+ Specifies the character encoding of records that are returned
+ by the target. This is primarily used for targets were records
+ are not UTF-8 encoded already. This setting is only used
+ if the record transform is enabled (see description of elementSet).
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>recordEncoding</term><listitem>
- <para>
- Specifies the character encoding of records that are returned
- by the target. This is primarily used for targets were records
- are not UTF-8 encoded already. This setting is only used
- if the record transform is enabled (see description of elementSet).
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>requestSyntax</term><listitem>
+ <para>
+ Specifies the record syntax to be specified for the target
+ if record transform is enabled; see description of elementSet.
+ If record transform is not enabled, the record syntax of the
+ client is passed verbatim to the target.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>requestSyntax</term><listitem>
- <para>
- Specifies the record syntax to be specified for the target
- if record transform is enabled; see description of elementSet.
- If record transform is not enabled, the record syntax of the
- client is passed verbatim to the target.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry id="sortmap">
+ <term>sortmap_<replaceable>field</replaceable></term><listitem>
+ <para>
+ This value the native field for a target. The form of the value is
+ given by <link linkend="sortStrategy">sortStrategy</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="sortStrategy">
+ <term>sortStrategy</term><listitem>
+ <para>
+ Specifies sort strategy for a target. One of:
+ <literal>z3950</literal>, <literal>type7</literal>,
+ <literal>cql</literal>, <literal>sru11</literal> or
+ <literal>embed</literal>. The <literal>embed</literal> chooses type-7
+ or CQL sortby depending on whether Type-1 or CQL is
+ actually sent to the target.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>sru</term><listitem>
+ <para>
+ If this setting is set, it specifies that the target is web service
+ based and must be one of : <literal>get</literal>,
+ <literal>post</literal>, <literal>soap</literal>
+ or <literal>solr</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>sru</term><listitem>
- <para>
- If this setting is set, it specifies that the target is web service
- based and must be one of : <literal>get</literal>,
- <literal>post</literal>, <literal>soap</literal>
- or <literal>solr</literal>.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>transform</term><listitem>
+ <para>
+ Specifies a XSL stylesheet filename to be used if record
+ transform is anabled; see description of elementSet.
+ The XSL transform is only used if the element set is set to the
+ value of <literal>element_transform</literal> in the configuration.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>transform</term><listitem>
- <para>
- Specifies a XSL stylesheet filename to be used if record
- transform is anabled; see desciprion of elementSet.
- The XSL transform is only used if the element set is set to the
- value of <literal>element_transform</literal> in the configuration.
- </para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>udb</term><listitem>
+ <para>
+ This value is required and specifies the unique database for
+ this profile . All target profiles should hold a unique database.
+ </para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
- <term>zurl</term><listitem>
- <para>
- This is setting is mandatory and specifies the ZURL of the
- target in the form of host/database. The HTTP method should
- not be provide as this is guessed from the "sru" attribute value.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
+ <varlistentry id="urlRecipe">
+ <term>urlRecipe</term><listitem>
+ <para>
+ The value of this field is a string that generates a dynamic link
+ based on record content. If the resulting string is non-zero in length
+ a new field, <literal>metadata</literal> with attribute
+ <literal>type="generated-url"</literal>.
+ The contents of this field is the result of the URL recipe conversion.
+ The urlRecipe value may refer to an existing metadata element by
+ ${field[pattern/result/flags]}, which will take content
+ of field and perform a regular expression conversion using the pattern
+ given. For example: <literal>${md-title[\s+/+/g]}</literal> takes
+ metadadata element <literal>title</literal> and converts one or more
+ spaces to a plus character.
+ </para>
+ <para>
+ If the <link linkend="contentConnector">contentConnector</link>
+ setting also defined, the resulting value is
+ augmented with a session string as well as the content proxy server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zurl</term><listitem>
+ <para>
+ This is setting is mandatory and specifies the ZURL of the
+ target in the form of host/database. The HTTP method should
+ not be provided as this is guessed from the "sru" attribute value.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
- <refsect1><title>SCHEMA</title>
- <literallayout><xi:include
- xi:href="../xml/schema/filter_zoom.rnc"
- xi:parse="text"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
- </literallayout>
+ <refsect1>
+ <title>SCHEMA</title>
+ <literallayout><xi:include
+ xi:href="../xml/schema/filter_zoom.rnc"
+ xi:parse="text"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </literallayout>
</refsect1>
- <refsect1><title>EXAMPLES</title>
+ <refsect1>
+ <title>EXAMPLES</title>
<para>
The following configuration illustrates most of the
facilities:
]]>
</screen>
</para>
-
+
</refsect1>
- <refsect1><title>SEE ALSO</title>
+ <refsect1>
+ <title>SEE ALSO</title>
<para>
<citerefentry>
<refentrytitle>metaproxy</refentrytitle>
<!-- Keep this comment at the end of the file
Local variables:
-mode: sgml
-sgml-omittag:t
-sgml-shorttag:t
-sgml-minimize-attributes:nil
-sgml-always-quote-attributes:t
-sgml-indent-step:1
-sgml-indent-data:t
-sgml-parent-document:nil
-sgml-local-catalogs: nil
-sgml-namecase-general:t
+mode: nxml
+nxml-child-indent: 1
End:
-->
<sru>get</sru>
<transform>tmarc.xsl</transform>
<zurl>localhost:9998/db01</zurl>
+ <sortStrategy>embed</sortStrategy>
+ <sortmap_title>dc.title</sortmap_title>
</record>
<!-- jstor1 -->
}
namespace std {
- std::ostream& operator<<(std::ostream& os, metaproxy_1::Origin& o);
+ std::ostream& operator<<(std::ostream& os, const metaproxy_1::Origin& o);
}
namespace metaproxy_1 {
class Origin {
public:
- Origin(std::string listen_host = "", unsigned int listen_port = 0);
+ Origin();
- /// get function - right val in assignment
- std::string listen_host() const;
-
- /// set function - left val in assignment
- std::string & listen_host();
-
- /// get function - right val in assignment
- unsigned int listen_port() const;
-
- /// set function - left val in assignment
- unsigned int & listen_port();
-
/// set client IP info - left val in assignment
void set_tcpip_address(std::string addr, unsigned long id);
/// get tcpip address
std::string get_address();
+
+ void set_custom_session(const std::string &s);
private:
friend std::ostream&
- std::operator<<(std::ostream& os, metaproxy_1::Origin& o);
+ std::operator<<(std::ostream& os, const metaproxy_1::Origin& o);
- enum origin_t {
- API,
- UNIX,
- TCPIP
- } m_type;
- std::string m_address; // UNIX+TCPIP
+ std::string m_address;
unsigned int m_origin_id;
- std::string m_listen_host;
- unsigned int m_listen_port;
int m_max_sockets;
+ std::string m_custom_session;
};
-
}
-
-
#endif
/*
* Local variables:
namespace std
{
- std::ostream& operator<<(std::ostream& os, metaproxy_1::Package& p);
+ std::ostream& operator<<(std::ostream& os, const metaproxy_1::Package& p);
}
namespace metaproxy_1 {
/// get function - right val in assignment
Origin origin() const;
-
+
/// set function - left val in assignment
Origin & origin();
/// set function - can be chained
- Package & origin(const Origin & origin);
-
- /// set function - can be chained
Package & router(const Router &router);
yazpp_1::GDU &request();
/// get function - right val in assignment
Session session() const;
-
+
+ void log(const char *module, int level, const char *fmt, ...) const;
private:
Session m_session;
Origin m_origin;
Summary: Z39.50/SRU router
Name: metaproxy
-Version: 1.3.9
+Version: 1.3.13
Release: 1indexdata
License: GPL
Group: Applications/Internet
Source: metaproxy-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
Prefix: %{_prefix} /etc/metaproxy
-BuildRequires: pkgconfig, libyaz4-devel >= 4.2.8, libyazpp4-devel >= 1.2.7
+BuildRequires: pkgconfig, libyaz4-devel >= 4.2.14, libyazpp4-devel >= 1.2.7
BuildRequires: libxslt-devel, boost-devel
Packager: Adam Dickmeiss <adam@indexdata.dk>
URL: http://www.indexdata.com/metaproxy
#include <sstream>
-//#include "config.hpp"
-//#include "filter.hpp"
-
-//#include <boost/thread/mutex.hpp>
-
-
-
-
-
namespace mp = metaproxy_1;
namespace yf = mp::filter;
#undef max
#endif
-//#include <iostream>
#include <list>
#include <map>
#include <limits>
time_t m_time_last_use;
mp::Package * m_close_package;
~BackendInstance();
+ void timestamp();
};
// backends of some class (all with same InitKey)
class SessionShared::BackendClass : boost::noncopyable {
void yf::SessionShared::BackendClass::use_backend(BackendInstancePtr backend)
{
backend->m_in_use = true;
- time(&backend->m_time_last_use);
backend->m_sequence_this = m_sequence_top++;
}
+void yf::SessionShared::BackendInstance::timestamp()
+{
+ assert(m_in_use);
+ time(&m_time_last_use);
+}
+
yf::SessionShared::BackendInstance::~BackendInstance()
{
delete m_close_package;
else
result_set_id = "default";
}
+ found_backend->timestamp();
+
// we must search ...
BackendSetPtr new_set(new BackendSet(result_set_id,
databases, query));
bc->release_backend(found_backend);
return;
}
+
+ found_backend->timestamp();
Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest);
Z_PresentRequest *p_req = p_apdu->u.presentRequest;
else
{
Package scan_package(backend->m_session, frontend_package.origin());
+ backend->timestamp();
scan_package.copy_filter(frontend_package);
scan_package.request() = apdu_req;
scan_package.move();
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
- xt.sec += 30;
+ xt.sec += m_session_ttl / 3;
boost::thread::sleep(xt);
BackendClassMap::const_iterator b_it = m_backend_map.begin();
{
package.origin().set_max_sockets(atoi(arg->value));
}
+ else if (!strcmp(arg->name, "x-session-id"))
+ {
+ package.origin().set_custom_session(arg->value);
+ }
assert(sru_pdu_req);
#include <yaz/log.h>
#include <yaz/zgdu.h>
#include <yaz/querytowrbuf.h>
-
-#define ZOOM_SORTBY2 0
-
-#if ZOOM_SORTBY2
#include <yaz/sortspec.h>
-#endif
+#include <yaz/tokenizer.h>
namespace mp = metaproxy_1;
namespace yf = mp::filter;
std::string transform_xsl_content;
std::string urlRecipe;
std::string contentConnector;
+ std::string sortStrategy;
bool use_turbomarc;
bool piggyback;
CCL_bibset ccl_bibset;
+ std::map<std::string, std::string> sortmap;
Searchable(CCL_bibset base);
~Searchable();
};
void handle_package(mp::Package &package);
void handle_search(mp::Package &package);
void handle_present(mp::Package &package);
- BackendPtr get_backend_from_databases(std::string &database,
+ BackendPtr get_backend_from_databases(const mp::Package &package,
+ std::string &database,
int *error,
char **addinfo,
ODR odr);
{
piggyback = true;
use_turbomarc = true;
+ sortStrategy = "embed";
ccl_bibset = ccl_qual_dup(base);
}
ccl_qual_fitem(s->ccl_bibset, value.c_str(),
(const char *) ptr->name + 7);
}
+ else if (!strncmp((const char *) ptr->name,
+ "sortmap_", 8))
+ {
+ std::string value = mp::xml::get_text(ptr);
+ s->sortmap[(const char *) ptr->name + 8] = value;
+ }
+ else if (!strcmp((const char *) ptr->name,
+ "sortStrategy"))
+ {
+ s->sortStrategy = mp::xml::get_text(ptr);
+ }
}
return s;
}
}
yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases(
+ const mp::Package &package,
std::string &database, int *error, char **addinfo, ODR odr)
{
std::list<BackendPtr>::const_iterator map_it;
it = m_p->s_map.find(torus_db);
if (it != m_p->s_map.end())
sptr = it->second;
- else
+ else if (m_p->torus_url.length() > 0)
{
xmlDoc *doc = mp::get_searchable(m_p->torus_url, torus_db, m_p->proxy);
if (!doc)
const char *param_user = 0;
const char *param_password = 0;
const char *param_proxy = 0;
+ char *x_args = 0; // all x-args to be passed to backend
+
if (db_args.length())
{
+
char **names;
char **values;
- int i;
int no_parms = yaz_uri_to_array(db_args.c_str(),
odr, &names, &values);
+ const char **x_names = (const char **)
+ odr_malloc(odr, (1 + no_parms) * sizeof(*x_names));
+ const char **x_values = (const char **)
+ odr_malloc(odr, (1 + no_parms) * sizeof(*x_values));
+ int no_x_names = 0;
+ int i;
for (i = 0; i < no_parms; i++)
{
const char *name = names[i];
const char *value = values[i];
+ assert(name);
+ assert(value);
if (!strcmp(name, "user"))
param_user = value;
else if (!strcmp(name, "password"))
param_proxy = value;
else if (!strcmp(name, "cproxysession"))
;
+ else if (name[0] == 'x' && name[1] == '-')
+ {
+ x_names[no_x_names] = name;
+ x_values[no_x_names] = value;
+ no_x_names++;
+ }
else
{
BackendPtr notfound;
return notfound;
}
}
+ if (no_x_names)
+ {
+ x_names[no_x_names] = 0; // terminate list
+ yaz_array_to_uri(&x_args, odr, (char **) x_names,
+ (char **) x_values);
+ }
if (param_user)
{
authentication = std::string(param_user);
}
else
{
- db_args.clear(); // no arguments to be passed (non-CF)
+ db_args.clear(); // Only x-args to be passed (non-CF)
+ if (x_args)
+ db_args = x_args;
size_t found = authentication.find('/');
FILE *file = fopen(fname, "w");
if (!file)
{
- yaz_log(YLOG_WARN|YLOG_ERRNO, "create %s", fname);
+ package.log("zoom", YLOG_WARN|YLOG_ERRNO, "create %s", fname);
*error = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
*addinfo = (char *) odr_malloc(odr, 40 + strlen(fname));
sprintf(*addinfo, "Could not create %s", fname);
fwrite(wrbuf_buf(w), 1, wrbuf_len(w), file);
fclose(file);
- yaz_log(YLOG_LOG, "file %s created\n", fname);
+ package.log("zoom", YLOG_LOG, "file %s created\n", fname);
xfree(fname);
}
}
if (db_args.length())
url += "," + db_args;
- yaz_log(YLOG_LOG, "url=%s", url.c_str());
+ package.log("zoom", YLOG_LOG, "url=%s", url.c_str());
b->connect(url, error, addinfo, odr);
if (*error == 0)
{
return r;
}
-
-#if !ZOOM_SORTBY2
-static void sort_pqf_type_7(WRBUF pqf_wrbuf, const char *sru_sortkeys)
-{
- /* sortkey layour: path,schema,ascending,caseSensitive,missingValue */
- /* see cql_sortby_to_sortkeys of YAZ. */
- char **sortspec;
- int num_sortspec = 0;
- int i;
- NMEM nmem = nmem_create();
-
- if (sru_sortkeys)
- nmem_strsplit_blank(nmem, sru_sortkeys, &sortspec, &num_sortspec);
- if (num_sortspec > 0)
- {
- WRBUF w = wrbuf_alloc();
- for (i = 0; i < num_sortspec; i++)
- {
- char **arg;
- int num_arg;
- int ascending = 1;
- nmem_strsplitx(nmem, ",", sortspec[i], &arg, &num_arg, 0);
-
- if (num_arg > 2 && arg[2][0])
- ascending = atoi(arg[2]);
-
- wrbuf_puts(w, "@or @attr 1=");
- yaz_encode_pqf_term(w, arg[0], strlen(arg[0]));
- wrbuf_printf(w, "@attr 7=%d %d ", ascending ? 1 : 2, i);
- }
- if (wrbuf_len(w))
- {
- wrbuf_puts(w, wrbuf_cstr(pqf_wrbuf));
- wrbuf_rewind(pqf_wrbuf);
- wrbuf_puts(pqf_wrbuf, wrbuf_cstr(w));
- }
- wrbuf_destroy(w);
- }
- nmem_destroy(nmem);
-}
-#endif
-
-#if !ZOOM_SORTBY2
-static void sort_via_cql(WRBUF cql_sortby, const char *sru_sortkeys)
-{
- /* sortkey layour: path,schema,ascending,caseSensitive,missingValue */
- /* see cql_sortby_to_sortkeys of YAZ. */
- char **sortspec;
- int num_sortspec = 0;
- int i;
- NMEM nmem = nmem_create();
-
- if (sru_sortkeys)
- nmem_strsplit_blank(nmem, sru_sortkeys, &sortspec, &num_sortspec);
- if (num_sortspec > 0)
- {
- WRBUF w = wrbuf_alloc();
- for (i = 0; i < num_sortspec; i++)
- {
- char **arg;
- int num_arg;
- int ascending = 1;
- int case_sensitive = 0;
- const char *missing = 0;
- nmem_strsplitx(nmem, ",", sortspec[i], &arg, &num_arg, 0);
-
- if (num_arg > 2 && arg[2][0])
- ascending = atoi(arg[2]);
- if (num_arg > 3 && arg[3][0])
- case_sensitive = atoi(arg[3]);
- if (num_arg > 4 && arg[4][0])
- missing = arg[4];
- if (i > 0)
- wrbuf_puts(w, " ");
- else
- wrbuf_puts(w, " sortby ");
- wrbuf_puts(w, arg[0]); /* field */
- wrbuf_puts(w, "/");
- wrbuf_puts(w, ascending ? "ascending" : "descending");
- if (case_sensitive)
- wrbuf_puts(w, "/respectCase");
- if (missing)
- {
- if (!strcmp(missing, "omit"))
- wrbuf_puts(w, "/missingOmit");
- else if (!strcmp(missing, "abort"))
- wrbuf_puts(w, "/missingFail");
- else if (!strcmp(missing, "lowValue"))
- wrbuf_puts(w, "/missingLow");
- else if (!strcmp(missing, "highValue"))
- wrbuf_puts(w, "/missingHigh");
- }
- }
- if (wrbuf_len(w))
- wrbuf_puts(cql_sortby, wrbuf_cstr(w));
- wrbuf_destroy(w);
- }
- nmem_destroy(nmem);
-}
-#endif
-
-#if YAZ_VERSIONL < 0x40206
-static void wrbuf_vp_puts(const char *buf, void *client_data)
-{
- WRBUF b = (WRBUF) client_data;
- wrbuf_puts(b, buf);
-}
-#endif
-
void yf::Zoom::Frontend::handle_search(mp::Package &package)
{
Z_GDU *gdu = package.request().get();
int error = 0;
char *addinfo = 0;
std::string db(sr->databaseNames[0]);
- BackendPtr b = get_backend_from_databases(db, &error, &addinfo, odr);
+ BackendPtr b = get_backend_from_databases(package, db, &error,
+ &addinfo, odr);
if (error)
{
apdu_res =
WRBUF sru_sortkeys_wrbuf = wrbuf_alloc();
cql_sortby_to_sortkeys(cn, wrbuf_vp_puts, sru_sortkeys_wrbuf);
-#if ZOOM_SORTBY2
WRBUF sort_spec_wrbuf = wrbuf_alloc();
yaz_srw_sortkeys_to_sort_spec(wrbuf_cstr(sru_sortkeys_wrbuf),
sort_spec_wrbuf);
- sortkeys.assign(wrbuf_cstr(sort_spec_wrbuf));
- wrbuf_destroy(sort_spec_wrbuf);
-#else
- sortkeys.assign(wrbuf_cstr(sru_sortkeys_wrbuf));
-#endif
wrbuf_destroy(sru_sortkeys_wrbuf);
+
+ yaz_tok_cfg_t tc = yaz_tok_cfg_create();
+ yaz_tok_parse_t tp =
+ yaz_tok_parse_buf(tc, wrbuf_cstr(sort_spec_wrbuf));
+ yaz_tok_cfg_destroy(tc);
+
+ /* go through sortspec and map fields */
+ int token = yaz_tok_move(tp);
+ while (token != YAZ_TOK_EOF)
+ {
+ if (token == YAZ_TOK_STRING)
+ {
+ const char *field = yaz_tok_parse_string(tp);
+ std::map<std::string,std::string>::iterator it;
+ it = b->sptr->sortmap.find(field);
+ if (it != b->sptr->sortmap.end())
+ sortkeys += it->second;
+ else
+ sortkeys += field;
+ }
+ sortkeys += " ";
+ token = yaz_tok_move(tp);
+ if (token == YAZ_TOK_STRING)
+ {
+ sortkeys += yaz_tok_parse_string(tp);
+ }
+ if (token != YAZ_TOK_EOF)
+ {
+ sortkeys += " ";
+ token = yaz_tok_move(tp);
+ }
+ }
+ yaz_tok_parse_destroy(tp);
+ wrbuf_destroy(sort_spec_wrbuf);
}
cql_parser_destroy(cp);
if (r)
assert(pqf_wrbuf == 0);
int cerror, cpos;
struct ccl_rpn_node *cn;
- yaz_log(YLOG_LOG, "CCL: %s", wrbuf_cstr(ccl_wrbuf));
+ package.log("zoom", YLOG_LOG, "CCL: %s", wrbuf_cstr(ccl_wrbuf));
cn = ccl_find_str(b->sptr->ccl_bibset, wrbuf_cstr(ccl_wrbuf),
&cerror, &cpos);
wrbuf_destroy(ccl_wrbuf);
}
pqf_wrbuf = wrbuf_alloc();
ccl_pquery(pqf_wrbuf, cn);
- yaz_log(YLOG_LOG, "RPN: %s", wrbuf_cstr(pqf_wrbuf));
+ package.log("zoom", YLOG_LOG, "RPN: %s", wrbuf_cstr(pqf_wrbuf));
ccl_rpn_delete(cn);
}
assert(pqf_wrbuf);
ZOOM_query q = ZOOM_query_create();
-#if ZOOM_SORTBY2
- ZOOM_query_sortby2(q, "embed", sortkeys.c_str());
-#endif
+ ZOOM_query_sortby2(q, b->sptr->sortStrategy.c_str(), sortkeys.c_str());
if (b->get_option("sru"))
{
status = cql_transform_rpn2cql_wrbuf(cqlt, wrb, zquery);
cql_transform_close(cqlt);
-#if !ZOOM_SORTBY2
- if (status == 0)
- sort_via_cql(wrb, sortkeys.c_str());
-#endif
}
if (status == 0)
{
ZOOM_query_cql(q, wrbuf_cstr(wrb));
- yaz_log(YLOG_LOG, "CQL: %s", wrbuf_cstr(wrb));
+ package.log("zoom", YLOG_LOG, "CQL: %s", wrbuf_cstr(wrb));
b->search(q, &hits, &error, &addinfo, odr);
}
ZOOM_query_destroy(q);
}
else
{
-#if !ZOOM_SORTBY2
- sort_pqf_type_7(pqf_wrbuf, sortkeys.c_str());
-#endif
ZOOM_query_prefix(q, wrbuf_cstr(pqf_wrbuf));
- yaz_log(YLOG_LOG, "search PQF: %s", wrbuf_cstr(pqf_wrbuf));
+ package.log("zoom", YLOG_LOG, "search PQF: %s", wrbuf_cstr(pqf_wrbuf));
b->search(q, &hits, &error, &addinfo, odr);
ZOOM_query_destroy(q);
wrbuf_destroy(pqf_wrbuf);
namespace mp = metaproxy_1;
-mp::Origin::Origin(std::string listen_host,
- unsigned int listen_port)
- : m_type(API), m_address(""), m_origin_id(0),
- m_listen_host(listen_host), m_listen_port(listen_port), m_max_sockets(0)
+mp::Origin::Origin() : m_address(""), m_origin_id(0), m_max_sockets(0)
{
}
-std::string mp::Origin::listen_host() const
-{
- return m_listen_host;
-};
-
-std::string & mp::Origin::listen_host()
-{
- return m_listen_host;
-};
-
-unsigned int mp::Origin::listen_port() const
-{
- return m_listen_port;
-};
-
-unsigned int & mp::Origin::listen_port()
-{
- return m_listen_port;
-};
-
void mp::Origin::set_max_sockets(int max_sockets)
{
m_max_sockets = max_sockets;
void mp::Origin::set_tcpip_address(std::string addr, unsigned long s)
{
- m_type = TCPIP;
m_address = addr;
m_origin_id = s;
}
+void mp::Origin::set_custom_session(const std::string &s)
+{
+ m_custom_session = s;
+}
+
std::string mp::Origin::get_address()
{
return m_address;
}
-std::ostream& std::operator<<(std::ostream& os, mp::Origin& o)
+std::ostream& std::operator<<(std::ostream& os, const mp::Origin& o)
{
- if (o.m_address != "")
+ if (o.m_address.length())
os << o.m_address;
else
os << "0";
os << ":" << o.m_origin_id;
+ if (o.m_custom_session.length())
+ os << ":" << o.m_custom_session;
return os;
}
#include "config.hpp"
#include <metaproxy/package.hpp>
+#include <yaz/snprintf.h>
+#include <yaz/log.h>
-#include <iostream>
+#include <sstream>
namespace mp = metaproxy_1;
{
return m_origin;
}
-
+
mp::Origin & mp::Package::origin()
{
return m_origin;
}
-mp::Package & mp::Package::origin(const Origin & origin)
-{
- m_origin = origin;
- return *this;
-}
-
mp::Package & mp::Package::router(const mp::Router &router)
{
m_route_pos = router.createpos();
return m_session;
}
-std::ostream& std::operator<<(std::ostream& os, mp::Package& p)
+std::ostream& std::operator<<(std::ostream& os, const mp::Package& p)
{
os << p.origin() << " ";
os << p.session().id();
return os;
}
+void mp::Package::log(const char *module, int level, const char *fmt, ...) const
+{
+ char buf[4096];
+ va_list ap;
+ va_start(ap, fmt);
+
+ yaz_vsnprintf(buf, sizeof(buf)-30, fmt, ap);
+
+ std::ostringstream os;
+
+ os << module << " " << *this << " " << buf;
+
+ va_end(ap);
+ yaz_log(level, "%s", os.str().c_str());
+}
/*
* Local variables:
#include "config.hpp"
#include <metaproxy/xmlutil.hpp>
+#include <string.h>
#include "router_flexml.hpp"
#include "factory_filter.hpp"
#include "factory_static.hpp"
bool test_only, const char *file_include_path);
void parse_xml_routes(xmlDocPtr doc, const xmlNode *node,
bool test_only, const char *file_include_path);
+ void check_routes_in_filters(const xmlNode *n);
bool m_xinclude;
private:
const char *file_include_path)
{
unsigned int filter_nr = 0;
- while(node && mp::xml::check_element_mp(node, "filter"))
+ while (node && mp::xml::check_element_mp(node, "filter"))
{
filter_nr++;
mp::xml::check_element_mp(node, "route");
unsigned int route_nr = 0;
- while(mp::xml::is_element_mp(node, "route"))
+ while (mp::xml::is_element_mp(node, "route"))
{
route_nr++;
const xmlNode* node3 = mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
unsigned int filter3_nr = 0;
- while(node3 && mp::xml::check_element_mp(node3, "filter"))
+ while (node3 && mp::xml::check_element_mp(node3, "filter"))
{
filter3_nr++;
}
}
+void mp::RouterFleXML::Rep::check_routes_in_filters(const xmlNode *node)
+{
+ while (node)
+ {
+ if (mp::xml::is_element_mp(node, "filter"))
+ {
+ const xmlNode *n =
+ mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
+ while (n)
+ {
+ const struct _xmlAttr *attr;
+ // we assume thar that route attribute is only at one level
+ // below filter.. At least that works for multi and virt_db.
+ for (attr = n->properties; attr; attr = attr->next)
+ {
+ if (!strcmp((const char *) attr->name, "route"))
+ {
+ std::string value;
+
+ if (attr->children && attr->children->type == XML_TEXT_NODE)
+ value = std::string((const char *)attr->children->content);
+
+ std::map<std::string,RouterFleXML::Route>::iterator it;
+ it = m_routes.find(value);
+ if (it == m_routes.end())
+ {
+ throw mp::XMLError("Route '" + value + "' does not exist");
+ }
+ }
+ }
+ n = mp::xml::jump_to_next(n, XML_ELEMENT_NODE);
+ }
+ }
+ node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
+ }
+}
+
void mp::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc,
bool test_only,
const char *file_include_path)
if (mp::xml::check_element_mp(node, "start"))
{
const struct _xmlAttr *attr;
- std::string id_value;
for (attr = node->properties; attr; attr = attr->next)
{
std::string name = std::string((const char *) attr->name);
if (name == "route")
m_start_route = value;
else
- throw mp::XMLError("Only attribute start allowed"
+ throw mp::XMLError("Only attribute route allowed"
" in element 'start'. Got " + name);
}
node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
throw mp::XMLError("Unexpected element "
+ std::string((const char *)node->name));
}
-}
+
+ node = mp::xml::jump_to_children(root, XML_ELEMENT_NODE);
+ while (node)
+ {
+ if (mp::xml::is_element_mp(node, "filters"))
+ check_routes_in_filters(
+ mp::xml::jump_to_children(node,
+ XML_ELEMENT_NODE));
+ else if (mp::xml::is_element_mp(node, "routes"))
+ {
+ const xmlNode* n = mp::xml::jump_to_children(node,
+ XML_ELEMENT_NODE);
+ while (n)
+ {
+ if (mp::xml::is_element_mp(n, "route"))
+ {
+ check_routes_in_filters(
+ mp::xml::jump_to_children(n, XML_ELEMENT_NODE));
+
+ }
+ n = mp::xml::jump_to_next(n, XML_ELEMENT_NODE);
+ }
+ }
+ node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
+ }
+}
mp::RouterFleXML::Rep::Rep() : m_xinclude(false)
{
mp_util::SRUServerInfo sruinfo;
// getting host and port info
- sruinfo.host = package.origin().listen_host();
- sruinfo.port = mp_util::to_string(package.origin().listen_port());
+ sruinfo.host = "localhost";
+ sruinfo.port = "80";
// overwriting host and port info if set from HTTP Host header
Z_GDU *zgdu_req = package.request().get();
0, /* content buf */
0 /* content_len */
);
- if (http_response->code == 200 && http_response->content_buf)
+ if (http_response && http_response->code == 200 &&
+ http_response->content_buf)
doc = xmlParseMemory(http_response->content_buf,
http_response->content_len);
yaz_url_destroy(url_p);
return result;
}
-
/*
* Local variables:
* c-basic-offset: 4
DEBUG=0 # 0 for release, 1 for debug
# Metaproxy version
-VERSION=1.3.9
+VERSION=1.3.13
# YAZ and YAZ++ directories
YAZ_DIR=..\..\yaz
element mp:cfAuth { xsd:string }?,
element mp:cfProxy { xsd:string }?,
element mp:cfSubDb { xsd:string }?,
- element mp:contentConnector { xsd:string }?
+ element mp:contentConnector { xsd:string }?,
+ element mp:sortStrategy { xsd:string }?,
+ element mp:sortmap_author { xsd:string }?,
+ element mp:sortmap_date { xsd:string }?,
+ element mp:sortmap_title { xsd:string }?
}*
}?
}?,