X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp_command.c;h=b37eca9484b6ad1fb26f0155848c6fad32c3a964;hb=3d39722ae64c21a6d5833ec667ef9fd2fb66913f;hp=6fe87b5d787edddcfc7cff8c8dfd96d49dba955b;hpb=f6f232081df89d867621187764818ea777178e82;p=pazpar2-moved-to-github.git diff --git a/src/http_command.c b/src/http_command.c index 6fe87b5..b37eca9 100644 --- a/src/http_command.c +++ b/src/http_command.c @@ -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,6 +51,8 @@ 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; @@ -58,6 +61,7 @@ struct http_session { struct http_sessions { struct http_session *session_list; YAZ_MUTEX mutex; + int log_level; }; http_sessions_t http_sessions_create(void) @@ -65,7 +69,8 @@ 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); + pazpar2_mutex_create(&hs->mutex, "http_sessions"); + hs->log_level = yaz_log_module_level("HTTP"); return hs; } @@ -96,15 +101,19 @@ static void session_timeout(IOCHAN i, int event) } struct http_session *http_session_create(struct conf_service *service, - http_sessions_t http_sessions) + 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->destroy_counter = r->activity_counter = 0; r->http_sessions = http_sessions; yaz_mutex_enter(http_sessions->mutex); @@ -112,8 +121,9 @@ struct http_session *http_session_create(struct conf_service *service, http_sessions->session_list = r; yaz_mutex_leave(http_sessions->mutex); - r->timeout_iochan = iochan_create(-1, session_timeout, 0); + r->timeout_iochan = iochan_create(-1, session_timeout, 0, "http_session_timeout"); iochan_setdata(r->timeout_iochan, r); + yaz_log(http_sessions->log_level, "%p Session %u created. timeout chan=%p timeout=%d", r, sesid, r->timeout_iochan, service->session_timeout); iochan_settimeout(r->timeout_iochan, service->session_timeout); iochan_add(service->server->iochan_man, r->timeout_iochan); @@ -122,22 +132,36 @@ struct http_session *http_session_create(struct conf_service *service, void http_session_destroy(struct http_session *s) { - struct http_session **p; + int must_destroy = 0; http_sessions_t http_sessions = s->http_sessions; + yaz_log(http_sessions->log_level, "%p Session %u destroyed", s, s->session_id); yaz_mutex_enter(http_sessions->mutex); - for (p = &http_sessions->session_list; *p; p = &(*p)->next) - if (*p == s) - { - *p = (*p)->next; - break; - } + /* only if http_session has no active http sessions on it can be destroyed */ + if (s->destroy_counter == s->activity_counter) { + struct http_session **p = 0; + must_destroy = 1; + 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); - nmem_destroy(s->nmem); + if (must_destroy) + { /* destroying for real */ + yaz_log(http_sessions->log_level, "%p Session %u destroyed", s, s->session_id); + iochan_destroy(s->timeout_iochan); + destroy_session(s->psession); + nmem_destroy(s->nmem); + } + else { + yaz_log(http_sessions->log_level, "%p Session %u destroyed delayed. Active clients (%d-%d). Waiting for new timeout.", + s, s->session_id, s->activity_counter, s->destroy_counter); + } + } static const char *get_msg(enum pazpar2_error_code code) @@ -245,6 +269,8 @@ static struct http_session *locate_session(struct http_channel *c) for (p = http_sessions->session_list; p; p = p->next) if (id == p->session_id) break; + if (p) + p->activity_counter++; yaz_mutex_leave(http_sessions->mutex); if (p) iochan_activity(p->timeout_iochan); @@ -253,6 +279,15 @@ static struct http_session *locate_session(struct http_channel *c) return p; } +// Call after use of locate_session, in order to increment the destroy_counter +static void release_session(struct http_channel *c, struct http_session *session) { + http_sessions_t http_sessions = c->http_sessions; + yaz_mutex_enter(http_sessions->mutex); + if (session) + session->destroy_counter++; + yaz_mutex_leave(http_sessions->mutex); +} + // Decode settings parameters and apply to session // Syntax: setting[target]=value static int process_settings(struct session *se, struct http_request *rq, @@ -330,21 +365,20 @@ static void cmd_init(struct http_channel *c) return; } } - s = http_session_create(service, c->http_sessions); + sesid = make_sessionid(); + s = http_session_create(service, c->http_sessions, sesid); - yaz_log(YLOG_DEBUG, "HTTP Session init"); + yaz_log(c->http_sessions->log_level, "%p Session init %u ", s, sesid); if (!clear || *clear == '0') session_init_databases(s->psession); else - yaz_log(YLOG_LOG, "No databases preloaded"); + yaz_log(YLOG_LOG, "HTTP Session %u init: No databases preloaded", sesid); - 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", sesid); + "OK%d", sesid); if (c->server->server_id) { strcat(buf, "."); @@ -392,10 +426,13 @@ static void cmd_settings(struct http_channel *c) xmlFreeDoc(doc); } - if (process_settings(s->psession, rq, rs) < 0) + if (process_settings(s->psession, rq, rs) < 0) { + release_session(c,s); return; + } rs->payload = HTTP_COMMAND_RESPONSE_PREFIX "OK"; http_send_response(c); + release_session(c,s); } // Compares two hitsbytarget nodes by hitcount @@ -518,6 +555,7 @@ static void cmd_termlist(struct http_channel *c) wrbuf_puts(c->wrbuf, "\n"); rs->payload = nmem_strdup(rq->channel->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); + release_session(c,s); } @@ -571,6 +609,7 @@ static void cmd_bytarget(struct http_channel *c) wrbuf_puts(c->wrbuf, ""); rs->payload = nmem_strdup(c->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); + release_session(c,s); } static void write_metadata(WRBUF w, struct conf_service *service, @@ -713,6 +752,7 @@ static void cmd_record(struct http_channel *c) { error(rs, PAZPAR2_RECORD_MISSING, idstr); } + release_session(c, s); return; } if (offsetstr) @@ -780,6 +820,7 @@ static void cmd_record(struct http_channel *c) http_send_response(c); } show_single_stop(s->psession, rec); + release_session(c, s); } static void cmd_record_ready(void *data) @@ -821,6 +862,7 @@ static void show_records(struct http_channel *c, int active) if (!(sp = reclist_parse_sortparms(c->nmem, sort, s->psession->service))) { error(rs, PAZPAR2_MALFORMED_PARAMETER_VALUE, "sort"); + release_session(c, s); return; } @@ -862,6 +904,7 @@ static void show_records(struct http_channel *c, int active) wrbuf_puts(c->wrbuf, "\n"); rs->payload = nmem_strdup(c->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); + release_session(c, s); } static void show_records_ready(void *data) @@ -891,13 +934,14 @@ static void cmd_show(struct http_channel *c) if (session_set_watch(s->psession, SESSION_WATCH_SHOW, show_records_ready, c, c) != 0) { - yaz_log(YLOG_DEBUG, "Blocking on cmd_show"); + yaz_log(c->http_sessions->log_level, "%p Session %u: Blocking on cmd_show", s, s->session_id); } + release_session(c,s); return; } } - show_records(c, status); + release_session(c,s); } static void cmd_ping(struct http_channel *c) @@ -908,6 +952,7 @@ static void cmd_ping(struct http_channel *c) return; rs->payload = HTTP_COMMAND_RESPONSE_PREFIX "OK"; http_send_response(c); + release_session(c, s); } static int utf_8_valid(const char *str) @@ -952,21 +997,25 @@ static void cmd_search(struct http_channel *c) if (!query) { error(rs, PAZPAR2_MISSING_PARAMETER, "query"); + release_session(c,s); return; } if (!utf_8_valid(query)) { error(rs, PAZPAR2_MALFORMED_PARAMETER_ENCODING, "query"); + release_session(c,s); return; } code = search(s->psession, query, startrecs, maxrecs, filter, &addinfo); if (code) { error(rs, code, addinfo); + release_session(c,s); return; } rs->payload = HTTP_COMMAND_RESPONSE_PREFIX "OK"; http_send_response(c); + release_session(c,s); } @@ -1005,6 +1054,7 @@ static void cmd_stat(struct http_channel *c) wrbuf_puts(c->wrbuf, ""); rs->payload = nmem_strdup(c->nmem, wrbuf_cstr(c->wrbuf)); http_send_response(c); + release_session(c,s); } static void cmd_info(struct http_channel *c)