Refactor ZOOM SRU stuff to separate source
authorAdam Dickmeiss <adam@indexdata.dk>
Wed, 11 Aug 2010 13:59:03 +0000 (15:59 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Wed, 11 Aug 2010 13:59:03 +0000 (15:59 +0200)
src/Makefile.am
src/zoom-c.c
src/zoom-p.h
src/zoom-sru.c [new file with mode: 0644]
win/makefile

index 95f8d9d..108d618 100644 (file)
@@ -88,8 +88,8 @@ libyaz_la_SOURCES=version.c options.c log.c \
   zget.c yaz-ccl.c diag-entry.c diag-entry.h \
   logrpn.c \
   otherinfo.c pquery.c sortspec.c charneg.c initopt.c \
-  zoom-c.c zoom-z3950.c zoom-query.c zoom-record-cache.c record_render.c \
-  zoom-socket.c zoom-opt.c zoom-p.h \
+  zoom-c.c zoom-z3950.c zoom-sru.c zoom-query.c zoom-record-cache.c \
+  record_render.c zoom-socket.c zoom-opt.c zoom-p.h \
   grs1disp.c zgdu.c soap.c srw.c srwutil.c uri.c \
   opacdisp.c cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \
   cclqfile.c cclstr.c cclxmlconfig.c ccl_stop_words.c \
index fa3e7ee..f5356b9 100644 (file)
@@ -176,22 +176,6 @@ int ZOOM_uri_to_code(const char *uri)
 }
 
 
-#if YAZ_HAVE_XML2
-static void set_HTTP_error(ZOOM_connection c, int error,
-                           const char *addinfo, const char *addinfo2)
-{
-    ZOOM_set_dset_error(c, error, "HTTP", addinfo, addinfo2);
-}
-
-static void set_SRU_error(ZOOM_connection c, Z_SRW_diagnostic *d)
-{
-    const char *uri = d->uri;
-    if (uri)
-        ZOOM_set_dset_error(c, ZOOM_uri_to_code(uri), uri, d->details, 0);
-}
-
-#endif
-
 
 void ZOOM_set_error(ZOOM_connection c, int error, const char *addinfo)
 {
@@ -1186,154 +1170,6 @@ static zoom_ret do_connect_host(ZOOM_connection c, const char *effective_host,
    0 if PDU was not sent OK (nothing to wait for) 
 */
 
-#if YAZ_HAVE_XML2
-static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
-{
-    Z_GDU *gdu;
-    ZOOM_Event event;
-    const char *database =  ZOOM_options_get(c->options, "databaseName");
-    char *fdatabase = 0;
-    
-    if (database)
-        fdatabase = yaz_encode_sru_dbpath_odr(c->odr_out, database);
-    gdu = z_get_HTTP_Request_host_path(c->odr_out, c->host_port,
-                                       fdatabase ? fdatabase : c->path);
-
-    if (c->sru_mode == zoom_sru_get)
-    {
-        yaz_sru_get_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
-    }
-    else if (c->sru_mode == zoom_sru_post)
-    {
-        yaz_sru_post_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
-    }
-    else if (c->sru_mode == zoom_sru_soap)
-    {
-        yaz_sru_soap_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
-    }
-    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);
-    ZOOM_connection_put_event(c, event);
-    odr_reset(c->odr_out);
-    return ZOOM_send_buf(c);
-}
-#endif
-
-#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)
-{
-    int i;
-    int *start, *count;
-    ZOOM_resultset resultset = 0;
-    Z_SRW_PDU *sr = 0;
-    const char *option_val = 0;
-    Z_Query *z_query;
-
-    if (c->error)                  /* don't continue on error */
-        return zoom_complete;
-    assert(c->tasks);
-    switch(c->tasks->which)
-    {
-    case ZOOM_TASK_SEARCH:
-        resultset = c->tasks->u.search.resultset;
-        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;
-        break;
-    case ZOOM_TASK_RETRIEVE:
-        resultset = c->tasks->u.retrieve.resultset;
-
-        start = &c->tasks->u.retrieve.start;
-        count = &c->tasks->u.retrieve.count;
-
-        if (*start >= resultset->size)
-            return zoom_complete;
-        if (*start + *count > resultset->size)
-            *count = resultset->size - *start;
-
-        for (i = 0; i < *count; i++)
-        {
-            ZOOM_record rec =
-                ZOOM_record_cache_lookup(resultset, i + *start,
-                                         c->tasks->u.retrieve.syntax,
-                                         c->tasks->u.retrieve.elementSetName);
-            if (!rec)
-                break;
-            else
-            {
-                ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
-                ZOOM_connection_put_event(c, event);
-            }
-        }
-        *start += i;
-        *count -= i;
-
-        if (*count == 0)
-            return zoom_complete;
-        break;
-    default:
-        return zoom_complete;
-    }
-    assert(resultset->query);
-        
-    sr = ZOOM_srw_get_pdu(c, Z_SRW_searchRetrieve_request);
-    z_query = ZOOM_query_get_Z_Query(resultset->query);
-
-    if (z_query->which == Z_Query_type_104
-        && z_query->u.type_104->which == Z_External_CQL)
-    {
-        sr->u.request->query_type = Z_SRW_query_type_cql;
-        sr->u.request->query.cql = z_query->u.type_104->u.cql;
-    }
-    else if (z_query->which == Z_Query_type_1 && z_query->u.type_1)
-    {
-        sr->u.request->query_type = Z_SRW_query_type_pqf;
-        sr->u.request->query.pqf =
-            ZOOM_query_get_query_string(resultset->query);
-    }
-    else
-    {
-        ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_QUERY, 0);
-        return zoom_complete;
-    }
-    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) ? 
-        resultset->step : *count);
-    sr->u.request->recordSchema = resultset->schema;
-    
-    option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
-    if (option_val)
-        sr->u.request->recordPacking = odr_strdup(c->odr_out, option_val);
-
-    option_val = ZOOM_resultset_option_get(resultset, "extraArgs");
-    yaz_encode_sru_extra(sr, c->odr_out, option_val);
-    return send_srw(c, sr);
-}
-#else
-static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
-{
-    return zoom_complete;
-}
-#endif
-
 ZOOM_API(ZOOM_record)
     ZOOM_resultset_record_immediate(ZOOM_resultset s,size_t pos)
 {
@@ -1452,60 +1288,6 @@ static zoom_ret send_package(ZOOM_connection c)
     return ZOOM_send_buf(c);
 }
 
-#if YAZ_HAVE_XML2
-static zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c)
-{
-    ZOOM_scanset scan;
-    Z_SRW_PDU *sr = 0;
-    const char *option_val = 0;
-    Z_Query *z_query;
-
-    if (!c->tasks)
-        return zoom_complete;
-    assert (c->tasks->which == ZOOM_TASK_SCAN);
-    scan = c->tasks->u.scan.scan;
-        
-    sr = ZOOM_srw_get_pdu(c, Z_SRW_scan_request);
-
-    z_query = ZOOM_query_get_Z_Query(scan->query);
-    /* SRU scan can only carry CQL and PQF */
-    if (z_query->which == Z_Query_type_104)
-    {
-        sr->u.scan_request->query_type = Z_SRW_query_type_cql;
-        sr->u.scan_request->scanClause.cql =
-            ZOOM_query_get_query_string(scan->query);
-    }
-    else if (z_query->which == Z_Query_type_1
-             || z_query->which == Z_Query_type_101)
-    {
-        sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
-        sr->u.scan_request->scanClause.pqf =
-            ZOOM_query_get_query_string(scan->query);
-    }
-    else
-    {
-        ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_QUERY, 0);
-        return zoom_complete;
-    }
-
-    sr->u.scan_request->maximumTerms = odr_intdup(
-        c->odr_out, ZOOM_options_get_int(scan->options, "number", 10));
-    
-    sr->u.scan_request->responsePosition = odr_intdup(
-        c->odr_out, ZOOM_options_get_int(scan->options, "position", 1));
-    
-    option_val = ZOOM_options_get(scan->options, "extraArgs");
-    yaz_encode_sru_extra(sr, c->odr_out, option_val);
-    return send_srw(c, sr);
-}
-#else
-static zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c)
-{
-    return zoom_complete;
-}
-#endif
-
-
 ZOOM_API(size_t)
     ZOOM_scanset_size(ZOOM_scanset scan)
 {
@@ -1757,150 +1539,6 @@ ZOOM_API(int)
 }
 
 #if YAZ_HAVE_XML2
-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, *count;
-    const char *syntax, *elementSetName;
-
-    if (!c->tasks)
-        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;        
-
-        if (!c->tasks->u.search.recv_search_fired)
-        {
-            event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
-            ZOOM_connection_put_event(c, event);
-            c->tasks->u.search.recv_search_fired = 1;
-        }
-        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 zoom_complete;
-    }
-
-    resultset->size = 0;
-
-    if (res->resultSetId)
-        ZOOM_resultset_option_set(resultset, "resultSetId", res->resultSetId);
-
-    yaz_log(c->log_details, "%p handle_srw_response got SRW response OK", c);
-
-    if (res->num_diagnostics > 0)
-    {
-        set_SRU_error(c, &res->diagnostics[0]);
-    }
-    else
-    {
-        if (res->numberOfRecords)
-            resultset->size = *res->numberOfRecords;
-        for (i = 0; i<res->num_records; i++)
-        {
-            int pos;
-            Z_SRW_record *sru_rec;
-            Z_SRW_diagnostic *diag = 0;
-            int num_diag;
-            
-            Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
-                odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
-            
-            if (res->records[i].recordPosition && 
-                *res->records[i].recordPosition > 0)
-                pos = *res->records[i].recordPosition - 1;
-            else
-                pos = *start + i;
-            
-            sru_rec = &res->records[i];
-            
-            npr->databaseName = 0;
-            npr->which = Z_NamePlusRecord_databaseRecord;
-            npr->u.databaseRecord = (Z_External *)
-                odr_malloc(c->odr_in, sizeof(Z_External));
-            npr->u.databaseRecord->descriptor = 0;
-            npr->u.databaseRecord->direct_reference =
-                odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
-            npr->u.databaseRecord->which = Z_External_octet;
-            
-            npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
-                odr_malloc(c->odr_in, sizeof(Odr_oct));
-            npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)
-                sru_rec->recordData_buf;
-            npr->u.databaseRecord->u.octet_aligned->len = 
-                npr->u.databaseRecord->u.octet_aligned->size = 
-                sru_rec->recordData_len;
-            
-            if (sru_rec->recordSchema 
-                && !strcmp(sru_rec->recordSchema,
-                           "info:srw/schema/1/diagnostics-v1.1"))
-            {
-                sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
-                                                 sru_rec->recordData_len,
-                                                 &diag, &num_diag,
-                                                 resultset->odr);
-            }
-            ZOOM_record_cache_add(resultset, npr, pos, syntax, elementSetName,
-                                  sru_rec->recordSchema, diag);
-        }
-        *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 (*count > 0)
-            return ZOOM_connection_srw_send_search(c);
-    }
-    return zoom_complete;
-}
-#endif
-
-#if YAZ_HAVE_XML2
-static void handle_srw_scan_response(ZOOM_connection c,
-                                     Z_SRW_scanResponse *res)
-{
-    NMEM nmem = odr_extract_mem(c->odr_in);
-    ZOOM_scanset scan;
-
-    if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
-        return;
-    scan = c->tasks->u.scan.scan;
-
-    if (res->num_diagnostics > 0)
-        set_SRU_error(c, &res->diagnostics[0]);
-
-    scan->scan_response = 0;
-    scan->srw_scan_response = res;
-    nmem_transfer(odr_getmem(scan->odr), nmem);
-
-    ZOOM_options_set_int(scan->options, "number", res->num_terms);
-    nmem_destroy(nmem);
-}
-#endif
-
-#if YAZ_HAVE_XML2
 static Z_GDU *get_HTTP_Request_url(ODR odr, const char *url)
 {
     Z_GDU *p = z_get_HTTP_Request(odr);
@@ -1927,7 +1565,7 @@ static Z_GDU *get_HTTP_Request_url(ODR odr, const char *url)
     return p;
 }
 
-static zoom_ret send_SRW_redirect(ZOOM_connection c, const char *uri,
+static zoom_ret send_HTTP_redirect(ZOOM_connection c, const char *uri,
                                   Z_HTTP_Response *cookie_hres)
 {
     struct Z_HTTP_Header *h;
@@ -1979,6 +1617,15 @@ static zoom_ret send_SRW_redirect(ZOOM_connection c, const char *uri,
     return ZOOM_send_buf(c);
 }
 
+#if YAZ_HAVE_XML2
+void ZOOM_set_HTTP_error(ZOOM_connection c, int error,
+                         const char *addinfo, const char *addinfo2)
+{
+    ZOOM_set_dset_error(c, error, "HTTP", addinfo, addinfo2);
+}
+#endif
+
+
 static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
 {
     zoom_ret cret = zoom_complete;
@@ -1997,7 +1644,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
         c->no_redirects++;
         if (c->no_redirects > 10)
         {
-            set_HTTP_error(c, hres->code, 0, 0);
+            ZOOM_set_HTTP_error(c, hres->code, 0, 0);
             c->no_redirects = 0;
             ZOOM_connection_close(c);
         }
@@ -2006,52 +1653,15 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
             /* since redirect may change host we just reconnect. A smarter
                implementation might check whether it's the same server */
             do_connect_host(c, location, 0);
-            send_SRW_redirect(c, location, hres);
+            send_HTTP_redirect(c, location, hres);
             /* we're OK for now. Operation is not really complete */
             ret = 0;
             cret = zoom_pending;
         }
     }
     else 
-    {   /* not redirect (normal response) */
-        if (!yaz_srw_check_content_type(hres))
-            addinfo = "content-type";
-        else
-        {
-            Z_SOAP *soap_package = 0;
-            ODR o = c->odr_in;
-            Z_SOAP_Handler soap_handlers[2] = {
-                {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
-                {0, 0, 0}
-            };
-            ret = z_soap_codec(o, &soap_package,
-                               &hres->content_buf, &hres->content_len,
-                               soap_handlers);
-            if (!ret && soap_package->which == Z_SOAP_generic &&
-                soap_package->u.generic->no == 0)
-            {
-                Z_SRW_PDU *sr = (Z_SRW_PDU*) soap_package->u.generic->p;
-                
-                ZOOM_options_set(c->options, "sru_version", sr->srw_version);
-                ZOOM_options_setl(c->options, "sru_extra_response_data",
-                                  sr->extraResponseData_buf, sr->extraResponseData_len);
-                if (sr->which == Z_SRW_searchRetrieve_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
-                    ret = -1;
-            }
-            else if (!ret && (soap_package->which == Z_SOAP_fault
-                              || soap_package->which == Z_SOAP_error))
-            {
-                set_HTTP_error(c, hres->code,
-                               soap_package->u.fault->fault_code,
-                               soap_package->u.fault->fault_string);
-            }
-            else
-                ret = -1;
-        }   
+    {  
+        ret = ZOOM_handle_sru(c, hres, &cret);
         if (ret == 0)
         {
             if (c->no_redirects) /* end of redirect. change hosts again */
@@ -2062,7 +1672,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
     if (ret)
     {
         if (hres->code != 200)
-            set_HTTP_error(c, hres->code, 0, 0);
+            ZOOM_set_HTTP_error(c, hres->code, 0, 0);
         else
             ZOOM_set_error(c, ZOOM_ERROR_DECODE, addinfo);
         ZOOM_connection_close(c);
index 06d4b29..bb3b132 100644 (file)
@@ -290,6 +290,15 @@ char *ZOOM_query_get_query_string(ZOOM_query s);
 
 int ZOOM_uri_to_code(const char *uri);
 
+zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c);
+zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c);
+
+int ZOOM_handle_sru(ZOOM_connection c, Z_HTTP_Response *hres,
+                    zoom_ret *cret);
+
+void ZOOM_set_HTTP_error(ZOOM_connection c, int error,
+                         const char *addinfo, const char *addinfo2);
+
 /*
  * Local variables:
  * c-basic-offset: 4
diff --git a/src/zoom-sru.c b/src/zoom-sru.c
new file mode 100644 (file)
index 0000000..1932f09
--- /dev/null
@@ -0,0 +1,429 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2010 Index Data
+ * See the file LICENSE for details.
+ */
+/**
+ * \file zoom-sru.c
+ * \brief Implements ZOOM SRU
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include "zoom-p.h"
+
+#include <yaz/log.h>
+
+#if YAZ_HAVE_XML2
+static void set_SRU_error(ZOOM_connection c, Z_SRW_diagnostic *d)
+{
+    const char *uri = d->uri;
+    if (uri)
+        ZOOM_set_dset_error(c, ZOOM_uri_to_code(uri), uri, d->details, 0);
+}
+#endif
+
+
+
+#if YAZ_HAVE_XML2
+static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
+{
+    Z_GDU *gdu;
+    ZOOM_Event event;
+    const char *database =  ZOOM_options_get(c->options, "databaseName");
+    char *fdatabase = 0;
+    
+    if (database)
+        fdatabase = yaz_encode_sru_dbpath_odr(c->odr_out, database);
+    gdu = z_get_HTTP_Request_host_path(c->odr_out, c->host_port,
+                                       fdatabase ? fdatabase : c->path);
+
+    if (c->sru_mode == zoom_sru_get)
+    {
+        yaz_sru_get_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
+    }
+    else if (c->sru_mode == zoom_sru_post)
+    {
+        yaz_sru_post_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
+    }
+    else if (c->sru_mode == zoom_sru_soap)
+    {
+        yaz_sru_soap_encode(gdu->u.HTTP_Request, sr, c->odr_out, c->charset);
+    }
+    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);
+    ZOOM_connection_put_event(c, event);
+    odr_reset(c->odr_out);
+    return ZOOM_send_buf(c);
+}
+#endif
+
+#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
+zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c)
+{
+    ZOOM_scanset scan;
+    Z_SRW_PDU *sr = 0;
+    const char *option_val = 0;
+    Z_Query *z_query;
+
+    if (!c->tasks)
+        return zoom_complete;
+    assert (c->tasks->which == ZOOM_TASK_SCAN);
+    scan = c->tasks->u.scan.scan;
+        
+    sr = ZOOM_srw_get_pdu(c, Z_SRW_scan_request);
+
+    z_query = ZOOM_query_get_Z_Query(scan->query);
+    /* SRU scan can only carry CQL and PQF */
+    if (z_query->which == Z_Query_type_104)
+    {
+        sr->u.scan_request->query_type = Z_SRW_query_type_cql;
+        sr->u.scan_request->scanClause.cql =
+            ZOOM_query_get_query_string(scan->query);
+    }
+    else if (z_query->which == Z_Query_type_1
+             || z_query->which == Z_Query_type_101)
+    {
+        sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
+        sr->u.scan_request->scanClause.pqf =
+            ZOOM_query_get_query_string(scan->query);
+    }
+    else
+    {
+        ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_QUERY, 0);
+        return zoom_complete;
+    }
+
+    sr->u.scan_request->maximumTerms = odr_intdup(
+        c->odr_out, ZOOM_options_get_int(scan->options, "number", 10));
+    
+    sr->u.scan_request->responsePosition = odr_intdup(
+        c->odr_out, ZOOM_options_get_int(scan->options, "position", 1));
+    
+    option_val = ZOOM_options_get(scan->options, "extraArgs");
+    yaz_encode_sru_extra(sr, c->odr_out, option_val);
+    return send_srw(c, sr);
+}
+#else
+zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c)
+{
+    return zoom_complete;
+}
+#endif
+
+#if YAZ_HAVE_XML2
+zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
+{
+    int i;
+    int *start, *count;
+    ZOOM_resultset resultset = 0;
+    Z_SRW_PDU *sr = 0;
+    const char *option_val = 0;
+    Z_Query *z_query;
+
+    if (c->error)                  /* don't continue on error */
+        return zoom_complete;
+    assert(c->tasks);
+    switch(c->tasks->which)
+    {
+    case ZOOM_TASK_SEARCH:
+        resultset = c->tasks->u.search.resultset;
+        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;
+        break;
+    case ZOOM_TASK_RETRIEVE:
+        resultset = c->tasks->u.retrieve.resultset;
+
+        start = &c->tasks->u.retrieve.start;
+        count = &c->tasks->u.retrieve.count;
+
+        if (*start >= resultset->size)
+            return zoom_complete;
+        if (*start + *count > resultset->size)
+            *count = resultset->size - *start;
+
+        for (i = 0; i < *count; i++)
+        {
+            ZOOM_record rec =
+                ZOOM_record_cache_lookup(resultset, i + *start,
+                                         c->tasks->u.retrieve.syntax,
+                                         c->tasks->u.retrieve.elementSetName);
+            if (!rec)
+                break;
+            else
+            {
+                ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
+                ZOOM_connection_put_event(c, event);
+            }
+        }
+        *start += i;
+        *count -= i;
+
+        if (*count == 0)
+            return zoom_complete;
+        break;
+    default:
+        return zoom_complete;
+    }
+    assert(resultset->query);
+        
+    sr = ZOOM_srw_get_pdu(c, Z_SRW_searchRetrieve_request);
+    z_query = ZOOM_query_get_Z_Query(resultset->query);
+
+    if (z_query->which == Z_Query_type_104
+        && z_query->u.type_104->which == Z_External_CQL)
+    {
+        sr->u.request->query_type = Z_SRW_query_type_cql;
+        sr->u.request->query.cql = z_query->u.type_104->u.cql;
+    }
+    else if (z_query->which == Z_Query_type_1 && z_query->u.type_1)
+    {
+        sr->u.request->query_type = Z_SRW_query_type_pqf;
+        sr->u.request->query.pqf =
+            ZOOM_query_get_query_string(resultset->query);
+    }
+    else
+    {
+        ZOOM_set_error(c, ZOOM_ERROR_UNSUPPORTED_QUERY, 0);
+        return zoom_complete;
+    }
+    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) ? 
+        resultset->step : *count);
+    sr->u.request->recordSchema = resultset->schema;
+    
+    option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
+    if (option_val)
+        sr->u.request->recordPacking = odr_strdup(c->odr_out, option_val);
+
+    option_val = ZOOM_resultset_option_get(resultset, "extraArgs");
+    yaz_encode_sru_extra(sr, c->odr_out, option_val);
+    return send_srw(c, sr);
+}
+#else
+zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
+{
+    return zoom_complete;
+}
+#endif
+
+#if YAZ_HAVE_XML2
+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, *count;
+    const char *syntax, *elementSetName;
+
+    if (!c->tasks)
+        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;        
+
+        if (!c->tasks->u.search.recv_search_fired)
+        {
+            event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
+            ZOOM_connection_put_event(c, event);
+            c->tasks->u.search.recv_search_fired = 1;
+        }
+        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 zoom_complete;
+    }
+
+    resultset->size = 0;
+
+    if (res->resultSetId)
+        ZOOM_resultset_option_set(resultset, "resultSetId", res->resultSetId);
+
+    yaz_log(c->log_details, "%p handle_srw_response got SRW response OK", c);
+
+    if (res->num_diagnostics > 0)
+    {
+        set_SRU_error(c, &res->diagnostics[0]);
+    }
+    else
+    {
+        if (res->numberOfRecords)
+            resultset->size = *res->numberOfRecords;
+        for (i = 0; i<res->num_records; i++)
+        {
+            int pos;
+            Z_SRW_record *sru_rec;
+            Z_SRW_diagnostic *diag = 0;
+            int num_diag;
+            
+            Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
+                odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
+            
+            if (res->records[i].recordPosition && 
+                *res->records[i].recordPosition > 0)
+                pos = *res->records[i].recordPosition - 1;
+            else
+                pos = *start + i;
+            
+            sru_rec = &res->records[i];
+            
+            npr->databaseName = 0;
+            npr->which = Z_NamePlusRecord_databaseRecord;
+            npr->u.databaseRecord = (Z_External *)
+                odr_malloc(c->odr_in, sizeof(Z_External));
+            npr->u.databaseRecord->descriptor = 0;
+            npr->u.databaseRecord->direct_reference =
+                odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
+            npr->u.databaseRecord->which = Z_External_octet;
+            
+            npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
+                odr_malloc(c->odr_in, sizeof(Odr_oct));
+            npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)
+                sru_rec->recordData_buf;
+            npr->u.databaseRecord->u.octet_aligned->len = 
+                npr->u.databaseRecord->u.octet_aligned->size = 
+                sru_rec->recordData_len;
+            
+            if (sru_rec->recordSchema 
+                && !strcmp(sru_rec->recordSchema,
+                           "info:srw/schema/1/diagnostics-v1.1"))
+            {
+                sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
+                                                 sru_rec->recordData_len,
+                                                 &diag, &num_diag,
+                                                 resultset->odr);
+            }
+            ZOOM_record_cache_add(resultset, npr, pos, syntax, elementSetName,
+                                  sru_rec->recordSchema, diag);
+        }
+        *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 (*count > 0)
+            return ZOOM_connection_srw_send_search(c);
+    }
+    return zoom_complete;
+}
+#endif
+
+#if YAZ_HAVE_XML2
+static void handle_srw_scan_response(ZOOM_connection c,
+                                     Z_SRW_scanResponse *res)
+{
+    NMEM nmem = odr_extract_mem(c->odr_in);
+    ZOOM_scanset scan;
+
+    if (!c->tasks || c->tasks->which != ZOOM_TASK_SCAN)
+        return;
+    scan = c->tasks->u.scan.scan;
+
+    if (res->num_diagnostics > 0)
+        set_SRU_error(c, &res->diagnostics[0]);
+
+    scan->scan_response = 0;
+    scan->srw_scan_response = res;
+    nmem_transfer(odr_getmem(scan->odr), nmem);
+
+    ZOOM_options_set_int(scan->options, "number", res->num_terms);
+    nmem_destroy(nmem);
+}
+#endif
+
+int ZOOM_handle_sru(ZOOM_connection c, Z_HTTP_Response *hres,
+                    zoom_ret *cret)
+{
+    int ret = 0;
+    const char *addinfo = 0;
+
+    /* not redirect (normal response) */
+    if (!yaz_srw_check_content_type(hres))
+        addinfo = "content-type";
+    else
+    {
+        Z_SOAP *soap_package = 0;
+        ODR o = c->odr_in;
+        Z_SOAP_Handler soap_handlers[2] = {
+            {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
+            {0, 0, 0}
+        };
+        ret = z_soap_codec(o, &soap_package,
+                           &hres->content_buf, &hres->content_len,
+                           soap_handlers);
+        if (!ret && soap_package->which == Z_SOAP_generic &&
+            soap_package->u.generic->no == 0)
+        {
+            Z_SRW_PDU *sr = (Z_SRW_PDU*) soap_package->u.generic->p;
+            
+            ZOOM_options_set(c->options, "sru_version", sr->srw_version);
+            ZOOM_options_setl(c->options, "sru_extra_response_data",
+                              sr->extraResponseData_buf, sr->extraResponseData_len);
+            if (sr->which == Z_SRW_searchRetrieve_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
+                ret = -1;
+        }
+        else if (!ret && (soap_package->which == Z_SOAP_fault
+                          || soap_package->which == Z_SOAP_error))
+        {
+            ZOOM_set_HTTP_error(c, hres->code,
+                                soap_package->u.fault->fault_code,
+                                soap_package->u.fault->fault_string);
+        }
+        else
+            ret = -1;
+    }   
+    return ret;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 7a1c94a..8df6c5e 100644 (file)
@@ -475,6 +475,7 @@ MISC_OBJS= \
    $(OBJDIR)\zoom-c.obj \
    $(OBJDIR)\zoom-record-cache.obj \
    $(OBJDIR)\zoom-z3950.obj \
+   $(OBJDIR)\zoom-sru.obj \
    $(OBJDIR)\zoom-query.obj \
    $(OBJDIR)\record-render.obj \
    $(OBJDIR)\facet.obj \