Initial checkin of proxy 2 code
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 5 Oct 2005 12:07:14 +0000 (12:07 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 5 Oct 2005 12:07:14 +0000 (12:07 +0000)
15 files changed:
src/.cvsignore
src/Makefile.am
src/p2.cpp [new file with mode: 0644]
src/p2_backend.h [new file with mode: 0644]
src/p2_backend_dummy.cpp [new file with mode: 0644]
src/p2_config.cpp [new file with mode: 0644]
src/p2_config.h [new file with mode: 0644]
src/p2_frontend.cpp [new file with mode: 0644]
src/p2_frontend.h [new file with mode: 0644]
src/p2_modules.cpp [new file with mode: 0644]
src/p2_modules.h [new file with mode: 0644]
src/p2_msg.cpp [new file with mode: 0644]
src/p2_xmlerror.cpp [new file with mode: 0644]
src/p2_xmlerror.h [new file with mode: 0644]
src/t-server.cpp

index 0fad00d..029305f 100644 (file)
@@ -8,3 +8,4 @@ Makefile.in
 cdetails
 t-server
 tstthreads
+p2
index 1747d6d..bd4a9b1 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.9 2005-06-21 21:54:05 adam Exp $
+## $Id: Makefile.am,v 1.10 2005-10-05 12:07:14 adam Exp $
 
 AM_CXXFLAGS = $(YAZPPINC) -I$(srcdir)/../include $(XSLT_CFLAGS) $(USEMARCONINC)
 
@@ -11,7 +11,7 @@ libyazproxy_la_SOURCES= yaz-proxy.cpp yaz-proxy-config.cpp yaz-bw.cpp \
 
 bin_PROGRAMS = yazproxy
 check_PROGRAMS = cdetails
-noinst_PROGRAMS = tstthreads t-server
+noinst_PROGRAMS = tstthreads t-server p2
 
 TESTS=$(check_PROGRAMS)
 
@@ -19,6 +19,11 @@ yazproxy_SOURCES=yaz-proxy-main.cpp
 cdetails_SOURCES=cdetails.cpp
 tstthreads_SOURCES=tstthreads.cpp
 t_server_SOURCES=t-server.cpp
+p2_SOURCES=p2_frontend.cpp p2_msg.cpp p2.cpp p2_frontend.h \
+ p2_config.cpp p2_config.h \
+ p2_backend.h p2_backend_dummy.cpp \
+ p2_modules.cpp p2_modules.h \
+ p2_xmlerror.cpp p2_xmlerror.h
 
 LDADD=libyazproxy.la $(YAZPPLALIB) $(XSLT_LIBS) $(USEMARCONLALIB)
 libyazproxy_la_LIBADD = $(XSLT_LIBS)
diff --git a/src/p2.cpp b/src/p2.cpp
new file mode 100644 (file)
index 0000000..ee586d5
--- /dev/null
@@ -0,0 +1,146 @@
+/* $Id: p2.cpp,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include <yaz/options.h>
+
+#include <yaz++/socket-manager.h>
+#include "p2_config.h"
+#include "p2_frontend.h"
+#include "p2_xmlerror.h"
+#include "p2_modules.h"
+
+using namespace yazpp_1;
+
+extern P2_ModuleEntry *p2_backend_dummy;
+
+/*
+  frontend result set map
+    resultset -> db,query
+
+  backend result set map
+    db,query -> resultset, target
+                resultset, target
+*/
+class P2_Frontend;
+
+P2_Config *P2_Server::lockConfig()
+{
+    pthread_mutex_lock(&m_mutex_config);
+    return m_config;
+}
+
+void P2_Server::unlockConfig()
+{
+    pthread_mutex_unlock(&m_mutex_config);
+}
+
+P2_Server::P2_Server(IPDU_Observable *the_PDU_Observable,
+                     Msg_Thread *my_thread,
+                     P2_Config *config,
+                     P2_ModuleFactory *modules)
+    :  Z_Assoc(the_PDU_Observable)
+{
+    m_my_thread = my_thread;
+    m_modules = modules;
+    m_config = config;
+
+    pthread_mutex_init(&m_mutex_config, 0);
+    
+    yaz_log(YLOG_LOG, "Construct P2_Server=%p", this);
+}
+
+IPDU_Observer *P2_Server::sessionNotify(IPDU_Observable
+                                       *the_PDU_Observable, int fd)
+{
+    P2_Frontend *my = new P2_Frontend(the_PDU_Observable, m_my_thread, this);
+    yaz_log(YLOG_LOG, "New session %s", the_PDU_Observable->getpeername());
+    return my;
+}
+
+P2_Server::~P2_Server()
+{
+    yaz_log(YLOG_LOG, "Destroy P2_server=%p", this);
+    pthread_mutex_destroy(&m_mutex_config);
+}
+
+void P2_Server::recv_GDU(Z_GDU *apdu, int len)
+{
+}
+
+void P2_Server::failNotify()
+{
+}
+
+void P2_Server::timeoutNotify()
+{
+}
+
+void P2_Server::connectNotify()
+{
+}
+
+int main(int argc, char **argv)
+{
+    p2_xmlerror_setup();
+
+    P2_Config config;
+
+    if (!config.parse_options(argc, argv))
+    {
+        yaz_log(YLOG_FATAL, "Configuration incorrect. Exiting");
+        exit(1);
+    }
+
+    SocketManager mySocketManager;
+
+    PDU_Assoc *my_PDU_Assoc = 0;
+    
+    Msg_Thread my_thread(&mySocketManager, config.m_no_threads);
+
+    my_PDU_Assoc = new PDU_Assoc(&mySocketManager);
+
+    P2_ModuleFactory modules;
+
+    modules.add(p2_backend_dummy);
+
+    std::list<P2_ConfigModule *>::const_iterator it;
+    for (it = config.m_modules.begin(); it != config.m_modules.end(); it++)
+        modules.add((*it)->m_fname.c_str());
+    
+    P2_Server z(my_PDU_Assoc, &my_thread, &config, &modules);
+    z.server(config.m_listen_address.c_str());
+
+    while (mySocketManager.processEvent() > 0)
+        ;
+    return 0;
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/p2_backend.h b/src/p2_backend.h
new file mode 100644 (file)
index 0000000..b5864b3
--- /dev/null
@@ -0,0 +1,31 @@
+
+#ifndef P2_BACKEND_H
+#define P2_BACKEND_H
+
+#include <yaz++/z-query.h>
+
+class IP2_BackendSet {
+public:
+    virtual ~IP2_BackendSet();
+    virtual int get(int start, int number) = 0;
+};
+
+class IP2_Backend {
+ public:
+    virtual ~IP2_Backend();
+    virtual int search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset, int *hits) = 0;
+};
+
+struct P2_ModuleInterface0 {
+    IP2_Backend *(*create)(const char *address);
+};
+    
+struct P2_ModuleEntry {
+    int version;
+    const char *name;
+    const char *description;
+    void *interface_ptr;
+};
+
+    
+#endif
diff --git a/src/p2_backend_dummy.cpp b/src/p2_backend_dummy.cpp
new file mode 100644 (file)
index 0000000..79e8490
--- /dev/null
@@ -0,0 +1,74 @@
+
+#include <yaz/log.h>
+#include "p2_backend.h"
+
+class P2_BackendSetDummy : public IP2_BackendSet {
+public:
+    P2_BackendSetDummy();
+    ~P2_BackendSetDummy();
+    int get(int start, int number);
+};
+
+class P2_BackendDummy : public IP2_Backend {
+public:
+    P2_BackendDummy(const char *address);
+    ~P2_BackendDummy();
+    int search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset, int *hits);
+};
+
+P2_BackendDummy::P2_BackendDummy(const char *address)
+{
+    yaz_log(YLOG_LOG, "P2_backendDummy %p create", this);
+}
+
+P2_BackendDummy::~P2_BackendDummy()
+{
+    yaz_log(YLOG_LOG, "P2_backendDummy %p destroy", this);
+}
+
+int P2_BackendDummy::search(yazpp_1::Yaz_Z_Query *q, IP2_BackendSet **rset,
+                           int *hits)
+{
+    yaz_log(YLOG_LOG, "P2_backendDummy %p search", this);
+
+    P2_BackendSetDummy *s = new P2_BackendSetDummy();
+
+    *rset = s;
+    *hits = 42;
+    return 0;
+}
+
+int P2_BackendSetDummy::get(int start, int number)
+{
+    yaz_log(YLOG_LOG, "P2_backendSetDummy %p get", this);
+    return 0;
+}
+
+P2_BackendSetDummy::P2_BackendSetDummy()
+{
+    yaz_log(YLOG_LOG, "P2_backendSetDummy %p create", this);
+
+}
+
+P2_BackendSetDummy::~P2_BackendSetDummy()
+{
+    yaz_log(YLOG_LOG, "P2_backendSetDummy %p destroy", this);
+}
+
+static IP2_Backend *dummy_create(const char *address)
+{
+    return new P2_BackendDummy(address);
+}
+
+P2_ModuleInterface0 int0 = {
+    dummy_create
+};
+
+P2_ModuleEntry p2_module_entry = {
+    0,
+    "dummy",
+    "Dummy Backend",
+    (void *) &int0
+};
+
+P2_ModuleEntry *p2_backend_dummy = &p2_module_entry;
diff --git a/src/p2_config.cpp b/src/p2_config.cpp
new file mode 100644 (file)
index 0000000..de50049
--- /dev/null
@@ -0,0 +1,383 @@
+/* $Id: p2_config.cpp,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <yaz/log.h>
+#include <yaz/options.h>
+#include <yaz/diagbib1.h>
+#include "p2_config.h"
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xinclude.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+#endif
+
+#include <iostream>
+
+using namespace std;
+
+class P2_Config::Rep {
+    
+public:
+    Rep();
+    ~Rep();
+public:
+#if HAVE_XSLT
+    xmlDocPtr m_docPtr;
+    xmlNodePtr m_proxyPtr;
+#endif
+};
+
+P2_Config::Rep::Rep()
+{
+#if HAVE_XSLT
+    m_docPtr = 0;
+    m_proxyPtr = 0;
+#endif
+}
+
+P2_Config::Rep::~Rep()
+{
+#if HAVE_XSLT
+    if (m_docPtr)
+        xmlFreeDoc(m_docPtr);
+#endif
+}
+    
+P2_Config::P2_Config()
+{
+    m_max_clients = 500;
+    m_client_idletime = 600;
+    m_debug_mode = 0;
+    m_no_limit_files = 0;
+    m_no_threads = 20;
+    m_target_idletime = 600;
+
+    m_rep = new Rep();
+}
+
+bool P2_Config::parse_options(int argc, char **argv)
+{
+    char *arg;
+    int ret;
+    bool show_config = false;
+    while ((ret = options("o:a:t:v:c:u:i:m:l:T:p:n:h:XS",
+                          argv, argc, &arg)) != -2)
+    {
+        switch (ret)
+        {
+        case 0:
+            if (m_listen_address.length())
+            {
+                yaz_log(YLOG_FATAL, "Multiple listener address given");
+                return false;
+            }
+            m_listen_address = arg;
+            break;
+        case 'a':
+            m_apdu_log = arg;
+            break;
+        case 'c':
+            if (m_xml_fname.length())
+            {
+                yaz_log(YLOG_FATAL, "Multiple -c options given");
+                return false;
+            }
+            if (!read_xml_config(arg))
+            {
+                return false;
+            }
+            m_xml_fname = arg;
+            break;
+        case 'i':
+            m_client_idletime = atoi(arg);
+            break;
+        case 'l':
+            m_log_file = arg;
+            break;
+        case 'm':
+            m_max_clients = atoi(arg);
+            break;
+        case 'n':
+            m_no_limit_files = atoi(arg);
+            break;
+        case 'h':
+            m_no_threads = atoi(arg);
+            break;
+        case 'o':
+            m_optimize_flags = arg;
+            break;
+        case 'p':
+            if (m_pid_fname.length())
+            {
+                yaz_log(YLOG_LOG, "Multiple -p options given");
+                return false;
+            }
+            m_pid_fname = arg;
+            break;
+        case 't':
+            if (m_default_target.length())
+            {
+                yaz_log(YLOG_LOG, "Multiple -t options given");
+                return false;
+            }
+            m_default_target = arg;
+            break;
+        case 'T':
+            m_target_idletime = atoi(arg);
+            break;
+        case 'u':
+            if (m_uid.length())
+            {
+                yaz_log(YLOG_FATAL, "-u specified more than once");
+                return false;
+            }
+            m_uid = arg;
+            break;
+        case 'v':
+            yaz_log_init_level(yaz_log_mask_str(arg));
+            break;
+        case 'X':
+            m_debug_mode = 1;
+            break;
+        case 'S':
+            show_config = true;
+            break;
+        default:
+            yaz_log(YLOG_FATAL, "Bad option %s", arg);
+            return false;
+        }
+    } 
+    if (m_log_file.length())
+        yaz_log_init_file(m_log_file.c_str());
+    if (show_config)
+        print();
+    return true;
+}
+
+bool P2_Config::parse_xml_text(void *xml_ptr, bool &val)
+{
+    string v;
+    if (!parse_xml_text(xml_ptr, v))
+        return false;
+    if (v.length() == 1 && v[0] == '1')
+        val = true;
+    else
+        val = false;
+    return true;
+}
+
+bool P2_Config::parse_xml_text(void *xml_ptr, string &val)
+{
+    xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+    bool found = false;
+    string v;
+    for(ptr = ptr->children; ptr; ptr = ptr->next)
+        if (ptr->type == XML_TEXT_NODE)
+        {
+            xmlChar *t = ptr->content;
+            if (t)
+            {
+                v += (const char *) t;
+                found = true;
+            }
+        }
+    if (found)
+        val = v;
+    return found;
+}
+
+void P2_Config::parse_xml_element_target(void *xml_ptr,
+                                         P2_ConfigTarget *t)
+{
+    xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+        if (ptr->type != XML_ELEMENT_NODE)
+            continue;
+        if (!strcmp((const char *) ptr->name, "url"))
+        {
+            parse_xml_text(ptr, t->m_target_address);
+        }
+        else if (!strcmp((const char *) ptr->name, "database"))
+        {
+            parse_xml_text(ptr, t->m_target_database);
+        }
+        else
+        {
+            yaz_log(YLOG_WARN, "Unknown element '%s' inside target",
+                    (const char *) ptr->name);
+            m_errors++;
+        }
+    }
+}
+
+void P2_Config::parse_xml_element_proxy(void *xml_ptr)
+{
+    xmlNodePtr ptr = (xmlNodePtr) xml_ptr;
+
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+        if (ptr->type != XML_ELEMENT_NODE)
+            continue;
+        if (!strcmp((const char *) ptr->name, "target"))
+        {
+            P2_ConfigTarget *t = new P2_ConfigTarget();
+
+            struct _xmlAttr *attr;
+            for (attr = ptr->properties; attr; attr = attr->next)
+                if (!strcmp((const char *) attr->name, "name")
+                    || !strcmp((const char *) attr->name, "host"))
+                {
+                    parse_xml_text(attr, t->m_virt_address);
+                }
+                else if (!strcmp((const char *) attr->name, "database"))
+                {
+                    parse_xml_text(attr, t->m_virt_database);
+                }
+                else if (!strcmp((const char *) attr->name, "default"))
+                {
+                    parse_xml_text(attr, t->m_default);
+                }
+                else if (!strcmp((const char *) attr->name, "type"))
+                {
+                    parse_xml_text(attr, t->m_type);
+                }
+                else
+                {
+                    yaz_log(YLOG_WARN, "Unknown attribute '%s' for "
+                            "element proxy",
+                            (const char *) attr->name);
+                    m_errors++;
+                }
+            parse_xml_element_target(ptr, t);
+            m_target_list.push_back(t);
+        }
+        else if (!strcmp((const char *) ptr->name, "max-clients"))
+        {
+            string v;
+            if (parse_xml_text(ptr, v))
+                m_max_clients = atoi(v.c_str());
+        }
+        else if (!strcmp((const char *) ptr->name, "module"))
+        {
+            P2_ConfigModule *t = new P2_ConfigModule();
+
+            string v;
+            if (parse_xml_text(ptr, v))
+            {
+                t->m_fname = v;
+                m_modules.push_back(t);
+            }
+        }
+        else
+        {
+            yaz_log(YLOG_WARN, "Unknown element '%s' inside proxy", ptr->name);
+            m_errors++;
+        }
+    }
+}
+
+void P2_Config::print()
+{
+    cout << "max_clients=" << m_max_clients << endl;
+    list<P2_ConfigTarget *>::const_iterator it;
+    
+    for (it = m_target_list.begin(); it != m_target_list.end(); it++)
+    {
+        cout << "type=" << (*it)->m_type << " ";
+        cout << "v-address=" << (*it)->m_virt_address << " ";
+        cout << "v-db=" << (*it)->m_virt_database << " ";
+        cout << "t-address=" << (*it)->m_target_address << " ";
+        cout << "t-db=" << (*it)->m_target_database << " ";
+        cout << "default=" << (*it)->m_default << endl;
+    }
+}
+
+bool P2_Config::read_xml_config(const char *fname)
+{
+    xmlDocPtr ndoc = xmlParseFile(fname);
+
+    if (!ndoc)
+    {
+        yaz_log(YLOG_WARN, "Config file %s not found or parse error", fname);
+        return false;
+    }
+    int noSubstitutions = xmlXIncludeProcess(ndoc);
+    if (noSubstitutions == -1)
+        yaz_log(YLOG_WARN, "XInclude processing failed on config %s", fname);
+
+    xmlNodePtr proxyPtr = xmlDocGetRootElement(ndoc);
+    if (!proxyPtr || proxyPtr->type != XML_ELEMENT_NODE ||
+        strcmp((const char *) proxyPtr->name, "proxy"))
+    {
+        yaz_log(YLOG_WARN, "No proxy element in %s", fname);
+        xmlFreeDoc(ndoc);
+        return false;
+    }
+    m_rep->m_proxyPtr = proxyPtr;
+    
+    // OK: release previous and make it the current one.
+    if (m_rep->m_docPtr)
+        xmlFreeDoc(m_rep->m_docPtr);
+    m_rep->m_docPtr = ndoc;
+
+    m_errors = 0;
+    parse_xml_element_proxy(proxyPtr);
+    if (m_errors && !m_debug_mode)
+        return false;
+    return true;
+}
+
+P2_Config::~P2_Config()
+{
+    delete m_rep;
+}
+
+P2_ConfigTarget::P2_ConfigTarget()
+{
+    m_default = false;
+}
+
+P2_ConfigTarget *P2_Config::find_target(string db)
+{
+    list<P2_ConfigTarget *>::const_iterator it;
+    for (it = m_target_list.begin(); it != m_target_list.end(); it++)
+    {
+        if ((*it)->m_virt_database == db)
+            return (*it);
+    }
+    return 0;
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_config.h b/src/p2_config.h
new file mode 100644 (file)
index 0000000..f4976e6
--- /dev/null
@@ -0,0 +1,90 @@
+/* $Id: p2_config.h,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_CONFIG_INCLUDED
+#define P2_CONFIG_INCLUDED
+
+#include <string>
+#include <list>
+
+class P2_ConfigTarget {
+ public:
+    P2_ConfigTarget();
+    std::string m_virt_address;
+    std::string m_virt_database;
+    std::string m_target_address;
+    std::string m_target_database;
+    std::string m_type;
+    bool m_default;
+};
+
+class P2_ConfigModule {
+ public:
+    std::string m_fname;
+};
+
+class P2_Config {
+    class Rep;
+ public:
+    P2_Config::P2_Config();
+    P2_Config::~P2_Config();
+    bool P2_Config::parse_options(int argc, char **argv);
+    P2_ConfigTarget *find_target(std::string db);
+    void print();
+ private:
+    bool read_xml_config(const char *fname);
+    void parse_xml_element_proxy(void *xml_ptr);
+    void parse_xml_element_target(void *xml_ptr,
+                                            P2_ConfigTarget *t);
+    bool parse_xml_text(void *xml_ptr, std::string &val);
+    bool parse_xml_text(void *xml_ptr, bool &val);
+ public:
+    std::string m_apdu_log;
+    std::string m_default_target;
+    std::string m_listen_address;
+    std::string m_log_file;
+    std::string m_optimize_flags;
+    std::string m_pid_fname;
+    std::string m_uid;
+    std::string m_xml_fname;
+
+    int m_max_clients;
+    int m_client_idletime;
+    int m_debug_mode;
+    int m_no_limit_files;
+    int m_no_threads;
+    int m_target_idletime;
+
+    std::list<P2_ConfigTarget *> m_target_list;
+    std::list<P2_ConfigModule *> m_modules;
+ private:
+    Rep *m_rep;
+    int m_errors;
+};
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_frontend.cpp b/src/p2_frontend.cpp
new file mode 100644 (file)
index 0000000..274b3d5
--- /dev/null
@@ -0,0 +1,95 @@
+/* $Id: p2_frontend.cpp,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include "p2_frontend.h"
+
+using namespace yazpp_1;
+using namespace std;
+
+P2_Frontend::P2_Frontend(IPDU_Observable *the_PDU_Observable,
+                         Msg_Thread *my_thread, P2_Server *server)
+    :  Z_Assoc(the_PDU_Observable)
+{
+    m_my_thread = my_thread;
+    m_server = server;
+    m_no_requests = 0;
+    m_delete_flag = 0;
+    yaz_log(YLOG_LOG, "Construct P2_Frontend=%p", this);
+}
+
+
+IPDU_Observer *P2_Frontend::sessionNotify(IPDU_Observable
+                                          *the_PDU_Observable, int fd)
+{
+    return 0;
+}
+
+P2_Frontend::~P2_Frontend()
+{
+    yaz_log(YLOG_LOG, "Destroy P2_Frontend=%p", this);
+
+    list<P2_FrontResultSet *>::iterator it;
+    
+    for (it = m_resultSets.begin(); it != m_resultSets.end(); it++)
+    {
+        delete *it;
+        *it = 0;
+    }
+}
+
+void P2_Frontend::recv_GDU(Z_GDU *z_pdu, int len)
+{
+    GDU *gdu = new GDU(z_pdu);
+
+    P2_Msg *m = new P2_Msg(gdu, this, m_server);
+    m_no_requests++;
+    m_my_thread->put(m);  
+}
+
+void P2_Frontend::failNotify()
+{
+    m_delete_flag = 1;
+    if (m_no_requests == 0)
+        delete this;
+    
+}
+
+void P2_Frontend::timeoutNotify()
+{
+    m_delete_flag = 1;
+    if (m_no_requests == 0)
+        delete this;
+}
+
+void P2_Frontend::connectNotify()
+{
+
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_frontend.h b/src/p2_frontend.h
new file mode 100644 (file)
index 0000000..fe403e6
--- /dev/null
@@ -0,0 +1,163 @@
+/* $Id: p2_frontend.h,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_FRONTEND_H
+#define P2_FRONTEND_H
+
+#include <list>
+#include <vector>
+#include <string>
+
+#include "msg-thread.h"
+#include <yaz++/z-assoc.h>
+#include <yaz++/pdu-assoc.h>
+#include <yaz++/gdu.h>
+#include <yaz++/z-query.h>
+
+class P2_Frontend;
+class P2_Server;
+class P2_Config;
+class P2_ConfigTarget;
+class P2_ModuleFactory;
+
+class IP2_BackendSet;
+
+class P2_BackendResultSet {
+ public:
+    P2_BackendResultSet();
+    ~P2_BackendResultSet();
+    yazpp_1::Yaz_Z_Query m_query;
+    std::list<std::string> m_db_list;
+    int m_hit_count;
+    IP2_BackendSet *m_int;
+    // record cache here 
+};
+
+class IP2_Backend;
+
+class P2_Backend {
+ public:
+    P2_Backend(P2_ConfigTarget *cfg, IP2_Backend *backend_interface);
+    ~P2_Backend();
+ public:
+    std::list<P2_BackendResultSet *>m_resultSets;
+    P2_ConfigTarget *m_configTarget;
+    bool m_busy;
+    IP2_Backend *m_int;
+};
+
+class P2_Server : public yazpp_1::Z_Assoc {
+public:
+    ~P2_Server();
+    P2_Server(yazpp_1::IPDU_Observable *the_PDU_Observable,
+              Msg_Thread *m_my_thread,
+              P2_Config *config,
+              P2_ModuleFactory *modules);
+    P2_Config *lockConfig();
+    void unlockConfig();
+    std::list<P2_Backend *>m_backend_list;
+    P2_ModuleFactory *m_modules;
+private:
+    yazpp_1::IPDU_Observer* sessionNotify(
+        yazpp_1::IPDU_Observable *the_PDU_Observable,
+        int fd);
+    void recv_GDU(Z_GDU *apdu, int len);
+
+    void failNotify();
+    void timeoutNotify();
+    void connectNotify();
+private:
+    P2_Config *m_config;
+    Msg_Thread *m_my_thread;
+    pthread_mutex_t m_mutex_config;
+};
+
+class P2_FrontResultSet {
+public:
+    P2_FrontResultSet(const char *id);
+    ~P2_FrontResultSet();
+    void setQuery(Z_Query *z_query);
+    void setDatabases(char **db, int num);
+    std::string m_resultSetId;
+    std::vector<std::string> m_db_list;
+    yazpp_1::Yaz_Z_Query m_query;
+};
+
+class P2_Msg : public IMsg_Thread {
+public:
+    int m_close_flag;
+    yazpp_1::GDU *m_gdu;
+    yazpp_1::GDU *m_output;
+    P2_Frontend *m_front;
+    P2_Server *m_server;
+    IMsg_Thread *handle();
+    void result();
+    P2_Msg(yazpp_1::GDU *gdu, P2_Frontend *front, P2_Server *server);
+    virtual ~P2_Msg();
+ private:
+
+    Z_APDU *frontend_search_resultset(Z_APDU *z_gdu, ODR odr,
+                                      P2_FrontResultSet **rset);
+    Z_APDU *frontend_present_resultset(Z_APDU *z_gdu, ODR odr,
+                                       P2_FrontResultSet **rset);
+    Z_APDU *frontend_search_apdu(Z_APDU *z_gdu, ODR odr);
+    Z_APDU *frontend_present_apdu(Z_APDU *z_gdu, ODR odr);
+    P2_Backend *select_backend(std::string db,
+                               yazpp_1::Yaz_Z_Query *query,
+                               P2_BackendResultSet **bset);
+    P2_Backend *create_backend(std::string db);
+};
+
+class P2_Frontend : public yazpp_1::Z_Assoc {
+ public:
+    ~P2_Frontend();
+    P2_Frontend(yazpp_1::IPDU_Observable *the_PDU_Observable,
+                Msg_Thread *m_my_thread, P2_Server *server);
+    IPDU_Observer* sessionNotify(yazpp_1::IPDU_Observable *the_PDU_Observable,
+                                 int fd);
+    
+    void recv_GDU(Z_GDU *apdu, int len);
+    
+    void failNotify();
+    void timeoutNotify();
+    void connectNotify();
+
+    int m_no_requests;
+    int m_delete_flag;
+    std::list<P2_FrontResultSet *> m_resultSets;
+    
+ private:
+    yazpp_1::GDUQueue m_in_queue;
+    Msg_Thread *m_my_thread;
+    P2_Server *m_server;
+ private:
+    bool P2_Frontend::search(Z_GDU *z_gdu);
+    bool P2_Frontend::handle_init(Z_GDU *z_gdu);
+};
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_modules.cpp b/src/p2_modules.cpp
new file mode 100644 (file)
index 0000000..6f1778b
--- /dev/null
@@ -0,0 +1,77 @@
+
+#include <dlfcn.h>
+
+#include "p2_modules.h"
+
+class P2_ModuleDLEntry {
+public:
+    void *m_dl_handle;
+    P2_ModuleEntry *m_entry;
+    P2_ModuleDLEntry();
+    ~P2_ModuleDLEntry();
+};
+
+P2_ModuleDLEntry::P2_ModuleDLEntry()
+{
+    m_dl_handle = 0;
+    m_entry = 0;
+}
+    
+P2_ModuleDLEntry::~P2_ModuleDLEntry()
+{
+    if (m_dl_handle)
+       dlclose(m_dl_handle);
+}
+    
+P2_ModuleFactory::P2_ModuleFactory()
+{
+}
+
+P2_ModuleFactory::~P2_ModuleFactory()
+{
+}
+
+bool P2_ModuleFactory::add(P2_ModuleEntry *entry)
+{
+    P2_ModuleDLEntry *m = new P2_ModuleDLEntry();
+    m->m_entry = entry;
+    m_modules.push_back(m);
+    return true;
+}
+
+bool P2_ModuleFactory::add(const char *fname)
+{
+    void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
+    if (!dl_handle)
+       return false;
+
+    P2_ModuleEntry *entry =
+       reinterpret_cast<P2_ModuleEntry *> 
+       (dlsym(dl_handle, "p2_module_entry"));
+    if (!entry)
+    {
+       dlclose(dl_handle);
+       return false;
+    }
+    P2_ModuleDLEntry *m = new P2_ModuleDLEntry();
+    m->m_dl_handle = dl_handle;
+    m->m_entry = entry;
+    m_modules.push_back(m);
+    return true;
+}
+
+void *P2_ModuleFactory::get_interface(const char *name, int version)
+{
+    std::list<P2_ModuleDLEntry *>::const_iterator it;
+    for (it = m_modules.begin();  it != m_modules.end(); it++)
+    {
+       P2_ModuleDLEntry *ent = *it;
+       if (!strcmp(ent->m_entry->name, name) &&
+           ent->m_entry->version == version)
+       {
+           return ent->m_entry->interface_ptr;
+       }
+    }
+    return 0;
+}
+
diff --git a/src/p2_modules.h b/src/p2_modules.h
new file mode 100644 (file)
index 0000000..c3f0e1b
--- /dev/null
@@ -0,0 +1,21 @@
+
+#ifndef P2_MODULES_H
+#define P2_MODULES_H
+
+#include "p2_backend.h"
+
+#include <list>
+
+class P2_ModuleDLEntry ;
+class P2_ModuleFactory {
+ public:
+    P2_ModuleFactory();
+    ~P2_ModuleFactory();
+    bool add(const char *fname);
+    bool add(P2_ModuleEntry *entry);
+    void *get_interface(const char *name, int version);
+ private:
+    std::list <P2_ModuleDLEntry *>m_modules;
+};
+
+#endif
diff --git a/src/p2_msg.cpp b/src/p2_msg.cpp
new file mode 100644 (file)
index 0000000..e113a21
--- /dev/null
@@ -0,0 +1,387 @@
+/* $Id: p2_msg.cpp,v 1.1 2005-10-05 12:07:14 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <yaz/log.h>
+#include <yaz/diagbib1.h>
+#include "p2_backend.h"
+#include "p2_frontend.h"
+#include "p2_config.h"
+#include "p2_modules.h"
+
+using namespace yazpp_1;
+using namespace std;
+
+IP2_BackendSet::~IP2_BackendSet()
+{
+}
+
+IP2_Backend::~IP2_Backend()
+{
+
+}
+
+P2_Backend::P2_Backend(P2_ConfigTarget *cfg, IP2_Backend *backend_int)
+{
+    m_configTarget = new P2_ConfigTarget;
+    *m_configTarget = *cfg;
+    m_busy = false;
+    m_int = backend_int;
+}
+
+P2_Backend::~P2_Backend()
+{
+    delete m_configTarget;
+}
+
+P2_BackendResultSet::P2_BackendResultSet()
+{
+    m_int = 0;
+}
+
+P2_BackendResultSet::~P2_BackendResultSet()
+{
+    delete m_int;
+}
+
+P2_Backend *P2_Msg::select_backend(string db,
+                                   Yaz_Z_Query *query,
+                                   P2_BackendResultSet **bset)
+{
+    P2_Config *cfg = m_server->lockConfig();
+
+    // see if some target has done this query before
+
+    *bset = 0;
+    P2_Backend *backend = 0;
+
+    list<P2_Backend *>::const_iterator it;
+    for (it = m_server->m_backend_list.begin(); 
+         it != m_server->m_backend_list.end(); it++)
+    {
+        if ((*it)->m_busy)
+            continue;
+
+        if (db != (*it)->m_configTarget->m_virt_database)
+            continue;
+        backend = *it;
+
+        if (query)
+        {
+            list<P2_BackendResultSet *>::const_iterator is;
+            for (is  = (*it)->m_resultSets.begin(); 
+                 is != (*it)->m_resultSets.end(); is++)
+            {
+                if (query->match(&(*is)->m_query))
+                {
+                    *bset = *is;
+                    break;
+                }
+            }
+        }
+        if (bset)
+            break;
+    }
+    if (!backend)
+    {
+        P2_ConfigTarget *target_cfg = cfg->find_target(db);
+
+        if (!target_cfg)
+        {
+            yaz_log(YLOG_WARN, "No backend for database %s",
+                    db.c_str());
+        }
+        else
+        {
+            P2_ModuleInterface0 *int0 =
+            reinterpret_cast<P2_ModuleInterface0 *>
+                (m_server->m_modules->get_interface(target_cfg->m_type.c_str(),
+                                                    0));
+            IP2_Backend *bint = 0;
+
+            if (int0)
+                bint = int0->create(target_cfg->m_target_address.c_str());
+
+            if (bint)
+                backend = new P2_Backend(target_cfg, bint);
+
+            if (backend)
+                m_server->m_backend_list.push_back(backend);
+        }
+    }
+    if (backend)
+        backend->m_busy = true;
+    m_server->unlockConfig();
+    return backend;
+}
+
+void P2_FrontResultSet::setQuery(Z_Query *z_query)
+{
+    m_query.set_Z_Query(z_query);
+}
+
+void P2_FrontResultSet::setDatabases(char **db, int num)
+{
+    m_db_list.clear();
+
+    int i;
+    for (i = 0; i<num; i++)
+        m_db_list.push_back(db[i]);
+}
+
+P2_FrontResultSet::P2_FrontResultSet(const char *id)
+{
+    m_resultSetId = id;
+}
+
+
+P2_FrontResultSet::~P2_FrontResultSet()
+{
+}
+
+P2_Msg::P2_Msg(GDU *gdu, P2_Frontend *front, P2_Server *server)
+{
+    m_front = front;
+    m_server = server;
+    m_output = 0;
+    m_gdu = gdu;
+    m_close_flag = 0;
+}
+
+P2_Msg::~P2_Msg()
+{
+    delete m_output;
+    delete m_gdu;
+}
+
+Z_APDU *P2_Msg::frontend_search_resultset(Z_APDU *z_gdu, ODR odr,
+                                          P2_FrontResultSet **rset)
+{
+    Z_SearchRequest *req = z_gdu->u.searchRequest;
+    list<P2_FrontResultSet *>::iterator it;
+    P2_FrontResultSet *s = 0;
+
+    string id = req->resultSetName;
+    for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++)
+    {
+       if ((*it)->m_resultSetId == id)
+        {
+            s = *it;
+           break;
+        }
+    }
+    if (s)
+    {
+       // result set already exists
+        *rset = s;
+       if (req->replaceIndicator && *req->replaceIndicator)
+       {  // replace indicator true
+           s->setQuery(req->query);
+           s->setDatabases(req->databaseNames, req->num_databaseNames);
+           return 0;
+       }
+       Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+       Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+       apdu->u.searchResponse->records = rec;
+       rec->which = Z_Records_NSD;
+       rec->u.nonSurrogateDiagnostic =
+           zget_DefaultDiagFormat(
+               odr, YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
+               req->resultSetName);
+       
+       return apdu;
+    }
+    // does not exist 
+    s = new P2_FrontResultSet(req->resultSetName);
+    s->setQuery(req->query);
+    s->setDatabases(req->databaseNames, req->num_databaseNames);
+    m_front->m_resultSets.push_back(s);
+    *rset = s;
+    return 0;
+}
+
+Z_APDU *P2_Msg::frontend_search_apdu(Z_APDU *request_apdu, ODR odr)
+{
+    P2_FrontResultSet *rset;
+    Z_APDU *response_apdu = frontend_search_resultset(request_apdu, odr,
+                                                      &rset);
+    if (response_apdu)
+        return response_apdu;
+
+    // no immediate error (yet) 
+    size_t i;
+    for (i = 0; i<rset->m_db_list.size(); i++)
+    {
+        string db = rset->m_db_list[i];
+        P2_BackendResultSet *bset;
+        P2_Backend *b = select_backend(db, &rset->m_query, &bset);
+        if (!b)
+        {
+            Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+            Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+            apdu->u.searchResponse->records = rec;
+            rec->which = Z_Records_NSD;
+            rec->u.nonSurrogateDiagnostic =
+                zget_DefaultDiagFormat(
+                    odr, YAZ_BIB1_DATABASE_UNAVAILABLE, db.c_str());
+            return apdu;
+        }
+        if (!bset)
+        {   // new set 
+            bset = new P2_BackendResultSet();
+
+            bset->m_query.set_Z_Query(request_apdu->u.searchRequest->query);
+            bset->m_db_list.push_back(db);
+
+            b->m_int->search(&bset->m_query, &bset->m_int, &bset->m_hit_count);
+            b->m_resultSets.push_back(bset);
+        }
+        else
+        {
+            bset->m_int->get(1, 1);
+        }
+        response_apdu = zget_APDU(odr, Z_APDU_searchResponse);
+        *response_apdu->u.searchResponse->resultCount = bset->m_hit_count;
+        b->m_busy = false;
+    }
+    if (!response_apdu)
+    {
+        Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+        Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+        apdu->u.searchResponse->records = rec;
+            rec->which = Z_Records_NSD;
+            rec->u.nonSurrogateDiagnostic =
+                zget_DefaultDiagFormat(odr, YAZ_BIB1_UNSUPP_SEARCH, 0);
+            return apdu;
+    }
+    return response_apdu;
+}
+
+Z_APDU *P2_Msg::frontend_present_resultset(Z_APDU *z_gdu, ODR odr,
+                                           P2_FrontResultSet **rset)
+{
+    Z_PresentRequest *req = z_gdu->u.presentRequest;
+    list<P2_FrontResultSet *>::iterator it;
+    P2_FrontResultSet *s = 0;
+
+    string id = req->resultSetId;
+    for (it = m_front->m_resultSets.begin(); it != m_front->m_resultSets.end(); it++)
+    {
+       if ((*it)->m_resultSetId == id)
+        {
+            s = *it;
+           break;
+        }
+    }
+    *rset = s;
+    if (s)
+       return 0;  // fine result set exists 
+
+    Z_APDU *apdu = zget_APDU(odr, Z_APDU_presentResponse);
+    
+    Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+    apdu->u.presentResponse->records = rec;
+    rec->which = Z_Records_NSD;
+    rec->u.nonSurrogateDiagnostic =
+       zget_DefaultDiagFormat(
+           odr,
+           YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
+           req->resultSetId);
+    return apdu;
+}
+
+Z_APDU *P2_Msg::frontend_present_apdu(Z_APDU *request_apdu, ODR odr)
+{
+    P2_FrontResultSet *rset;
+    Z_APDU *response_apdu = frontend_present_resultset(request_apdu, odr,
+                                                       &rset);
+    if (response_apdu)
+        return response_apdu;
+    return zget_APDU(odr, Z_APDU_presentResponse);
+}
+    
+IMsg_Thread *P2_Msg::handle()
+{
+    ODR odr = odr_createmem(ODR_ENCODE);
+    yaz_log(YLOG_LOG, "P2_Msg:handle begin");
+    Z_GDU *request_gdu = m_gdu->get();
+
+    if (request_gdu->which == Z_GDU_Z3950)
+    {
+       Z_APDU *request_apdu = request_gdu->u.z3950;
+        Z_APDU *response_apdu = 0;
+        switch(request_apdu->which)
+        {
+        case Z_APDU_initRequest:
+            response_apdu = zget_APDU(odr, Z_APDU_initResponse);
+            ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_triggerResourceCtrl);
+            ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_search);
+            ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_present);
+           ODR_MASK_SET(response_apdu->u.initResponse->options, Z_Options_namedResultSets);
+            break;
+        case Z_APDU_searchRequest:
+            response_apdu = frontend_search_apdu(request_apdu, odr);
+            break;
+       case Z_APDU_presentRequest:
+           response_apdu = frontend_present_apdu(request_apdu, odr);
+            break;
+        case Z_APDU_triggerResourceControlRequest:
+            break;
+        default:
+            response_apdu = zget_APDU(odr, Z_APDU_close);
+            m_close_flag = 1;
+            break;
+        }
+        if (response_apdu)
+            m_output = new GDU(response_apdu);
+    }
+    yaz_log(YLOG_LOG, "P2_Msg:handle end");
+    odr_destroy(odr);
+    return this;
+}
+
+void P2_Msg::result()
+{
+    m_front->m_no_requests--;
+    if (!m_front->m_delete_flag)
+    {
+        if (m_output)
+        {
+            int len;
+            m_front->send_GDU(m_output->get(), &len);
+        }
+        if (m_close_flag)
+        {
+            m_front->close();
+            m_front->m_delete_flag = 1;
+        }
+    }
+    if (m_front->m_delete_flag && m_front->m_no_requests == 0)
+        delete m_front;
+    delete this;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_xmlerror.cpp b/src/p2_xmlerror.cpp
new file mode 100644 (file)
index 0000000..d2bcaac
--- /dev/null
@@ -0,0 +1,70 @@
+/* $Id: p2_xmlerror.cpp,v 1.1 2005-10-05 12:07:15 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <yaz/log.h>
+
+#include "p2_xmlerror.h"
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxslt/xsltutils.h>
+#endif
+
+#if HAVE_XSLT
+static void p2_xml_error_handler(void *ctx, const char *fmt, ...)
+{
+    char buf[1024];
+    size_t sz;
+
+    va_list ap;
+    va_start(ap, fmt);
+
+#ifdef WIN32
+    vsprintf(buf, fmt, ap);
+#else
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+#endif
+    sz = strlen(buf);
+    if (sz > 0 && buf[sz-1] == '\n')
+        buf[sz-1] = '\0';
+        
+    yaz_log(YLOG_WARN, "%s: %s", (char*) ctx, buf);
+
+    va_end (ap);
+}
+#endif
+
+void p2_xmlerror_setup()
+{
+#if HAVE_XSLT
+    xmlSetGenericErrorFunc((void *) "XML", p2_xml_error_handler);
+    xsltSetGenericErrorFunc((void *) "XSLT", p2_xml_error_handler);
+#endif
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/p2_xmlerror.h b/src/p2_xmlerror.h
new file mode 100644 (file)
index 0000000..df6a346
--- /dev/null
@@ -0,0 +1,35 @@
+/* $Id: p2_xmlerror.h,v 1.1 2005-10-05 12:07:15 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#ifndef P2_XMLERROR_H
+#define P2_XMLERROR_H
+
+void p2_xmlerror_setup();
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
index a264ddf..b7133a5 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1998-2005, Index Data.
+ * Copyright (c) 2005, Index Data.
  * See the file LICENSE for details.
  * 
- * $Id: t-server.cpp,v 1.5 2005-09-26 09:24:14 adam Exp $
+ * $Id: t-server.cpp,v 1.6 2005-10-05 12:07:15 adam Exp $
  */
 
 #include <stdlib.h>