Fixed memory leak (setname in ZOOM_resultset)
[yaz-moved-to-github.git] / src / zoom-c.c
index ea52a61..2c12c6a 100644 (file)
@@ -596,6 +596,13 @@ ZOOM_API(void)
         ZOOM_options_get_int(c->options, "preferredMessageSize", 1024*1024);
 
     c->async = ZOOM_options_get_bool(c->options, "async", 0);
+    if (ZOOM_options_get_bool(c->options, "apdulog", 0))
+    {
+        c->odr_print = odr_createmem(ODR_PRINT);
+        odr_setprint(c->odr_print, yaz_log_file());
+    }
+    else
+        c->odr_print = 0;
     yaz_log(log_details, "%p ZOOM_connection_connect async=%d", c, c->async);
  
     task = ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
@@ -774,6 +781,11 @@ ZOOM_API(void)
     xfree(c->diagset);
     odr_destroy(c->odr_in);
     odr_destroy(c->odr_out);
+    if (c->odr_print)
+    {
+        odr_setprint(c->odr_print, 0); /* prevent destroy from fclose'ing */
+        odr_destroy(c->odr_print);
+    }
     ZOOM_options_destroy(c->options);
     ZOOM_connection_remove_tasks(c);
     ZOOM_connection_remove_events(c);
@@ -1301,6 +1313,8 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
         odr_reset(out);
         return -1;
     }
+    if (c->odr_print)
+        z_APDU(c->odr_print, &a, 0, 0);
     yaz_log(log_details, "%p encoding_APDU encoding OK", c);
     return 0;
 }
@@ -1429,6 +1443,8 @@ static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
     }
     if (!z_GDU(c->odr_out, &gdu, 0, 0))
         return zoom_complete;
+    if (c->odr_print)
+        z_GDU(c->odr_print, &gdu, 0, 0);
     c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0);
         
     event = ZOOM_Event_create(ZOOM_EVENT_SEND_APDU);
@@ -1438,13 +1454,15 @@ static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
 }
 #endif
 
-
-static Z_SRW_PDU *ZOOM_srw_get_pdu(ZOOM_connection c, int type) {
+#if YAZ_HAVE_XML2
+static Z_SRW_PDU *ZOOM_srw_get_pdu(ZOOM_connection c, int type)
+{
     Z_SRW_PDU *sr = yaz_srw_get_pdu(c->odr_out, type, c->sru_version);
     sr->username = c->user;
     sr->password = c->password;
     return sr;
 }
+#endif
 
 #if YAZ_HAVE_XML2
 static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
@@ -1462,7 +1480,8 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
     {
     case ZOOM_TASK_SEARCH:
         resultset = c->tasks->u.search.resultset;
-        resultset->setname = xstrdup("default");
+        if (!resultset->setname)
+            resultset->setname = xstrdup("default");
         ZOOM_options_set(resultset->options, "setname", resultset->setname);
         start = &c->tasks->u.search.start;
         count = &c->tasks->u.search.count;
@@ -1472,7 +1491,7 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
 
         start = &c->tasks->u.retrieve.start;
         count = &c->tasks->u.retrieve.count;
-        
+
         if (*start >= resultset->size)
             return zoom_complete;
         if (*start + *count > resultset->size)
@@ -1523,7 +1542,8 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
     }
     sr->u.request->startRecord = odr_intdup(c->odr_out, *start + 1);
     sr->u.request->maximumRecords = odr_intdup(
-        c->odr_out, resultset->step>0 ? resultset->step : *count);
+        c->odr_out, (resultset->step > 0 && resultset->step < *count) ? 
+        resultset->step : *count);
     sr->u.request->recordSchema = resultset->schema;
     
     option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
@@ -2636,8 +2656,12 @@ static zoom_ret send_present(ZOOM_connection c)
         yaz_log(log_details, "%p send_present skip=%d", c, i);
 
     *req->resultSetStartPoint = *start + 1;
-    *req->numberOfRecordsRequested = resultset->step>0 ?
-        resultset->step : *count;
+
+    if (resultset->step > 0 && resultset->step < *count)
+        *req->numberOfRecordsRequested = resultset->step;
+    else
+        *req->numberOfRecordsRequested = *count;
+    
     if (*req->numberOfRecordsRequested + *start > resultset->size)
         *req->numberOfRecordsRequested = resultset->size - *start;
     assert(*req->numberOfRecordsRequested > 0);
@@ -3922,35 +3946,37 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu)
 }
 
 #if YAZ_HAVE_XML2
-static void handle_srw_response(ZOOM_connection c,
-                                Z_SRW_searchRetrieveResponse *res)
+static zoom_ret handle_srw_response(ZOOM_connection c,
+                                    Z_SRW_searchRetrieveResponse *res)
 {
     ZOOM_resultset resultset = 0;
     int i;
     NMEM nmem;
     ZOOM_Event event;
-    int *start;
+    int *start, *count;
     const char *syntax, *elementSetName;
 
     if (!c->tasks)
-        return;
+        return zoom_complete;
 
     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;        
         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;
         break;
     default:
-        return;
+        return zoom_complete;
     }
     event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
     ZOOM_connection_put_event(c, event);
@@ -4012,11 +4038,22 @@ static void handle_srw_response(ZOOM_connection c,
         record_cache_add(resultset, npr, pos, syntax, elementSetName,
                          sru_rec->recordSchema, diag);
     }
-    if (res->num_diagnostics > 0)
-        set_SRU_error(c, &res->diagnostics[0]);
+    *count -= i;
+    *start += i;
+    if (*count + *start > resultset->size)
+        *count = resultset->size - *start;
+    if (*count < 0)
+        *count = 0;
+
     nmem = odr_extract_mem(c->odr_in);
     nmem_transfer(odr_getmem(resultset->odr), nmem);
     nmem_destroy(nmem);
+    
+    if (res->num_diagnostics > 0)
+        set_SRU_error(c, &res->diagnostics[0]);
+    else if (*count > 0)
+        return ZOOM_connection_srw_send_search(c);
+    return zoom_complete;
 }
 #endif
 
@@ -4046,6 +4083,7 @@ static void handle_srw_scan_response(ZOOM_connection c,
 #if YAZ_HAVE_XML2
 static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
 {
+    zoom_ret cret = zoom_complete;
     int ret = -1;
     const char *addinfo = 0;
     const char *connection_head = z_HTTP_header_lookup(hres->headers,
@@ -4073,7 +4111,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
 
             ZOOM_options_set(c->options, "sru_version", sr->srw_version);
             if (sr->which == Z_SRW_searchRetrieve_response)
-                handle_srw_response(c, sr->u.response);
+                cret = handle_srw_response(c, sr->u.response);
             else if (sr->which == Z_SRW_scan_response)
                 handle_srw_scan_response(c, sr->u.scan_response);
             else
@@ -4097,7 +4135,8 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
             set_ZOOM_error(c, ZOOM_ERROR_DECODE, addinfo);
         do_close(c);
     }
-    ZOOM_connection_remove_task(c);
+    if (cret == zoom_complete)
+        ZOOM_connection_remove_task(c);
     if (!strcmp(hres->version, "1.0"))
     {
         /* HTTP 1.0: only if Keep-Alive we stay alive.. */
@@ -4163,16 +4202,21 @@ static int do_read(ZOOM_connection c)
             }
             do_close(c);
         }
-        else if (gdu->which == Z_GDU_Z3950)
-            recv_apdu(c, gdu->u.z3950);
-        else if (gdu->which == Z_GDU_HTTP_Response)
+        else
         {
+            if (c->odr_print)
+                z_GDU(c->odr_print, &gdu, 0, 0);
+            if (gdu->which == Z_GDU_Z3950)
+                recv_apdu(c, gdu->u.z3950);
+            else if (gdu->which == Z_GDU_HTTP_Response)
+            {
 #if YAZ_HAVE_XML2
-            handle_http(c, gdu->u.HTTP_Response);
+                handle_http(c, gdu->u.HTTP_Response);
 #else
-            set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
-            do_close(c);
+                set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
+                do_close(c);
 #endif
+            }
         }
         c->reconnect_ok = 0;
     }