X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fzoom-c.c;h=cb16f924a67a0e237a09e55930702fbec27e28e4;hp=2cb5bc9eb411fcf6e43f2c722ce93b5e2f29b80b;hb=e4ef95b2ccfe88d7049543664f00e5fda957dd0c;hpb=69d044abe3d3a3560267a16dc4db13386974d5e1 diff --git a/src/zoom-c.c b/src/zoom-c.c index 2cb5bc9..cb16f92 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2006, Index Data ApS + * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: zoom-c.c,v 1.92 2006-10-05 14:58:58 adam Exp $ + * $Id: zoom-c.c,v 1.113 2007-02-21 09:19:26 adam Exp $ */ /** * \file zoom-c.c @@ -27,24 +27,7 @@ #include #include -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_SYS_TIME_H -#include -#endif -#if HAVE_SYS_POLL_H -#include -#endif -#if HAVE_SYS_SELECT_H -#include -#endif -#ifdef WIN32 -#if FD_SETSIZE < 512 -#define FD_SETSIZE 512 -#endif -#include -#endif +#define TASK_FIX 1 static int log_api = 0; static int log_details = 0; @@ -58,6 +41,21 @@ 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; @@ -122,6 +120,14 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c) return 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, @@ -148,11 +154,16 @@ 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 : ""); +#if TASK_FIX + ZOOM_connection_remove_tasks(c); +#endif + } } #if YAZ_HAVE_XML2 @@ -163,6 +174,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) { @@ -193,6 +205,33 @@ static void clear_error(ZOOM_connection c) } } +void ZOOM_connection_show_task(ZOOM_task task) +{ + switch(task->which) + { + case ZOOM_TASK_SEARCH: + yaz_log(YLOG_LOG, "search p=%p", task); + break; + case ZOOM_TASK_RETRIEVE: + yaz_log(YLOG_LOG, "retrieve p=%p", task); + break; + case ZOOM_TASK_CONNECT: + yaz_log(YLOG_LOG, "connect p=%p", task); + break; + case ZOOM_TASK_SCAN: + yaz_log(YLOG_LOG, "scant p=%p", task); + break; + } +} + +void ZOOM_connection_show_tasks(ZOOM_connection c) +{ + ZOOM_task task; + yaz_log(YLOG_LOG, "connection p=%p tasks", c); + for (task = c->tasks; task; task = task->next) + ZOOM_connection_show_task(task); +} + ZOOM_task ZOOM_connection_add_task(ZOOM_connection c, int which) { ZOOM_task *taskp = &c->tasks; @@ -235,9 +274,13 @@ void ZOOM_connection_remove_task(ZOOM_connection c) { case ZOOM_TASK_SEARCH: ZOOM_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); + xfree(task->u.retrieve.syntax); + xfree(task->u.retrieve.elementSetName); break; case ZOOM_TASK_CONNECT: break; @@ -272,7 +315,9 @@ void ZOOM_connection_remove_tasks(ZOOM_connection c) ZOOM_connection_remove_task(c); } -static ZOOM_record record_cache_lookup(ZOOM_resultset r, int pos); +static ZOOM_record record_cache_lookup(ZOOM_resultset r, int pos, + const char *syntax, + const char *elementSetName); ZOOM_API(ZOOM_connection) ZOOM_connection_create(ZOOM_options options) @@ -285,7 +330,7 @@ ZOOM_API(ZOOM_connection) c->proto = PROTO_Z3950; c->cs = 0; - c->mask = 0; + ZOOM_connection_set_mask(c, 0); c->reconnect_ok = 0; c->state = STATE_IDLE; c->addinfo = 0; @@ -326,7 +371,7 @@ ZOOM_API(ZOOM_connection) /* set database names. Take local databases (if set); otherwise take databases given in ZURL (if set); otherwise use Default */ static char **set_DatabaseNames(ZOOM_connection con, ZOOM_options options, - int *num) + int *num, ODR odr) { char **databaseNames; const char *cp = ZOOM_options_get(options, "databaseName"); @@ -342,7 +387,7 @@ static char **set_DatabaseNames(ZOOM_connection con, ZOOM_options options, } if (!cp) cp = "Default"; - nmem_strsplit(con->odr_out->mem, "+", cp, &databaseNames, num); + nmem_strsplit(odr->mem, "+", cp, &databaseNames, num); return databaseNames; } @@ -420,9 +465,6 @@ ZOOM_API(void) else c->lang = 0; - val = ZOOM_options_get(c->options, "sru"); - c->sru_mode = get_sru_mode_from_string(val); - xfree(c->host_port); if (portnum) { @@ -464,6 +506,9 @@ ZOOM_API(void) } } + val = ZOOM_options_get(c->options, "sru"); + c->sru_mode = get_sru_mode_from_string(val); + ZOOM_options_set(c->options, "host", c->host_port); val = ZOOM_options_get(c->options, "cookie"); @@ -704,6 +749,8 @@ ZOOM_resultset ZOOM_resultset_create(void) r->query = 0; r->connection = 0; r->next = 0; + r->databaseNames = 0; + r->num_databaseNames = 0; return r; } @@ -727,6 +774,7 @@ ZOOM_API(ZOOM_resultset) ZOOM_task task; const char *cp; int start, count; + const char *syntax, *elementSetName; yaz_log(log_api, "%p ZOOM_connection_search set %p query %p", c, r, q); r->r_sort_spec = q->sort_spec; @@ -749,6 +797,9 @@ ZOOM_API(ZOOM_resultset) cp = ZOOM_options_get(r->options, "schema"); if (cp) r->schema = xstrdup(cp); + + r->databaseNames = set_DatabaseNames(c, c->options, &r->num_databaseNames, + r->odr); r->connection = c; @@ -773,7 +824,14 @@ ZOOM_API(ZOOM_resultset) task->u.search.resultset = r; task->u.search.start = start; task->u.search.count = count; - ZOOM_resultset_addref(r); + + syntax = ZOOM_options_get(r->options, "preferredRecordSyntax"); + task->u.search.syntax = syntax ? xstrdup(syntax) : 0; + elementSetName = ZOOM_options_get(r->options, "elementSetName"); + task->u.search.elementSetName = elementSetName + ? xstrdup(elementSetName) : 0; + + ZOOM_resultset_addref(r); (q->refcount)++; @@ -904,6 +962,8 @@ ZOOM_API(void) ZOOM_API(size_t) ZOOM_resultset_size(ZOOM_resultset r) { + yaz_log(log_details, "ZOOM_resultset_size r=%p count=%d", + r, r->size); return r->size; } @@ -912,7 +972,7 @@ static void do_close(ZOOM_connection c) if (c->cs) cs_close(c->cs); c->cs = 0; - c->mask = 0; + ZOOM_connection_set_mask(c, 0); c->state = STATE_IDLE; } @@ -933,6 +993,7 @@ static void ZOOM_resultset_retrieve(ZOOM_resultset r, ZOOM_task task; ZOOM_connection c; const char *cp; + const char *syntax, *elementSetName; if (!r) return; @@ -961,6 +1022,12 @@ static void ZOOM_resultset_retrieve(ZOOM_resultset r, task->u.retrieve.start = start; task->u.retrieve.count = count; + syntax = ZOOM_options_get(r->options, "preferredRecordSyntax"); + task->u.retrieve.syntax = syntax ? xstrdup(syntax) : 0; + elementSetName = ZOOM_options_get(r->options, "elementSetName"); + task->u.retrieve.elementSetName = elementSetName + ? xstrdup(elementSetName) : 0; + cp = ZOOM_options_get(r->options, "schema"); if (cp) { @@ -1060,7 +1127,7 @@ static zoom_ret do_connect(ZOOM_connection c) /* no init request for SRW .. */ assert(c->tasks->which == ZOOM_TASK_CONNECT); ZOOM_connection_remove_task(c); - c->mask = 0; + ZOOM_connection_set_mask(c, 0); ZOOM_connection_exec_task(c); } c->state = STATE_ESTABLISHED; @@ -1068,12 +1135,13 @@ static zoom_ret do_connect(ZOOM_connection c) } else if (ret > 0) { - c->state = STATE_CONNECTING; - c->mask = ZOOM_SELECT_EXCEPT; + int mask = ZOOM_SELECT_EXCEPT; if (c->cs->io_pending & CS_WANT_WRITE) - c->mask += ZOOM_SELECT_WRITE; + mask += ZOOM_SELECT_WRITE; if (c->cs->io_pending & CS_WANT_READ) - c->mask += ZOOM_SELECT_READ; + mask += ZOOM_SELECT_READ; + ZOOM_connection_set_mask(c, mask); + c->state = STATE_CONNECTING; return zoom_pending; } } @@ -1082,20 +1150,6 @@ static zoom_ret do_connect(ZOOM_connection c) return zoom_complete; } -int z3950_connection_socket(ZOOM_connection c) -{ - if (c->cs) - return cs_fileno(c->cs); - return -1; -} - -int z3950_connection_mask(ZOOM_connection c) -{ - if (c->cs) - return c->mask; - return 0; -} - static void otherInfo_attach(ZOOM_connection c, Z_APDU *a, ODR out) { int i; @@ -1221,7 +1275,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.92 $"); + version = odr_strdup(c->odr_out, "$Revision: 1.113 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; ireq->implementationVersion = @@ -1344,16 +1398,16 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c) if (c->error) /* don't continue on error */ return zoom_complete; assert(c->tasks); - if (c->tasks->which == ZOOM_TASK_SEARCH) + switch(c->tasks->which) { + case ZOOM_TASK_SEARCH: resultset = c->tasks->u.search.resultset; resultset->setname = xstrdup("default"); ZOOM_options_set(resultset->options, "setname", resultset->setname); start = &c->tasks->u.search.start; count = &c->tasks->u.search.count; - } - else if (c->tasks->which == ZOOM_TASK_RETRIEVE) - { + break; + case ZOOM_TASK_RETRIEVE: resultset = c->tasks->u.retrieve.resultset; start = &c->tasks->u.retrieve.start; @@ -1367,7 +1421,9 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c) for (i = 0; i < *count; i++) { ZOOM_record rec = - record_cache_lookup(resultset, i + *start); + record_cache_lookup(resultset, i + *start, + c->tasks->u.retrieve.syntax, + c->tasks->u.retrieve.elementSetName); if (!rec) break; else @@ -1381,6 +1437,9 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c) if (*count == 0) return zoom_complete; + break; + default: + return zoom_complete; } assert(resultset->query); @@ -1466,11 +1525,11 @@ static zoom_ret ZOOM_connection_send_search(ZOOM_connection c) return zoom_complete; } - search_req->databaseNames = - set_DatabaseNames(c, r->options, &search_req->num_databaseNames); + search_req->databaseNames = r->databaseNames; + search_req->num_databaseNames = r->num_databaseNames; /* get syntax (no need to provide unless piggyback is in effect) */ - syntax = ZOOM_options_get(r->options, "preferredRecordSyntax"); + syntax = c->tasks->u.search.syntax; lslb = ZOOM_options_get_int(r->options, "largeSetLowerBound", -1); ssub = ZOOM_options_get_int(r->options, "smallSetUpperBound", -1); @@ -1518,7 +1577,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) { @@ -1611,7 +1670,12 @@ ZOOM_API(ZOOM_record) ZOOM_API(ZOOM_record) ZOOM_resultset_record_immediate(ZOOM_resultset s,size_t pos) { - return record_cache_lookup(s, pos); + const char *syntax = + ZOOM_options_get(s->options, "preferredRecordSyntax"); + const char *elementSetName = + ZOOM_options_get(s->options, "elementSetName"); + + return record_cache_lookup(s, pos, syntax, elementSetName); } ZOOM_API(ZOOM_record) @@ -1771,6 +1835,53 @@ static const char *record_iconv_return(ZOOM_record rec, int *len, return buf; } +ZOOM_API(int) + ZOOM_record_error(ZOOM_record rec, const char **cp, + const char **addinfo, const char **diagset) +{ + Z_NamePlusRecord *npr; + + if (!rec) + return 0; + npr = rec->npr; + if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic) + { + Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic; + int error = YAZ_BIB1_UNSPECIFIED_ERROR; + const char *add = 0; + + if (diag_rec->which == Z_DiagRec_defaultFormat) + { + Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat; + int oclass; + + error = *ddf->condition; + switch (ddf->which) + { + case Z_DefaultDiagFormat_v2Addinfo: + add = ddf->u.v2Addinfo; + break; + case Z_DefaultDiagFormat_v3Addinfo: + add = ddf->u.v3Addinfo; + break; + } + if (diagset) + *diagset = yaz_z3950oid_to_str(ddf->diagnosticSetId, &oclass); + } + else + { + if (diagset) + *diagset = "Bib-1"; + } + if (addinfo) + *addinfo = add ? add : ""; + if (cp) + *cp = diagbib1_str(error); + return error; + } + return 0; +} + ZOOM_API(const char *) ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len) { @@ -2026,13 +2137,10 @@ static size_t record_hash(int pos) } static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, - int pos) + int pos, + const char *syntax, const char *elementSetName) { ZOOM_record_cache rc; - const char *elementSetName = - ZOOM_resultset_option_get(r, "elementSetName"); - const char *syntax = - ZOOM_resultset_option_get(r, "preferredRecordSyntax"); ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD); ZOOM_connection_put_event(r->connection, event); @@ -2079,13 +2187,11 @@ static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, r->record_hash[record_hash(pos)] = rc; } -static ZOOM_record record_cache_lookup(ZOOM_resultset r, int pos) +static ZOOM_record record_cache_lookup(ZOOM_resultset r, int pos, + const char *syntax, + const char *elementSetName) { ZOOM_record_cache rc; - const char *elementSetName = - ZOOM_resultset_option_get(r, "elementSetName"); - const char *syntax = - ZOOM_resultset_option_get(r, "preferredRecordSyntax"); for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next) { @@ -2108,6 +2214,7 @@ static void handle_records(ZOOM_connection c, Z_Records *sr, { ZOOM_resultset resultset; int *start, *count; + const char *syntax = 0, *elementSetName = 0; if (!c->tasks) return ; @@ -2117,11 +2224,15 @@ static void handle_records(ZOOM_connection c, Z_Records *sr, 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; @@ -2149,9 +2260,12 @@ static void handle_records(ZOOM_connection c, Z_Records *sr, sr->u.databaseOrSurDiagnostics; for (i = 0; inum_records; i++) { - record_cache_add(resultset, p->records[i], i + *start); + record_cache_add(resultset, p->records[i], i + *start, + syntax, elementSetName); } *count -= i; + if (*count < 0) + *count = 0; *start += i; yaz_log(log_details, "handle_records resultset=%p start=%d count=%d", @@ -2165,7 +2279,8 @@ static void handle_records(ZOOM_connection c, Z_Records *sr, /* present response and we didn't get any records! */ Z_NamePlusRecord *myrec = zget_surrogateDiagRec(resultset->odr, 0, 14, 0); - record_cache_add(resultset, myrec, *start); + record_cache_add(resultset, myrec, *start, + syntax, elementSetName); } } else if (present_phase) @@ -2173,7 +2288,7 @@ static void handle_records(ZOOM_connection c, Z_Records *sr, /* present response and we didn't get any records! */ Z_NamePlusRecord *myrec = zget_surrogateDiagRec(resultset->odr, 0, 14, 0); - record_cache_add(resultset, myrec, *start); + record_cache_add(resultset, myrec, *start, syntax, elementSetName); } } } @@ -2302,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; @@ -2385,20 +2510,15 @@ static zoom_ret send_present(ZOOM_connection c) 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; - - if (*start >= resultset->size) - { - yaz_log(log_details, "%p send_present start=%d >= size=%d", - c, *start, resultset->size); - return zoom_complete; - } - if (*start + *count > resultset->size) - *count = resultset->size - *start; + syntax = c->tasks->u.retrieve.syntax; + elementSetName = c->tasks->u.retrieve.elementSetName; break; default: return zoom_complete; @@ -2406,20 +2526,20 @@ static zoom_ret send_present(ZOOM_connection c) yaz_log(log_details, "%p send_present start=%d count=%d", c, *start, *count); - syntax = ZOOM_resultset_option_get(resultset, "preferredRecordSyntax"); - elementSetName = ZOOM_resultset_option_get(resultset, "elementSetName"); - + if (*start < 0 || *count < 0 || *start + *count > resultset->size) + { + set_dset_error(c, YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE, "Bib-1", + "", 0); + } if (c->error) /* don't continue on error */ return zoom_complete; - if (*start < 0) - return zoom_complete; yaz_log(log_details, "send_present resultset=%p start=%d count=%d", resultset, *start, *count); for (i = 0; i < *count; i++) { ZOOM_record rec = - record_cache_lookup(resultset, i + *start); + record_cache_lookup(resultset, i + *start, syntax, elementSetName); if (!rec) break; else @@ -2452,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) { @@ -2472,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) { @@ -2564,7 +2684,7 @@ ZOOM_API(ZOOM_scanset) c, q, q->query_string); abort(); } - + scan = (ZOOM_scanset) xmalloc(sizeof(*scan)); scan->connection = c; scan->odr = odr_createmem(ODR_DECODE); @@ -2574,6 +2694,10 @@ ZOOM_API(ZOOM_scanset) scan->termListAndStartPoint = p_query_scan(scan->odr, PROTO_Z3950, &scan->attributeSet, start); xfree(freeme); + + scan->databaseNames = set_DatabaseNames(c, c->options, + &scan->num_databaseNames, + scan->odr); if (scan->termListAndStartPoint != 0) { ZOOM_task task = ZOOM_connection_add_task(c, ZOOM_TASK_SCAN); @@ -2648,8 +2772,8 @@ static zoom_ret send_scan(ZOOM_connection c) odr_intdup(c->odr_out, ZOOM_options_get_int(scan->options, "stepSize", 0)); - req->databaseNames = set_DatabaseNames(c, scan->options, - &req->num_databaseNames); + req->databaseNames = scan->databaseNames; + req->num_databaseNames = scan->num_databaseNames; return send_APDU(c, apdu); } @@ -2869,7 +2993,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; } @@ -2886,7 +3016,8 @@ Z_APDU *create_admin_package(ZOOM_package p, int type, Z_External *r = (Z_External *) odr_malloc(p->odr_out, sizeof(*r)); const char *first_db = "Default"; int num_db; - char **db = set_DatabaseNames(p->connection, p->options, &num_db); + char **db = set_DatabaseNames(p->connection, p->options, &num_db, + p->odr_out); if (num_db > 0) first_db = db[0]; @@ -2952,7 +3083,7 @@ static Z_APDU *create_update_package(ZOOM_package p) Z_APDU *apdu = 0; const char *first_db = "Default"; int num_db; - char **db = set_DatabaseNames(p->connection, p->options, &num_db); + char **db = set_DatabaseNames(p->connection, p->options, &num_db, p->odr_out); const char *action = ZOOM_options_get(p->options, "action"); const char *recordIdOpaque = ZOOM_options_get(p->options, "recordIdOpaque"); const char *recordIdNumber = ZOOM_options_get(p->options, "recordIdNumber"); @@ -3322,11 +3453,21 @@ static void interpret_otherinformation_field(ZOOM_connection c, } } + +static void set_init_option(const char *name, void *clientData) { + ZOOM_connection c = clientData; + char buf[80]; + + sprintf(buf, "init_opt_%.70s", name); + ZOOM_connection_option_set(c, buf, "1"); +} + + static void recv_apdu(ZOOM_connection c, Z_APDU *apdu) { Z_InitResponse *initrs; - c->mask = 0; + ZOOM_connection_set_mask(c, 0); yaz_log(log_details, "%p recv_apdu apdu->which=%d", c, apdu->which); switch(apdu->which) { @@ -3352,6 +3493,10 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu) ZOOM_connection_option_set(c, "targetImplementationVersion", initrs->implementationVersion ? initrs->implementationVersion : ""); + + /* Make initrs->options available as ZOOM-level options */ + yaz_init_opt_decode(initrs->options, set_init_option, (void*) c); + if (!*initrs->result) { Z_External *uif = initrs->userInformationField; @@ -3462,23 +3607,28 @@ static void handle_srw_response(ZOOM_connection c, NMEM nmem; ZOOM_Event event; int *start; + const char *syntax, *elementSetName; if (!c->tasks) return; - if (c->tasks->which == ZOOM_TASK_SEARCH) + switch(c->tasks->which) { + case ZOOM_TASK_SEARCH: resultset = c->tasks->u.search.resultset; start = &c->tasks->u.search.start; - } - else if (c->tasks->which == ZOOM_TASK_RETRIEVE) - { + 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; + syntax = c->tasks->u.retrieve.syntax; + elementSetName = c->tasks->u.retrieve.elementSetName; + break; + default: + return; } - else - return ; - event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH); ZOOM_connection_put_event(c, event); @@ -3518,7 +3668,7 @@ static void handle_srw_response(ZOOM_connection c, npr->u.databaseRecord->u.octet_aligned->len = npr->u.databaseRecord->u.octet_aligned->size = res->records[i].recordData_len; - record_cache_add(resultset, npr, pos); + record_cache_add(resultset, npr, pos, syntax, elementSetName); } if (res->num_diagnostics > 0) { @@ -3547,7 +3697,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres) "Content-Type"); const char *connection_head = z_HTTP_header_lookup(hres->headers, "Connection"); - c->mask = 0; + ZOOM_connection_set_mask(c, 0); yaz_log(log_details, "%p handle_http", c); if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) @@ -3555,8 +3705,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres) Z_SOAP *soap_package = 0; ODR o = c->odr_in; Z_SOAP_Handler soap_handlers[2] = { - {"http://www.loc.gov/zing/srw/", 0, - (Z_SOAP_fun) yaz_srw_codec}, + {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec}, {0, 0, 0} }; ret = z_soap_codec(o, &soap_package, @@ -3692,17 +3841,18 @@ static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out) } else if (r == 1) { - c->mask = ZOOM_SELECT_EXCEPT; + int mask = ZOOM_SELECT_EXCEPT; if (c->cs->io_pending & CS_WANT_WRITE) - c->mask += ZOOM_SELECT_WRITE; + mask += ZOOM_SELECT_WRITE; if (c->cs->io_pending & CS_WANT_READ) - c->mask += ZOOM_SELECT_READ; + mask += ZOOM_SELECT_READ; + ZOOM_connection_set_mask(c, mask); yaz_log(log_details, "%p do_write_ex write incomplete mask=%d", c, c->mask); } else { - c->mask = ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT; + ZOOM_connection_set_mask(c, ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT); yaz_log(log_details, "%p do_write_ex write complete mask=%d", c, c->mask); } @@ -3880,11 +4030,12 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask) "cs_rcvconnect returned %d", c, ret); if (ret == 1) { - c->mask = ZOOM_SELECT_EXCEPT; + int mask = ZOOM_SELECT_EXCEPT; if (c->cs->io_pending & CS_WANT_WRITE) - c->mask += ZOOM_SELECT_WRITE; + mask += ZOOM_SELECT_WRITE; if (c->cs->io_pending & CS_WANT_READ) - c->mask += ZOOM_SELECT_READ; + mask += ZOOM_SELECT_READ; + ZOOM_connection_set_mask(c, mask); } else if (ret == 0) { @@ -3898,7 +4049,7 @@ static void ZOOM_connection_do_io(ZOOM_connection c, int mask) /* no init request for SRW .. */ assert(c->tasks->which == ZOOM_TASK_CONNECT); ZOOM_connection_remove_task(c); - c->mask = 0; + ZOOM_connection_set_mask(c, 0); ZOOM_connection_exec_task(c); } c->state = STATE_ESTABLISHED; @@ -3940,193 +4091,6 @@ ZOOM_API(int) return cs->last_event; } -ZOOM_API(int) - ZOOM_event(int no, ZOOM_connection *cs) -{ - int timeout = 30; /* default timeout in seconds */ - int timeout_set = 0; /* whether it was overriden at all */ -#if HAVE_SYS_POLL_H - struct pollfd pollfds[1024]; - ZOOM_connection poll_cs[1024]; -#else - struct timeval tv; - fd_set input, output, except; -#endif - int i, r, nfds; - int max_fd = 0; - - yaz_log(log_details, "ZOOM_event(no=%d,cs=%p)", no, cs); - for (i = 0; ioptions, "timeout", -2); - if (this_timeout != -2) - { - /* ensure the minimum timeout is used */ - if (!timeout_set) - timeout = this_timeout; - else if (this_timeout != -1 && this_timeout < timeout) - timeout = this_timeout; - timeout_set = 1; - } -#if HAVE_SYS_POLL_H - if (mask) - { - short poll_events = 0; - - if (mask & ZOOM_SELECT_READ) - poll_events += POLLIN; - if (mask & ZOOM_SELECT_WRITE) - poll_events += POLLOUT; - if (mask & ZOOM_SELECT_EXCEPT) - poll_events += POLLERR; - pollfds[nfds].fd = fd; - pollfds[nfds].events = poll_events; - pollfds[nfds].revents = 0; - poll_cs[nfds] = c; - nfds++; - } -#else - if (mask & ZOOM_SELECT_READ) - { - FD_SET(fd, &input); - nfds++; - } - if (mask & ZOOM_SELECT_WRITE) - { - FD_SET(fd, &output); - nfds++; - } - if (mask & ZOOM_SELECT_EXCEPT) - { - FD_SET(fd, &except); - nfds++; - } -#endif - } - if (!nfds) - return 0; - -#if HAVE_SYS_POLL_H - r = poll(pollfds, nfds, (timeout == -1 ? -1 : timeout * 1000)); - for (i = 0; imask) - { - int mask = 0; - if (pollfds[i].revents & POLLIN) - mask += ZOOM_SELECT_READ; - if (pollfds[i].revents & POLLOUT) - mask += ZOOM_SELECT_WRITE; - if (pollfds[i].revents & POLLERR) - mask += ZOOM_SELECT_EXCEPT; - if (mask) - ZOOM_connection_do_io(c, mask); - } - else if (r == 0 && c->mask) - { - ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT); - /* timeout and this connection was waiting */ - set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0); - do_close(c); - ZOOM_connection_put_event(c, event); - } - } -#else - tv.tv_sec = timeout; - tv.tv_usec = 0; - r = select(max_fd+1, &input, &output, &except, (timeout == -1 ? 0 : &tv)); - for (i = 0; imask) - { - /* no timeout and real socket */ - if (FD_ISSET(fd, &input)) - mask += ZOOM_SELECT_READ; - if (FD_ISSET(fd, &output)) - mask += ZOOM_SELECT_WRITE; - if (FD_ISSET(fd, &except)) - mask += ZOOM_SELECT_EXCEPT; - if (mask) - ZOOM_connection_do_io(c, mask); - } - if (r == 0 && c->mask) - { - ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT); - /* timeout and this connection was waiting */ - set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0); - do_close(c); - ZOOM_connection_put_event(c, event); - } - } -#endif - for (i = 0; imask) + { + ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT); + /* timeout and this connection was waiting */ + set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0); + do_close(c); + ZOOM_connection_put_event(c, event); + } + return 0; +} + +ZOOM_API(int) + 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_process_event(no=%d,cs=%p)", no, cs); + + for (i = 0; imask && mask) + ZOOM_connection_do_io(c, mask); + return 0; +} + +ZOOM_API(int) ZOOM_connection_get_socket(ZOOM_connection c) +{ + if (c->cs) + return cs_fileno(c->cs); + return -1; +} + +ZOOM_API(int) ZOOM_connection_set_mask(ZOOM_connection c, int mask) +{ + c->mask = mask; + if (!c->cs) + return -1; + return 0; +} + +ZOOM_API(int) ZOOM_connection_get_mask(ZOOM_connection c) +{ + if (c->cs) + return c->mask; + return 0; +} + +ZOOM_API(int) ZOOM_connection_get_timeout(ZOOM_connection c) +{ + return ZOOM_options_get_int(c->options, "timeout", 30); +} + /* * Local variables: * c-basic-offset: 4