From: Christopher Faulet Date: Tue, 21 Nov 2023 06:51:45 +0000 (+0100) Subject: MINOR: channel: Use dedicated functions to deal with STREAMER flags X-Git-Tag: v3.0-dev1~136 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a40321eb3b4188ac013db570d104e00d27f7afda;p=thirdparty%2Fhaproxy.git MINOR: channel: Use dedicated functions to deal with STREAMER flags For now, CF_STREAMER and CF_STREAMER_FAST flags are set in sc_conn_recv() function. The logic is moved in dedicated functions. First, channel_check_idletimer() function is now responsible to check the channel's last read date against the idle timer value to be sure the producer is still streaming data. Otherwise, it removes STREAMER flags. Then, channel_check_xfer() function is responsible to check amount of data transferred avec a receive, to eventually update STREAMER flags. In sc_conn_recv(), we now use these functions. --- diff --git a/include/haproxy/channel.h b/include/haproxy/channel.h index 17dd75fba6..1b5c8a06fa 100644 --- a/include/haproxy/channel.h +++ b/include/haproxy/channel.h @@ -818,6 +818,69 @@ static inline size_t channel_empty(const struct channel *chn) return (IS_HTX_STRM(chn) ? htx_is_empty(htxbuf(&chn->buf)) : c_empty(chn)); } +/* Check channel's last_read date against the idle timeer to verify the producer + * is still streaming data or not + */ +static inline void channel_check_idletimer(struct channel *chn) +{ + if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(chn) && + global.tune.idle_timer && + (unsigned short)(now_ms - chn->last_read) >= global.tune.idle_timer) { + /* The buffer was empty and nothing was transferred for more + * than one second. This was caused by a pause and not by + * congestion. Reset any streaming mode to reduce latency. + */ + chn->xfer_small = 0; + chn->xfer_large = 0; + chn->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); + } +} + +/* Check amount of transferred data after a receive. If is greater + * than 0, the date is updated and STREAMER flags for the channels + * are verified. + */ +static inline void channel_check_xfer(struct channel *chn, size_t xferred) +{ + if (!xferred) + return; + + if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) && + (xferred <= c_size(chn) / 2)) { + chn->xfer_large = 0; + chn->xfer_small++; + if (chn->xfer_small >= 3) { + /* we have read less than half of the buffer in + * one pass, and this happened at least 3 times. + * This is definitely not a streamer. + */ + chn->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); + } + else if (chn->xfer_small >= 2) { + /* if the buffer has been at least half full twchne, + * we receive faster than we send, so at least it + * is not a "fast streamer". + */ + chn->flags &= ~CF_STREAMER_FAST; + } + } + else if (!(chn->flags & CF_STREAMER_FAST) && (xferred >= channel_data_limit(chn))) { + /* we read a full buffer at once */ + chn->xfer_small = 0; + chn->xfer_large++; + if (chn->xfer_large >= 3) { + /* we call this buffer a fast streamer if it manages + * to be filled in one call 3 consecutive times. + */ + chn->flags |= (CF_STREAMER | CF_STREAMER_FAST); + } + } + else { + chn->xfer_small = 0; + chn->xfer_large = 0; + } + chn->last_read = now_ms; +} /* Returns the amount of bytes that can be written over the input data at once, * including reserved space which may be overwritten. This is used by Lua to diff --git a/src/stconn.c b/src/stconn.c index 63dd9bf1f3..b3aed9521f 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1251,17 +1251,7 @@ int sc_conn_recv(struct stconn *sc) /* prepare to detect if the mux needs more room */ sc_ep_clr(sc, SE_FL_WANT_ROOM); - if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(ic) && - global.tune.idle_timer && - (unsigned short)(now_ms - ic->last_read) >= global.tune.idle_timer) { - /* The buffer was empty and nothing was transferred for more - * than one second. This was caused by a pause and not by - * congestion. Reset any streaming mode to reduce latency. - */ - ic->xfer_small = 0; - ic->xfer_large = 0; - ic->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); - } + channel_check_idletimer(ic); #if defined(USE_LINUX_SPLICE) /* Detect if the splicing is possible depending on the stream policy */ @@ -1447,41 +1437,7 @@ int sc_conn_recv(struct stconn *sc) if (!cur_read) se_have_no_more_data(sc->sedesc); else { - if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && - (cur_read <= ic->buf.size / 2)) { - ic->xfer_large = 0; - ic->xfer_small++; - if (ic->xfer_small >= 3) { - /* we have read less than half of the buffer in - * one pass, and this happened at least 3 times. - * This is definitely not a streamer. - */ - ic->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); - } - else if (ic->xfer_small >= 2) { - /* if the buffer has been at least half full twice, - * we receive faster than we send, so at least it - * is not a "fast streamer". - */ - ic->flags &= ~CF_STREAMER_FAST; - } - } - else if (!(ic->flags & CF_STREAMER_FAST) && (cur_read >= channel_data_limit(ic))) { - /* we read a full buffer at once */ - ic->xfer_small = 0; - ic->xfer_large++; - if (ic->xfer_large >= 3) { - /* we call this buffer a fast streamer if it manages - * to be filled in one call 3 consecutive times. - */ - ic->flags |= (CF_STREAMER | CF_STREAMER_FAST); - } - } - else { - ic->xfer_small = 0; - ic->xfer_large = 0; - } - ic->last_read = now_ms; + channel_check_xfer(ic, cur_read); sc_ep_report_read_activity(sc); }