session_shared: remove log msg about backend classes
[metaproxy-moved-to-github.git] / src / filter_session_shared.cpp
index 038b467..00b05c9 100644 (file)
@@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #include <metaproxy/util.hpp>
 #include "filter_session_shared.hpp"
 
+#include <yaz/copy_types.h>
 #include <yaz/log.h>
 #include <yaz/zgdu.h>
 #include <yaz/otherinfo.h>
@@ -79,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,
@@ -117,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;
@@ -159,6 +166,9 @@ namespace metaproxy_1 {
             void present(Package &package, Z_APDU *apdu);
             void scan(Package &package, Z_APDU *apdu);
 
+            int result_set_ref(ODR o,
+                               const Databases &databases,
+                               Z_RPNStructure *s, std::string &rset);
             void get_set(mp::Package &package,
                          const Z_APDU *apdu_req,
                          const Databases &databases,
@@ -185,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();
@@ -454,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)
 {
@@ -547,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)
@@ -570,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();
 
@@ -597,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;
@@ -675,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;
@@ -697,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;
@@ -761,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());
@@ -844,6 +900,54 @@ restart:
     found_backend->m_sets.push_back(found_set);
 }
 
+int yf::SessionShared::Frontend::result_set_ref(ODR o,
+                                                const Databases &databases,
+                                                Z_RPNStructure *s,
+                                                std::string &rset)
+{
+    int ret = 0;
+    switch (s->which)
+    {
+    case Z_RPNStructure_simple:
+        if (s->u.simple->which == Z_Operand_resultSetId)
+        {
+            const char *id = s->u.simple->u.resultSetId;
+            rset = id;
+
+            FrontendSets::iterator fset_it = m_frontend_sets.find(id);
+            if (fset_it == m_frontend_sets.end())
+            {
+                ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
+            }
+            else if (fset_it->second->get_databases() != databases)
+            {
+                ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
+            }
+            else
+            {
+                yazpp_1::Yaz_Z_Query query = fset_it->second->get_query();
+                Z_Query *q = yaz_copy_Z_Query(query.get_Z_Query(), o);
+                if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
+                {
+                    s->which = q->u.type_1->RPNStructure->which;
+                    s->u.simple = q->u.type_1->RPNStructure->u.simple;
+                }
+                else
+                {
+                    ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
+                }
+            }
+        }
+        break;
+    case Z_RPNStructure_complex:
+        ret = result_set_ref(o, databases, s->u.complex->s1, rset);
+        if (!ret)
+            ret = result_set_ref(o, databases, s->u.complex->s2, rset);
+        break;
+    }
+    return ret;
+}
+
 void yf::SessionShared::Frontend::search(mp::Package &package,
                                          Z_APDU *apdu_req)
 {
@@ -864,19 +968,40 @@ void yf::SessionShared::Frontend::search(mp::Package &package,
                     YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
                     0);
             package.response() = apdu;
-
             return;
         }
         m_frontend_sets.erase(fset_it);
     }
 
-    yazpp_1::Yaz_Z_Query query;
-    query.set_Z_Query(req->query);
     Databases databases;
     int i;
     for (i = 0; i < req->num_databaseNames; i++)
         databases.push_back(req->databaseNames[i]);
 
+
+    yazpp_1::Yaz_Z_Query query;
+    query.set_Z_Query(req->query);
+
+    Z_Query *q = query.get_Z_Query();
+    if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
+    {
+        mp::odr odr;
+        std::string rset;
+        int diag = result_set_ref(odr, databases, q->u.type_1->RPNStructure,
+                                  rset);
+        if (diag)
+        {
+            Z_APDU *apdu =
+                odr.create_searchResponse(
+                    apdu_req,
+                    diag,
+                    rset.c_str());
+            package.response() = apdu;
+            return;
+        }
+        query.set_Z_Query(q);
+    }
+
     BackendSetPtr found_set; // null
     BackendInstancePtr found_backend; // null
 
@@ -888,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));
@@ -992,11 +1118,13 @@ 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,
@@ -1056,7 +1184,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);
@@ -1085,6 +1213,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()
@@ -1102,9 +1249,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();
     }
 }