Sort: no need for present/search handling for sort response
[yaz-moved-to-github.git] / src / zoom-z3950.c
index fe86050..6e06f14 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2013 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 /**
@@ -633,14 +633,14 @@ zoom_ret ZOOM_connection_Z3950_send_init(ZOOM_connection c)
     return send_APDU(c, apdu);
 }
 
-zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c)
+static zoom_ret Z3950_send_search(ZOOM_connection c)
 {
     ZOOM_resultset r;
     int lslb, ssub, mspn;
     const char *syntax;
     const char *schema;
-    Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_searchRequest);
-    Z_SearchRequest *search_req = apdu->u.searchRequest;
+    Z_APDU *apdu;
+    Z_SearchRequest *search_req;
     const char *elementSetName;
     const char *smallSetElementSetName;
     const char *mediumSetElementSetName;
@@ -648,13 +648,14 @@ zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c)
 
     assert(c->tasks);
     assert(c->tasks->which == ZOOM_TASK_SEARCH);
-
     r = c->tasks->u.search.resultset;
 
+    apdu = zget_APDU(c->odr_out, Z_APDU_searchRequest);
+    search_req = apdu->u.searchRequest;
+
     yaz_log(c->log_details, "%p ZOOM_connection_send_search set=%p", c, r);
 
-    elementSetName =
-        ZOOM_options_get(r->options, "elementSetName");
+    elementSetName = c->tasks->u.search.elementSetName;
     smallSetElementSetName  =
         ZOOM_options_get(r->options, "smallSetElementSetName");
     mediumSetElementSetName =
@@ -670,8 +671,7 @@ zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c)
     if (facets) {
         Z_FacetList *facet_list = yaz_pqf_parse_facet_list(c->odr_out, facets);
         if (facet_list) {
-            Z_OtherInformation **oi;
-            yaz_oi_APDU(apdu, &oi);
+            Z_OtherInformation **oi = &search_req->additionalSearchInfo;
             yaz_oi_set_facetlist(oi, c->odr_out, facet_list);
         }
         else
@@ -779,15 +779,6 @@ zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c)
                result sets on the server. */
             for (ord = 1; ; ord++)
             {
-#if ZOOM_RESULT_LISTS
-                ZOOM_resultsets rsp;
-                sprintf(setname, "%d", ord);
-                for (rsp = c->resultsets; rsp; rsp = rsp->next)
-                    if (rsp->resultset->setname && !strcmp(rsp->resultset->setname, setname))
-                        break;
-                if (!rsp)
-                    break;
-#else
                 ZOOM_resultset rp;
                 sprintf(setname, "%d", ord);
                 for (rp = c->resultsets; rp; rp = rp->next)
@@ -795,8 +786,6 @@ zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c)
                         break;
                 if (!rp)
                     break;
-#endif
-
             }
             r->setname = xstrdup(setname);
             yaz_log(c->log_details, "%p ZOOM_connection_send_search: "
@@ -1047,12 +1036,12 @@ static int es_response_taskpackage(ZOOM_connection c,
     return 1;
 }
 
-
-static int handle_Z3950_es_response(ZOOM_connection c,
-                                    Z_ExtendedServicesResponse *res)
+static void handle_Z3950_es_response(ZOOM_connection c,
+                                     Z_ExtendedServicesResponse *res)
 {
-    if (!c->tasks || c->tasks->which != ZOOM_TASK_PACKAGE)
-        return 0;
+    if (!c->tasks)
+        return;
+    assert(c->tasks->which == ZOOM_TASK_PACKAGE);
     switch (*res->operationStatus)
     {
     case Z_ExtendedServicesResponse_done:
@@ -1080,7 +1069,6 @@ static int handle_Z3950_es_response(ZOOM_connection c,
         ZOOM_options_setl(c->tasks->u.package->options,
                           "xmlUpdateDoc", (char*) doc->buf, doc->len);
     }
-    return 1;
 }
 
 static char *get_term_cstr(ODR odr, Z_Term *term) {
@@ -1263,13 +1251,15 @@ static void handle_Z3950_search_response(ZOOM_connection c,
     ZOOM_Event event;
 
     if (!c->tasks || c->tasks->which != ZOOM_TASK_SEARCH)
-        return ;
-
-    event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
-    ZOOM_connection_put_event(c, event);
+        return;
 
     resultset = c->tasks->u.search.resultset;
 
+    if (resultset->live_set == 0)
+    {
+        event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
+        ZOOM_connection_put_event(c, event);
+    }
     if (sr->resultSetStatus)
     {
         ZOOM_options_set_int(resultset->options, "resultSetStatus",
@@ -1285,6 +1275,25 @@ static void handle_Z3950_search_response(ZOOM_connection c,
     handle_facet_result(c, resultset, sr->additionalSearchInfo);
 
     resultset->size = *sr->resultCount;
+    resultset->live_set = 2;
+
+#if HAVE_LIBMEMCACHED_MEMCACHED_H
+    if (c->mc_st)
+    {
+        uint32_t flags = 0;
+        memcached_return_t rc;
+        time_t expiration = 36000;
+        char str[40];
+
+        sprintf(str, ODR_INT_PRINTF, *sr->resultCount);
+        rc = memcached_set(c->mc_st,
+                           wrbuf_buf(resultset->mc_key),wrbuf_len(resultset->mc_key),
+                           str, strlen(str), expiration, flags);
+        yaz_log(YLOG_LOG, "Store Z39.50 hit count key=%s value=%s rc=%u %s",
+                wrbuf_cstr(resultset->mc_key), str, (unsigned) rc,
+                memcached_last_error_message(c->mc_st));
+    }
+#endif
     handle_Z3950_records(c, sr->records, 0);
 }
 
@@ -1294,13 +1303,13 @@ static void handle_Z3950_sort_response(ZOOM_connection c, Z_SortResponse *res)
         response_diag(c, res->diagnostics[0]);
 }
 
-static int handle_Z3950_scan_response(ZOOM_connection c, Z_ScanResponse *res)
+static void handle_Z3950_scan_response(ZOOM_connection c, Z_ScanResponse *res)
 {
     NMEM nmem = odr_extract_mem(c->odr_in);
     ZOOM_scanset scan;
 
     if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
-        return 0;
+        return;
     scan = c->tasks->u.scan.scan;
 
     if (res->entries && res->entries->nonsurrogateDiagnostics)
@@ -1318,7 +1327,6 @@ static int handle_Z3950_scan_response(ZOOM_connection c, Z_ScanResponse *res)
         ZOOM_options_set_int(scan->options, "number",
                              *res->numberOfEntriesReturned);
     nmem_destroy(nmem);
-    return 1;
 }
 
 static void handle_Z3950_records(ZOOM_connection c, Z_Records *sr,
@@ -1328,29 +1336,16 @@ static void handle_Z3950_records(ZOOM_connection c, Z_Records *sr,
     int *start, *count;
     const char *syntax = 0, *elementSetName = 0, *schema = 0;
 
-    if (!c->tasks)
+    if (!c->tasks || c->tasks->which != ZOOM_TASK_SEARCH)
         return ;
-    switch (c->tasks->which)
-    {
-    case ZOOM_TASK_SEARCH:
-        resultset = c->tasks->u.search.resultset;
-        start = &c->tasks->u.search.start;
-        count = &c->tasks->u.search.count;
-        syntax = c->tasks->u.search.syntax;
-        elementSetName = c->tasks->u.search.elementSetName;
-        schema =  c->tasks->u.search.schema;
-        break;
-    case ZOOM_TASK_RETRIEVE:
-        resultset = c->tasks->u.retrieve.resultset;
-        start = &c->tasks->u.retrieve.start;
-        count = &c->tasks->u.retrieve.count;
-        syntax = c->tasks->u.retrieve.syntax;
-        elementSetName = c->tasks->u.retrieve.elementSetName;
-        schema =  c->tasks->u.retrieve.schema;
-        break;
-    default:
-        return;
-    }
+
+    resultset = c->tasks->u.search.resultset;
+    start = &c->tasks->u.search.start;
+    count = &c->tasks->u.search.count;
+    syntax = c->tasks->u.search.syntax;
+    elementSetName = c->tasks->u.search.elementSetName;
+    schema =  c->tasks->u.search.schema;
+
     if (sr && sr->which == Z_Records_NSD)
         response_default_diag(c, sr->u.nonSurrogateDiagnostic);
     else if (sr && sr->which == Z_Records_multipleNSD)
@@ -1398,6 +1393,7 @@ static void handle_Z3950_records(ZOOM_connection c, Z_Records *sr,
                         "ZOOM C generated. Present phase and no records");
                 ZOOM_record_cache_add(resultset, myrec, *start,
                                       syntax, elementSetName, schema, 0);
+                *count = 0;
             }
         }
         else if (present_phase)
@@ -1410,6 +1406,7 @@ static void handle_Z3950_records(ZOOM_connection c, Z_Records *sr,
                     "ZOOM C generated: Present response and no records");
             ZOOM_record_cache_add(resultset, myrec, *start,
                                   syntax, elementSetName, schema, 0);
+            *count = 0;
         }
     }
 }
@@ -1452,7 +1449,7 @@ zoom_ret send_Z3950_sort(ZOOM_connection c, ZOOM_resultset resultset)
     return zoom_complete;
 }
 
-zoom_ret send_Z3950_present(ZOOM_connection c)
+zoom_ret ZOOM_connection_Z3950_present(ZOOM_connection c)
 {
     Z_APDU *apdu = 0;
     Z_PresentRequest *req = 0;
@@ -1464,40 +1461,29 @@ zoom_ret send_Z3950_present(ZOOM_connection c)
     int *start, *count;
 
     if (!c->tasks)
-    {
-        yaz_log(c->log_details, "%p send_present no tasks", c);
         return zoom_complete;
-    }
+    assert(c->tasks->which == ZOOM_TASK_SEARCH);
+    resultset = c->tasks->u.search.resultset;
+    start = &c->tasks->u.search.start;
+    count = &c->tasks->u.search.count;
+    syntax = c->tasks->u.search.syntax;
+    elementSetName = c->tasks->u.search.elementSetName;
+    schema =  c->tasks->u.search.schema;
 
-    switch (c->tasks->which)
-    {
-    case ZOOM_TASK_SEARCH:
-        resultset = c->tasks->u.search.resultset;
-        start = &c->tasks->u.search.start;
-        count = &c->tasks->u.search.count;
-        syntax = c->tasks->u.search.syntax;
-        elementSetName = c->tasks->u.search.elementSetName;
-        schema =  c->tasks->u.search.schema;
-        break;
-    case ZOOM_TASK_RETRIEVE:
-        resultset = c->tasks->u.retrieve.resultset;
-        start = &c->tasks->u.retrieve.start;
-        count = &c->tasks->u.retrieve.count;
-        syntax = c->tasks->u.retrieve.syntax;
-        elementSetName = c->tasks->u.retrieve.elementSetName;
-        schema = c->tasks->u.retrieve.schema;
-        break;
-    default:
-        return zoom_complete;
-    }
     yaz_log(c->log_details, "%p send_present start=%d count=%d",
             c, *start, *count);
 
-    if (*start < 0 || *count < 0 || *start + *count > resultset->size)
+    if (*start < 0 || *count < 0)
+    {
+        ZOOM_set_dset_error(c, YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE, "Bib-1",
+                       "", 0);
+    }
+    if (resultset->live_set && *start + *count > resultset->size)
     {
         ZOOM_set_dset_error(c, YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE, "Bib-1",
                        "", 0);
     }
+
     if (c->error)                  /* don't continue on error */
         return zoom_complete;
     yaz_log(c->log_details, "send_present resultset=%p start=%d count=%d",
@@ -1519,18 +1505,15 @@ zoom_ret send_Z3950_present(ZOOM_connection c)
     *start += i;
     *count -= i;
 
-    if (*count == 0)
-    {
-        yaz_log(c->log_details, "%p send_present skip=%d no more to fetch", c, i);
+    if (*count == 0 && resultset->live_set)
         return zoom_complete;
-    }
+
+    if (resultset->live_set != 2)
+        return Z3950_send_search(c);
 
     apdu = zget_APDU(c->odr_out, Z_APDU_presentRequest);
     req = apdu->u.presentRequest;
 
-    if (i)
-        yaz_log(c->log_details, "%p send_present skip=%d", c, i);
-
     *req->resultSetStartPoint = *start + 1;
 
     if (resultset->step > 0 && resultset->step < *count)
@@ -1613,7 +1596,7 @@ static zoom_ret send_Z3950_sort_present(ZOOM_connection c)
     if (c->tasks && c->tasks->which == ZOOM_TASK_SEARCH)
         r = send_Z3950_sort(c, c->tasks->u.search.resultset);
     if (r == zoom_complete)
-        r = send_Z3950_present(c);
+        r = ZOOM_connection_Z3950_present(c);
     return r;
 }
 
@@ -1718,14 +1701,13 @@ void ZOOM_handle_Z3950_apdu(ZOOM_connection c, Z_APDU *apdu)
     case Z_APDU_presentResponse:
         yaz_log(c->log_api, "%p handle_Z3950_apdu Present response", c);
         handle_Z3950_present_response(c, apdu->u.presentResponse);
-        if (send_Z3950_present(c) == zoom_complete)
+        if (ZOOM_connection_Z3950_present(c) == zoom_complete)
             ZOOM_connection_remove_task(c);
         break;
     case Z_APDU_sortResponse:
         yaz_log(c->log_api, "%p handle_Z3950_apdu Sort response", c);
         handle_Z3950_sort_response(c, apdu->u.sortResponse);
-        if (send_Z3950_present(c) == zoom_complete)
-            ZOOM_connection_remove_task(c);
+        ZOOM_connection_remove_task(c);
         break;
     case Z_APDU_scanResponse:
         yaz_log(c->log_api, "%p handle_Z3950_apdu Scan response", c);