Start work on Torus extension for virt_db
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 31 May 2011 13:29:47 +0000 (15:29 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 31 May 2011 13:29:47 +0000 (15:29 +0200)
etc/Makefile.am
etc/config-torus.xml [new file with mode: 0644]
src/Makefile.am
src/filter_virt_db.cpp
src/filter_virt_db.hpp
src/torus.cpp [new file with mode: 0644]
src/torus.hpp [new file with mode: 0644]
win/makefile
xml/schema/metaproxy.rnc
xml/schema/metaproxy.rng
xml/schema/metaproxy.xsd

index 5d70da1..ec83b73 100644 (file)
@@ -20,6 +20,7 @@ xmlconfig = $(srcdir)/config-bytarget.xml \
     $(srcdir)/config4.xml \
     $(srcdir)/config5.xml \
     $(srcdir)/config-cgi.xml \
+    $(srcdir)/config-torus.xml \
     $(srcdir)/retrieval-info.xml
 
 config = example.simple-auth example.target-auth pqf2pqf.xsl explain.xml
diff --git a/etc/config-torus.xml b/etc/config-torus.xml
new file mode 100644 (file)
index 0000000..1a5310c
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<metaproxy xmlns="http://indexdata.com/metaproxy" version="1.0">
+  <!-- Offers virtual databases .. No authentication -->
+  <start route="start"/>
+  <routes>
+    <route id="start">
+      <filter type="frontend_net">
+        <threads>10</threads>
+        <port>@:9000</port>
+       <timeout>30</timeout>
+      </filter>
+      <filter type="log">
+        <message>F</message>
+       <category session="true" apdu="true"/>
+      </filter>
+      <filter type="virt_db">
+        <torus url="http://localhost:8181/torus2/sample/records"/>
+      </filter>
+      <filter type="log">
+        <message>M</message>
+      </filter>
+      <filter type="multi">
+        <hideunavailable/>
+        <mergetype>roundrobin</mergetype>
+      </filter>
+      <filter type="log">
+        <message>B</message>
+       <category session="true"/>
+      </filter>
+      <filter type="z3950_client">
+        <timeout>30</timeout>
+      </filter>
+      <filter type="bounce"/>
+    </route>
+  </routes>
+</metaproxy>
+
index e7e54f0..ddd779e 100644 (file)
@@ -51,6 +51,7 @@ libmetaproxy_la_SOURCES = \
        session.cpp \
        sru_util.cpp sru_util.hpp \
        thread_pool_observer.cpp thread_pool_observer.hpp \
+       torus.cpp torus.hpp \
        util.cpp \
        xmlutil.cpp 
 
index 8d68ceb..72a9eb6 100644 (file)
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <boost/shared_ptr.hpp>
 
 #include <metaproxy/util.hpp>
+#include "torus.hpp"
 
 #include <yaz/zgdu.h>
 #include <yaz/otherinfo.h>
@@ -115,6 +116,7 @@ namespace metaproxy_1 {
             boost::condition m_cond_session_ready;
             std::map<mp::Session, FrontendPtr> m_clients;
             bool pass_vhosts;
+            mp::Torus torus;
         };
     }
 }
@@ -821,7 +823,6 @@ void yf::VirtualDB::process(mp::Package &package) const
     m_p->release_frontend(package);
 }
 
-
 void mp::filter::VirtualDB::configure(const xmlNode * ptr, bool test_only)
 {
     for (ptr = ptr->children; ptr; ptr = ptr->next)
@@ -856,6 +857,21 @@ void mp::filter::VirtualDB::configure(const xmlNode * ptr, bool test_only)
             std::string route = mp::xml::get_route(ptr);
             add_map_db2targets(database, targets, route);
         }
+        else if (!strcmp((const char *) ptr->name, "torus"))
+        {
+            std::string url;
+            const struct _xmlAttr *attr;
+            for (attr = ptr->properties; attr; attr = attr->next)
+            {
+                if (!strcmp((const char *) attr->name, "url"))
+                    url = mp::xml::get_text(attr->children);
+                else
+                    throw mp::filter::FilterException(
+                        "Bad attribute " + std::string((const char *)
+                                                       attr->name));
+            }
+            m_p->torus.read_searchables(url);
+        }
         else
         {
             throw mp::filter::FilterException
index e4cb028..800bf7f 100644 (file)
@@ -47,6 +47,7 @@ namespace metaproxy_1 {
             void add_map_db2target(std::string db,
                                    std::string target,
                                    std::string route);
+            void read_torus();
         private:
             boost::scoped_ptr<Rep> m_p;
         };
diff --git a/src/torus.cpp b/src/torus.cpp
new file mode 100644 (file)
index 0000000..39f87da
--- /dev/null
@@ -0,0 +1,192 @@
+/* This file is part of Metaproxy.
+   Copyright (C) 2005-2011 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <metaproxy/xmlutil.hpp>
+
+#include <string.h>
+#include <yaz/wrbuf.h>
+#include <yaz/zgdu.h>
+#include <yaz/srw.h>
+#include <yaz/comstack.h>
+
+#include "torus.hpp"
+
+namespace mp = metaproxy_1;
+
+
+static Z_GDU *get_HTTP_Request_url(ODR odr, const char *url)
+{
+    Z_GDU *p = z_get_HTTP_Request(odr);
+    const char *host = url;
+    const char *cp0 = strstr(host, "://");
+    const char *cp1 = 0;
+    if (cp0)
+        cp0 = cp0+3;
+    else
+        cp0 = host;
+    
+    cp1 = strchr(cp0, '/');
+    if (!cp1)
+        cp1 = cp0 + strlen(cp0);
+    
+    if (cp0 && cp1)
+    {
+        char *h = (char*) odr_malloc(odr, cp1 - cp0 + 1);
+        memcpy (h, cp0, cp1 - cp0);
+        h[cp1-cp0] = '\0';
+        z_HTTP_header_add(odr, &p->u.HTTP_Request->headers, "Host", h);
+    }
+    p->u.HTTP_Request->path = odr_strdup(odr, *cp1 ? cp1 : "/");
+    return p;
+}
+
+static WRBUF get_url(const char *uri, WRBUF username, WRBUF password,
+                     int *code)
+{
+    int number_of_redirects = 0;
+    WRBUF result = 0;
+    ODR out = odr_createmem(ODR_ENCODE);
+    ODR in = odr_createmem(ODR_DECODE);
+
+    while (1)
+    {
+        Z_HTTP_Response *res = 0;
+        const char *location = 0;
+        Z_GDU *gdu = get_HTTP_Request_url(out, uri);
+        yaz_log(YLOG_LOG, "GET %s", uri);
+        gdu->u.HTTP_Request->method = odr_strdup(out, "GET");
+        if (username && password)
+        {
+            z_HTTP_header_add_basic_auth(out, &gdu->u.HTTP_Request->headers,
+                                         wrbuf_cstr(username),
+                                         wrbuf_cstr(password));
+        }
+        z_HTTP_header_add(out, &gdu->u.HTTP_Request->headers, "Accept",
+                          "application/xml");
+        if (!z_GDU(out, &gdu, 0, 0))
+        {
+            yaz_log(YLOG_WARN, "Can not encode HTTP request URL:%s", uri);        
+            break;
+        }
+        void *add;
+        COMSTACK conn = cs_create_host(uri, 1, &add);
+        if (!conn)
+            yaz_log(YLOG_WARN, "Bad address for URL:%s", uri);
+        else if (cs_connect(conn, add) < 0)
+            yaz_log(YLOG_WARN, "Can not connect to URL:%s", uri);
+        else
+        {
+            int len;
+            char *buf = odr_getbuf(out, &len, 0);
+            
+            if (cs_put(conn, buf, len) < 0)
+                yaz_log(YLOG_WARN, "cs_put failed URL:%s", uri);
+            else
+            {
+                char *netbuffer = 0;
+                int netlen = 0;
+                int cs_res = cs_get(conn, &netbuffer, &netlen);
+                if (cs_res <= 0)
+                {
+                    yaz_log(YLOG_WARN, "cs_get failed URL:%s", uri);
+                }
+                else
+                {
+                    Z_GDU *gdu;
+                    odr_setbuf(in, netbuffer, cs_res, 0);
+                    if (!z_GDU(in, &gdu, 0, 0)
+                        || gdu->which != Z_GDU_HTTP_Response)
+                    {
+                        yaz_log(YLOG_WARN, "HTTP decoding failed "
+                                "URL:%s", uri);
+                    }
+                    else
+                    {
+                        res = gdu->u.HTTP_Response;
+                    }
+                }
+                xfree(netbuffer);
+            }
+            cs_close(conn);
+        }
+        if (!res)
+            break; // ERROR
+        *code = res->code;
+        location = z_HTTP_header_lookup(res->headers, "Location");
+        if (++number_of_redirects < 10 &&
+            location && (*code == 301 || *code == 302 || *code == 307))
+        {
+            odr_reset(out);
+            uri = odr_strdup(out, location);
+            odr_reset(in);
+        }
+        else
+        {
+            result = wrbuf_alloc();
+            wrbuf_write(result, res->content_buf, res->content_len);
+            break;
+        }
+    }
+    odr_destroy(out);
+    odr_destroy(in);
+    return result;
+}
+
+
+mp::Torus::Torus()
+{
+    doc = 0;
+}
+
+mp::Torus::~Torus()
+{
+    if (doc)
+        xmlFreeDoc(doc);
+}
+
+void mp::Torus::read_searchables(std::string url)
+{
+    if (url.length() == 0)
+        return;
+
+    if (doc)
+    {
+        xmlFreeDoc(doc);
+        doc = 0;
+    }
+       
+    int code;
+    WRBUF w = get_url(url.c_str(), 0, 0, &code);
+    if (code == 200)
+    {
+        doc = xmlParseMemory(wrbuf_buf(w), wrbuf_len(w));
+        if (doc)
+            yaz_log(YLOG_LOG, "xmlParseMemory OK");
+    }
+    wrbuf_destroy(w);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/torus.hpp b/src/torus.hpp
new file mode 100644 (file)
index 0000000..e3a54a9
--- /dev/null
@@ -0,0 +1,46 @@
+/* This file is part of Metaproxy.
+   Copyright (C) 2005-2011 Index Data
+
+Metaproxy is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef METAPROXY_TORUS_HPP
+#define METAPROXY_TORUS_HPP
+
+#include <string>
+#include <stdexcept>
+#include <libxml/tree.h>
+
+namespace metaproxy_1 {
+    class Torus {
+    public:
+        Torus();
+        ~Torus();
+        void read_searchables(std::string url);
+    private:
+        xmlDocPtr doc;
+    };
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index c6b518b..d6cf870 100644 (file)
@@ -248,6 +248,7 @@ PROJECT_DLL_OBJS = \
         $(OBJDIR)\session.obj \
         $(OBJDIR)\sru_util.obj \
        $(OBJDIR)\thread_pool_observer.obj \
+        $(OBJDIR)\torus.obj \
         $(OBJDIR)\util.obj \
         $(OBJDIR)\xmlutil.obj 
 
index 2eccb00..12a44b3 100644 (file)
@@ -190,11 +190,14 @@ filter_virt_db =
   attribute id { xsd:NCName }?,
   attribute name { xsd:NCName }?,
   element mp:pass-vhosts { xsd:boolean }?,
+  element mp:torus {
+    attribute url { xsd:string }
+  }?,
   element mp:virtual {
     attribute route { xsd:NCName }?,
     element mp:database { xsd:string },
     element mp:target { xsd:string }+
-  }+
+  }*
 
 filter_z3950_client =
   attribute type { "z3950_client" },
index 769fd9d..602ea75 100644 (file)
         <data type="boolean"/>
       </element>
     </optional>
-    <oneOrMore>
+    <optional>
+      <element name="mp:torus">
+        <attribute name="url">
+          <data type="string"/>
+        </attribute>
+      </element>
+    </optional>
+    <zeroOrMore>
       <element name="mp:virtual">
         <optional>
           <attribute name="route">
           </element>
         </oneOrMore>
       </element>
-    </oneOrMore>
+    </zeroOrMore>
   </define>
   <define name="filter_z3950_client">
     <attribute name="type">
index 00dc21b..8fb6159 100644 (file)
   <xs:group name="filter_virt_db">
     <xs:sequence>
       <xs:element minOccurs="0" ref="mp:pass-vhosts"/>
-      <xs:element maxOccurs="unbounded" ref="mp:virtual"/>
+      <xs:element minOccurs="0" ref="mp:torus"/>
+      <xs:element minOccurs="0" maxOccurs="unbounded" ref="mp:virtual"/>
     </xs:sequence>
   </xs:group>
   <xs:element name="pass-vhosts" type="xs:boolean"/>
+  <xs:element name="torus">
+    <xs:complexType>
+      <xs:attribute name="url" use="required" type="xs:string"/>
+    </xs:complexType>
+  </xs:element>
   <xs:element name="virtual">
     <xs:complexType>
       <xs:sequence>