session_shared: only reuse sets with matching db
[metaproxy-moved-to-github.git] / src / filter_session_shared.cpp
index dbbd0fc..55c45a7 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of Metaproxy.
-   Copyright (C) 2005-2011 Index Data
+   Copyright (C) 2005-2012 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
@@ -104,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 {
@@ -161,7 +162,8 @@ namespace metaproxy_1 {
                          BackendInstancePtr &found_backend,
                          BackendSetPtr &found_set);
             void override_set(BackendInstancePtr &found_backend,
-                              std::string &result_set_id);
+                              std::string &result_set_id,
+                              const Databases &databases);
 
             Rep *m_p;
             BackendClassPtr m_backend_class;
@@ -331,10 +333,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;
@@ -528,6 +535,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();
@@ -558,13 +569,15 @@ bool yf::SessionShared::BackendSet::search(
 
 void yf::SessionShared::Frontend::override_set(
     BackendInstancePtr &found_backend,
-    std::string &result_set_id)
+    std::string &result_set_id,
+    const Databases &databases)
 {
     BackendClassPtr bc = m_backend_class;
     BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
     time_t now;
     time(&now);
-    
+
+    size_t max_sets = bc->m_named_result_sets ? bc->m_backend_set_max : 1;
     for (; it != bc->m_backend_list.end(); it++)
     {
         if (!(*it)->m_in_use)
@@ -572,8 +585,10 @@ void yf::SessionShared::Frontend::override_set(
             BackendSetList::iterator set_it = (*it)->m_sets.begin();
             for (; set_it != (*it)->m_sets.end(); set_it++)
             {
-                if (now >= (*set_it)->m_time_last_use &&
-                    now - (*set_it)->m_time_last_use > bc->m_backend_set_ttl)
+                if ((max_sets > 1 || (*set_it)->m_databases == databases)
+                    &&
+                    (now < (*set_it)->m_time_last_use ||
+                     now - (*set_it)->m_time_last_use >= bc->m_backend_set_ttl))
                 {
                     found_backend = *it;
                     result_set_id = (*set_it)->m_result_set_id;
@@ -583,7 +598,6 @@ void yf::SessionShared::Frontend::override_set(
             }
         }
     }
-    size_t max_sets = bc->m_named_result_sets ? bc->m_backend_set_max : 1;
     for (it = bc->m_backend_list.begin(); it != bc->m_backend_list.end(); it++)
     {
         if (!(*it)->m_in_use && (*it)->m_sets.size() < max_sets)
@@ -643,7 +657,7 @@ restart:
                 }
             }
         }
-        override_set(found_backend, result_set_id);
+        override_set(found_backend, result_set_id, databases);
         if (found_backend)
             bc->use_backend(found_backend);
     }
@@ -683,6 +697,8 @@ restart:
         else
             result_set_id = "default";
     }
+    found_backend->timestamp();
+
     // we must search ...
     BackendSetPtr new_set(new BackendSet(result_set_id,
                                          databases, query));
@@ -877,6 +893,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;
@@ -950,6 +968,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();
@@ -987,8 +1006,7 @@ void yf::SessionShared::BackendClass::expire_class()
         {
             bit++;
         }
-        else if ((now >= last_use && now - last_use > m_backend_expiry_ttl)
-            || (now < last_use))
+        else if (now < last_use || now - last_use > m_backend_expiry_ttl)
         {
             mp::odr odr;
             (*bit)->m_close_package->response() = odr.create_close(
@@ -1011,7 +1029,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();
@@ -1162,7 +1180,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)
     {