X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Fhttp.c;h=27ce668065491d4b8b9d5cdc5b22b347457f675b;hb=8432e60d3fa90e5bb4abf49607fdeca3fa8a19ba;hp=5158ddbd1929e0c2b3532b64d1ea6ed043d687b2;hpb=d24d65a3a42bbb6e8c8d0f919bf33510dd356a45;p=pazpar2-moved-to-github.git diff --git a/src/http.c b/src/http.c index 5158ddb..27ce668 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,5 @@ /* This file is part of Pazpar2. - Copyright (C) 2006-2010 Index Data + Copyright (C) 2006-2011 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 @@ -63,7 +63,8 @@ typedef int socklen_t; #include #include -#include "pazpar2.h" +#include "ppmutex.h" +#include "session.h" #include "http.h" #define MAX_HTTP_HEADER 4096 @@ -94,7 +95,12 @@ static void http_server_incref(http_server_t hs); struct http_server { struct http_buf *http_buf_freelist; + int http_buf_freelist_count; + int http_buf_freelist_max; + struct http_channel *http_channel_freelist; + int http_channel_freelist_count; + int http_channel_freelist_max; YAZ_MUTEX mutex; int listener_socket; int ref_count; @@ -129,6 +135,7 @@ static struct http_buf *http_buf_create(http_server_t hs) { r = hs->http_buf_freelist; hs->http_buf_freelist = hs->http_buf_freelist->next; + hs->http_buf_freelist_count--; } yaz_mutex_leave(hs->mutex); if (!r) @@ -142,8 +149,20 @@ static struct http_buf *http_buf_create(http_server_t hs) static void http_buf_destroy(http_server_t hs, struct http_buf *b) { yaz_mutex_enter(hs->mutex); - b->next = hs->http_buf_freelist; - hs->http_buf_freelist = b; + if (hs->http_buf_freelist_max > 0 && hs->http_buf_freelist_count >= hs->http_buf_freelist_max) { + xfree(b); + while ((b = hs->http_buf_freelist)) { + xfree(b); + hs->http_buf_freelist = hs->http_buf_freelist->next; + } + hs->http_buf_freelist_count = 0; + } + else { + b->next = hs->http_buf_freelist; + hs->http_buf_freelist = b; + hs->http_buf_freelist_count++; + yaz_log(YLOG_DEBUG, "Free %d http buffers on server.", hs->http_buf_freelist_count); + } yaz_mutex_leave(hs->mutex); } @@ -797,7 +816,7 @@ static int http_proxy(struct http_request *rq) p->first_response = 1; c->proxy = p; // We will add EVENT_OUTPUT below - p->iochan = iochan_create(sock, proxy_io, EVENT_INPUT); + p->iochan = iochan_create(sock, proxy_io, EVENT_INPUT, "http_proxy"); iochan_setdata(p->iochan, p); iochan_add(ser->iochan_man, p->iochan); @@ -877,13 +896,13 @@ static void http_error(struct http_channel *hc, int no, const char *msg) static void http_io(IOCHAN i, int event) { struct http_channel *hc = iochan_getdata(i); - - switch (event) + while (event) { - int res, reqlen; - struct http_buf *htbuf; - - case EVENT_INPUT: + if (event == EVENT_INPUT) + { + int res, reqlen; + struct http_buf *htbuf; + htbuf = http_buf_create(hc->http_server); res = recv(iochan_getfd(i), htbuf->buf, HTTP_BUF_SIZE -1, 0); if (res == -1 && errno == EAGAIN) @@ -932,12 +951,16 @@ static void http_io(IOCHAN i, int event) http_command(hc); } } - break; - case EVENT_OUTPUT: + } + else if (event == EVENT_OUTPUT) + { + event = 0; if (hc->oqueue) { struct http_buf *wb = hc->oqueue; - res = send(iochan_getfd(hc->iochan), wb->buf + wb->offset, wb->len, 0); + int res; + res = send(iochan_getfd(hc->iochan), + wb->buf + wb->offset, wb->len, 0); if (res <= 0) { yaz_log(YLOG_WARN|YLOG_ERRNO, "write"); @@ -954,7 +977,8 @@ static void http_io(IOCHAN i, int event) wb->len -= res; wb->offset += res; } - if (!hc->oqueue) { + if (!hc->oqueue) + { if (!hc->keep_alive) { http_channel_destroy(i); @@ -964,17 +988,19 @@ static void http_io(IOCHAN i, int event) { iochan_clearflag(i, EVENT_OUTPUT); if (hc->iqueue) - iochan_setevent(hc->iochan, EVENT_INPUT); + event = EVENT_INPUT; } } } - if (!hc->oqueue && hc->proxy && !hc->proxy->iochan) http_channel_destroy(i); // Server closed; we're done - break; - default: + } + else + { yaz_log(YLOG_WARN, "Unexpected event on connection"); http_channel_destroy(i); + event = 0; + } } } @@ -1090,8 +1116,21 @@ static void http_channel_destroy(IOCHAN i) http_server = s->http_server; /* save it for destroy (decref) */ yaz_mutex_enter(s->http_server->mutex); - s->next = s->http_server->http_channel_freelist; - s->http_server->http_channel_freelist = s; + if (s->http_server->http_channel_freelist_max > 0 && s->http_server->http_channel_freelist_count >= s->http_server->http_channel_freelist_max) { + while ((s->next = s->http_server->http_channel_freelist)) { + nmem_destroy(s->next->nmem); + wrbuf_destroy(s->next->wrbuf); + xfree(s->next); + s->http_server->http_channel_freelist = s->http_server->http_channel_freelist->next; + } + s->http_server->http_channel_freelist_count = 0; + } + else { + s->next = s->http_server->http_channel_freelist; + s->http_server->http_channel_freelist = s; + s->http_server->http_channel_freelist_count++; + yaz_log(YLOG_DEBUG, "Free %d channels on server.", s->http_server->http_channel_freelist_count); + } yaz_mutex_leave(s->http_server->mutex); http_server_destroy(http_server); @@ -1112,8 +1151,10 @@ static struct http_channel *http_channel_create(http_server_t hs, yaz_mutex_enter(hs->mutex); r = hs->http_channel_freelist; - if (r) + if (r) { hs->http_channel_freelist = r->next; + hs->http_channel_freelist_count--; + } yaz_mutex_leave(hs->mutex); if (r) @@ -1170,7 +1211,7 @@ static void http_accept(IOCHAN i, int event) enable_nonblock(s); yaz_log(YLOG_DEBUG, "New command connection"); - c = iochan_create(s, http_io, EVENT_INPUT | EVENT_EXCEPT); + c = iochan_create(s, http_io, EVENT_INPUT | EVENT_EXCEPT, "http_session_socket"); ch = http_channel_create(server->http_server, inet_ntoa(addr.sin_addr), server); @@ -1245,7 +1286,7 @@ int http_init(const char *addr, struct conf_server *server) server->http_server->listener_socket = l; - c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT); + c = iochan_create(l, http_accept, EVENT_INPUT | EVENT_EXCEPT, "http_server"); iochan_setdata(c, server); iochan_add(server->iochan_man, c); @@ -1361,9 +1402,17 @@ http_server_t http_server_create(void) hs->mutex = 0; hs->proxy_addr = 0; hs->ref_count = 1; - hs->http_buf_freelist = 0; - hs->http_channel_freelist = 0; hs->http_sessions = 0; + + hs->http_channel_freelist = 0; + hs->http_channel_freelist_count = 0; + /* Disable max check */ + hs->http_channel_freelist_max = 0; + + hs->http_buf_freelist = 0; + hs->http_buf_freelist_count = 0; + /* Disable max check */ + hs->http_buf_freelist_max = 0; return hs; } @@ -1373,14 +1422,9 @@ void http_server_destroy(http_server_t hs) { int r; - if (hs->mutex) - { - yaz_mutex_enter(hs->mutex); - r = --(hs->ref_count); - yaz_mutex_leave(hs->mutex); - } - else - r = --(hs->ref_count); + yaz_mutex_enter(hs->mutex); /* OK: hs->mutex may be NULL */ + r = --(hs->ref_count); + yaz_mutex_leave(hs->mutex); if (r == 0) { @@ -1421,7 +1465,7 @@ void http_mutex_init(struct conf_server *server) assert(server); assert(server->http_server->mutex == 0); - yaz_mutex_create(&server->http_server->mutex); + pazpar2_mutex_create(&server->http_server->mutex, "http_server"); server->http_server->http_sessions = http_sessions_create(); }