X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp_command.c;h=9b1825d0eae7ce03f04048d8fa1967b8fab456a9;hb=e20a024ae2ec8f81b4520ac811b215c9a9ed403d;hp=752c3295452bb3baf26c282933789dd3235a90a3;hpb=907fd760f429fa5f0da73b856221bdaac3ab45ee;p=pazpar2-moved-to-github.git diff --git a/src/http_command.c b/src/http_command.c index 752c329..9b1825d 100644 --- a/src/http_command.c +++ b/src/http_command.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2009 Index Data + Copyright (C) 2006-2010 Index Data Pazpar2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -33,9 +33,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include +#include "ppmutex.h" #include "eventl.h" #include "parameters.h" -#include "pazpar2.h" +#include "session.h" #include "http.h" #include "settings.h" #include "client.h" @@ -50,11 +51,44 @@ struct http_session { struct session *psession; unsigned int session_id; int timestamp; + int destroy_counter; + int activity_counter; NMEM nmem; + http_sessions_t http_sessions; struct http_session *next; }; -static struct http_session *session_list = 0; /* thread pr */ +struct http_sessions { + struct http_session *session_list; + YAZ_MUTEX mutex; +}; + +http_sessions_t http_sessions_create(void) +{ + http_sessions_t hs = xmalloc(sizeof(*hs)); + hs->session_list = 0; + hs->mutex = 0; + pazpar2_mutex_create(&hs->mutex, "http_sessions"); + return hs; +} + +void http_sessions_destroy(http_sessions_t hs) +{ + if (hs) + { + struct http_session *s = hs->session_list; + while (s) + { + struct http_session *s_next = s->next; + iochan_destroy(s->timeout_iochan); + destroy_session(s->psession); + nmem_destroy(s->nmem); + s = s_next; + } + yaz_mutex_destroy(&hs->mutex); + xfree(hs); + } +} void http_session_destroy(struct http_session *s); @@ -64,39 +98,73 @@ static void session_timeout(IOCHAN i, int event) http_session_destroy(s); } -struct http_session *http_session_create(struct conf_service *service) +struct http_session *http_session_create(struct conf_service *service, + http_sessions_t http_sessions, + unsigned int sesid) { NMEM nmem = nmem_create(); struct http_session *r = nmem_malloc(nmem, sizeof(*r)); + char tmp_str[50]; - r->psession = new_session(nmem, service); - r->session_id = 0; + sprintf(tmp_str, "session#%u", sesid); + r->psession = new_session(nmem, service, tmp_str); + r->session_id = sesid; r->timestamp = 0; r->nmem = nmem; - r->next = session_list; - session_list = r; - r->timeout_iochan = iochan_create(-1, session_timeout, 0); + r->destroy_counter = r->activity_counter = 0; + r->http_sessions = http_sessions; + + yaz_mutex_enter(http_sessions->mutex); + r->next = http_sessions->session_list; + http_sessions->session_list = r; + yaz_mutex_leave(http_sessions->mutex); + + r->timeout_iochan = iochan_create(-1, session_timeout, 0, "http_session_timeout"); iochan_setdata(r->timeout_iochan, r); + yaz_log(YLOG_LOG, "timeout=%d", service->session_timeout); iochan_settimeout(r->timeout_iochan, service->session_timeout); - pazpar2_add_channel(r->timeout_iochan); + iochan_add(service->server->iochan_man, r->timeout_iochan); return r; } void http_session_destroy(struct http_session *s) { - struct http_session **p; + int must_destroy = 1; + + http_sessions_t http_sessions = s->http_sessions; + + yaz_log(YLOG_LOG, "http_session_destroy %u", s->session_id); + yaz_mutex_enter(http_sessions->mutex); + + /* only if http_session destroy was already called, we will allow it + to be destroyed */ + if (s->destroy_counter != s->activity_counter) + must_destroy = 0; + + s->destroy_counter = s->activity_counter = 0; + if (must_destroy) + { + struct http_session **p = 0; + for (p = &http_sessions->session_list; *p; p = &(*p)->next) + if (*p == s) + { + *p = (*p)->next; + break; + } + } + yaz_mutex_leave(http_sessions->mutex); + if (must_destroy) + { /* destroying for real */ + yaz_log(YLOG_LOG, "Destroying session %u", s->session_id); + iochan_destroy(s->timeout_iochan); + destroy_session(s->psession); + nmem_destroy(s->nmem); + } + else { + yaz_log(YLOG_LOG, "Active clients on session %u. Waiting for new timeout.", s->session_id); + } - for (p = &session_list; *p; p = &(*p)->next) - if (*p == s) - { - *p = (*p)->next; - break; - } - yaz_log(YLOG_LOG, "Destroying session %u", s->session_id); - iochan_destroy(s->timeout_iochan); - destroy_session(s->psession); - nmem_destroy(s->nmem); } static const char *get_msg(enum pazpar2_error_code code) @@ -117,6 +185,7 @@ static const char *get_msg(enum pazpar2_error_code code) { PAZPAR2_CONFIG_TARGET, "Target cannot be configured"}, { PAZPAR2_RECORD_FAIL, "Record command failed"}, { PAZPAR2_NOT_IMPLEMENTED, "Not implemented"}, + { PAZPAR2_NO_SERVICE, "No service"}, { PAZPAR2_LAST_ERROR, "Last error"}, { 0, 0 } }; @@ -184,10 +253,13 @@ unsigned int make_sessionid(void) return res; } -static struct http_session *locate_session(struct http_request *rq, struct http_response *rs) +static struct http_session *locate_session(struct http_channel *c) { + struct http_response *rs = c->response; + struct http_request *rq = c->request; struct http_session *p; const char *session = http_argbyname(rq, "session"); + http_sessions_t http_sessions = c->http_sessions; unsigned int id; if (!session) @@ -196,14 +268,18 @@ static struct http_session *locate_session(struct http_request *rq, struct http_ return 0; } id = atoi(session); - for (p = session_list; p; p = p->next) + yaz_mutex_enter(http_sessions->mutex); + for (p = http_sessions->session_list; p; p = p->next) if (id == p->session_id) - { - iochan_activity(p->timeout_iochan); - return p; - } - error(rs, PAZPAR2_NO_SESSION, session); - return 0; + break; + if (p) + p->activity_counter++; + yaz_mutex_leave(http_sessions->mutex); + if (p) + iochan_activity(p->timeout_iochan); + else + error(rs, PAZPAR2_NO_SESSION, session); + return p; } // Decode settings parameters and apply to session @@ -279,12 +355,12 @@ static void cmd_init(struct http_channel *c) service = locate_service(c->server, service_name); if (!service) { - error(rs, PAZPAR2_MALFORMED_PARAMETER_VALUE, "service"); + error(rs, PAZPAR2_NO_SERVICE, service_name ? service_name : "unnamed"); return; } - service_incref(service); } - s = http_session_create(service); + sesid = make_sessionid(); + s = http_session_create(service, c->http_sessions, sesid); yaz_log(YLOG_DEBUG, "HTTP Session init"); if (!clear || *clear == '0') @@ -292,12 +368,18 @@ static void cmd_init(struct http_channel *c) else yaz_log(YLOG_LOG, "No databases preloaded"); - sesid = make_sessionid(); - s->session_id = sesid; if (process_settings(s->psession, c->request, c->response) < 0) return; - sprintf(buf, HTTP_COMMAND_RESPONSE_PREFIX "OK%u" - "" PAZPAR2_PROTOCOL_VERSION "", sesid); + + sprintf(buf, HTTP_COMMAND_RESPONSE_PREFIX + "OK%d", sesid); + if (c->server->server_id) + { + strcat(buf, "."); + strcat(buf, c->server->server_id); + } + strcat(buf, "" + "" PAZPAR2_PROTOCOL_VERSION ""); rs->payload = nmem_strdup(c->nmem, buf); http_send_response(c); } @@ -316,7 +398,7 @@ static void cmd_settings(struct http_channel *c) { struct http_response *rs = c->response; struct http_request *rq = c->request; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); const char *content_type = http_lookup_header(rq->headers, "Content-Type"); if (!s) @@ -379,7 +461,8 @@ static void targets_termlist(WRBUF wrbuf, struct session *se, int num, wrbuf_xmlputs(wrbuf, ht[i].name); wrbuf_puts(wrbuf, "\n"); - wrbuf_printf(wrbuf, "%d\n", ht[i].hits); + wrbuf_printf(wrbuf, "" ODR_INT_PRINTF "\n", + ht[i].hits); wrbuf_puts(wrbuf, ""); wrbuf_xmlputs(wrbuf, ht[i].state); @@ -395,7 +478,7 @@ static void cmd_termlist(struct http_channel *c) { struct http_response *rs = c->response; struct http_request *rq = c->request; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); struct termlist_score **p; int len; int i; @@ -470,7 +553,7 @@ static void cmd_bytarget(struct http_channel *c) { struct http_response *rs = c->response; struct http_request *rq = c->request; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); struct hitsbytarget *ht; const char *settings = http_argbyname(rq, "settings"); int count, i; @@ -496,7 +579,7 @@ static void cmd_bytarget(struct http_channel *c) wrbuf_puts(c->wrbuf, "\n"); } - wrbuf_printf(c->wrbuf, "%d\n", ht[i].hits); + wrbuf_printf(c->wrbuf, "" ODR_INT_PRINTF "\n", ht[i].hits); wrbuf_printf(c->wrbuf, "%d\n", ht[i].diagnostic); wrbuf_printf(c->wrbuf, "%d\n", ht[i].records); @@ -630,7 +713,7 @@ static void cmd_record(struct http_channel *c) { struct http_response *rs = c->response; struct http_request *rq = c->request; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); struct record_cluster *rec, *prev_r, *next_r; struct record *r; struct conf_service *service; @@ -647,7 +730,7 @@ static void cmd_record(struct http_channel *c) return; } wrbuf_rewind(c->wrbuf); - if (!(rec = show_single(s->psession, idstr, &prev_r, &next_r))) + if (!(rec = show_single_start(s->psession, idstr, &prev_r, &next_r))) { if (session_active_clients(s->psession) == 0) { @@ -677,7 +760,6 @@ static void cmd_record(struct http_channel *c) if (!r) { error(rs, PAZPAR2_RECORD_FAIL, "no record at offset given"); - return; } else { @@ -725,6 +807,7 @@ static void cmd_record(struct http_channel *c) rs->payload = nmem_strdup(c->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); } + show_single_stop(s->psession, rec); } static void cmd_record_ready(void *data) @@ -738,7 +821,7 @@ static void show_records(struct http_channel *c, int active) { struct http_request *rq = c->request; struct http_response *rs = c->response; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); struct record_cluster **rl; struct reclist_sortparms *sp; const char *start = http_argbyname(rq, "start"); @@ -747,7 +830,7 @@ static void show_records(struct http_channel *c, int active) int startn = 0; int numn = 20; int total; - int total_hits; + Odr_int total_hits; int i; if (!s) @@ -769,13 +852,14 @@ static void show_records(struct http_channel *c, int active) return; } - rl = show(s->psession, sp, startn, &numn, &total, &total_hits, c->nmem); + + rl = show_range_start(s->psession, sp, startn, &numn, &total, &total_hits); wrbuf_rewind(c->wrbuf); wrbuf_puts(c->wrbuf, HTTP_COMMAND_RESPONSE_PREFIX "\nOK\n"); wrbuf_printf(c->wrbuf, "%d\n", active); wrbuf_printf(c->wrbuf, "%d\n", total); - wrbuf_printf(c->wrbuf, "%d\n", total_hits); + wrbuf_printf(c->wrbuf, "" ODR_INT_PRINTF "\n", total_hits); wrbuf_printf(c->wrbuf, "%d\n", startn); wrbuf_printf(c->wrbuf, "%d\n", numn); @@ -793,13 +877,16 @@ static void show_records(struct http_channel *c, int active) if (ccount > 1) wrbuf_printf(c->wrbuf, "%d\n", ccount); if (strstr(sort, "relevance")) - wrbuf_printf(c->wrbuf, "%d\n", rec->relevance); + wrbuf_printf(c->wrbuf, "%d\n", + rec->relevance_score); wrbuf_puts(c->wrbuf, ""); wrbuf_xmlputs(c->wrbuf, rec->recid); wrbuf_puts(c->wrbuf, "\n"); wrbuf_puts(c->wrbuf, "\n"); } + show_range_stop(s->psession, rl); + wrbuf_puts(c->wrbuf, "\n"); rs->payload = nmem_strdup(c->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); @@ -815,8 +902,7 @@ static void show_records_ready(void *data) static void cmd_show(struct http_channel *c) { struct http_request *rq = c->request; - struct http_response *rs = c->response; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); const char *block = http_argbyname(rq, "block"); int status; @@ -844,9 +930,8 @@ static void cmd_show(struct http_channel *c) static void cmd_ping(struct http_channel *c) { - struct http_request *rq = c->request; struct http_response *rs = c->response; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); if (!s) return; rs->payload = HTTP_COMMAND_RESPONSE_PREFIX "OK"; @@ -882,7 +967,7 @@ static void cmd_search(struct http_channel *c) { struct http_request *rq = c->request; struct http_response *rs = c->response; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); const char *query = http_argbyname(rq, "query"); const char *filter = http_argbyname(rq, "filter"); const char *maxrecs = http_argbyname(rq, "maxrecs"); @@ -915,9 +1000,8 @@ static void cmd_search(struct http_channel *c) static void cmd_stat(struct http_channel *c) { - struct http_request *rq = c->request; struct http_response *rs = c->response; - struct http_session *s = locate_session(rq, rs); + struct http_session *s = locate_session(c); struct statistics stat; int clients; @@ -936,7 +1020,7 @@ static void cmd_stat(struct http_channel *c) wrbuf_rewind(c->wrbuf); wrbuf_puts(c->wrbuf, HTTP_COMMAND_RESPONSE_PREFIX ""); wrbuf_printf(c->wrbuf, "%d\n", clients); - wrbuf_printf(c->wrbuf, "%d\n", stat.num_hits); + wrbuf_printf(c->wrbuf, "" ODR_INT_PRINTF "\n", stat.num_hits); wrbuf_printf(c->wrbuf, "%d\n", stat.num_records); wrbuf_printf(c->wrbuf, "%d\n", stat.num_clients); wrbuf_printf(c->wrbuf, "%d\n", stat.num_no_connection);