X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp_command.c;h=913af7929a8e6a11bf84604b4df371912cae4294;hb=d24d65a3a42bbb6e8c8d0f919bf33510dd356a45;hp=7cbcda6535be81bf3290c3d414711a40561ff019;hpb=5c017d34db6ea43ee6a95b8c462b9b824c26fbb8;p=pazpar2-moved-to-github.git diff --git a/src/http_command.c b/src/http_command.c index 7cbcda6..913af79 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 @@ -51,10 +51,41 @@ struct http_session { unsigned int session_id; int timestamp; 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; + yaz_mutex_create(&hs->mutex); + 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,7 +95,8 @@ 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) { NMEM nmem = nmem_create(); struct http_session *r = nmem_malloc(nmem, sizeof(*r)); @@ -73,13 +105,18 @@ struct http_session *http_session_create(struct conf_service *service) r->session_id = 0; r->timestamp = 0; r->nmem = nmem; - r->next = session_list; - session_list = r; + 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); iochan_setdata(r->timeout_iochan, r); 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; } @@ -87,12 +124,16 @@ void http_session_destroy(struct http_session *s) { struct http_session **p; - for (p = &session_list; *p; p = &(*p)->next) + http_sessions_t http_sessions = s->http_sessions; + + yaz_mutex_enter(http_sessions->mutex); + for (p = &http_sessions->session_list; *p; p = &(*p)->next) if (*p == s) { *p = (*p)->next; break; } + yaz_mutex_leave(http_sessions->mutex); yaz_log(YLOG_LOG, "Destroying session %u", s->session_id); iochan_destroy(s->timeout_iochan); destroy_session(s->psession); @@ -117,6 +158,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 +226,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 +241,16 @@ 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; + 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 +326,11 @@ 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); + s = http_session_create(service, c->http_sessions); yaz_log(YLOG_DEBUG, "HTTP Session init"); if (!clear || *clear == '0') @@ -296,8 +342,16 @@ static void cmd_init(struct http_channel *c) 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%u", 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 +370,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 +433,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 +450,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,8 +525,9 @@ 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; if (!s) @@ -495,15 +551,21 @@ 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); wrbuf_puts(c->wrbuf, ""); wrbuf_xmlputs(c->wrbuf, ht[i].state); wrbuf_puts(c->wrbuf, "\n"); - + if (settings && *settings == '1') + { + wrbuf_puts(c->wrbuf, "\n"); + wrbuf_puts(c->wrbuf, wrbuf_cstr(ht[i].settings_xml)); + wrbuf_puts(c->wrbuf, "\n"); + } wrbuf_puts(c->wrbuf, ""); + wrbuf_destroy(ht[i].settings_xml); } wrbuf_puts(c->wrbuf, ""); @@ -524,8 +586,16 @@ static void write_metadata(WRBUF w, struct conf_service *service, continue; for (md = ml[imeta]; md; md = md->next) { - wrbuf_printf(w, "\n", cmd->name); + struct record_metadata_attr *attr = md->attributes; + wrbuf_printf(w, "\nname); + for (; attr; attr = attr->next) + { + wrbuf_printf(w, " %s=\"", attr->name); + wrbuf_xmlputs(w, attr->value); + wrbuf_puts(w, "\""); + } + wrbuf_puts(w, ">"); switch (cmd->type) { case Metadata_type_generic: @@ -615,7 +685,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; @@ -723,7 +793,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"); @@ -732,7 +802,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) @@ -760,7 +830,7 @@ static void show_records(struct http_channel *c, int active) 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); @@ -800,8 +870,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; @@ -829,9 +898,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"; @@ -867,10 +935,11 @@ 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"); + const char *startrecs = http_argbyname(rq, "startrecs"); enum pazpar2_error_code code; const char *addinfo = 0; @@ -886,7 +955,7 @@ static void cmd_search(struct http_channel *c) error(rs, PAZPAR2_MALFORMED_PARAMETER_ENCODING, "query"); return; } - code = search(s->psession, query, maxrecs, filter, &addinfo); + code = search(s->psession, query, startrecs, maxrecs, filter, &addinfo); if (code) { error(rs, code, addinfo); @@ -899,9 +968,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; @@ -920,7 +988,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);