X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=zoom%2Fzoom-c.c;h=59ba7654896bb89300333e38df98e69f9724a50f;hp=907aa2d7b75d37801f8d779fcf841ee0670d25a4;hb=366e11a6ab3c8cb8d12558ff1d76566c5ebca80e;hpb=bc66c2a11aa31c16f46c49100e99dc9b7e940faf diff --git a/zoom/zoom-c.c b/zoom/zoom-c.c index 907aa2d..59ba765 100644 --- a/zoom/zoom-c.c +++ b/zoom/zoom-c.c @@ -1,5 +1,5 @@ /* - * $Id: zoom-c.c,v 1.2 2001-10-24 12:24:43 adam Exp $ + * $Id: zoom-c.c,v 1.7 2001-11-15 13:16:02 adam Exp $ * * ZOOM layer for C, connections, result sets, queries. */ @@ -12,9 +12,59 @@ #include "zoom-p.h" -static Z3950_record record_cache_lookup (Z3950_resultset r, - int pos, - const char *elementSetName); +#if HAVE_SYS_POLL_H +#include +#endif + +static Z3950_Event Z3950_Event_create (int kind) +{ + Z3950_Event event = xmalloc (sizeof(*event)); + event->kind = kind; + event->next = 0; + event->prev = 0; + return event; +} + +static void Z3950_Event_destroy (Z3950_Event event) +{ + xfree (event); +} + +static void Z3950_connection_put_event (Z3950_connection c, Z3950_Event event) +{ + // put in back of queue + if (c->m_queue_back) + { + c->m_queue_back->prev = event; + assert (c->m_queue_front); + } + else + { + assert (!c->m_queue_front); + c->m_queue_front = event; + } + event->next = c->m_queue_back; + event->prev = 0; + c->m_queue_back = event; +} + +static Z3950_Event Z3950_connection_get_event(Z3950_connection c) +{ + // get from front of queue + Z3950_Event event = c->m_queue_front; + if (!event) + return 0; + assert (c->m_queue_back); + c->m_queue_front = event->prev; + if (c->m_queue_front) + { + assert (c->m_queue_back); + c->m_queue_front->next = 0; + } + else + c->m_queue_back = 0; + return event; +} static void clear_error (Z3950_connection c) { @@ -23,11 +73,58 @@ static void clear_error (Z3950_connection c) c->addinfo = 0; } +Z3950_task Z3950_connection_add_task (Z3950_connection c, int which) +{ + Z3950_task *taskp = &c->tasks; + while (*taskp) + taskp = &(*taskp)->next; + *taskp = xmalloc (sizeof(**taskp)); + (*taskp)->running = 0; + (*taskp)->which = which; + (*taskp)->u.resultset = 0; /* one null pointer there at least */ + (*taskp)->next = 0; + clear_error (c); + return *taskp; +} + +void Z3950_connection_remove_task (Z3950_connection c) +{ + Z3950_task task = c->tasks; + + if (task) + { + c->tasks = task->next; + switch (task->which) + { + case Z3950_TASK_SEARCH: + Z3950_resultset_destroy (task->u.resultset); + break; + case Z3950_TASK_RETRIEVE: + Z3950_resultset_destroy (task->u.resultset); + break; + case Z3950_TASK_CONNECT: + break; + default: + assert (0); + } + xfree (task); + } +} + +void Z3950_connection_remove_tasks (Z3950_connection c) +{ + while (c->tasks) + Z3950_connection_remove_task(c); +} + +static Z3950_record record_cache_lookup (Z3950_resultset r, + int pos, + const char *elementSetName); + Z3950_connection Z3950_connection_create (Z3950_options options) { Z3950_connection c = xmalloc (sizeof(*c)); - c->event_pending = 0; c->cs = 0; c->mask = 0; c->state = STATE_IDLE; @@ -52,6 +149,9 @@ Z3950_connection Z3950_connection_create (Z3950_options options) c->odr_out = odr_createmem (ODR_ENCODE); c->async = 0; + + c->m_queue_front = 0; + c->m_queue_back = 0; return c; } @@ -119,6 +219,7 @@ void Z3950_connection_connect(Z3950_connection c, const char *host, int portnum) { const char *val; + Z3950_task task; val = Z3950_options_get (c->options, "proxy"); if (val && *val) @@ -137,6 +238,8 @@ void Z3950_connection_connect(Z3950_connection c, c->async = Z3950_options_get_bool (c->options, "async", 0); + task = Z3950_connection_add_task (c, Z3950_TASK_CONNECT); + if (!c->async) { while (Z3950_event (1, &c)) @@ -144,9 +247,9 @@ void Z3950_connection_connect(Z3950_connection c, } } -Z3950_search Z3950_search_create(void) +Z3950_query Z3950_query_create(void) { - Z3950_search s = xmalloc (sizeof(*s)); + Z3950_query s = xmalloc (sizeof(*s)); s->refcount = 1; s->query = 0; @@ -161,13 +264,13 @@ const char *Z3950_connection_host (Z3950_connection c) return c->host_port; } -void Z3950_search_destroy(Z3950_search s) +void Z3950_query_destroy(Z3950_query s) { if (!s) return; (s->refcount)--; - yaz_log (LOG_DEBUG, "Z3950_search_destroy count=%d", s->refcount); + yaz_log (LOG_DEBUG, "Z3950_query_destroy count=%d", s->refcount); if (s->refcount == 0) { odr_destroy (s->odr); @@ -175,7 +278,7 @@ void Z3950_search_destroy(Z3950_search s) } } -int Z3950_search_prefix(Z3950_search s, const char *str) +int Z3950_query_prefix(Z3950_query s, const char *str) { s->query = odr_malloc (s->odr, sizeof(*s->query)); s->query->which = Z_Query_type_1; @@ -185,7 +288,7 @@ int Z3950_search_prefix(Z3950_search s, const char *str) return 0; } -int Z3950_search_sortby(Z3950_search s, const char *criteria) +int Z3950_query_sortby(Z3950_query s, const char *criteria) { s->sort_spec = yaz_sort_spec (s->odr, criteria); if (!s->sort_spec) @@ -195,49 +298,6 @@ int Z3950_search_sortby(Z3950_search s, const char *criteria) static int do_write(Z3950_connection c); - -Z3950_task Z3950_connection_add_task (Z3950_connection c, int which) -{ - Z3950_task *taskp = &c->tasks; - while (*taskp) - taskp = &(*taskp)->next; - *taskp = xmalloc (sizeof(**taskp)); - (*taskp)->running = 0; - (*taskp)->which = which; - (*taskp)->u.resultset = 0; /* one null pointer there at least */ - (*taskp)->next = 0; - clear_error (c); - return *taskp; -} - -void Z3950_connection_remove_task (Z3950_connection c) -{ - Z3950_task task = c->tasks; - - if (task) - { - c->tasks = task->next; - switch (task->which) - { - case Z3950_TASK_SEARCH: - Z3950_resultset_destroy (task->u.resultset); - break; - case Z3950_TASK_RETRIEVE: - Z3950_resultset_destroy (task->u.resultset); - break; - default: - assert (0); - } - xfree (task); - } -} - -void Z3950_connection_remove_tasks (Z3950_connection c) -{ - while (c->tasks) - Z3950_connection_remove_task(c); -} - void Z3950_connection_destroy(Z3950_connection c) { Z3950_resultset r; @@ -285,16 +345,16 @@ Z3950_resultset Z3950_resultset_create () Z3950_resultset Z3950_connection_search_pqf(Z3950_connection c, const char *q) { Z3950_resultset r; - Z3950_search s = Z3950_search_create(); + Z3950_query s = Z3950_query_create(); - Z3950_search_prefix (s, q); + Z3950_query_prefix (s, q); r = Z3950_connection_search (c, s); - Z3950_search_destroy (s); + Z3950_query_destroy (s); return r; } -Z3950_resultset Z3950_connection_search(Z3950_connection c, Z3950_search q) +Z3950_resultset Z3950_connection_search(Z3950_connection c, Z3950_query q) { Z3950_resultset r = Z3950_resultset_create (); Z3950_task task; @@ -350,14 +410,14 @@ void Z3950_resultset_destroy(Z3950_resultset r) rp = &(*rp)->next; } } - Z3950_search_destroy (r->search); + Z3950_query_destroy (r->search); Z3950_options_destroy (r->options); odr_destroy (r->odr); xfree (r); } } -int Z3950_resultset_size (Z3950_resultset r) +size_t Z3950_resultset_size (Z3950_resultset r) { return r->size; } @@ -395,27 +455,24 @@ static void Z3950_resultset_retrieve (Z3950_resultset r, } void Z3950_resultset_records (Z3950_resultset r, Z3950_record *recs, - size_t *cnt) + size_t start, size_t count) { int force_present = 0; - int start, count; if (!r) return ; - start = Z3950_options_get_int (r->options, "start", 0); - count = Z3950_options_get_int (r->options, "count", 0); - if (cnt && recs) + if (count && recs) force_present = 1; Z3950_resultset_retrieve (r, force_present, start, count); if (force_present) { size_t i; - for (i = 0; i< *cnt; i++) + for (i = 0; i< count; i++) recs[i] = Z3950_resultset_record_immediate (r, i+start); } } -static void do_connect (Z3950_connection c) +static int do_connect (Z3950_connection c) { void *add; const char *effective_host; @@ -437,13 +494,14 @@ static void do_connect (Z3950_connection c) if (ret >= 0) { c->state = STATE_CONNECTING; - c->mask = Z3950_SELECT_READ | Z3950_SELECT_WRITE | Z3950_SELECT_EXCEPT; - return; + c->mask = Z3950_SELECT_READ | Z3950_SELECT_WRITE | + Z3950_SELECT_EXCEPT; + return 1; } } - c->event_pending = 1; c->state = STATE_IDLE; c->error = Z3950_ERROR_CONNECT; + return 0; } int z3950_connection_socket(Z3950_connection c) @@ -709,7 +767,7 @@ static void response_diag (Z3950_connection c, Z_DiagRec *p) c->error = *r->condition; } -Z3950_record Z3950_record_dup (Z3950_record srec) +Z3950_record Z3950_record_dup (const Z3950_record srec) { char *buf; int size; @@ -731,15 +789,12 @@ Z3950_record Z3950_record_dup (Z3950_record srec) return nrec; } -Z3950_record Z3950_resultset_record_immediate (Z3950_resultset s, int pos) +Z3950_record Z3950_resultset_record_immediate (Z3950_resultset s,size_t pos) { - Z3950_record rec = record_cache_lookup (s, pos, 0); - if (!rec) - return 0; - return Z3950_record_dup (rec); + return record_cache_lookup (s, pos, 0); } -Z3950_record Z3950_resultset_record (Z3950_resultset r, int pos) +Z3950_record Z3950_resultset_record (Z3950_resultset r, size_t pos) { Z3950_resultset_retrieve (r, 1, pos, 1); return Z3950_resultset_record_immediate (r, pos); @@ -755,7 +810,7 @@ void Z3950_record_destroy (Z3950_record rec) xfree (rec); } -void *Z3950_record_get (Z3950_record rec, const char *type, int *len) +void *Z3950_record_get (Z3950_record rec, const char *type, size_t *len) { Z_NamePlusRecord *npr; if (!rec) @@ -823,16 +878,18 @@ void *Z3950_record_get (Z3950_record rec, const char *type, int *len) } return 0; } + else if (!strcmp (type, "raw")) + { + if (npr->which == Z_NamePlusRecord_databaseRecord) + { + *len = -1; + return (Z_External *) npr->u.databaseRecord; + } + return 0; + } return 0; } -void *Z3950_resultset_get (Z3950_resultset s, int pos, const char *type, - int *len) -{ - Z3950_record rec = record_cache_lookup (s, pos, 0); - return Z3950_record_get (rec, type, len); -} - static void record_cache_add (Z3950_resultset r, Z_NamePlusRecord *npr, int pos, @@ -1070,10 +1127,11 @@ static int Z3950_connection_exec_task (Z3950_connection c) { Z3950_task task = c->tasks; - yaz_log (LOG_DEBUG, "Z3950_connection_exec_task"); + yaz_log (LOG_LOG, "Z3950_connection_exec_task"); if (!task) return 0; - if (c->error != Z3950_ERROR_NONE || !c->cs) + if (c->error != Z3950_ERROR_NONE || + (!c->cs && task->which != Z3950_TASK_CONNECT)) { Z3950_connection_remove_tasks (c); return 0; @@ -1093,6 +1151,9 @@ static int Z3950_connection_exec_task (Z3950_connection c) if (send_present (c)) return 1; break; + case Z3950_TASK_CONNECT: + if (do_connect(c)) + return 1; } Z3950_connection_remove_task (c); return 0; @@ -1129,6 +1190,11 @@ static void handle_apdu (Z3950_connection c, Z_APDU *apdu) c->cookie_in = 0; if (cookie) c->cookie_in = xstrdup(cookie); + if (c->tasks) + { + assert (c->tasks->which == Z3950_TASK_CONNECT); + Z3950_connection_remove_task (c); + } Z3950_connection_exec_task (c); } break; @@ -1195,12 +1261,12 @@ static int do_write_ex (Z3950_connection c, char *buf_out, int len_out) else if (r == 1) { c->state = STATE_ESTABLISHED; - c->mask = Z3950_SELECT_READ|Z3950_SELECT_WRITE; + c->mask = Z3950_SELECT_READ|Z3950_SELECT_WRITE|Z3950_SELECT_EXCEPT; } else { c->state = STATE_ESTABLISHED; - c->mask = Z3950_SELECT_READ; + c->mask = Z3950_SELECT_READ|Z3950_SELECT_EXCEPT; } return 0; } @@ -1210,26 +1276,27 @@ static int do_write(Z3950_connection c) return do_write_ex (c, c->buf_out, c->len_out); } -const char *Z3950_connection_option (Z3950_connection c, const char *key, - const char *val) + +const char *Z3950_connection_option_get (Z3950_connection c, const char *key) { - const char *old_val = Z3950_options_get (c->options, key); - if (val) - { - Z3950_options_set (c->options, key, val); - } - return old_val; + return Z3950_options_get (c->options, key); } -const char *Z3950_resultset_option (Z3950_resultset r, const char *key, - const char *val) +void Z3950_connection_option_set (Z3950_connection c, const char *key, + const char *val) { - const char *old_val = Z3950_options_get (r->options, key); - if (val) - { - Z3950_options_set (r->options, key, val); - } - return old_val; + Z3950_options_set (c->options, key, val); +} + +const char *Z3950_resultset_option_get (Z3950_resultset r, const char *key) +{ + return Z3950_options_get (r->options, key); +} + +void Z3950_resultset_option_set (Z3950_resultset r, const char *key, + const char *val) +{ + Z3950_options_set (r->options, key, val); } @@ -1294,9 +1361,10 @@ int Z3950_connection_error (Z3950_connection c, const char **cp, int Z3950_connection_do_io(Z3950_connection c, int mask) { + Z3950_Event event; #if 0 int r = cs_look(c->cs); - yaz_log (LOG_DEBUG, "Z3950_connection_do_io c=%p mask=%d cs_look=%d", + yaz_log (LOG_LOG, "Z3950_connection_do_io c=%p mask=%d cs_look=%d", c, mask, r); if (r == CS_NONE) @@ -1306,7 +1374,7 @@ int Z3950_connection_do_io(Z3950_connection c, int mask) } else if (r == CS_CONNECT) { - yaz_log (LOG_DEBUG, "calling rcvconnect"); + yaz_log (LOG_LOG, "calling rcvconnect"); if (cs_rcvconnect (c->cs) < 0) { c->error = Z3950_ERROR_CONNECT; @@ -1347,34 +1415,51 @@ int Z3950_connection_do_io(Z3950_connection c, int mask) do_close (c); } #endif - c->event_pending = 1; + event = Z3950_Event_create (1); + Z3950_connection_put_event (c, event); return 1; } + int Z3950_event (int no, Z3950_connection *cs) { +#if HAVE_SYS_POLL_H + struct pollfd pollfds[1024]; + Z3950_connection poll_cs[1024]; +#else struct timeval tv; fd_set input, output, except; - int i, r; +#endif + int i, r, nfds; int max_fd = 0; for (i = 0; ievent_pending) - { - c->event_pending = 0; + Z3950_Event event; + if (c && (event = Z3950_connection_get_event(c))) + { + Z3950_Event_destroy (event); return i+1; - } + } } + for (i = 0; ics && c->host_port && c->error == Z3950_ERROR_NONE) - { - do_connect (c); - return i+1; - } - else - { - if (Z3950_connection_exec_task (c)) - return i+1; - } - } - yaz_log (LOG_DEBUG, "no more events"); - return 0; + Z3950_connection c = poll_cs[i]; + if (r && c->mask) + { + int mask = 0; + if (pollfds[i].revents & POLLIN) + mask += Z3950_SELECT_READ; + if (pollfds[i].revents & POLLOUT) + mask += Z3950_SELECT_WRITE; + if (pollfds[i].revents & POLLERR) + mask += Z3950_SELECT_EXCEPT; + if (mask) + Z3950_connection_do_io(c, mask); + } + else if (r == 0 && c->mask) + { + Z3950_Event event = Z3950_Event_create(0); + /* timeout and this connection was waiting */ + c->error = Z3950_ERROR_TIMEOUT; + do_close (c); + Z3950_connection_put_event(c, event); + } } +#else yaz_log (LOG_DEBUG, "select start"); r = select (max_fd+1, &input, &output, &except, &tv); yaz_log (LOG_DEBUG, "select stop, returned r=%d", r); - for (i = 0; imask) { + Z3950_Event event = Z3950_Event_create(0); /* timeout and this connection was waiting */ c->error = Z3950_ERROR_TIMEOUT; - c->event_pending = 1; + do_close (c); + yaz_log (LOG_LOG, "timeout"); + Z3950_connection_put_event(c, event); } } +#endif for (i = 0; ievent_pending) - { - c->event_pending = 0; + Z3950_Event event; + if (c && (event = Z3950_connection_get_event(c))) + { + Z3950_Event_destroy (event); return i+1; - } + } } return 0; }