[core] change srv->conns to doubly-linked-list
avoids separate memory allocation for list of pointers
This commit is contained in:
parent
5a58f6963c
commit
81a107b4e6
|
@ -21,7 +21,6 @@ struct connection {
|
|||
h2con *h2;
|
||||
|
||||
int fd; /* the FD for this connection */
|
||||
uint32_t ndx; /* reverse mapping to server->connection[ndx] */
|
||||
fdnode *fdn; /* fdevent (fdnode *) object */
|
||||
|
||||
/* fd states */
|
||||
|
@ -62,6 +61,7 @@ struct connection {
|
|||
int keep_alive_idle; /* remember max_keep_alive_idle from config */
|
||||
|
||||
connection *next;
|
||||
connection *prev;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -153,7 +153,6 @@ struct server {
|
|||
/* buffers */
|
||||
buffer *tmp_buf;
|
||||
|
||||
connections conns;
|
||||
connections joblist_A;
|
||||
connections joblist_B;
|
||||
connections fdwaitqueue;
|
||||
|
@ -171,6 +170,7 @@ struct server {
|
|||
int sockets_disabled;
|
||||
|
||||
uint32_t lim_conns;
|
||||
connection *conns;
|
||||
connection *conns_pool;
|
||||
|
||||
log_error_st *errh;
|
||||
|
|
|
@ -48,7 +48,6 @@ static connection *connection_init(server *srv);
|
|||
static void connection_reset(connection *con);
|
||||
|
||||
static connection *connections_get_new_connection(server *srv) {
|
||||
connections * const conns = &srv->conns;
|
||||
connection *con;
|
||||
--srv->lim_conns;
|
||||
if (srv->conns_pool) {
|
||||
|
@ -61,16 +60,22 @@ static connection *connections_get_new_connection(server *srv) {
|
|||
if (srv->srvconf.h2proto)
|
||||
request_pool_extend(srv, 8);
|
||||
}
|
||||
con->next = NULL;
|
||||
return (conns->ptr[(con->ndx = conns->used++)] = con);
|
||||
/*con->prev = NULL;*//*(already set)*/
|
||||
if ((con->next = srv->conns))
|
||||
con->next->prev = con;
|
||||
return (srv->conns = con);
|
||||
}
|
||||
|
||||
static void connection_del(server *srv, connection *con) {
|
||||
if (con->next)
|
||||
con->next->prev = con->prev;
|
||||
if (con->prev)
|
||||
con->prev->next = con->next;
|
||||
else
|
||||
srv->conns = con->next;
|
||||
con->prev = NULL;
|
||||
con->next = srv->conns_pool;
|
||||
srv->conns_pool = con;
|
||||
connections * const conns = &srv->conns;
|
||||
if (con->ndx != --conns->used) /* not last element */
|
||||
(conns->ptr[con->ndx] = conns->ptr[conns->used])->ndx = con->ndx;
|
||||
++srv->lim_conns;
|
||||
}
|
||||
|
||||
|
@ -555,18 +560,11 @@ void connections_pool_clear(server * const srv) {
|
|||
void connections_free(server *srv) {
|
||||
connections_pool_clear(srv);
|
||||
|
||||
connections * const conns = &srv->conns;
|
||||
for (uint32_t i = 0; i < conns->used; ++i)
|
||||
connection_free(conns->ptr[i]);
|
||||
free(conns->ptr);
|
||||
conns->ptr = NULL;
|
||||
}
|
||||
|
||||
void connections_init(server *srv) {
|
||||
connections * const conns = &srv->conns;
|
||||
conns->size = srv->srvconf.max_conns;
|
||||
conns->ptr = calloc(conns->size, sizeof(*conns->ptr));
|
||||
force_assert(NULL != conns->ptr);
|
||||
connection *con;
|
||||
while ((con = srv->conns)) {
|
||||
srv->conns = con->next;
|
||||
connection_free(con);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1566,18 +1564,17 @@ static void connection_check_timeout (connection * const con, const unix_time64_
|
|||
|
||||
void connection_periodic_maint (server * const srv, const unix_time64_t cur_ts) {
|
||||
/* check all connections for timeouts */
|
||||
connections * const conns = &srv->conns;
|
||||
for (size_t ndx = 0; ndx < conns->used; ++ndx) {
|
||||
connection_check_timeout(conns->ptr[ndx], cur_ts);
|
||||
for (connection *con = srv->conns, *tc; con; con = tc) {
|
||||
tc = con->next;
|
||||
connection_check_timeout(con, cur_ts);
|
||||
}
|
||||
}
|
||||
|
||||
void connection_graceful_shutdown_maint (server *srv) {
|
||||
connections * const conns = &srv->conns;
|
||||
const int graceful_expire =
|
||||
(srv->graceful_expire_ts && srv->graceful_expire_ts < log_monotonic_secs);
|
||||
for (uint32_t ndx = 0; ndx < conns->used; ++ndx) {
|
||||
connection * const con = conns->ptr[ndx];
|
||||
for (connection *con = srv->conns, *tc; con; con = tc) {
|
||||
tc = con->next;
|
||||
int changed = 0;
|
||||
|
||||
request_st * const r = &con->request;
|
||||
|
|
|
@ -8,8 +8,6 @@ struct server_socket; /* declaration */
|
|||
|
||||
void connections_pool_clear(server *srv);
|
||||
|
||||
__attribute_cold__
|
||||
void connections_init(server *srv);
|
||||
__attribute_cold__
|
||||
void connections_free(server *srv);
|
||||
|
||||
|
|
|
@ -131,13 +131,11 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) {
|
|||
if (p->conf.max_conns == 0) return HANDLER_GO_ON;
|
||||
|
||||
sock_addr * const dst_addr = &r->con->dst_addr;
|
||||
const connections * const conns = &r->con->srv->conns;
|
||||
for (uint32_t i = 0, conns_by_ip = 0; i < conns->used; ++i) {
|
||||
connection *c = conns->ptr[i];
|
||||
|
||||
uint32_t conns_by_ip = 0;
|
||||
for (const connection *c = r->con->srv->conns; c; c = c->next) {
|
||||
/* check if other connections are already actively serving data for the same IP
|
||||
* we can only ban connections which are already behind the 'read request' state
|
||||
* */
|
||||
*/
|
||||
if (c->request.state <= CON_STATE_REQUEST_END) continue;
|
||||
|
||||
if (!sock_addr_is_addr_eq(&c->dst_addr, dst_addr)) continue;
|
||||
|
|
|
@ -298,9 +298,7 @@ static void mod_status_html_rtable (request_st * const rq, const server * const
|
|||
* (avoid write() per connection) */
|
||||
buffer * const b = rq->tmp_buf;
|
||||
buffer_clear(b);
|
||||
connection * const * const cptr = srv->conns.ptr;
|
||||
for (uint32_t i = 0, used = srv->conns.used; i < used; ++i) {
|
||||
const connection * const con = cptr[i];
|
||||
for (const connection *con = srv->conns; con; con = con->next) {
|
||||
const request_st * const r = &con->request;
|
||||
if (r->http_status <= HTTP_VERSION_1_1) {
|
||||
if (buffer_string_space(b) < 4096) {
|
||||
|
@ -547,8 +545,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, request_st *
|
|||
buffer_append_string_len(b, CONST_STR_LEN(" connections</b>\n"));
|
||||
|
||||
int per_line = 50;
|
||||
for (j = 0; j < srv->conns.used; ++j) {
|
||||
connection *c = srv->conns.ptr[j];
|
||||
for (const connection *c = srv->conns; c; c = c->next) {
|
||||
const request_st * const cr = &c->request;
|
||||
const char *state;
|
||||
|
||||
|
@ -635,8 +632,7 @@ static handler_t mod_status_handle_server_status_text(server *srv, request_st *
|
|||
buffer_append_int(b, srv->lim_conns); /*(could omit)*/
|
||||
|
||||
buffer_append_string_len(b, CONST_STR_LEN("\nScoreboard: "));
|
||||
for (uint32_t i = 0; i < srv->conns.used; ++i) {
|
||||
connection *c = srv->conns.ptr[i];
|
||||
for (const connection *c = srv->conns; c; c = c->next) {
|
||||
const request_st * const cr = &c->request;
|
||||
const char *state =
|
||||
((c->h2 && 0 == c->h2->rused)
|
||||
|
@ -894,11 +890,8 @@ TRIGGER_FUNC(mod_status_trigger) {
|
|||
plugin_data *p = p_d;
|
||||
|
||||
/* check all connections */
|
||||
for (uint32_t i = 0; i < srv->conns.used; ++i) {
|
||||
connection *c = srv->conns.ptr[i];
|
||||
|
||||
for (const connection *c = srv->conns; c; c = c->next)
|
||||
p->bytes_written += c->bytes_written_cur_second;
|
||||
}
|
||||
|
||||
/* a sliding average */
|
||||
p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
|
||||
|
|
|
@ -592,8 +592,7 @@ TRIGGER_FUNC(mod_wstunnel_handle_trigger) {
|
|||
|
||||
gw_handle_trigger(srv, p_d);
|
||||
|
||||
for (uint32_t i = 0; i < srv->conns.used; ++i) {
|
||||
connection *con = srv->conns.ptr[i];
|
||||
for (connection *con = srv->conns; con; con = con->next) {
|
||||
request_st * const r = &con->request;
|
||||
handler_ctx *hctx = r->plugin_ctx[p->id];
|
||||
if (NULL == hctx || r->handler_module != p->self)
|
||||
|
|
|
@ -1766,7 +1766,6 @@ static int server_main_setup (server * const srv, int argc, char **argv) {
|
|||
/* or use the default: we really don't want to hit max-fds */
|
||||
srv->lim_conns = srv->srvconf.max_conns = srv->max_fds/3;
|
||||
}
|
||||
connections_init(srv);
|
||||
|
||||
/* libev backend overwrites our SIGCHLD handler and calls waitpid on SIGCHLD; we want our own SIGCHLD handling. */
|
||||
#ifdef HAVE_SIGACTION
|
||||
|
@ -1969,7 +1968,7 @@ static void server_main_loop (server * const srv) {
|
|||
|
||||
if (graceful_shutdown) {
|
||||
server_graceful_state(srv);
|
||||
if (0 == srv->conns.used && graceful_shutdown) {
|
||||
if (NULL == srv->conns && graceful_shutdown) {
|
||||
/* we are in graceful shutdown phase and all connections are closed
|
||||
* we are ready to terminate without harming anyone */
|
||||
srv_shutdown = 1;
|
||||
|
@ -2035,7 +2034,7 @@ int main (int argc, char **argv) {
|
|||
server_graceful_state(srv);
|
||||
}
|
||||
|
||||
if (0 == srv->conns.used) rc = 0;
|
||||
if (NULL == srv->conns) rc = 0;
|
||||
if (2 == graceful_shutdown) { /* value 2 indicates idle timeout */
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"server stopped after idle timeout");
|
||||
|
|
Loading…
Reference in New Issue