From 3da77c5abd3d79046d55663c425491ccc9fbd013 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 29 Aug 2008 09:58:42 +0200 Subject: [PATCH] [MINOR] re-arrange buffer flags and rename some of them The buffer flags became a big bazaar. Re-arrange them so that their names are more explicit and so that they are more easily readable in hex form. Some aggregates have also been adjusted. --- include/proto/buffers.h | 12 ++++++ include/types/buffers.h | 84 +++++++++++++++++++++++++---------------- src/client.c | 2 +- src/proto_http.c | 42 ++++++++++----------- src/proto_uxst.c | 8 ++-- src/senddata.c | 2 +- src/stream_sock.c | 20 +++++----- 7 files changed, 101 insertions(+), 69 deletions(-) diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 194f4ee12..e5df177c0 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -120,6 +120,18 @@ static inline void buffer_stop_hijack(struct buffer *buf) buf->flags &= ~BF_HIJACK; } +/* allows the consumer to send the buffer contents */ +static inline void buffer_write_ena(struct buffer *buf) +{ + buf->flags |= BF_WRITE_ENA; +} + +/* prevents the consumer from sending the buffer contents */ +static inline void buffer_write_dis(struct buffer *buf) +{ + buf->flags &= ~BF_WRITE_ENA; +} + /* returns the maximum number of bytes writable at once in this buffer */ static inline int buffer_max(const struct buffer *buf) { diff --git a/include/types/buffers.h b/include/types/buffers.h index d67c93241..c35ef3716 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -26,53 +26,73 @@ #include /* The BF_* macros designate Buffer Flags, which may be ORed in the bit field - * member 'flags' in struct buffer. Some of them are persistent (BF_SHUT*), - * some of them (BF_EMPTY,BF_FULL) may only be set by the low-level read/write - * functions as well as those who change the buffer's read limit. + * member 'flags' in struct buffer. Here we have several types of flags : + * + * - pure status flags, reported by the lower layer, which must be cleared + * before doing further I/O : + * BF_*_NULL, BF_*_PARTIAL + * + * - pure status flags, reported by mid-layer, which must also be cleared + * before doing further I/O : + * BF_*_TIMEOUT, BF_*_ERROR + * + * - read-only indicators reported by lower levels : + * BF_STREAMER, BF_STREAMER_FAST + * + * - write-once status flags reported by the mid-level : BF_SHUTR, BF_SHUTW + * + * - persistent control flags managed only by higher level : + * BF_SHUT*_NOW, BF_*_ENA, BF_HIJACK + * + * The flags have been arranged for readability, so that the read and write + * bits have se same position in a byte (read being the lower byte and write + * the second one). */ -#define BF_EMPTY 1 /* buffer is empty */ -#define BF_FULL 2 /* buffer cannot accept any more data (l >= rlim-data) */ -#define BF_SHUTR 4 /* producer has already shut down */ -#define BF_SHUTW 8 /* consumer has already shut down */ +#define BF_READ_NULL 0x000001 /* last read detected on producer side */ +#define BF_READ_PARTIAL 0x000002 /* some data were read from producer */ +#define BF_READ_TIMEOUT 0x000004 /* timeout while waiting for producer */ +#define BF_READ_ERROR 0x000008 /* unrecoverable error on producer side */ +#define BF_READ_ACTIVITY (BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR) +#define BF_READ_STATUS (BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_TIMEOUT) +#define BF_CLEAR_READ (~BF_READ_STATUS) -#define BF_PARTIAL_READ 16 -#define BF_COMPLETE_READ 32 -#define BF_READ_ERROR 64 -#define BF_READ_NULL 128 -#define BF_READ_STATUS (BF_PARTIAL_READ|BF_COMPLETE_READ|BF_READ_ERROR|BF_READ_NULL) -#define BF_CLEAR_READ (~BF_READ_STATUS) +#define BF_FULL 0x000010 /* buffer cannot accept any more data (l >= rlim-data) */ +#define BF_SHUTR 0x000020 /* producer has already shut down */ +#define BF_SHUTR_NOW 0x000040 /* the producer must shut down for reads immediately */ +#define BF_READ_ENA 0x000080 /* producer is allowed to feed data into the buffer */ -#define BF_PARTIAL_WRITE 256 -#define BF_COMPLETE_WRITE 512 -#define BF_WRITE_ERROR 1024 -#define BF_WRITE_NULL 2048 -#define BF_WRITE_STATUS (BF_PARTIAL_WRITE|BF_COMPLETE_WRITE|BF_WRITE_ERROR|BF_WRITE_NULL) -#define BF_CLEAR_WRITE (~BF_WRITE_STATUS) +#define BF_WRITE_NULL 0x000100 /* write(0) or connect() succeeded on consumer side */ +#define BF_WRITE_PARTIAL 0x000200 /* some data were written to the consumer */ +#define BF_WRITE_TIMEOUT 0x000400 /* timeout while waiting for consumer */ +#define BF_WRITE_ERROR 0x000800 /* unrecoverable error on consumer side */ +#define BF_WRITE_ACTIVITY (BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR) +#define BF_WRITE_STATUS (BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_WRITE_TIMEOUT) +#define BF_CLEAR_WRITE (~BF_WRITE_STATUS) -#define BF_STREAMER 4096 -#define BF_STREAMER_FAST 8192 +#define BF_EMPTY 0x001000 /* buffer is empty */ +#define BF_SHUTW 0x002000 /* consumer has already shut down */ +#define BF_SHUTW_NOW 0x004000 /* the consumer must shut down for writes immediately */ +#define BF_WRITE_ENA 0x008000 /* consumer is allowed to forward all buffer contents */ -#define BF_MAY_FORWARD 16384 /* consumer side is allowed to forward the data */ -#define BF_READ_TIMEOUT 32768 /* timeout while waiting for producer */ -#define BF_WRITE_TIMEOUT 65536 /* timeout while waiting for consumer */ +#define BF_STREAMER 0x010000 /* the producer is identified as streaming data */ +#define BF_STREAMER_FAST 0x020000 /* the consumer seems to eat the stream very fast */ /* When either BF_SHUTR_NOW or BF_HIJACK is set, it is strictly forbidden for * the stream interface to alter the buffer contents. When BF_SHUTW_NOW is set, * it is strictly forbidden for the stream interface to send anything from the * buffer. */ -#define BF_SHUTR_NOW 131072 /* the producer must shut down for reads ASAP */ -#define BF_SHUTW_NOW 262144 /* the consumer must shut down for writes ASAP */ -#define BF_HIJACK 524288 /* the producer is temporarily replaced */ +#define BF_HIJACK 0x040000 /* the producer is temporarily replaced */ -/* masks which define input bits for stream interfaces and stream analysers */ -#define BF_MASK_INTERFACE_I (BF_FULL|BF_HIJACK|BF_READ_NULL|BF_SHUTR|BF_SHUTR_NOW|BF_SHUTW) -#define BF_MASK_INTERFACE_O (BF_EMPTY|BF_HIJACK|BF_MAY_FORWARD|BF_SHUTR|BF_SHUTW|BF_SHUTW_NOW) +/* Masks which define input bits for stream interfaces and stream analysers */ +#define BF_MASK_INTERFACE_I (BF_FULL|BF_HIJACK|BF_READ_ENA|BF_READ_STATUS|BF_SHUTR_NOW|BF_SHUTR|BF_SHUTW) +#define BF_MASK_INTERFACE_O (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_WRITE_STATUS|BF_SHUTW_NOW|BF_SHUTR|BF_SHUTW) #define BF_MASK_INTERFACE (BF_MASK_INTF_I | BF_MASK_INTF_O) -#define BF_MASK_ANALYSER (BF_FULL|BF_READ_NULL|BF_READ_ERROR|BF_READ_TIMEOUT|BF_SHUTR|BF_WRITE_ERROR) -#define BF_MASK_INJECTER (BF_FULL|BF_WRITE_STATUS|BF_WRITE_TIMEOUT|BF_SHUTW) +#define BF_MASK_ANALYSER (BF_FULL|BF_READ_STATUS|BF_SHUTR|BF_WRITE_ERROR) +#define BF_MASK_HIJACKER (BF_FULL|BF_WRITE_STATUS|BF_WRITE_TIMEOUT|BF_SHUTW) + /* Analysers (buffer->analysers). * Those bits indicate that there are some processing to do on the buffer diff --git a/src/client.c b/src/client.c index 5df5c0dff..606cf79dd 100644 --- a/src/client.c +++ b/src/client.c @@ -347,7 +347,7 @@ int event_accept(int fd) { s->req->analysers |= AN_REQ_HTTP_HDR; if (!s->req->analysers) - s->req->flags |= BF_MAY_FORWARD; /* don't wait to establish connection */ + buffer_write_ena(s->req); /* don't wait to establish connection */ s->req->rto = s->fe->timeout.client; s->req->wto = s->be->timeout.server; diff --git a/src/proto_http.c b/src/proto_http.c index 66f8e169b..1432fe393 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -544,7 +544,7 @@ int http_find_header(const char *name, void srv_close_with_err(struct session *t, int err, int finst, int status, const struct chunk *msg) { - t->rep->flags |= BF_MAY_FORWARD; + buffer_write_ena(t->rep); buffer_shutw(t->req); buffer_shutr(t->rep); if (status > 0 && msg) { @@ -719,13 +719,13 @@ void process_session(struct task *t, int *next) ((rqf_srv ^ s->req->flags) & BF_MASK_INTERFACE_O)) { resync = 1; - if (s->req->cons->state < SI_ST_EST && s->req->flags & BF_MAY_FORWARD) + if (s->req->cons->state < SI_ST_EST && s->req->flags & BF_WRITE_ENA) process_srv_conn(s); if (s->req->cons->state == SI_ST_EST) { - if ((s->req->flags & (BF_SHUTW|BF_EMPTY|BF_MAY_FORWARD)) == (BF_EMPTY|BF_MAY_FORWARD) && + if ((s->req->flags & (BF_SHUTW|BF_EMPTY|BF_WRITE_ENA)) == (BF_EMPTY|BF_WRITE_ENA) && s->be->options & PR_O_FORCE_CLO && - s->rep->flags & BF_READ_STATUS) { + s->rep->flags & BF_READ_ACTIVITY) { /* We want to force the connection to the server to close, * and the server has begun to respond. That's the right * time. @@ -765,7 +765,7 @@ void process_session(struct task *t, int *next) /* the analysers must block it themselves */ if (s->req->prod->state >= SI_ST_EST) { resync = 1; - s->req->flags |= BF_MAY_FORWARD; + buffer_write_ena(s->req); if (s->req->analysers) process_request(s); } @@ -776,7 +776,7 @@ void process_session(struct task *t, int *next) /* In inject mode, we wake up everytime something has * happened on the write side of the buffer. */ - if ((s->rep->flags & (BF_PARTIAL_WRITE|BF_WRITE_ERROR|BF_SHUTW)) && + if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) && !(s->rep->flags & BF_FULL)) { if (produce_content(s) != 0) resync = 1; /* completed, better re-check flags */ @@ -786,7 +786,7 @@ void process_session(struct task *t, int *next) if ((rpf_rep ^ s->rep->flags) & BF_MASK_ANALYSER) { /* the analysers must block it themselves */ resync = 1; - s->rep->flags |= BF_MAY_FORWARD; + buffer_write_ena(s->rep); if (s->rep->analysers) process_response(s); rpf_rep = s->rep->flags; @@ -818,7 +818,7 @@ void process_session(struct task *t, int *next) * request timeout is set and the server has not yet sent a response. */ - if ((s->rep->flags & (BF_MAY_FORWARD|BF_SHUTR)) == 0 && + if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 && (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) s->req->rex = TICK_ETERNITY; @@ -1692,11 +1692,11 @@ void http_msg_analyzer(struct buffer *buf, struct http_msg *msg, struct hdr_idx * - all enabled analysers are called in turn from the lower to the higher * bit. * - if an analyser does not have enough data, it must return without calling - * other ones. It should also probably reset the BF_MAY_FORWARD bit to ensure + * other ones. It should also probably reset the BF_WRITE_ENA bit to ensure * that unprocessed data will not be forwarded. But that probably depends on * the protocol. Generally it is not reset in case of errors. * - if an analyser has enough data, it just has to pass on to the next - * analyser without touching BF_MAY_FORWARD (it is enabled prior to + * analyser without touching BF_WRITE_ENA (it is enabled prior to * analysis). * - if an analyser thinks it has no added value anymore staying here, it must * reset its bit from the analysers flags in order not to be called anymore. @@ -1773,7 +1773,7 @@ int process_request(struct session *t) if (rule->cond) { ret = acl_exec_cond(rule->cond, t->fe, t, NULL, ACL_DIR_REQ | partial); if (ret == ACL_PAT_MISS) { - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); /* just set the request timeout once at the beginning of the request */ if (!tick_isset(req->analyse_exp)) req->analyse_exp = tick_add_ifset(now_ms, t->fe->tcp_req.inspect_delay); @@ -1931,7 +1931,7 @@ int process_request(struct session *t) return 0; } - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); /* just set the request timeout once at the beginning of the request */ if (!tick_isset(req->analyse_exp)) req->analyse_exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq); @@ -2519,7 +2519,7 @@ int process_request(struct session *t) ctx.idx = 0; http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx); if (ctx.idx && ctx.vlen >= 7 && strncasecmp(ctx.line+ctx.val, "chunked", 7) == 0) { - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); req->analysers |= AN_REQ_HTTP_BODY; } else { @@ -2542,7 +2542,7 @@ int process_request(struct session *t) hint = t->be->url_param_post_limit; /* now do we really need to buffer more data? */ if (len < hint) { - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); req->analysers |= AN_REQ_HTTP_BODY; } /* else... There are no body bytes to wait for */ @@ -2569,7 +2569,7 @@ int process_request(struct session *t) /* flush the request so that we can drop the connection early * if the client closes first. */ - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); req->analysers |= AN_REQ_HTTP_TARPIT; req->analyse_exp = tick_add_ifset(now_ms, t->be->timeout.tarpit); if (!req->analyse_exp) @@ -2700,7 +2700,7 @@ int process_request(struct session *t) * request timeout once at the beginning of the * request. */ - req->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(req); if (!tick_isset(req->analyse_exp)) req->analyse_exp = tick_add_ifset(now_ms, t->fe->timeout.httpreq); return 0; @@ -2907,7 +2907,7 @@ int process_response(struct session *t) return 0; } - rep->flags &= ~BF_MAY_FORWARD; + buffer_write_dis(rep); return 0; } @@ -3464,7 +3464,7 @@ int tcp_connection_status(struct session *t) if ((req->flags & BF_SHUTW_NOW) || (rep->flags & BF_SHUTW) || ((req->flags & BF_SHUTR) && /* FIXME: this should not prevent a connection from establishing */ - ((req->flags & BF_EMPTY && !(req->flags & BF_WRITE_STATUS)) || + ((req->flags & BF_EMPTY && !(req->flags & BF_WRITE_ACTIVITY)) || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ trace_term(t, TT_HTTP_SRV_5); @@ -3495,7 +3495,7 @@ int tcp_connection_status(struct session *t) if (!req->cons->err_type) req->cons->err_type = SI_ET_CONN_ERR; } - else if (!(req->flags & BF_WRITE_STATUS)) { + else if (!(req->flags & BF_WRITE_ACTIVITY)) { /* nothing happened, maybe we timed out */ if (tick_is_expired(req->wex, now_ms)) { conn_err = SI_ET_CONN_TO; @@ -3616,7 +3616,7 @@ int tcp_connection_status(struct session *t) } if (!rep->analysers) - t->rep->flags |= BF_MAY_FORWARD; + buffer_write_ena(t->rep); req->wex = TICK_ETERNITY; return 0; } @@ -3809,7 +3809,7 @@ int stream_sock_connect_server(struct session *t) /* * Tries to establish a connection to the server and associate it to the * request buffer's consumer side. It is assumed that this function will not be - * be called with SI_ST_EST nor with BF_MAY_FORWARD cleared. It normally + * be called with SI_ST_EST nor with BF_WRITE_ENA cleared. It normally * returns zero, but may return 1 if it absolutely wants to be called again. */ int process_srv_conn(struct session *t) diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 050c38a53..2185f9ff7 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -867,7 +867,7 @@ static int process_uxst_srv(struct session *t) else if (s == SV_STCONN) { /* connection in progress */ if (c == CL_STCLOSE || c == CL_STSHUTW || (c == CL_STSHUTR && - ((t->req->flags & BF_EMPTY && !(req->flags & BF_WRITE_STATUS)) || + ((t->req->flags & BF_EMPTY && !(req->flags & BF_WRITE_ACTIVITY)) || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ tv_eternity(&req->cex); fd_delete(t->srv_fd); @@ -877,11 +877,11 @@ static int process_uxst_srv(struct session *t) srv_close_with_err(t, SN_ERR_CLICL, SN_FINST_C); return 1; } - if (!(req->flags & BF_WRITE_STATUS) && !tv_isle(&req->cex, &now)) { + if (!(req->flags & BF_WRITE_ACTIVITY) && !tv_isle(&req->cex, &now)) { //fprintf(stderr,"1: c=%d, s=%d, now=%d.%06d, exp=%d.%06d\n", c, s, now.tv_sec, now.tv_usec, req->cex.tv_sec, req->cex.tv_usec); return 0; /* nothing changed */ } - else if (!(req->flags & BF_WRITE_STATUS) || (req->flags & BF_WRITE_ERROR)) { + else if (!(req->flags & BF_WRITE_ACTIVITY) || (req->flags & BF_WRITE_ERROR)) { /* timeout, asynchronous connect error or first write error */ //fprintf(stderr,"2: c=%d, s=%d\n", c, s); @@ -889,7 +889,7 @@ static int process_uxst_srv(struct session *t) if (t->srv) t->srv->cur_sess--; - if (!(req->flags & BF_WRITE_STATUS)) + if (!(req->flags & BF_WRITE_ACTIVITY)) conn_err = SN_ERR_SRVTO; // it was a connect timeout. else conn_err = SN_ERR_SRVCL; // it was an asynchronous connect error. diff --git a/src/senddata.c b/src/senddata.c index dea2c9674..5d4b8a6be 100644 --- a/src/senddata.c +++ b/src/senddata.c @@ -60,7 +60,7 @@ void client_retnclose(struct session *s, const struct chunk *msg) buffer_write(s->rep, msg->str, msg->len); s->rep->wex = tick_add_ifset(now_ms, s->rep->wto); - s->rep->flags |= BF_MAY_FORWARD; + buffer_write_ena(s->rep); } diff --git a/src/stream_sock.c b/src/stream_sock.c index 0b935314a..4ddb121c8 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -112,7 +112,7 @@ int stream_sock_read(int fd) { b->r += ret; b->l += ret; cur_read += ret; - b->flags |= BF_PARTIAL_READ; + b->flags |= BF_READ_PARTIAL; b->flags &= ~BF_EMPTY; if (b->r == b->data + BUFSIZE) { @@ -233,10 +233,10 @@ int stream_sock_read(int fd) { * have at least read something. */ - if (tick_isset(b->rex) && b->flags & BF_PARTIAL_READ) + if (tick_isset(b->rex) && b->flags & BF_READ_PARTIAL) b->rex = tick_add_ifset(now_ms, b->rto); - if (!(b->flags & BF_READ_STATUS)) + if (!(b->flags & BF_READ_ACTIVITY)) goto out_skip_wakeup; out_wakeup: task_wakeup(fdtab[fd].owner); @@ -352,7 +352,7 @@ int stream_sock_write(int fd) { b->l -= ret; b->w += ret; - b->flags |= BF_PARTIAL_WRITE; + b->flags |= BF_WRITE_PARTIAL; if (b->l < b->rlim - b->data) b->flags &= ~BF_FULL; @@ -395,7 +395,7 @@ int stream_sock_write(int fd) { * written something. */ - if (tick_isset(b->wex) && b->flags & BF_PARTIAL_WRITE) { + if (tick_isset(b->wex) && b->flags & BF_WRITE_PARTIAL) { b->wex = tick_add_ifset(now_ms, b->wto); if (tick_isset(b->wex)) { /* FIXME: to prevent the client from expiring read timeouts during writes, @@ -408,7 +408,7 @@ int stream_sock_write(int fd) { } out_may_wakeup: - if (!(b->flags & BF_WRITE_STATUS)) + if (!(b->flags & BF_WRITE_ACTIVITY)) goto out_skip_wakeup; out_wakeup: task_wakeup(fdtab[fd].owner); @@ -533,7 +533,7 @@ int stream_sock_data_update(int fd) if (!(ob->flags & BF_SHUTW)) { /* Forced write-shutdown or other end closed with empty buffer. */ if ((ob->flags & BF_SHUTW_NOW) || - (ob->flags & (BF_EMPTY|BF_HIJACK|BF_MAY_FORWARD|BF_SHUTR)) == (BF_EMPTY|BF_MAY_FORWARD|BF_SHUTR)) { + (ob->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) == (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)) { //trace_term(t, TT_HTTP_SRV_11); buffer_shutw(ob); if (ib->flags & BF_SHUTR) { @@ -582,7 +582,7 @@ int stream_sock_data_finish(int fd) * update it if is was not yet set, or if we already got some read status. */ EV_FD_COND_S(fd, DIR_RD); - if (!tick_isset(ib->rex) || ib->flags & BF_READ_STATUS) + if (!tick_isset(ib->rex) || ib->flags & BF_READ_ACTIVITY) ib->rex = tick_add_ifset(now_ms, ib->rto); } } @@ -591,7 +591,7 @@ int stream_sock_data_finish(int fd) if (!(ob->flags & BF_SHUTW)) { /* Write not closed, update FD status and timeout for writes */ if ((ob->flags & BF_EMPTY) || - (ob->flags & (BF_HIJACK|BF_MAY_FORWARD)) == 0) { + (ob->flags & (BF_HIJACK|BF_WRITE_ENA)) == 0) { /* stop writing */ EV_FD_COND_C(fd, DIR_WR); ob->wex = TICK_ETERNITY; @@ -602,7 +602,7 @@ int stream_sock_data_finish(int fd) * update it if is was not yet set, or if we already got some write status. */ EV_FD_COND_S(fd, DIR_WR); - if (!tick_isset(ob->wex) || ob->flags & BF_WRITE_STATUS) { + if (!tick_isset(ob->wex) || ob->flags & BF_WRITE_ACTIVITY) { ob->wex = tick_add_ifset(now_ms, ob->wto); if (tick_isset(ob->wex) && !(ib->flags & BF_SHUTR) && tick_isset(ib->rex)) { /* Note: depending on the protocol, we don't know if we're waiting