X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fzoom-c.c;h=bf4beb0913d63bd7f46a05595e365cdf9931f5ce;hb=82aa6fe37332e0b2a79a14f3d50c3c9f54034817;hp=44408840d8821b5a6a8823b1d2d02dbd353f8252;hpb=84cb4c71eb572b5700cd7b3230446d9578521870;p=yaz-moved-to-github.git diff --git a/src/zoom-c.c b/src/zoom-c.c index 4440884..bf4beb0 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: zoom-c.c,v 1.109 2007-01-22 10:35:07 adam Exp $ + * $Id: zoom-c.c,v 1.122 2007-03-21 11:27:46 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,6 +119,13 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c) return event; } +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; @@ -110,6 +133,8 @@ ZOOM_API(int) ZOOM_connection_peek_event(ZOOM_connection c) 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,16 +853,11 @@ 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_resultset_sort(ZOOM_resultset r, - const char *sort_type, const char *sort_spec) + const char *sort_type, const char *sort_spec) { - (void) ZOOM_resultset_sort1(r, sort_type, sort_spec); + (void) ZOOM_resultset_sort(r, sort_type, sort_spec); } ZOOM_API(int) @@ -888,11 +918,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 +931,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 +988,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 +1291,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.109 $"); + version = odr_strdup(c->odr_out, "$Revision: 1.122 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; ireq->implementationVersion = @@ -1552,7 +1593,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 +1721,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 +1778,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) @@ -1755,6 +1796,7 @@ static const char *record_iconv_return(ZOOM_record rec, int *len, *from = '\0'; strcpy(to, "UTF-8"); + if (record_charset && *record_charset) { /* Use "from,to" or just "from" */ @@ -1776,32 +1818,15 @@ static const char *record_iconv_return(ZOOM_record rec, int *len, if (*from && *to && (cd = yaz_iconv_open(to, from))) { - char outbuf[12]; - size_t inbytesleft = sz; - const char *inp = buf; - if (!rec->wrbuf_iconv) rec->wrbuf_iconv = wrbuf_alloc(); wrbuf_rewind(rec->wrbuf_iconv); - while (inbytesleft) - { - size_t outbytesleft = sizeof(outbuf); - char *outp = outbuf; - size_t r = yaz_iconv(cd, (char**) &inp, - &inbytesleft, - &outp, &outbytesleft); - if (r == (size_t) (-1)) - { - int e = yaz_iconv_error(cd); - if (e != YAZ_ICONV_E2BIG) - break; - } - wrbuf_write(rec->wrbuf_iconv, outbuf, outp - outbuf); - } - wrbuf_puts(rec->wrbuf_iconv, ""); - buf = wrbuf_buf(rec->wrbuf_iconv); + wrbuf_iconv_write(rec->wrbuf_iconv, cd, buf, sz); + wrbuf_iconv_reset(rec->wrbuf_iconv, cd); + + buf = wrbuf_cstr(rec->wrbuf_iconv); sz = wrbuf_len(rec->wrbuf_iconv); yaz_iconv_close(cd); } @@ -2392,6 +2417,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 +2572,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 +2592,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) { @@ -3734,11 +3769,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); @@ -4029,12 +4060,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); @@ -4057,6 +4083,12 @@ ZOOM_API(int) } +static void cql2pqf_wrbuf_puts(const char *buf, void *client_data) +{ + WRBUF wrbuf = client_data; + wrbuf_puts(wrbuf, buf); +} + /* * Returns an xmalloc()d string containing RPN that corresponds to the * CQL passed in. On error, sets the Connection object's error state @@ -4067,10 +4099,9 @@ static char *cql2pqf(ZOOM_connection c, const char *cql) { CQL_parser parser; int error; - struct cql_node *node; const char *cqlfile; - static cql_transform_t trans; - char pqfbuf[512]; + cql_transform_t trans; + char *result = 0; parser = cql_parser_create(); if ((error = cql_parser_string(parser, cql)) != 0) { @@ -4079,42 +4110,40 @@ static char *cql2pqf(ZOOM_connection c, const char *cql) return 0; } - node = cql_parser_result(parser); - /* ### Do not call cql_parser_destroy() yet: it destroys `node'! */ - cqlfile = ZOOM_connection_option_get(c, "cqlfile"); - if (cqlfile == 0) { - cql_parser_destroy(parser); - cql_node_destroy(node); + if (cqlfile == 0) + { set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file"); - return 0; } - - if ((trans = cql_transform_open_fname(cqlfile)) == 0) { + else if ((trans = cql_transform_open_fname(cqlfile)) == 0) + { char buf[512]; - cql_parser_destroy(parser); - cql_node_destroy(node); sprintf(buf, "can't open CQL transform file '%.200s': %.200s", cqlfile, strerror(errno)); set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); - return 0; } - - error = cql_transform_buf(trans, node, pqfbuf, sizeof pqfbuf); - cql_parser_destroy(parser); - cql_node_destroy(node); - if (error != 0) { - char buf[512]; - const char *addinfo; - error = cql_transform_error(trans, &addinfo); + else + { + WRBUF wrbuf_result = wrbuf_alloc(); + error = cql_transform(trans, cql_parser_result(parser), + cql2pqf_wrbuf_puts, wrbuf_result); + if (error != 0) { + char buf[512]; + const char *addinfo; + error = cql_transform_error(trans, &addinfo); + sprintf(buf, "%.200s (addinfo=%.200s)", + cql_strerror(error), addinfo); + set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); + } + else + { + result = xstrdup(wrbuf_cstr(wrbuf_result)); + } cql_transform_close(trans); - sprintf(buf, "%.200s (addinfo=%.200s)", cql_strerror(error), addinfo); - set_ZOOM_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); - return 0; + wrbuf_destroy(wrbuf_result); } - - cql_transform_close(trans); - return xstrdup(pqfbuf); + cql_parser_destroy(parser); + return result; } ZOOM_API(int) ZOOM_connection_fire_event_timeout(ZOOM_connection c)