Added yp2::PlainFile class which reads Unix-style plain text files.
[metaproxy-moved-to-github.git] / src / filter_virt_db.cpp
index d861701..98ed55a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_virt_db.cpp,v 1.29 2006-01-17 13:34:51 adam Exp $
+/* $Id: filter_virt_db.cpp,v 1.33 2006-01-18 10:57:27 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -56,6 +56,7 @@ namespace yp2 {
             yp2::Session m_session;
             bool m_is_virtual;
             bool m_in_use;
+            yazpp_1::GDU m_init_gdu;
             std::list<BackendPtr> m_backend_list;
             std::map<std::string,Virt_db::Set> m_sets;
 
@@ -70,6 +71,7 @@ namespace yp2 {
                 std::list<std::string> databases);
             BackendPtr create_backend_from_databases(
                 std::list<std::string> databases,
+                int &error_code,
                 std::string &failing_database);
             
             BackendPtr init_backend(std::list<std::string> database,
@@ -111,7 +113,7 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::lookup_backend_from_databases(
 }
 
 yf::Virt_db::BackendPtr yf::Virt_db::Frontend::create_backend_from_databases(
-    std::list<std::string> databases, std::string &failing_database)
+    std::list<std::string> databases, int &error_code, std::string &addinfo)
 {
     BackendPtr b(new Backend);
     std::list<std::string>::const_iterator db_it = databases.begin();
@@ -120,6 +122,8 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::create_backend_from_databases(
     b->m_frontend_databases = databases;
     b->m_named_result_sets = false;
 
+    bool first_route = true;
+
     std::map<std::string,bool> targets_dedup;
     for (; db_it != databases.end(); db_it++)
     {
@@ -127,7 +131,8 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::create_backend_from_databases(
         map_it = m_p->m_maps.find(*db_it);
         if (map_it == m_p->m_maps.end())  // database not found
         {
-            failing_database = *db_it;
+            error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
+            addinfo = *db_it;
             BackendPtr ptr;
             return ptr;
         }
@@ -135,7 +140,17 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::create_backend_from_databases(
             map_it->second.m_targets.begin();
         for (; t_it != map_it->second.m_targets.end(); t_it++)
             targets_dedup[*t_it] = true;
+
+        // see if we have a route conflict.
+        if (!first_route && b->m_route != map_it->second.m_route)
+        {
+            // we have a conflict.. 
+            error_code =  YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP;
+            BackendPtr ptr;
+            return ptr;
+        }
         b->m_route = map_it->second.m_route;
+        first_route = false;
     }
     std::map<std::string,bool>::const_iterator tm_it = targets_dedup.begin();
     for (; tm_it != targets_dedup.end(); tm_it++)
@@ -148,14 +163,10 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::init_backend(
     std::list<std::string> databases, Package &package,
     int &error_code, std::string &addinfo)
 {
-    std::string failing_database;
-    BackendPtr b = create_backend_from_databases(databases, failing_database);
+    BackendPtr b = create_backend_from_databases(databases, error_code,
+                                                 addinfo);
     if (!b)
-    {
-        error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
-        addinfo = failing_database;
         return b;
-    }
     Package init_package(b->m_backend_session, package.origin());
     init_package.copy_filter(package);
 
@@ -163,16 +174,19 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::init_backend(
 
     Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
 
-    std::list<std::string>::const_iterator t_it = b->m_targets.begin();
-    int cat = 1;
-    for (; t_it != b->m_targets.end(); t_it++, cat++)
-    {
-        yaz_oi_set_string_oidval(&init_apdu->u.initRequest->otherInfo, odr,
-                                 VAL_PROXY, cat, t_it->c_str());
-    }
-        
+    yp2::util::set_vhost_otherinfo(&init_apdu->u.initRequest->otherInfo, odr,
+                                   b->m_targets);
     Z_InitRequest *req = init_apdu->u.initRequest;
 
+    // copy stuff from Frontend Init Request
+    Z_GDU *org_gdu = m_init_gdu.get();
+    Z_InitRequest *org_init = org_gdu->u.z3950->u.initRequest;
+
+    req->idAuthentication = org_init->idAuthentication;
+    req->implementationId = org_init->implementationId;
+    req->implementationName = org_init->implementationName;
+    req->implementationVersion = org_init->implementationVersion;
+
     ODR_MASK_SET(req->options, Z_Options_search);
     ODR_MASK_SET(req->options, Z_Options_present);
     ODR_MASK_SET(req->options, Z_Options_namedResultSets);
@@ -185,24 +199,24 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::init_backend(
     init_package.request() = init_apdu;
     
     init_package.move(b->m_route);  // sending init 
-    
-    if (init_package.session().is_closed())
-    {
-        error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
-        // addinfo = database;
-        BackendPtr null;
-        return null;
-    }
+
     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))
+        Z_InitResponse *res = gdu->u.z3950->u.initResponse;
+        if (ODR_MASK_GET(res->options, Z_Options_namedResultSets))
         {
             b->m_named_result_sets = true;
         }
+        std::cout << "GOT INIT res=" << *res->result << "\n";
+        if (!*res->result)
+        {
+            yp2::util::get_init_diagnostics(res, error_code, addinfo);
+            BackendPtr null;
+            return null; 
+        }
     }
     else
     {
@@ -211,6 +225,14 @@ yf::Virt_db::BackendPtr yf::Virt_db::Frontend::init_backend(
         BackendPtr null;
         return null;
     }        
+    if (init_package.session().is_closed())
+    {
+        error_code = YAZ_BIB1_DATABASE_UNAVAILABLE;
+        // addinfo = database;
+        BackendPtr null;
+        return null;
+    }
+
     m_backend_list.push_back(b);
     return b;
 }
@@ -468,7 +490,7 @@ void yf::Virt_db::Frontend::present(Package &package, Z_APDU *apdu_req)
     
     present_package.request() = yazpp_1::GDU(apdu_req);
 
-    present_package.move();
+    present_package.move(sets_it->second.m_backend->m_route);
 
     if (present_package.session().is_closed())
     {
@@ -578,10 +600,12 @@ void yf::Virt_db::process(Package &package) const
     {
         Z_InitRequest *req = gdu->u.z3950->u.initRequest;
         
-        const char *vhost =
-            yaz_oi_get_string_oidval(&req->otherInfo, VAL_PROXY, 1, 0);
-        if (!vhost)
+        std::list<std::string> vhosts;
+        yp2::util::get_vhost_otherinfo(&req->otherInfo, false, vhosts);
+        if (vhosts.size() == 0)
         {
+            f->m_init_gdu = gdu;
+            
             yp2::odr odr;
             Z_APDU *apdu = odr.create_initResponse(gdu->u.z3950, 0, 0);
             Z_InitResponse *resp = apdu->u.initResponse;