API changes to ZOOM. Functions for setting options returns int, rather
[yaz-moved-to-github.git] / src / zoom-c.c
index 3563ab5..10cf790 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.106 2007-01-10 13:25:46 adam Exp $
+ * $Id: zoom-c.c,v 1.118 2007-03-19 20:58:34 adam Exp $
  */
 /**
  * \file zoom-c.c
@@ -35,10 +35,26 @@ typedef enum {
     zoom_complete
 } zoom_ret;
 
+static void resultset_destroy(ZOOM_resultset r);
 static zoom_ret ZOOM_connection_send_init(ZOOM_connection c);
 static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out);
 static char *cql2pqf(ZOOM_connection c, const char *cql);
 
+
+/*
+ * This wrapper is just for logging failed lookups.  It would be nicer
+ * if it could cause failure when a lookup fails, but that's hard.
+ */
+static Odr_oid *zoom_yaz_str_to_z3950oid(ZOOM_connection c,
+                                         int oid_class, const char *str) {
+    Odr_oid *res = yaz_str_to_z3950oid(c->odr_out, oid_class, str);
+    if (res == 0)
+        yaz_log(YLOG_WARN, "%p OID lookup (%d, '%s') failed",
+                c, (int) oid_class, str);
+    return res;
+}
+
+
 static void initlog(void)
 {
     static int log_level_initialized = 0;
@@ -103,13 +119,22 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
     return event;
 }
 
-int ZOOM_connection_peek_event(ZOOM_connection c)
+static void ZOOM_connection_remove_events(ZOOM_connection c)
+{
+    ZOOM_Event event;
+    while ((event = ZOOM_connection_get_event(c)))
+        ZOOM_Event_destroy(event);
+}
+
+ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c)
 {
     ZOOM_Event event = c->m_queue_front;
 
     return event ? event->kind : ZOOM_EVENT_NONE;
 }
 
+void ZOOM_connection_remove_tasks(ZOOM_connection c);
+
 static void set_dset_error(ZOOM_connection c, int error,
                            const char *dset,
                            const char *addinfo, const char *addinfo2)
@@ -135,11 +160,14 @@ static void set_dset_error(ZOOM_connection c, int error,
     }
     else if (addinfo)
         c->addinfo = xstrdup(addinfo);
-    if (error)
+    if (error != ZOOM_ERROR_NONE)
+    {
         yaz_log(log_api, "%p set_dset_error %s %s:%d %s %s",
                 c, c->host_port ? c->host_port : "<>", dset, error,
                 addinfo ? addinfo : "",
                 addinfo2 ? addinfo2 : "");
+        ZOOM_connection_remove_tasks(c);
+    }
 }
 
 #if YAZ_HAVE_XML2
@@ -150,6 +178,7 @@ static void set_HTTP_error(ZOOM_connection c, int error,
 }
 #endif
 
+
 static void set_ZOOM_error(ZOOM_connection c, int error,
                            const char *addinfo)
 {
@@ -165,6 +194,8 @@ static void clear_error(ZOOM_connection c)
      * or Init Refused are not cleared, because they are not
      * recoverable: doing another search doesn't help.
      */
+
+    ZOOM_connection_remove_events(c);
     switch (c->error)
     {
     case ZOOM_ERROR_CONNECT:
@@ -248,12 +279,12 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
         switch (task->which)
         {
         case ZOOM_TASK_SEARCH:
-            ZOOM_resultset_destroy(task->u.search.resultset);
+            resultset_destroy(task->u.search.resultset);
             xfree(task->u.search.syntax);
             xfree(task->u.search.elementSetName);
             break;
         case ZOOM_TASK_RETRIEVE:
-            ZOOM_resultset_destroy(task->u.retrieve.resultset);
+            resultset_destroy(task->u.retrieve.resultset);
             xfree(task->u.retrieve.syntax);
             xfree(task->u.retrieve.elementSetName);
             break;
@@ -266,7 +297,7 @@ void ZOOM_connection_remove_task(ZOOM_connection c)
             ZOOM_package_destroy(task->u.package);
             break;
         case ZOOM_TASK_SORT:
-            ZOOM_resultset_destroy(task->u.sort.resultset);
+            resultset_destroy(task->u.sort.resultset);
             ZOOM_query_destroy(task->u.sort.q);
             break;
         default:
@@ -398,7 +429,7 @@ ZOOM_API(void)
     initlog();
 
     yaz_log(log_api, "%p ZOOM_connection_connect host=%s portnum=%d",
-            c, host, portnum);
+            c, host ? host : "null", portnum);
 
     set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     ZOOM_connection_remove_tasks(c);
@@ -440,15 +471,18 @@ ZOOM_API(void)
     else
         c->lang = 0;
 
-    xfree(c->host_port);
-    if (portnum)
+    if (host)
     {
-        char hostn[128];
-        sprintf(hostn, "%.80s:%d", host, portnum);
-        c->host_port = xstrdup(hostn);
-    }
-    else
-        c->host_port = xstrdup(host);
+        xfree(c->host_port);
+        if (portnum)
+        {
+            char hostn[128];
+            sprintf(hostn, "%.80s:%d", host, portnum);
+            c->host_port = xstrdup(hostn);
+        }
+        else
+            c->host_port = xstrdup(host);
+    }        
 
     {
         /*
@@ -640,8 +674,8 @@ ZOOM_API(int)
         WRBUF wr = wrbuf_alloc();
         ccl_pquery(wr, rpn);
         ccl_rpn_delete(rpn);
-        ret = ZOOM_query_prefix(s, wrbuf_buf(wr));
-        wrbuf_free(wr, 1);
+        ret = ZOOM_query_prefix(s, wrbuf_cstr(wr));
+        wrbuf_destroy(wr);
     }
     ccl_qual_rm(&bibset);
     return ret;
@@ -682,6 +716,7 @@ ZOOM_API(void)
     odr_destroy(c->odr_out);
     ZOOM_options_destroy(c->options);
     ZOOM_connection_remove_tasks(c);
+    ZOOM_connection_remove_events(c);
     xfree(c->host_port);
     xfree(c->path);
     xfree(c->proxy);
@@ -818,22 +853,10 @@ ZOOM_API(ZOOM_resultset)
     return r;
 }
 
-/*
- * This is the old result-set sorting API, which is maintained only
- * for the sake of binary compatibility.  There is no reason ever to
- * use this rather than ZOOM_resultset_sort1().
- */
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_resultset_sort(ZOOM_resultset r,
                         const char *sort_type, const char *sort_spec)
 {
-    (void) ZOOM_resultset_sort1(r, sort_type, sort_spec);
-}
-
-ZOOM_API(int)
-    ZOOM_resultset_sort1(ZOOM_resultset r,
-                         const char *sort_type, const char *sort_spec)
-{
     ZOOM_connection c = r->connection;
     ZOOM_task task;
     ZOOM_query newq;
@@ -888,11 +911,11 @@ ZOOM_API(void)
         for (rc = r->record_hash[i]; rc; rc = rc->next)
         {
             if (rc->rec.wrbuf_marc)
-                wrbuf_free(rc->rec.wrbuf_marc, 1);
+                wrbuf_destroy(rc->rec.wrbuf_marc);
             if (rc->rec.wrbuf_iconv)
-                wrbuf_free(rc->rec.wrbuf_iconv, 1);
+                wrbuf_destroy(rc->rec.wrbuf_iconv);
             if (rc->rec.wrbuf_opac)
-                wrbuf_free(rc->rec.wrbuf_opac, 1);
+                wrbuf_destroy(rc->rec.wrbuf_opac);
         }
         r->record_hash[i] = 0;
     }
@@ -901,6 +924,11 @@ ZOOM_API(void)
 ZOOM_API(void)
     ZOOM_resultset_destroy(ZOOM_resultset r)
 {
+    resultset_destroy(r);
+}
+
+static void resultset_destroy(ZOOM_resultset r)
+{
     if (!r)
         return;
     (r->refcount)--;
@@ -953,12 +981,18 @@ static void do_close(ZOOM_connection c)
 
 static int ZOOM_test_reconnect(ZOOM_connection c)
 {
+    ZOOM_Event event;
+
     if (!c->reconnect_ok)
         return 0;
     do_close(c);
     c->reconnect_ok = 0;
     c->tasks->running = 0;
     ZOOM_connection_insert_task(c, ZOOM_TASK_CONNECT);
+
+    event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
+    ZOOM_connection_put_event(c, event);
+
     return 1;
 }
 
@@ -1250,7 +1284,7 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
                     odr_prepend(c->odr_out, "ZOOM-C",
                                 ireq->implementationName));
     
-    version = odr_strdup(c->odr_out, "$Revision: 1.106 $");
+    version = odr_strdup(c->odr_out, "$Revision: 1.118 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     ireq->implementationVersion = 
@@ -1552,7 +1586,7 @@ static zoom_ret ZOOM_connection_send_search(ZOOM_connection c)
     }
     if (syntax)
         search_req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
     
     if (!r->setname)
     {
@@ -1680,11 +1714,11 @@ ZOOM_API(void)
     if (!rec)
         return;
     if (rec->wrbuf_marc)
-        wrbuf_free(rec->wrbuf_marc, 1);
+        wrbuf_destroy(rec->wrbuf_marc);
     if (rec->wrbuf_iconv)
-        wrbuf_free(rec->wrbuf_iconv, 1);
+        wrbuf_destroy(rec->wrbuf_iconv);
     if (rec->wrbuf_opac)
-        wrbuf_free(rec->wrbuf_opac, 1);
+        wrbuf_destroy(rec->wrbuf_opac);
     odr_destroy(rec->odr);
     xfree(rec);
 }
@@ -1737,7 +1771,7 @@ static const char *marc_iconv_return(ZOOM_record rec, int marc_type,
             yaz_iconv_close(cd);
         if (len)
             *len = wrbuf_len(rec->wrbuf_marc);
-        return wrbuf_buf(rec->wrbuf_marc);
+        return wrbuf_cstr(rec->wrbuf_marc);
     }
     yaz_marc_destroy(mt);
     if (cd)
@@ -1800,8 +1834,7 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
             }
             wrbuf_write(rec->wrbuf_iconv, outbuf, outp - outbuf);
         }
-        wrbuf_puts(rec->wrbuf_iconv, "");
-        buf = wrbuf_buf(rec->wrbuf_iconv);
+        buf = wrbuf_cstr(rec->wrbuf_iconv);
         sz = wrbuf_len(rec->wrbuf_iconv);
         yaz_iconv_close(cd);
     }
@@ -2392,6 +2425,16 @@ static void handle_search_response(ZOOM_connection c, Z_SearchResponse *sr)
 
     resultset = c->tasks->u.search.resultset;
 
+    if (sr->resultSetStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "resultSetStatus",
+                             *sr->resultSetStatus);
+    }
+    if (sr->presentStatus)
+    {
+        ZOOM_options_set_int(resultset->options, "presentStatus",
+                             *sr->presentStatus);
+    }
     handle_searchResult(c, resultset, sr->additionalSearchInfo);
 
     resultset->size = *sr->resultCount;
@@ -2537,7 +2580,7 @@ static zoom_ret send_present(ZOOM_connection c)
 
     if (syntax && *syntax)
         req->preferredRecordSyntax =
-            yaz_str_to_z3950oid(c->odr_out, CLASS_RECSYN, syntax);
+            zoom_yaz_str_to_z3950oid(c, CLASS_RECSYN, syntax);
 
     if (resultset->schema && *resultset->schema)
     {
@@ -2557,14 +2600,14 @@ static zoom_ret send_present(ZOOM_connection c)
 
         compo->u.complex->generic->which = Z_Schema_oid;
         compo->u.complex->generic->schema.oid = (Odr_oid *)
-            yaz_str_to_z3950oid (c->odr_out, CLASS_SCHEMA, resultset->schema);
+            zoom_yaz_str_to_z3950oid (c, CLASS_SCHEMA, resultset->schema);
 
         if (!compo->u.complex->generic->schema.oid)
         {
             /* OID wasn't a schema! Try record syntax instead. */
 
             compo->u.complex->generic->schema.oid = (Odr_oid *)
-                yaz_str_to_z3950oid (c->odr_out, CLASS_RECSYN, resultset->schema);
+                zoom_yaz_str_to_z3950oid (c, CLASS_RECSYN, resultset->schema);
         }
         if (elementSetName && *elementSetName)
         {
@@ -2600,21 +2643,21 @@ static zoom_ret send_present(ZOOM_connection c)
 }
 
 ZOOM_API(ZOOM_scanset)
-    ZOOM_connection_scan(ZOOM_connection c, const char *start)
+    ZOOM_connection_scan_pqf(ZOOM_connection c, const char *start)
 {
     ZOOM_scanset s;
     ZOOM_query q = ZOOM_query_create();
 
     ZOOM_query_prefix(q, start);
 
-    s = ZOOM_connection_scan1(c, q);
+    s = ZOOM_connection_scan(c, q);
     ZOOM_query_destroy(q);
     return s;
 
 }
 
 ZOOM_API(ZOOM_scanset)
-    ZOOM_connection_scan1(ZOOM_connection c, ZOOM_query q)
+    ZOOM_connection_scan(ZOOM_connection c, ZOOM_query q)
 {
     char *start;
     char *freeme = 0;
@@ -2814,11 +2857,12 @@ ZOOM_API(const char *)
     return ZOOM_options_get(scan->options, key);
 }
 
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_scanset_option_set(ZOOM_scanset scan, const char *key,
                             const char *val)
 {
     ZOOM_options_set(scan->options, key, val);
+    return 0;
 }
 
 static Z_APDU *create_es_package(ZOOM_package p, int type)
@@ -2958,7 +3002,13 @@ static Z_ItemOrder *encode_item_order(ZOOM_package p)
         *req->u.esRequest->notToKeep->resultSetItem->item =
             (str ? atoi(str) : 1);
     }
-    req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
+
+    str = ZOOM_options_get(p->options, "doc");
+    if (str)
+        req->u.esRequest->notToKeep->itemRequest =
+            z_ext_record(p->odr_out, VAL_TEXT_XML, str, strlen(str));
+    else
+        req->u.esRequest->notToKeep->itemRequest = encode_ill_request(p);
     
     return req;
 }
@@ -3264,11 +3314,12 @@ ZOOM_API(const char *)
 }
 
 
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_package_option_set(ZOOM_package p, const char *key,
                             const char *val)
 {
     ZOOM_options_set(p->options, key, val);
+    return 0;
 }
 
 static int ZOOM_connection_exec_task(ZOOM_connection c)
@@ -3728,11 +3779,7 @@ static int do_read(ZOOM_connection c)
         return 0;
     if (r <= 0)
     {
-        if (ZOOM_test_reconnect(c))
-        {
-            yaz_log(log_details, "%p do_read reconnect read", c);
-        }
-        else
+        if (!ZOOM_test_reconnect(c))
         {
             set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
             do_close(c);
@@ -3836,18 +3883,20 @@ ZOOM_API(const char *)
     return ZOOM_options_getl(c->options, key, lenp);
 }
 
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_connection_option_set(ZOOM_connection c, const char *key,
                                const char *val)
 {
     ZOOM_options_set(c->options, key, val);
+    return 0;
 }
 
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_connection_option_setl(ZOOM_connection c, const char *key,
                                 const char *val, int len)
 {
     ZOOM_options_setl(c->options, key, val, len);
+    return 0;
 }
 
 ZOOM_API(const char *)
@@ -3856,11 +3905,12 @@ ZOOM_API(const char *)
     return ZOOM_options_get(r->options, key);
 }
 
-ZOOM_API(void)
+ZOOM_API(int)
     ZOOM_resultset_option_set(ZOOM_resultset r, const char *key,
                               const char *val)
 {
     ZOOM_options_set(r->options, key, val);
+    return 0;
 }
 
 
@@ -4023,12 +4073,7 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask)
     {
         if (mask & ZOOM_SELECT_EXCEPT)
         {
-            if (ZOOM_test_reconnect(c))
-            {
-                event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
-                ZOOM_connection_put_event(c, event);
-            }
-            else
+            if (!ZOOM_test_reconnect(c))
             {
                 set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, c->host_port);
                 do_close(c);
@@ -4125,41 +4170,41 @@ ZOOM_API(int) ZOOM_connection_fire_event_timeout(ZOOM_connection c)
 }
 
 ZOOM_API(int)
-    ZOOM_process_event(int no, ZOOM_connection *cs)
+    ZOOM_connection_process(ZOOM_connection c)
+{
+    ZOOM_Event event;
+    if (!c)
+        return 0;
+
+    event = ZOOM_connection_get_event(c);
+    if (event)
+    {
+        ZOOM_Event_destroy(event);
+        return 1;
+    }
+    ZOOM_connection_exec_task(c);
+    event = ZOOM_connection_get_event(c);
+    if (event)
+    {
+        ZOOM_Event_destroy(event);
+        return 1;
+    }
+    return 0;
+}
+
+ZOOM_API(int)
+    ZOOM_event_nonblock(int no, ZOOM_connection *cs)
 {
     int i;
 
-    yaz_log(log_details, "ZOOM_event_poll(no=%d,cs=%p)", no, cs);
+    yaz_log(log_details, "ZOOM_process_event(no=%d,cs=%p)", no, cs);
     
     for (i = 0; i<no; i++)
     {
         ZOOM_connection c = cs[i];
-        ZOOM_Event event;
-
-#if 0
-        if (c)
-            ZOOM_connection_show_tasks(c);
-#endif
 
-        if (c && (event = ZOOM_connection_get_event(c)))
-        {
-            ZOOM_Event_destroy(event);
+        if (c && ZOOM_connection_process(c))
             return i+1;
-        }
-    }
-    for (i = 0; i<no; i++)
-    {
-        ZOOM_connection c = cs[i];
-        if (c)
-        {
-            ZOOM_Event event;
-            ZOOM_connection_exec_task(c);
-            if ((event = ZOOM_connection_get_event(c)))
-            {
-                ZOOM_Event_destroy(event);
-                return i+1;
-            }
-        }
     }
     return 0;
 }