From d7704b5343b27a116505528a15c1ded08f44cbdb Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 4 Sep 2008 11:51:16 +0200 Subject: [PATCH] [MINOR] add an expiration flag to the stream_sock_interface This expiration flag is used to indicate that the timer has expired without having to check it everywhere. --- include/proto/stream_sock.h | 2 +- include/types/stream_interface.h | 7 ++++ src/client.c | 2 ++ src/proto_http.c | 9 +++-- src/stream_sock.c | 57 +++++--------------------------- 5 files changed, 25 insertions(+), 52 deletions(-) diff --git a/include/proto/stream_sock.h b/include/proto/stream_sock.h index d005be56f7..7a2dd3d528 100644 --- a/include/proto/stream_sock.h +++ b/include/proto/stream_sock.h @@ -33,11 +33,11 @@ /* main event functions used to move data between sockets and buffers */ int stream_sock_read(int fd); int stream_sock_write(int fd); -int stream_sock_data_check_timeouts(int fd); int stream_sock_data_update(int fd); int stream_sock_data_finish(int fd); int stream_sock_shutr(struct stream_interface *si); int stream_sock_shutw(struct stream_interface *si); +int stream_sock_check_timeouts(struct stream_interface *si); /* This either returns the sockname or the original destination address. Code diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index ba8d7a76ee..ba1a36dcb4 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -56,11 +56,18 @@ enum { SI_ET_DATA_ABRT = 0x0200, /* data phase aborted by external cause */ }; +/* flags set after I/O */ +enum { + SI_FL_NONE = 0x0000, /* nothing */ + SI_FL_EXP = 0x0001, /* timeout has expired */ +}; + struct stream_interface { unsigned int state; /* SI_ST* */ unsigned int prev_state;/* SI_ST*, copy of previous state */ void *owner; /* generally a (struct task*) */ int fd; /* file descriptor for a stream driver when known */ + unsigned int flags; /* SI_FL_*, must be cleared before I/O */ unsigned int exp; /* wake up time for connect, queue, turn-around, ... */ int (*shutr)(struct stream_interface *); /* shutr function */ int (*shutw)(struct stream_interface *); /* shutw function */ diff --git a/src/client.c b/src/client.c index 547e215da2..d56a33ec0d 100644 --- a/src/client.c +++ b/src/client.c @@ -177,6 +177,7 @@ int event_accept(int fd) { s->si[0].shutr = stream_sock_shutr; s->si[0].shutw = stream_sock_shutw; s->si[0].fd = cfd; + s->si[0].flags = SI_FL_NONE; s->si[0].exp = TICK_ETERNITY; s->cli_fd = cfd; @@ -188,6 +189,7 @@ int event_accept(int fd) { s->si[1].shutw = stream_sock_shutw; s->si[1].exp = TICK_ETERNITY; s->si[1].fd = -1; /* just to help with debugging */ + s->si[1].flags = SI_FL_NONE; s->srv = s->prev_srv = s->srv_conn = NULL; s->pend_pos = NULL; diff --git a/src/proto_http.c b/src/proto_http.c index d5760aedd7..9b3d0bc6c8 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -659,10 +659,12 @@ void process_session(struct task *t, int *next) unsigned int rqf_cli, rpf_cli; unsigned int rqf_srv, rpf_srv; - /* Check timeouts only during data phase for now */ + /* 1: Check timeouts only during data phase for now */ if (unlikely(t->state & TASK_WOKEN_TIMER)) { buffer_check_timeouts(s->req); buffer_check_timeouts(s->rep); + stream_sock_check_timeouts(&s->si[0]); + stream_sock_check_timeouts(&s->si[1]); if (unlikely(s->req->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) { if (s->req->flags & BF_READ_TIMEOUT) { @@ -690,7 +692,7 @@ void process_session(struct task *t, int *next) */ } - /* Check if we need to close the write side. This can only happen + /* 2: Check if we need to close the write side. This can only happen * when either SHUTR or EMPTY appears, because WRITE_ENA cannot appear * from low level, and neither HIJACK nor SHUTW can disappear from low * level. @@ -705,7 +707,7 @@ void process_session(struct task *t, int *next) s->rep->cons->shutw(s->rep->cons); } - /* When a server-side connection is released, we have to + /* 3: When a server-side connection is released, we have to * count it and check for pending connections on this server. */ if (unlikely(s->req->cons->state == SI_ST_CLO && @@ -907,6 +909,7 @@ void process_session(struct task *t, int *next) s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT; s->si[0].prev_state = s->si[0].state; s->si[1].prev_state = s->si[1].state; + s->si[0].flags = s->si[1].flags = 0; /* Trick: if a request is being waiting for the server to respond, * and if we know the server can timeout, we don't want the timeout diff --git a/src/stream_sock.c b/src/stream_sock.c index efc33a6ef8..3418e985d3 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -534,56 +534,17 @@ int stream_sock_shutr(struct stream_interface *si) } /* - * This function only has to be called once after a wakeup event during a data - * phase. It controls the file descriptor's status, as well as read and write - * timeouts. + * This function only has to be called once after a wakeup event in case of + * suspected timeout. It controls the stream interface timeouts and sets + * si->flags accordingly. It does NOT close anything, as this timeout may + * be used for any purpose. It returns 1 if the timeout fired, otherwise + * zero. */ -int stream_sock_data_check_timeouts(int fd) +int stream_sock_check_timeouts(struct stream_interface *si) { - struct buffer *ib = fdtab[fd].cb[DIR_RD].b; - struct buffer *ob = fdtab[fd].cb[DIR_WR].b; - - DPRINTF(stderr,"[%u] %s: fd=%d owner=%p ib=%p, ob=%p, exp(r,w)=%u,%u ibf=%08x obf=%08x ibl=%d obl=%d\n", - now_ms, __FUNCTION__, - fd, fdtab[fd].owner, - ib, ob, - ib->rex, ob->wex, - ib->flags, ob->flags, - ib->l, ob->l); - - /* Read timeout */ - if (unlikely(!(ib->flags & (BF_SHUTR|BF_READ_TIMEOUT)) && tick_is_expired(ib->rex, now_ms))) { - //trace_term(t, TT_HTTP_SRV_12); - ib->flags |= BF_READ_TIMEOUT; - if (!ob->cons->err_type) { - //ob->cons->err_loc = t->srv; - ob->cons->err_type = SI_ET_DATA_TO; - } - buffer_shutr(ib); - if (ob->flags & BF_SHUTW) { - do_close_and_return: - fd_delete(fd); - ob->cons->state = SI_ST_CLO; - return 0; - } - - EV_FD_CLR(fd, DIR_RD); - } - - /* Write timeout */ - if (unlikely(!(ob->flags & (BF_SHUTW|BF_WRITE_TIMEOUT)) && tick_is_expired(ob->wex, now_ms))) { - //trace_term(t, TT_HTTP_SRV_13); - ob->flags |= BF_WRITE_TIMEOUT; - if (!ob->cons->err_type) { - //ob->cons->err_loc = t->srv; - ob->cons->err_type = SI_ET_DATA_TO; - } - buffer_shutw(ob); - if (ib->flags & BF_SHUTR) - goto do_close_and_return; - - EV_FD_CLR(fd, DIR_WR); - shutdown(fd, SHUT_WR); + if (tick_is_expired(si->exp, now_ms)) { + si->flags |= SI_FL_EXP; + return 1; } return 0; } -- 2.39.5