Fix bug #4612: session_shared returns diagnostic 2
[metaproxy-moved-to-github.git] / src / filter_session_shared.cpp
index f0f84f7..4d4606a 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of Metaproxy.
-   Copyright (C) 2005-2010 Index Data
+   Copyright (C) 2005-2011 Index Data
 
 Metaproxy is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
@@ -85,6 +85,7 @@ namespace metaproxy_1 {
                 const yazpp_1::Yaz_Z_Query &query);
             bool search(
                 Package &frontend_package,
+                Package &search_package,
                 const Z_APDU *apdu_req,
                 const BackendInstancePtr bp,
                 Z_Records **z_records);
@@ -103,6 +104,7 @@ namespace metaproxy_1 {
             time_t m_time_last_use;
             mp::Package * m_close_package;
             ~BackendInstance();
+            void timestamp();
         };
         // backends of some class (all with same InitKey)
         class SessionShared::BackendClass : boost::noncopyable {
@@ -190,6 +192,7 @@ namespace metaproxy_1 {
             int m_resultset_ttl;
             int m_resultset_max;
             int m_session_ttl;
+            bool m_optimize_search;
         };
     }
 }
@@ -329,10 +332,15 @@ yf::SessionShared::BackendClass::get_backend(
 void yf::SessionShared::BackendClass::use_backend(BackendInstancePtr backend)
 {
     backend->m_in_use = true;
-    time(&backend->m_time_last_use);
     backend->m_sequence_this = m_sequence_top++;
 }
 
+void yf::SessionShared::BackendInstance::timestamp()
+{
+    assert(m_in_use);
+    time(&m_time_last_use);
+}
+
 yf::SessionShared::BackendInstance::~BackendInstance()
 {
     delete m_close_package;
@@ -506,14 +514,11 @@ static int get_diagnostic(Z_DefaultDiagFormat *r)
 
 bool yf::SessionShared::BackendSet::search(
     mp::Package &frontend_package,
+    mp::Package &search_package,
     const Z_APDU *frontend_apdu,
     const BackendInstancePtr bp,
     Z_Records **z_records)
 {
-    Package search_package(bp->m_session, frontend_package.origin());
-
-    search_package.copy_filter(frontend_package);
-
     mp::odr odr;
     Z_APDU *apdu_req = zget_APDU(odr, Z_APDU_searchRequest);
     Z_SearchRequest *req = apdu_req->u.searchRequest;
@@ -529,6 +534,10 @@ bool yf::SessionShared::BackendSet::search(
     for (; it != m_databases.end(); it++)
         req->databaseNames[i++] = odr_strdup(odr, it->c_str());
 
+    if (frontend_apdu->which == Z_APDU_searchRequest)
+        req->preferredRecordSyntax =
+            frontend_apdu->u.searchRequest->preferredRecordSyntax;
+
     search_package.request() = apdu_req;
 
     search_package.move();
@@ -618,25 +627,28 @@ restart:
     BackendClassPtr bc = m_backend_class;
     {
         boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
-        // look at each backend and see if we have a similar search
-        BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
         
-        for (; it != bc->m_backend_list.end(); it++)
+        if (m_p->m_optimize_search)
         {
-            if (!(*it)->m_in_use)
+            // look at each backend and see if we have a similar search
+            BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
+            for (; it != bc->m_backend_list.end(); it++)
             {
-                BackendSetList::const_iterator set_it = (*it)->m_sets.begin();
-                for (; set_it != (*it)->m_sets.end(); set_it++)
+                if (!(*it)->m_in_use)
                 {
-                    if ((*set_it)->m_databases == databases 
-                        && query.match(&(*set_it)->m_query))
+                    BackendSetList::const_iterator set_it = (*it)->m_sets.begin();
+                    for (; set_it != (*it)->m_sets.end(); set_it++)
                     {
-                        found_set = *set_it;
-                        found_backend = *it;
-                        bc->use_backend(found_backend);
-                        found_set->timestamp();
-                        // found matching set. No need to search again
-                        return;
+                        if ((*set_it)->m_databases == databases
+                            && query.match(&(*set_it)->m_query))
+                        {
+                            found_set = *set_it;
+                            found_backend = *it;
+                            bc->use_backend(found_backend);
+                            found_set->timestamp();
+                            // found matching set. No need to search again
+                            return;
+                        }
                     }
                 }
             }
@@ -681,11 +693,18 @@ restart:
         else
             result_set_id = "default";
     }
+    found_backend->timestamp();
+
     // we must search ...
     BackendSetPtr new_set(new BackendSet(result_set_id,
                                          databases, query));
     Z_Records *z_records = 0;
-    if (!new_set->search(package, apdu_req, found_backend, &z_records))
+
+    Package search_package(found_backend->m_session, package.origin());
+    search_package.copy_filter(package);
+
+    if (!new_set->search(package, search_package,
+                         apdu_req, found_backend, &z_records))
     {
         bc->remove_backend(found_backend);
         return; // search error 
@@ -870,6 +889,8 @@ void yf::SessionShared::Frontend::present(mp::Package &package,
         bc->release_backend(found_backend);
         return;
     }
+
+    found_backend->timestamp();
                               
     Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest);
     Z_PresentRequest *p_req = p_apdu->u.presentRequest;
@@ -943,6 +964,7 @@ void yf::SessionShared::Frontend::scan(mp::Package &frontend_package,
     else
     {
         Package scan_package(backend->m_session, frontend_package.origin());
+        backend->timestamp();
         scan_package.copy_filter(frontend_package);
         scan_package.request() = apdu_req;
         scan_package.move();
@@ -1004,7 +1026,7 @@ void yf::SessionShared::Rep::expire()
     {
         boost::xtime xt;
         boost::xtime_get(&xt, boost::TIME_UTC);
-        xt.sec += 30;
+        xt.sec += m_session_ttl / 3;
         boost::thread::sleep(xt);
         
         BackendClassMap::const_iterator b_it = m_backend_map.begin();
@@ -1018,6 +1040,7 @@ yf::SessionShared::Rep::Rep()
     m_resultset_ttl = 30;
     m_resultset_max = 10;
     m_session_ttl = 90;
+    m_optimize_search = true;
 }
 
 void yf::SessionShared::Rep::start()
@@ -1154,7 +1177,8 @@ void yf::SessionShared::process(mp::Package &package) const
     m_p->release_frontend(package);
 }
 
-void yf::SessionShared::configure(const xmlNode *ptr, bool test_only)
+void yf::SessionShared::configure(const xmlNode *ptr, bool test_only,
+                                  const char *path)
 {
     for (ptr = ptr->children; ptr; ptr = ptr->next)
     {
@@ -1173,6 +1197,11 @@ void yf::SessionShared::configure(const xmlNode *ptr, bool test_only)
                     m_p->m_resultset_max = 
                         mp::xml::get_int(attr->children, 10);
                 }
+                else if (!strcmp((const char *) attr->name, "optimizesearch"))
+                {
+                    m_p->m_optimize_search =
+                        mp::xml::get_bool(attr->children, true);
+                }
                 else
                     throw mp::filter::FilterException(
                         "Bad attribute " + std::string((const char *)