first functional filter factory implementation plus test case added
[metaproxy-moved-to-github.git] / src / filter_virt_db.cpp
index 250a7a6..2ea70c4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: filter_virt_db.cpp,v 1.7 2005-10-25 22:44:39 adam Exp $
+/* $Id: filter_virt_db.cpp,v 1.10 2005-10-29 15:54:29 adam Exp $
    Copyright (c) 2005, Index Data.
 
 %LICENSE%
@@ -29,13 +29,14 @@ namespace yp2 {
     namespace filter {
         struct Virt_db_set {
             Virt_db_set(yp2::Session &id, std::string setname,
-                        std::string vhost);
+                        std::string vhost, bool named_result_sets);
             Virt_db_set();
             ~Virt_db_set();
 
             yp2::Session m_backend_session;
-            std::string m_setname;
+            std::string m_backend_setname;
             std::string m_vhost;
+            bool m_named_result_sets;
         };
         struct Virt_db_session {
             Virt_db_session(yp2::Session &id, bool use_vhost);
@@ -68,8 +69,9 @@ namespace yp2 {
 }
 
 yf::Virt_db_set::Virt_db_set(yp2::Session &id, std::string setname,
-                             std::string vhost)
-    :   m_backend_session(id), m_setname(setname), m_vhost(vhost)
+                             std::string vhost, bool named_result_sets)
+    :   m_backend_session(id), m_backend_setname(setname), m_vhost(vhost),
+        m_named_result_sets(named_result_sets)
 {
 }
 
@@ -105,12 +107,11 @@ yf::Virt_db_session::Virt_db_session(yp2::Session &id,
 
 }
 
-yf::Virt_db::Virt_db() {
-    m_p = new Virt_db::Rep;
+yf::Virt_db::Virt_db() : m_p(new Virt_db::Rep)
+{
 }
 
 yf::Virt_db::~Virt_db() {
-    delete m_p;
 }
 
 void yf::Virt_db::Rep::release_session(Package &package)
@@ -122,10 +123,9 @@ void yf::Virt_db::Rep::release_session(Package &package)
 
 void yf::Virt_db::Rep::present(Package &package, Z_APDU *apdu, bool &move_later){
     Session *id = 0;
-    std::string resultSetId;
     Z_PresentRequest *req = apdu->u.presentRequest;
+    std::string resultSetId = req->resultSetId;
     {
-        resultSetId = req->resultSetId;
         boost::mutex::scoped_lock lock(m_sessions_mutex);
         
         Ses_it it = m_sessions.find(package.session());
@@ -217,6 +217,8 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
     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
     {
         boost::mutex::scoped_lock lock(m_sessions_mutex);
 
@@ -270,7 +272,7 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
             rec->which = Z_Records_NSD;
             rec->u.nonSurrogateDiagnostic =
                 zget_DefaultDiagFormat(
-                    odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
+                    odr, YAZ_BIB1_DATABASE_DOES_NOT_EXIST, database.c_str());
             package.response() = apdu;
             
             odr_destroy(odr);
@@ -335,6 +337,31 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
             
             odr_destroy(odr);
         }
+        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
+        {
+            ODR odr = odr_createmem(ODR_ENCODE);
+            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;
+            
+            odr_destroy(odr);
+            return;
+        }
     }
     // sending search to backend
     Package search_package(id, package.origin());
@@ -346,7 +373,9 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
         req->databaseNames[0] = odr_strdup(odr, sep+1);
 
     *req->replaceIndicator = 1;
-    req->resultSetName = odr_strdup(odr, "default");
+
+    std::string backend_resultSetId = "default";
+    req->resultSetName = odr_strdup(odr, backend_resultSetId.c_str());
     search_package.request() = yazpp_1::GDU(apdu);
     
     odr_destroy(odr);
@@ -374,8 +403,9 @@ void yf::Virt_db::Rep::search(Package &package, Z_APDU *apdu, bool &move_later)
     boost::mutex::scoped_lock lock(m_sessions_mutex);
     Ses_it it = m_sessions.find(package.session());
     if (it != m_sessions.end())
-        it->second.m_sets[req->resultSetName] =
-            Virt_db_set(id, req->resultSetName, vhost);
+        it->second.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)