Changed ZOOM_query_ccl2rpn function so that it takes a CCL config
[yaz-moved-to-github.git] / src / zoom-c.c
index 148b54e..22c4719 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.69 2006-04-19 10:05:03 adam Exp $
+ * $Id: zoom-c.c,v 1.78 2006-06-15 10:34:17 adam Exp $
  */
 /**
  * \file zoom-c.c
@@ -25,6 +25,7 @@
 #include <yaz/ill.h>
 #include <yaz/srw.h>
 #include <yaz/cql.h>
+#include <yaz/ccl.h>
 
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -563,12 +564,16 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
 {
     char *rpn;
     int ret;
+    ZOOM_connection freeme = 0;
 
     yaz_log(log_details, "%p ZOOM_query_cql2rpn str=%s conn=%p", s, str, conn);
     if (conn == 0)
-        conn = ZOOM_connection_create(0);
+        conn = freeme = ZOOM_connection_create(0);
 
-    if ((rpn = cql2pqf(conn, str)) == 0)
+    rpn = cql2pqf(conn, str);
+    if (freeme != 0)
+        ZOOM_connection_destroy(freeme);
+    if (rpn == 0)
         return -1;
 
     ret = ZOOM_query_prefix(s, rpn);
@@ -576,6 +581,41 @@ ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
     return ret;
 }
 
+/*
+ * Analogous in every way to ZOOM_query_cql2rpn(), except that there
+ * is no analogous ZOOM_query_ccl() that just sends uninterpreted CCL
+ * to the server, as the YAZ GFS doesn't know how to handle this.
+ */
+ZOOM_API(int)
+    ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config,
+                       int *ccl_error, const char **error_string,
+                       int *error_pos)
+{
+    int ret;
+    struct ccl_rpn_node *rpn;
+    CCL_bibset bibset = ccl_qual_mk();
+
+    if (config)
+        ccl_qual_buf(bibset, config);
+
+    rpn = ccl_find_str(bibset, str, ccl_error, error_pos);
+    if (!rpn)
+    {
+        *error_string = ccl_err_msg(*ccl_error);
+        ret = -1;
+    }
+    else
+    {
+        WRBUF wr = wrbuf_alloc();
+        ccl_pquery(wr, rpn);
+        ccl_rpn_delete(rpn);
+        ret = ZOOM_query_prefix(s, wrbuf_buf(wr));
+        wrbuf_free(wr, 1);
+    }
+    ccl_qual_rm(&bibset);
+    return ret;
+}
+
 ZOOM_API(int)
 ZOOM_query_sortby(ZOOM_query s, const char *criteria)
 {
@@ -634,6 +674,7 @@ void ZOOM_resultset_addref (ZOOM_resultset r)
 
 ZOOM_resultset ZOOM_resultset_create ()
 {
+    int i;
     ZOOM_resultset r = (ZOOM_resultset) xmalloc (sizeof(*r));
 
     initlog();
@@ -648,7 +689,8 @@ ZOOM_resultset ZOOM_resultset_create ()
     r->schema = 0;
     r->count = 0;
     r->step = 0;
-    r->record_cache = 0;
+    for (i = 0; i<RECORD_HASH_SIZE; i++)
+        r->record_hash[i] = 0;
     r->r_sort_spec = 0;
     r->query = 0;
     r->connection = 0;
@@ -794,18 +836,21 @@ ZOOM_resultset_sort1(ZOOM_resultset r,
 ZOOM_API(void)
     ZOOM_resultset_cache_reset(ZOOM_resultset r)
 {
-    ZOOM_record_cache rc;
-    
-    for (rc = r->record_cache; rc; rc = rc->next)
+    int i;
+    for (i = 0; i<RECORD_HASH_SIZE; i++)
     {
-        if (rc->rec.wrbuf_marc)
-            wrbuf_free (rc->rec.wrbuf_marc, 1);
-        if (rc->rec.wrbuf_iconv)
-            wrbuf_free (rc->rec.wrbuf_iconv, 1);
-        if (rc->rec.wrbuf_opac)
-            wrbuf_free (rc->rec.wrbuf_opac, 1);
+        ZOOM_record_cache rc;
+        for (rc = r->record_hash[i]; rc; rc = rc->next)
+        {
+            if (rc->rec.wrbuf_marc)
+                wrbuf_free (rc->rec.wrbuf_marc, 1);
+            if (rc->rec.wrbuf_iconv)
+                wrbuf_free (rc->rec.wrbuf_iconv, 1);
+            if (rc->rec.wrbuf_opac)
+                wrbuf_free (rc->rec.wrbuf_opac, 1);
+        }
+        r->record_hash[i] = 0;
     }
-    r->record_cache = 0;
 }
 
 ZOOM_API(void)
@@ -918,8 +963,8 @@ ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs,
 
     if (!r)
         return ;
-    yaz_log(log_api, "%p ZOOM_resultset_records r=%p start=%d count=%d",
-            r, r, start, count);
+    yaz_log(log_api, "%p ZOOM_resultset_records r=%p start=%ld count=%ld",
+            r, r, (long) start, (long) count);
     if (count && recs)
         force_present = 1;
     ZOOM_resultset_retrieve (r, force_present, start, count);
@@ -1150,7 +1195,7 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c)
         ZOOM_options_get(c->options, "implementationName"),
         odr_prepend(c->odr_out, "ZOOM-C", ireq->implementationName));
 
-    version = odr_strdup(c->odr_out, "$Revision: 1.69 $");
+    version = odr_strdup(c->odr_out, "$Revision: 1.78 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     ireq->implementationVersion = odr_prepend(c->odr_out,
@@ -1231,41 +1276,10 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c)
 #if HAVE_XML2
 static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr)
 {
-    Z_SOAP_Handler h[2] = {
-        {"http://www.loc.gov/zing/srw/", 0, (Z_SOAP_fun) yaz_srw_codec},
-        {0, 0, 0}
-    };
-    ODR o = odr_createmem(ODR_ENCODE);
-    int ret;
-    Z_SOAP *p = (Z_SOAP*) odr_malloc(o, sizeof(*p));
     Z_GDU *gdu;
     ZOOM_Event event;
 
-    gdu = z_get_HTTP_Request(c->odr_out);
-    gdu->u.HTTP_Request->path = c->path;
-
-    if (c->host_port)
-    {
-        const char *cp0 = strstr(c->host_port, "://");
-        const char *cp1 = 0;
-        if (cp0)
-            cp0 = cp0+3;
-        else
-            cp0 = c->host_port;
-
-        cp1 = strchr(cp0, '/');
-        if (!cp1)
-            cp1 = cp0+strlen(cp0);
-
-        if (cp0 && cp1)
-        {
-            char *h = (char*) odr_malloc(c->odr_out, cp1 - cp0 + 1);
-            memcpy (h, cp0, cp1 - cp0);
-            h[cp1-cp0] = '\0';
-            z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers,
-                              "Host", h);
-        }
-    }
+    gdu = z_get_HTTP_Request_host_path(c->odr_out, c->host_port, c->path);
 
     if (c->sru_mode == zoom_sru_get)
     {
@@ -1277,29 +1291,11 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr)
     }
     else if (c->sru_mode == zoom_sru_soap)
     {
-        z_HTTP_header_add_content_type(c->odr_out,
-                                       &gdu->u.HTTP_Request->headers,
-                                       "text/xml", c->charset);
-
-        z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers,
-                          "SOAPAction", "\"\"");
-        p->which = Z_SOAP_generic;
-        p->u.generic = (Z_SOAP_Generic *) odr_malloc(o, sizeof(*p->u.generic));
-        p->u.generic->no = 0;
-        p->u.generic->ns = 0;
-        p->u.generic->p = sr;
-        p->ns = "http://schemas.xmlsoap.org/soap/envelope/";
-        
-        ret = z_soap_codec_enc(o, &p,
-                               &gdu->u.HTTP_Request->content_buf,
-                               &gdu->u.HTTP_Request->content_len, h,
-                               c->charset);
-
+        yaz_sru_post_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
     }
     if (!z_GDU(c->odr_out, &gdu, 0, 0))
         return zoom_complete;
     c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0);
-    odr_destroy(o);
         
     event = ZOOM_Event_create (ZOOM_EVENT_SEND_APDU);
     ZOOM_connection_put_event (c, event);
@@ -1584,7 +1580,15 @@ ZOOM_resultset_record (ZOOM_resultset r, size_t pos)
 
     if (!rec)
     {
-        ZOOM_resultset_retrieve (r, 1, pos, 1);
+        /*
+         * MIKE: I think force_sync should always be zero, but I don't
+         * want to make this change until I get the go-ahead from
+         * Adam, in case something depends on the old synchronous
+         * behaviour.
+         */
+        int force_sync = 1;
+        if (getenv("ZOOM_RECORD_NO_FORCE_SYNC")) force_sync = 0;
+        ZOOM_resultset_retrieve (r, force_sync, pos, 1);
         rec = ZOOM_resultset_record_immediate (r, pos);
     }
     return rec;
@@ -1973,6 +1977,13 @@ static int strcmp_null(const char *v1, const char *v2)
     return strcmp(v1, v2);
 }
 
+static size_t record_hash(int pos)
+{
+    if (pos < 0)
+        pos = 0;
+    return pos % RECORD_HASH_SIZE;
+}
+
 static void record_cache_add (ZOOM_resultset r, Z_NamePlusRecord *npr, 
                               int pos)
 {
@@ -1985,7 +1996,7 @@ static void record_cache_add (ZOOM_resultset r, Z_NamePlusRecord *npr,
     ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
     ZOOM_connection_put_event(r->connection, event);
 
-    for (rc = r->record_cache; rc; rc = rc->next)
+    for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
     {
         if (pos == rc->pos)
         {
@@ -2023,8 +2034,8 @@ static void record_cache_add (ZOOM_resultset r, Z_NamePlusRecord *npr,
         rc->schema = 0;
 
     rc->pos = pos;
-    rc->next = r->record_cache;
-    r->record_cache = rc;
+    rc->next = r->record_hash[record_hash(pos)];
+    r->record_hash[record_hash(pos)] = rc;
 }
 
 static ZOOM_record record_cache_lookup (ZOOM_resultset r, int pos)
@@ -2035,7 +2046,7 @@ static ZOOM_record record_cache_lookup (ZOOM_resultset r, int pos)
     const char *syntax = 
         ZOOM_resultset_option_get (r, "preferredRecordSyntax");
     
-    for (rc = r->record_cache; rc; rc = rc->next)
+    for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
     {
         if (pos == rc->pos)
         {
@@ -2469,12 +2480,11 @@ ZOOM_connection_scan1 (ZOOM_connection c, ZOOM_query q)
 
     /*
      * We need to check the query-type, so we can recognise CQL and
-     * compile it into a form that we can use here.  The ZOOM_query
-     * structure has no explicit `type' member, but inspection of the
-     * ZOOM_query_prefix() and ZOOM_query_cql() functions shows how
-     * the structure is set up in each case.
+     * CCL and compile them into a form that we can use here.  The
+     * ZOOM_query structure has no explicit `type' member, but
+     * inspection of the ZOOM_query_prefix() and ZOOM_query_cql()
+     * functions shows how the structure is set up in each case.
      */
-
     if (q->z_query->which == Z_Query_type_1) {
         yaz_log(log_api, "%p ZOOM_connection_scan1 q=%p PQF '%s'",
                 c, q, q->query_string);
@@ -2536,8 +2546,10 @@ static zoom_ret send_package (ZOOM_connection c)
     event = ZOOM_Event_create (ZOOM_EVENT_SEND_APDU);
     ZOOM_connection_put_event (c, event);
     
-    return do_write_ex (c, c->tasks->u.package->buf_out,
-                        c->tasks->u.package->len_out);
+    c->buf_out = c->tasks->u.package->buf_out;
+    c->len_out = c->tasks->u.package->len_out;
+
+    return do_write(c);
 }
 
 static zoom_ret send_scan (ZOOM_connection c)
@@ -3744,6 +3756,10 @@ ZOOM_diag_str (int error)
         return "CQL parsing error";
     case ZOOM_ERROR_CQL_TRANSFORM:
         return "CQL transformation error";
+    case ZOOM_ERROR_CCL_CONFIG:
+        return "CCL configuration error";
+    case ZOOM_ERROR_CCL_PARSE:
+        return "CCL parsing error";
     default:
         return diagbib1_str (error);
     }
@@ -4099,7 +4115,6 @@ static char *cql2pqf(ZOOM_connection c, const char *cql)
     return xstrdup(pqfbuf);
 }
 
-
 /*
  * Local variables:
  * c-basic-offset: 4