Call fixed RecordCache::add MP-499
[metaproxy-moved-to-github.git] / src / filter_session_shared.cpp
index e3833e1..0ee10fb 100644 (file)
@@ -80,10 +80,16 @@ namespace metaproxy_1 {
             time_t m_time_last_use;
             void timestamp();
             yazpp_1::RecordCache m_record_cache;
+
+            Z_OtherInformation *additionalSearchInfoRequest;
+            Z_OtherInformation *additionalSearchInfoResponse;
+            NMEM mem_additionalSearchInfo;
             BackendSet(
                 const std::string &result_set_id,
                 const Databases &databases,
-                const yazpp_1::Yaz_Z_Query &query);
+                const yazpp_1::Yaz_Z_Query &query,
+                Z_OtherInformation *additionalSearchInfoRequest);
+            ~BackendSet();
             bool search(
                 Package &frontend_package,
                 Package &search_package,
@@ -118,7 +124,7 @@ namespace metaproxy_1 {
             BackendInstancePtr get_backend(const Package &package);
             void use_backend(BackendInstancePtr b);
             void release_backend(BackendInstancePtr b);
-            void expire_class();
+            bool expire_instances();
             yazpp_1::GDU m_init_request;
             yazpp_1::GDU m_init_response;
             boost::mutex m_mutex_backend_class;
@@ -189,6 +195,8 @@ namespace metaproxy_1 {
         public:
             void expire();
         private:
+            void expire_classes();
+            void stat();
             void init(Package &package, const Z_GDU *gdu,
                       FrontendPtr frontend);
             void start();
@@ -458,6 +466,24 @@ yf::SessionShared::BackendClass::BackendClass(const yazpp_1::GDU &init_request,
 yf::SessionShared::BackendClass::~BackendClass()
 {}
 
+void yf::SessionShared::Rep::stat()
+{
+    int no_classes = 0;
+    int no_instances = 0;
+    BackendClassMap::const_iterator it;
+    {
+        boost::mutex::scoped_lock lock(m_mutex_backend_map);
+        for (it = m_backend_map.begin(); it != m_backend_map.end(); it++)
+        {
+            BackendClassPtr bc = it->second;
+            no_classes++;
+            BackendInstanceList::iterator bit = bc->m_backend_list.begin();
+            for (; bit != bc->m_backend_list.end(); bit++)
+                no_instances++;
+        }
+    }
+}
+
 void yf::SessionShared::Rep::init(mp::Package &package, const Z_GDU *gdu,
                                   FrontendPtr frontend)
 {
@@ -551,11 +577,22 @@ void yf::SessionShared::BackendSet::timestamp()
 yf::SessionShared::BackendSet::BackendSet(
     const std::string &result_set_id,
     const Databases &databases,
-    const yazpp_1::Yaz_Z_Query &query) :
+    const yazpp_1::Yaz_Z_Query &query,
+    Z_OtherInformation *additionalSearchInfo) :
     m_result_set_id(result_set_id),
     m_databases(databases), m_result_set_size(0), m_query(query)
 {
     timestamp();
+    mem_additionalSearchInfo = nmem_create();
+    additionalSearchInfoResponse = 0;
+    additionalSearchInfoRequest =
+        yaz_clone_z_OtherInformation(additionalSearchInfo,
+                                     mem_additionalSearchInfo);
+}
+
+yf::SessionShared::BackendSet::~BackendSet()
+{
+    nmem_destroy(mem_additionalSearchInfo);
 }
 
 static int get_diagnostic(Z_DefaultDiagFormat *r)
@@ -574,6 +611,7 @@ bool yf::SessionShared::BackendSet::search(
     Z_APDU *apdu_req = zget_APDU(odr, Z_APDU_searchRequest);
     Z_SearchRequest *req = apdu_req->u.searchRequest;
 
+    req->additionalSearchInfo = additionalSearchInfoRequest;
     req->resultSetName = odr_strdup(odr, m_result_set_id.c_str());
     req->query = m_query.get_Z_Query();
 
@@ -601,6 +639,9 @@ bool yf::SessionShared::BackendSet::search(
         Z_SearchResponse *b_resp = gdu->u.z3950->u.searchResponse;
         *z_records = b_resp->records;
         m_result_set_size = *b_resp->resultCount;
+
+        additionalSearchInfoResponse = yaz_clone_z_OtherInformation(
+            b_resp->additionalSearchInfo, mem_additionalSearchInfo);
         return true;
     }
     Z_APDU *f_apdu = 0;
@@ -679,6 +720,10 @@ void yf::SessionShared::Frontend::get_set(mp::Package &package,
                                           BackendSetPtr &found_set)
 {
     bool session_restarted = false;
+    Z_OtherInformation *additionalSearchInfo = 0;
+
+    if (apdu_req->which == Z_APDU_searchRequest)
+        additionalSearchInfo = apdu_req->u.searchRequest->additionalSearchInfo;
 
 restart:
     std::string result_set_id;
@@ -701,8 +746,14 @@ restart:
                     BackendSetList::const_iterator set_it = (*it)->m_sets.begin();
                     for (; set_it != (*it)->m_sets.end(); set_it++)
                     {
+                        // for real present request we don't care
+                        // if additionalSearchInfo matches: same records
                         if ((*set_it)->m_databases == databases
-                            && query.match(&(*set_it)->m_query))
+                            && query.match(&(*set_it)->m_query)
+                            && (apdu_req->which != Z_APDU_searchRequest ||
+                                yaz_compare_z_OtherInformation(
+                                    additionalSearchInfo,
+                                (*set_it)->additionalSearchInfoRequest)))
                         {
                             found_set = *set_it;
                             found_backend = *it;
@@ -765,7 +816,8 @@ restart:
 
     // we must search ...
     BackendSetPtr new_set(new BackendSet(result_set_id,
-                                         databases, query));
+                                         databases, query,
+                                         additionalSearchInfo));
     Z_Records *z_records = 0;
 
     Package search_package(found_backend->m_session, package.origin());
@@ -961,6 +1013,7 @@ void yf::SessionShared::Frontend::search(mp::Package &package,
     Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0);
     Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
     *f_resp->resultCount = found_set->m_result_set_size;
+    f_resp->additionalSearchInfo = found_set->additionalSearchInfoResponse;
     package.response() = f_apdu;
 
     FrontendSetPtr fset(new FrontendSet(databases, query));
@@ -1065,16 +1118,17 @@ void yf::SessionShared::Frontend::present(mp::Package &package,
 
         if (b_resp->records && b_resp->records->which ==  Z_Records_DBOSD)
         {
+#if 0
             yaz_log(YLOG_LOG, "Adding " ODR_INT_PRINTF "+" ODR_INT_PRINTF
                     " records to cache %p",
                     *req->resultSetStartPoint,
                     *f_resp->numberOfRecordsReturned,
                     &found_set->m_record_cache);
+#endif
             found_set->m_record_cache.add(
                 odr,
                 b_resp->records->u.databaseOrSurDiagnostics,
-                *req->resultSetStartPoint,
-                *f_resp->numberOfRecordsReturned);
+                *req->resultSetStartPoint, p_req->recordComposition);
         }
         bc->release_backend(found_backend);
     }
@@ -1129,7 +1183,7 @@ void yf::SessionShared::Worker::operator() (void)
     m_p->expire();
 }
 
-void yf::SessionShared::BackendClass::expire_class()
+bool yf::SessionShared::BackendClass::expire_instances()
 {
     time_t now;
     time(&now);
@@ -1158,6 +1212,25 @@ void yf::SessionShared::BackendClass::expire_class()
             bit++;
         }
     }
+    if (m_backend_list.empty())
+        return true;
+    return false;
+}
+
+void yf::SessionShared::Rep::expire_classes()
+{
+    boost::mutex::scoped_lock lock(m_mutex_backend_map);
+    BackendClassMap::iterator b_it = m_backend_map.begin();
+    while (b_it != m_backend_map.end())
+    {
+        if (b_it->second->expire_instances())
+        {
+            m_backend_map.erase(b_it);
+            b_it = m_backend_map.begin();
+        }
+        else
+            b_it++;
+    }
 }
 
 void yf::SessionShared::Rep::expire()
@@ -1175,9 +1248,8 @@ void yf::SessionShared::Rep::expire()
         xt.sec += m_session_ttl / 3;
         boost::thread::sleep(xt);
 
-        BackendClassMap::const_iterator b_it = m_backend_map.begin();
-        for (; b_it != m_backend_map.end(); b_it++)
-            b_it->second->expire_class();
+        stat();
+        expire_classes();
     }
 }