All filters declare a yp2_filter_struct - used for both static and
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 4 Jan 2006 11:19:04 +0000 (11:19 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 4 Jan 2006 11:19:04 +0000 (11:19 +0000)
dynamic loading. RouterFlexML updated to use FilterFactory to load
modules.

25 files changed:
src/Makefile.am
src/ex_filter_frontend_net.cpp
src/ex_router_flexml.cpp
src/factory_static.cpp [new file with mode: 0644]
src/factory_static.hpp [new file with mode: 0644]
src/filter.hpp
src/filter_backend_test.cpp
src/filter_backend_test.hpp
src/filter_dl.cpp
src/filter_frontend_net.cpp
src/filter_frontend_net.hpp
src/filter_log.cpp
src/filter_log.hpp
src/filter_session_shared.cpp
src/filter_session_shared.hpp
src/filter_template.cpp
src/filter_template.hpp
src/filter_virt_db.cpp
src/filter_virt_db.hpp
src/filter_z3950_client.cpp
src/filter_z3950_client.hpp
src/package.cpp
src/package.hpp
src/router_flexml.cpp
src/test_router_flexml.cpp

index 197c06a..f580fc9 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.38 2005-12-10 09:59:10 adam Exp $
+## $Id: Makefile.am,v 1.39 2006-01-04 11:19:04 adam Exp $
 
 MAINTAINERCLEANFILES = Makefile.in config.in config.hpp
 
@@ -25,6 +25,7 @@ libyp2_la_SOURCES = \
        filter_backend_test.cpp filter_backend_test.hpp \
        filter_session_shared.cpp filter_session_shared.hpp \
        filter_template.cpp filter_template.hpp \
+       factory_static.cpp factory_static.hpp \
        pipe.cpp pipe.hpp \
        util.cpp util.hpp
 
index 38ac433..b77a063 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ex_filter_frontend_net.cpp,v 1.19 2005-12-09 11:27:59 adam Exp $
+/* $Id: ex_filter_frontend_net.cpp,v 1.20 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -104,11 +104,12 @@ int main(int argc, char **argv)
             // put Virt db filter in router
             yp2::filter::Virt_db filter_virt_db;
             filter_virt_db.add_map_db2vhost("gils", "indexdata.dk/gils");
-            filter_virt_db.add_map_db2vhost("Default", "localhost:9100/Default");
-           router.append(filter_virt_db);
+            filter_virt_db.add_map_db2vhost("Default", "localhost:9999/Default");
+            filter_virt_db.add_map_db2vhost("2", "localhost:9999/2");
+           // router.append(filter_virt_db);
 
-//            yp2::filter::Session_shared filter_session_shared;
-//         router.append(filter_session_shared);
+            yp2::filter::SessionShared filter_session_shared;
+            //router.append(filter_session_shared);
 
             yp2::filter::Log filter_log_back("BACK");
             router.append(filter_log_back);
index c7cffb3..013aa32 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ex_router_flexml.cpp,v 1.2 2005-10-31 11:59:08 marc Exp $
+/* $Id: ex_router_flexml.cpp,v 1.3 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -14,8 +14,8 @@
 int main(int argc, char **argv)
 {
     try 
-   {
-       
+    {
+        
        std::string xmlconf = "<?xml version=\"1.0\"?>\n"
            "<yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">\n"
            "<start route=\"start\"/>\n"
diff --git a/src/factory_static.cpp b/src/factory_static.cpp
new file mode 100644 (file)
index 0000000..ff70983
--- /dev/null
@@ -0,0 +1,53 @@
+/* $Id: factory_static.cpp,v 1.1 2006-01-04 11:19:04 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+
+*/
+
+#include <iostream>
+#include <stdexcept>
+
+#include "factory_static.hpp"
+
+#include "config.hpp"
+#include "filter.hpp"
+#include "package.hpp"
+
+#include "filter_factory.hpp"
+
+#include "filter_backend_test.hpp"
+#include "filter_frontend_net.hpp"
+#include "filter_log.hpp"
+#include "filter_session_shared.hpp"
+#include "filter_template.hpp"
+#include "filter_virt_db.hpp"
+#include "filter_z3950_client.hpp"
+
+yp2::FactoryStatic::FactoryStatic(yp2::FilterFactory &factory)
+{
+    const struct yp2_filter_struct *buildins[] = {
+        &yp2_filter_backend_test,
+        &yp2_filter_frontend_net,        
+        &yp2_filter_log,
+        &yp2_filter_session_shared,
+        &yp2_filter_template,
+        &yp2_filter_virt_db,
+        &yp2_filter_z3950_client,
+        0
+    };
+    int i;
+
+    for (i = 0; buildins[i]; i++)
+        factory.add_creator(buildins[i]->type, buildins[i]->creator);
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
diff --git a/src/factory_static.hpp b/src/factory_static.hpp
new file mode 100644 (file)
index 0000000..9433979
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Id: factory_static.hpp,v 1.1 2006-01-04 11:19:04 adam Exp $
+   Copyright (c) 2005, Index Data.
+
+%LICENSE%
+ */
+
+#ifndef FACTORY_STATIC_HPP
+#define FACTORY_STATIC_HPP
+
+#include "filter_factory.hpp"
+
+namespace yp2 {
+    class FactoryStatic {
+    public:
+        FactoryStatic(yp2::FilterFactory &factory);
+    };
+}
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * c-file-style: "stroustrup"
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
index c2855bd..5635eaf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter.hpp,v 1.10 2005-12-10 09:59:10 adam Exp $
+/* $Id: filter.hpp,v 1.11 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -38,6 +38,7 @@ namespace yp2 {
 
 struct yp2_filter_struct {
     int ver;
+    const char *type;
     yp2::filter::Base* (*creator)();
 };
 
index 577e2b1..d622530 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_backend_test.cpp,v 1.10 2005-11-10 23:10:42 adam Exp $
+/* $Id: filter_backend_test.cpp,v 1.11 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -142,6 +142,19 @@ void yf::Backend_test::process(Package &package) const
         m_p->m_sessions.release(package.session());
 }
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::Backend_test;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_backend_test = {
+        0,
+        "backend_test",
+        filter_creator
+    };
+}
+
 
 /*
  * Local variables:
index 6842af8..66dcc5d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_backend_test.hpp,v 1.5 2005-11-10 23:10:42 adam Exp $
+/* $Id: filter_backend_test.hpp,v 1.6 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -25,6 +25,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_backend_test;
+}
+
 #endif
 /*
  * Local variables:
index 7ce559b..04a088e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_dl.cpp,v 1.1 2005-12-10 09:59:10 adam Exp $
+/* $Id: filter_dl.cpp,v 1.2 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -30,8 +30,9 @@ static yp2::filter::Base* filter_creator()
 }
 
 extern "C" {
-    struct yp2_filter_struct yp2_filter_dl = {
+    const struct yp2_filter_struct yp2_filter_dl = {
         0,
+        "dl",
         filter_creator
     };
 }
index 68f28ba..8aa35a2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_frontend_net.cpp,v 1.9 2005-11-07 21:57:10 adam Exp $
+/* $Id: filter_frontend_net.cpp,v 1.10 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -285,6 +285,19 @@ int &yp2::filter::FrontendNet::listen_duration()
     return m_listen_duration;
 }
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::FrontendNet;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_frontend_net = {
+        0,
+        "frontend_net",
+        filter_creator
+    };
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
index 89478a2..0f6abe9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_frontend_net.hpp,v 1.8 2005-11-07 12:31:43 adam Exp $
+/* $Id: filter_frontend_net.hpp,v 1.9 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -31,6 +31,9 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_frontend_net;
+}
 
 #endif
 /*
index 2ed0b96..4142be7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_log.cpp,v 1.9 2005-12-11 17:23:05 adam Exp $
+/* $Id: filter_log.cpp,v 1.10 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -98,6 +98,20 @@ void yf::Log::process(Package &package) const
     }
 }
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::Log;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_log = {
+        0,
+        "log",
+        filter_creator
+    };
+}
+
+
 /*
  * Local variables:
  * c-basic-offset: 4
index 28545eb..a829d80 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_log.hpp,v 1.10 2005-12-11 17:23:05 adam Exp $
+/* $Id: filter_log.hpp,v 1.11 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -25,6 +25,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_log;
+}
+
 #endif
 /*
  * Local variables:
index abd2214..0936bc0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_session_shared.cpp,v 1.2 2005-12-02 11:05:08 adam Exp $
+/* $Id: filter_session_shared.cpp,v 1.3 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -28,32 +28,32 @@ namespace yf = yp2::filter;
 
 namespace yp2 {
     namespace filter {
-        class Session_shared::Rep {
-            friend class Session_shared;
+        class SessionShared::Rep {
+            friend class SessionShared;
             void handle_init(Z_InitRequest *req, Package &package);
             void handle_search(Z_SearchRequest *req, Package &package);
         public:
-            typedef boost::shared_ptr<Session_shared::List> SharedList;
+            typedef boost::shared_ptr<SessionShared::List> SharedList;
 
-            typedef std::map<Session_shared::InitKey,SharedList> InitListMap;
+            typedef std::map<SessionShared::InitKey,SharedList> InitListMap;
             InitListMap m_init_list_map;
 
             typedef std::map<Session,SharedList> SessionListMap;
             SessionListMap m_session_list_map;
 
         };
-        class Session_shared::InitKey {
-            friend class Session_shared;
-            friend class Session_shared::Rep;
+        class SessionShared::InitKey {
+            friend class SessionShared;
+            friend class SessionShared::Rep;
             std::string m_vhost;
             std::string m_open;
             std::string m_user;
             std::string m_group;
             std::string m_password;
         public:
-            bool operator < (const Session_shared::InitKey &k) const;
+            bool operator < (const SessionShared::InitKey &k) const;
         };
-        class Session_shared::List {
+        class SessionShared::List {
         public:
             yazpp_1::GDU m_init_response;  // init response for backend 
             Session m_session;             // session for backend
@@ -65,7 +65,7 @@ namespace yp2 {
 
 using namespace yp2;
 
-bool yf::Session_shared::InitKey::operator < (const Session_shared::InitKey
+bool yf::SessionShared::InitKey::operator < (const SessionShared::InitKey
                                               &k) const 
 {
     if (m_vhost < k.m_vhost)
@@ -95,15 +95,15 @@ bool yf::Session_shared::InitKey::operator < (const Session_shared::InitKey
     return false;
 }
 
-yf::Session_shared::Session_shared() : m_p(new Rep)
+yf::SessionShared::SessionShared() : m_p(new Rep)
 {
 }
 
-yf::Session_shared::~Session_shared()
+yf::SessionShared::~SessionShared()
 {
 }
 
-void yf::Session_shared::Rep::handle_search(Z_SearchRequest *req,
+void yf::SessionShared::Rep::handle_search(Z_SearchRequest *req,
                                             Package &package)
 {
     yaz_log(YLOG_LOG, "Got search");
@@ -129,11 +129,11 @@ void yf::Session_shared::Rep::handle_search(Z_SearchRequest *req,
     package.response() = search_package.response();
 }
 
-void yf::Session_shared::Rep::handle_init(Z_InitRequest *req, Package &package)
+void yf::SessionShared::Rep::handle_init(Z_InitRequest *req, Package &package)
 {
     yaz_log(YLOG_LOG, "Got init");
 
-    Session_shared::InitKey key;
+    SessionShared::InitKey key;
     const char *vhost =
         yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
     if (vhost)
@@ -176,7 +176,7 @@ void yf::Session_shared::Rep::handle_init(Z_InitRequest *req, Package &package)
         yaz_log(YLOG_LOG, "New KEY");
 
         // building new package with original init and new session 
-        SharedList l(new Session_shared::List);  // new session for backend
+        SharedList l(new SessionShared::List);  // new session for backend
 
         Package init_package(l->m_session, package.origin());
         init_package.copy_filter(package);
@@ -210,7 +210,7 @@ void yf::Session_shared::Rep::handle_init(Z_InitRequest *req, Package &package)
     }
 }
 
-void yf::Session_shared::process(Package &package) const
+void yf::SessionShared::process(Package &package) const
 {
     // don't tell the backend if the "fronent" filter closes..
     // we want to keep them alive
@@ -251,6 +251,20 @@ void yf::Session_shared::process(Package &package) const
         package.move();  // Not Z39.50 or not Init
 }
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::SessionShared;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_session_shared = {
+        0,
+        "session_shared",
+        filter_creator
+    };
+}
+
+
 
 /*
  * Local variables:
index ce79af1..c584467 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_session_shared.hpp,v 1.1 2005-11-14 23:35:22 adam Exp $
+/* $Id: filter_session_shared.hpp,v 1.2 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
 
 namespace yp2 {
     namespace filter {
-        class Session_shared : public Base {
+        class SessionShared : public Base {
             class Rep;
             class InitKey;
             class List;
         public:
-            ~Session_shared();
-            Session_shared();
+            ~SessionShared();
+            SessionShared();
             void process(yp2::Package & package) const;
         private:
             boost::scoped_ptr<Rep> m_p;
@@ -27,6 +27,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_session_shared;
+}
+
 #endif
 /*
  * Local variables:
index 4d47dab..07c0d2a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_template.cpp,v 1.2 2005-12-11 17:20:18 adam Exp $
+/* $Id: filter_template.cpp,v 1.3 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -43,6 +43,19 @@ void yf::Template::process(Package &package) const
     package.move();
 }
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::Template;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_template = {
+        0,
+        "template",
+        filter_creator
+    };
+}
+
 
 /*
  * Local variables:
index 5fcbcfd..f6b2e38 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_template.hpp,v 1.2 2005-12-11 17:20:18 adam Exp $
+/* $Id: filter_template.hpp,v 1.3 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -25,6 +25,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_template;
+}
+
 #endif
 /*
  * Local variables:
index 3dc1337..3ba8487 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_virt_db.cpp,v 1.15 2005-12-19 08:42:59 adam Exp $
+/* $Id: filter_virt_db.cpp,v 1.16 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -11,6 +11,7 @@
 #include "package.hpp"
 
 #include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
 
 #include "util.hpp"
 #include "filter_virt_db.hpp"
@@ -49,6 +50,19 @@ namespace yp2 {
             Virt_db_map();
             std::string m_vhost;
         };
+        struct Frontend {
+            Frontend();
+            ~Frontend();
+            yp2::Session m_session;
+            bool m_use_vhost;
+            bool m_in_use;
+            std::map<std::string,Virt_db_set> m_sets;
+            void search(Package &package, Z_APDU *apdu,
+                        const std::map<std::string, Virt_db_map> &maps);
+            void present(Package &package, Z_APDU *apdu);
+            void close(Package &package);
+            typedef std::map<std::string,Virt_db_set>::iterator Sets_it;
+        };            
         class Virt_db::Rep {
             friend class Virt_db;
             
@@ -56,6 +70,9 @@ namespace yp2 {
             void init(Package &package, Z_APDU *apdu, bool &move_later);
             void search(Package &package, Z_APDU *apdu, bool &move_later);
             void present(Package &package, Z_APDU *apdu, bool &move_later);
+
+            Frontend *get_frontend(Package &package);
+            void release_frontend(Package &package);
         private:
             boost::mutex m_sessions_mutex;
             std::map<yp2::Session,Virt_db_session>m_sessions;
@@ -63,12 +80,87 @@ namespace yp2 {
 
             typedef std::map<yp2::Session,Virt_db_session>::iterator Ses_it;
             typedef std::map<std::string,Virt_db_set>::iterator Sets_it;
+
+            boost::mutex m_mutex;
+            boost::condition m_cond_session_ready;
+            std::map<yp2::Session,Frontend *> m_clients;
         };
     }
 }
 
 using namespace yp2;
 
+yf::Frontend::Frontend()
+{
+    m_use_vhost = false;
+}
+
+void yf::Frontend::close(Package &package)
+{
+    Sets_it sit = m_sets.begin();
+    for (; sit != m_sets.end(); sit++)
+    {
+        sit->second.m_backend_session.close();
+        Package close_package(sit->second.m_backend_session, package.origin());
+        close_package.copy_filter(package);
+        
+        close_package.move();
+    }
+}
+
+yf::Frontend::~Frontend()
+{
+}
+
+yf::Frontend *yf::Virt_db::Rep::get_frontend(Package &package)
+{
+    boost::mutex::scoped_lock lock(m_mutex);
+
+    std::map<yp2::Session,yf::Frontend *>::iterator it;
+    
+    while(true)
+    {
+        it = m_clients.find(package.session());
+        if (it == m_clients.end())
+            break;
+        
+        if (!it->second->m_in_use)
+        {
+            it->second->m_in_use = true;
+            return it->second;
+        }
+        m_cond_session_ready.wait(lock);
+    }
+    Frontend *f = new Frontend;
+    m_clients[package.session()] = f;
+    f->m_in_use = true;
+    return f;
+}
+
+
+void yf::Virt_db::Rep::release_frontend(Package &package)
+{
+    boost::mutex::scoped_lock lock(m_mutex);
+    std::map<yp2::Session,yf::Frontend *>::iterator it;
+    
+    it = m_clients.find(package.session());
+    if (it != m_clients.end())
+    {
+        if (package.session().is_closed())
+        {
+            std::cout << "Closing IT\n";
+            it->second->close(package);
+            delete it->second;
+            m_clients.erase(it);
+        }
+        else
+        {
+            it->second->m_in_use = false;
+        }
+        m_cond_session_ready.notify_all();
+    }
+}
+
 yf::Virt_db_set::Virt_db_set(yp2::Session &id, std::string setname,
                              std::string vhost, bool named_result_sets)
     :   m_backend_session(id), m_backend_setname(setname), m_vhost(vhost),
@@ -213,6 +305,64 @@ void yf::Virt_db::Rep::present(Package &package, Z_APDU *apdu, bool &move_later)
     delete id;
 }
 
+void yf::Frontend::present(Package &package, Z_APDU *apdu)
+{
+    Session *id = 0;
+    Z_PresentRequest *req = apdu->u.presentRequest;
+    std::string resultSetId = req->resultSetId;
+    yp2::odr odr;
+
+    Sets_it sets_it = m_sets.find(resultSetId);
+    if (sets_it == m_sets.end())
+    {
+        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,
+                resultSetId.c_str());
+        package.response() = apdu;
+        
+        return;
+    }
+    id = new yp2::Session(sets_it->second.m_backend_session);
+    
+    // sending present to backend
+    Package present_package(*id, package.origin());
+    present_package.copy_filter(package);
+    
+    req->resultSetId = odr_strdup(odr, "default");
+    present_package.request() = yazpp_1::GDU(apdu);
+
+    present_package.move();
+
+    if (present_package.session().is_closed())
+    {
+        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_RESULT_SET_NO_LONGER_EXISTS_UNILATERALLY_DELETED_BY_,
+                resultSetId.c_str());
+        package.response() = apdu;
+        
+        m_sets.erase(resultSetId);
+    }
+    else
+    {
+        package.response() = present_package.response();
+    }
+    delete id;
+}
+
 void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
 {
     Z_SearchRequest *req = apdu->u.searchRequest;
@@ -386,6 +536,159 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
                         support_named_result_sets);
 }
 
+void yf::Frontend::search(Package &package, Z_APDU *apdu,
+                          const std::map<std::string, Virt_db_map> &maps)
+{
+    Z_SearchRequest *req = apdu->u.searchRequest;
+    std::string vhost;
+    std::string database;
+    std::string resultSetId = req->resultSetName;
+    bool support_named_result_sets = false;  // whether backend supports it
+    yp2::odr odr;
+    
+    if (req->num_databaseNames != 1)
+    {   // exactly one database must be specified
+        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_TOO_MANY_DATABASES_SPECIFIED, 0);
+        package.response() = apdu;
+        
+        return;
+    }
+    database = req->databaseNames[0];
+    std::map<std::string, Virt_db_map>::const_iterator map_it;
+    map_it = maps.find(database);
+    if (map_it == maps.end()) 
+    {   // no map for database: return diagnostic
+        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_DOES_NOT_EXIST, database.c_str());
+        package.response() = apdu;
+        
+        return;
+    }
+    if (*req->replaceIndicator == 0)
+    {
+        Sets_it sets_it = m_sets.find(req->resultSetName);
+        if (sets_it != m_sets.end())
+        {
+            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,
+                    0);
+            package.response() = apdu;
+            
+            return;
+        }
+    }
+    m_sets.erase(req->resultSetName);
+    vhost = map_it->second.m_vhost;
+    // we might look for an existing session with same vhost
+    Session id;
+    const char *vhost_cstr = vhost.c_str();
+    if (true)
+    {  // sending init to backend
+        Package init_package(id, package.origin());
+        init_package.copy_filter(package);
+        
+        Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
+        
+        yaz_oi_set_string_oidval(&init_apdu->u.initRequest->otherInfo, odr,
+                                 VAL_PROXY, 1, vhost_cstr);
+        
+        init_package.request() = init_apdu;
+
+        init_package.move();  // sending init 
+
+        if (init_package.session().is_closed())
+        {
+            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, database.c_str());
+            package.response() = apdu;
+        }
+        Z_GDU *gdu = init_package.response().get();
+        // we hope to get an init response
+        if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
+            Z_APDU_initResponse)
+        {
+            if (ODR_MASK_GET(gdu->u.z3950->u.initResponse->options,
+                             Z_Options_namedResultSets))
+                support_named_result_sets = true;
+        }
+        else
+        {
+            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, database.c_str());
+            package.response() = apdu;
+            
+            return;
+        }
+    }
+    // sending search to backend
+    Package search_package(id, package.origin());
+
+    search_package.copy_filter(package);
+    const char *sep = strchr(vhost_cstr, '/');
+    if (sep)
+        req->databaseNames[0] = odr_strdup(odr, sep+1);
+
+    *req->replaceIndicator = 1;
+
+    std::string backend_resultSetId = "default";
+    req->resultSetName = odr_strdup(odr, backend_resultSetId.c_str());
+    search_package.request() = yazpp_1::GDU(apdu);
+    
+    search_package.move();
+
+    if (search_package.session().is_closed())
+    {
+        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, database.c_str());
+        package.response() = apdu;
+        
+        return;
+    }
+    package.response() = search_package.response();
+    
+    m_sets[resultSetId] =
+        Virt_db_set(id, backend_resultSetId, vhost,
+                    support_named_result_sets);
+}
+
 void yf::Virt_db::Rep::init(Package &package, Z_APDU *apdu, bool &move_later)
 {
     release_session(package);
@@ -428,7 +731,7 @@ void yf::Virt_db::Rep::init(Package &package, Z_APDU *apdu, bool &move_later)
     else
     {
         m_sessions[package.session()] = Virt_db_session(package.session(), true);
-        move_later = true;
+        package.move();
     }
 }
 
@@ -437,6 +740,82 @@ void yf::Virt_db::add_map_db2vhost(std::string db, std::string vhost)
     m_p->m_maps[db] = Virt_db_map(vhost);
 }
 
+#if 0
+void yf::Virt_db::process(Package &package) const
+{
+    yf::Frontend *f = m_p->get_frontend(package);
+    if (f)
+    {
+        Z_GDU *gdu = package.request().get();
+        if (!gdu || gdu->which != Z_GDU_Z3950 || f->m_use_vhost)
+            package.move();
+        else
+        {
+            Z_APDU *apdu = gdu->u.z3950;
+            if (apdu->which == Z_APDU_initRequest)
+            {
+                Z_InitRequest *req = apdu->u.initRequest;
+                
+                const char *vhost =
+                    yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
+                if (!vhost)
+                {
+                    yp2::odr odr;
+                    Z_APDU *apdu = zget_APDU(odr, Z_APDU_initResponse);
+                    Z_InitResponse *resp = apdu->u.initResponse;
+                    
+                    int i;
+                    static const int masks[] = {
+                        Z_Options_search, Z_Options_present, Z_Options_namedResultSets, -1 
+                    };
+                    for (i = 0; masks[i] != -1; i++)
+                        if (ODR_MASK_GET(req->options, masks[i]))
+                            ODR_MASK_SET(resp->options, masks[i]);
+                    
+                    static const int versions[] = {
+                        Z_ProtocolVersion_1,
+                        Z_ProtocolVersion_2,
+                        Z_ProtocolVersion_3,
+                        -1
+                    };
+                    for (i = 0; versions[i] != -1; i++)
+                        if (ODR_MASK_GET(req->protocolVersion, versions[i]))
+                            ODR_MASK_SET(resp->protocolVersion, versions[i]);
+                        else
+                            break;
+                    
+                    package.response() = apdu;
+                }
+                else
+                {
+                    f->m_use_vhost = true;
+                    package.move();
+                }
+            }
+            else if (apdu->which == Z_APDU_searchRequest)
+            {
+                f->search(package, apdu, m_p->m_maps);
+            }
+            else if (apdu->which == Z_APDU_presentRequest)
+            {
+                f->present(package, apdu);
+            }
+            else
+            {
+                yp2::odr odr;
+                
+                package.response() = odr.create_close(
+                    Z_Close_protocolError,
+                    "unsupported APDU in filter_virt_db");
+                
+                package.session().close();
+            }
+        }
+    }
+    m_p->release_frontend(package);
+}
+
+#else
 void yf::Virt_db::process(Package &package) const
 {
     Z_GDU *gdu = package.request().get();
@@ -481,6 +860,21 @@ void yf::Virt_db::process(Package &package) const
             package.move();
     }
 }
+#endif
+
+
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::Virt_db;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_virt_db = {
+        0,
+        "virt_db",
+        filter_creator
+    };
+}
 
 
 /*
index 8c514f6..9e2991e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_virt_db.hpp,v 1.4 2005-10-31 09:40:18 marc Exp $
+/* $Id: filter_virt_db.hpp,v 1.5 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -28,6 +28,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_virt_db;
+}
+
 #endif
 /*
  * Local variables:
index 21e4325..d98a5b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_z3950_client.cpp,v 1.13 2006-01-03 15:34:10 adam Exp $
+/* $Id: filter_z3950_client.cpp,v 1.14 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -326,6 +326,19 @@ void yf::Z3950Client::process(Package &package) const
 }
 
 
+static yp2::filter::Base* filter_creator()
+{
+    return new yp2::filter::Z3950Client;
+}
+
+extern "C" {
+    const struct yp2_filter_struct yp2_filter_z3950_client = {
+        0,
+        "z3950_client",
+        filter_creator
+    };
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
index a65b021..3f254c6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_z3950_client.hpp,v 1.5 2005-11-10 23:10:42 adam Exp $
+/* $Id: filter_z3950_client.hpp,v 1.6 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -26,6 +26,10 @@ namespace yp2 {
     }
 }
 
+extern "C" {
+    extern const struct yp2_filter_struct yp2_filter_z3950_client;
+}
+
 #endif
 /*
  * Local variables:
index aa38db0..3f99491 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: package.cpp,v 1.1 2005-11-11 15:00:25 adam Exp $
+/* $Id: package.cpp,v 1.2 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -40,18 +40,17 @@ yp2::Session & yp2::Package::session()
 }
 
 
-unsigned int yp2::Package::data() const
+int yp2::Package::data() const
 {
     return m_data;
 }
 
-unsigned int & yp2::Package::data()
+int & yp2::Package::data()
 {
     return m_data;
 }
         
-
-yp2::Package & yp2::Package::data(const unsigned int & data)
+yp2::Package & yp2::Package::data(const int & data)
 {
     m_data = data;
     return *this;
index c5e63ff..b104c85 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: package.hpp,v 1.10 2005-11-11 15:00:25 adam Exp $
+/* $Id: package.hpp,v 1.11 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -44,14 +44,13 @@ namespace yp2 {
         yp2::Session & session();
         
         /// get function - right val in assignment
-        unsigned int data() const;
+        int data() const;
 
-        
         /// set function - left val in assignment
-        unsigned int & data();
+        int & data();
         
         /// set function - can be chained
-        Package & data(const unsigned int & data);
+        Package & data(const int & data);
         
         /// get function - right val in assignment
         Origin origin() const;
@@ -77,7 +76,7 @@ namespace yp2 {
         
         const filter::Base *m_filter;
         const Router *m_router;
-        unsigned int m_data;
+        int m_data;
         
         yazpp_1::GDU m_request_gdu;
         yazpp_1::GDU m_response_gdu;
index 47501df..fc3c6f0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: router_flexml.cpp,v 1.6 2005-12-08 22:32:57 adam Exp $
+/* $Id: router_flexml.cpp,v 1.7 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -6,6 +6,8 @@
 
 #include "config.hpp"
 #include "router_flexml.hpp"
+#include "filter_factory.hpp"
+#include "factory_static.hpp"
 
 #include <iostream>
 #include <map>
@@ -54,6 +56,7 @@ namespace yp2 {
         const xmlNode* jump_to_next(const xmlNode* node, int xml_node_type);
         
         const xmlNode* jump_to_children(const xmlNode* node, int xml_node_type);
+        FilterFactory m_factory;
     };
 }
 
@@ -139,6 +142,32 @@ void yp2::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc)
         filter_nr++;
         std::cout << "processing /yp2/filters/filter[" 
                   << filter_nr << "]" << std::endl;
+
+        const struct _xmlAttr *attr;
+        std::string id_value;
+        std::string type_value;
+        for (attr = node2->properties; attr; attr = attr->next)
+        {
+            std::string name = std::string((const char *) attr->name);
+            std::string value;
+
+            if (attr->children && attr->children->type == XML_TEXT_NODE)
+                value = std::string((const char *)attr->children->content);
+
+            if (name == "id")
+                id_value = value;
+            else if (name == "type")
+                type_value = value;
+            else
+                throw XMLError("Error. Only attribute id or type allowed in filter element. Got " + name);
+                
+            std::cout << "attr " << name << "=" << value << "\n";
+
+            //const xmlNode *val;
+        }
+
+        yp2::filter::Base* filter_base = m_factory.create(type_value);
+
         node2 = jump_to_next(node2, XML_ELEMENT_NODE);
     }
     
@@ -193,6 +222,10 @@ yp2::RouterFleXML::Rep::Rep() :
 yp2::RouterFleXML::RouterFleXML(std::string xmlconf) 
     : m_p(new Rep)
 {            
+    {
+        yp2::FactoryStatic fs(m_p->m_factory);
+    }
+
     LIBXML_TEST_VERSION;
     
     xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(),
index 000ee0b..e6ee8fc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: test_router_flexml.cpp,v 1.7 2005-12-08 22:32:58 adam Exp $
+/* $Id: test_router_flexml.cpp,v 1.8 2006-01-04 11:19:04 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -10,6 +10,7 @@
 
 #include "filter.hpp"
 #include "router_flexml.hpp"
+#include "filter_factory.hpp"
 
 #define BOOST_AUTO_TEST_MAIN
 #include <boost/test/auto_unit_test.hpp>
@@ -30,7 +31,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_1 )
             "<yp2 xmlns=\"http://indexdata.dk/yp2/config/1\">\n"
             "  <start route=\"start\"/>\n"
             "  <filters>\n"
-            "    <filter id=\"front_default\" type=\"frontend-net\">\n"
+            "    <filter id=\"front_default\" type=\"frontend_net\">\n"
             "      <port>210</port>\n"
             "    </filter>\n"
             "    <filter id=\"log_cout\" type=\"log\">\n"
@@ -46,6 +47,14 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_1 )
             "</yp2>\n";
         yp2::RouterFleXML rflexml(xmlconf);
     }
+    catch ( yp2::RouterFleXML::XMLError &e) {
+        std::cout << "XMLError: " << e.what() << "\n";
+        BOOST_CHECK (false);
+    }
+    catch ( yp2::FilterFactoryException &e) {
+        std::cout << "FilterFactoryException: " << e.what() << "\n";
+        BOOST_CHECK (false);
+    }
     catch ( ... ) {
         BOOST_CHECK (false);
     }
@@ -60,7 +69,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_2 )
             "<y:yp2 xmlns:y=\"http://indexdata.dk/yp2/config/1\">\n"
             "  <start route=\"start\"/>\n"
             "  <filters>\n"
-            "    <filter id=\"front_default\" type=\"frontend-net\">\n"
+            "    <filter id=\"front_default\" type=\"frontend_net\">\n"
             "      <port>210</port>\n";
         
         yp2::RouterFleXML rflexml(xmlconf_invalid);
@@ -82,7 +91,7 @@ BOOST_AUTO_UNIT_TEST( test_router_flexml_3 )
             "<y:yp2 xmlns:y=\"http://indexdata.dk/yp2/config/1\">\n"
             "  <y:start route=\"start\"/>\n"
             "  <y:filters>\n"
-            "    <y:filter id=\"front_default\" type=\"frontend-net\">\n"
+            "    <y:filter id=\"front_default\" type=\"frontend_net\">\n"
             "      <port>210</port>\n"
             "    </y:filter>\n"
             "    <y:filter id=\"log_cout\" type=\"log\">\n"