mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-14 07:21:01 +01:00
MINOR: mux-h2: add rxbuf head/tail/count management for h2s
Now the h2s get their rx_head, rx_tail and rx_count associated with the shared rxbufs. A few functions are provided to manipulate all this, essentially allocate/release a buffer for the stream, return a buffer pointer to the head/tail, counting allocated buffers for the stream and reporting if a stream may still allocate. For now this code is not used.
This commit is contained in:
parent
a891534bfd
commit
8cf418811d
94
src/mux_h2.c
94
src/mux_h2.c
@ -117,6 +117,9 @@ struct h2s {
|
||||
uint64_t curr_rx_ofs; /* stream offset at which next FC-data will arrive (includes padding) */
|
||||
uint64_t last_adv_ofs; /* stream offset corresponding to last emitted WU */
|
||||
uint64_t next_max_ofs; /* max stream offset that next WU must permit (curr_rx_ofs+rx_win) */
|
||||
uint rx_head, rx_tail; /* head and tail of rx buffer in the conn's shared rx buf */
|
||||
uint rx_count; /* total number of allocated rxbufs */
|
||||
/* 4 bytes hole here */
|
||||
struct buffer rxbuf; /* receive buffer, always valid (buf_empty or real buffer) */
|
||||
struct wait_event *subs; /* recv wait_event the stream connector associated is waiting on (via h2_subscribe) */
|
||||
struct list list; /* To be used when adding in h2c->send_list or h2c->fctl_lsit */
|
||||
@ -692,6 +695,94 @@ static inline int h2c_max_concurrent_streams(const struct h2c *h2c)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the oldest rxbuf of the stream, or NULL if there is
|
||||
* none. Note that this doesn't indicate that the buffer is allocated nor
|
||||
* contains any data.
|
||||
*/
|
||||
static inline struct buffer *h2s_rxbuf_head(const struct h2s *h2s)
|
||||
{
|
||||
if (!h2s->rx_head)
|
||||
return NULL;
|
||||
return &h2s->h2c->shared_rx_bufs[h2s->rx_head].buf;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the newest rxbuf of the stream, or NULL if there is
|
||||
* none. Note that this doesn't indicate that the buffer is allocated nor
|
||||
* contains any data.
|
||||
*/
|
||||
static inline struct buffer *h2s_rxbuf_tail(const struct h2s *h2s)
|
||||
{
|
||||
if (!h2s->rx_tail)
|
||||
return NULL;
|
||||
return &h2s->h2c->shared_rx_bufs[h2s->rx_tail].buf;
|
||||
}
|
||||
|
||||
/* Returns the number of allocated rxbuf slots for the stream */
|
||||
static inline uint h2s_rxbuf_cnt(const struct h2s *h2s)
|
||||
{
|
||||
return h2s->rx_count;
|
||||
}
|
||||
|
||||
/* Tries to get an rxbuf slot from the connection for the stream, returns its
|
||||
* non-zero number on success, or 0 on failure. On success, it will update the
|
||||
* stream's tail and count, and possibly head (if there was no buffer before).
|
||||
* The buffer cell is not initialized, it's up to the caller to do it.
|
||||
*/
|
||||
static inline uint h2s_get_rxbuf(struct h2s *h2s)
|
||||
{
|
||||
uint slot;
|
||||
|
||||
/* FIXME: for now each stream is granted exactly one buffer */
|
||||
if (h2s->rx_count)
|
||||
return 0;
|
||||
|
||||
slot = bl_get(h2s->h2c->shared_rx_bufs, h2s->rx_tail);
|
||||
if (!slot)
|
||||
return 0;
|
||||
|
||||
h2s->rx_count++;
|
||||
h2s->rx_tail = slot;
|
||||
if (!h2s->rx_head)
|
||||
h2s->rx_head = slot;
|
||||
return slot;
|
||||
}
|
||||
|
||||
/* Gives back the oldest rxbuf to the connection. It's the caller's
|
||||
* responsibility to make sure that the possible buffer there was released
|
||||
* prior to calling this function (it may change in the future). It's safe
|
||||
* to call this if no rxbufs are allocated. The index of the next remaining
|
||||
* rxbuf slot is returned, or 0 when none remain.
|
||||
*/
|
||||
static inline uint h2s_put_rxbuf(struct h2s *h2s)
|
||||
{
|
||||
if (h2s->rx_head) {
|
||||
BUG_ON_HOT(({ const struct buffer *buf = h2s_rxbuf_head(h2s); !!(buf && b_size(buf)); }),
|
||||
"Attempted to release a used buffer slot");
|
||||
h2s->rx_head = bl_put(h2s->h2c->shared_rx_bufs, h2s->rx_head);
|
||||
if (!h2s->rx_head)
|
||||
h2s->rx_tail = 0;
|
||||
h2s->rx_count--;
|
||||
}
|
||||
return h2s->rx_head;
|
||||
}
|
||||
|
||||
/* Checks if the the HTX rxbuf still has available room. Returns 1 if OK, 0 if
|
||||
* it's full. The buffer is cast to HTX for the operation, but no buffer is
|
||||
* allocated if there is none (in which case 0 is returned).
|
||||
*/
|
||||
static inline int h2s_may_append_to_rxbuf(const struct h2s *h2s)
|
||||
{
|
||||
struct buffer *rxbuf;
|
||||
struct htx *htx;
|
||||
|
||||
rxbuf = h2s_rxbuf_tail(h2s);
|
||||
if (!rxbuf || b_is_null(rxbuf))
|
||||
return 0;
|
||||
|
||||
htx = htxbuf(rxbuf);
|
||||
return !!htx_free_data_space(htx);
|
||||
}
|
||||
|
||||
/* update h2c timeout if needed */
|
||||
static void h2c_update_timeout(struct h2c *h2c)
|
||||
{
|
||||
@ -1709,6 +1800,9 @@ static struct h2s *h2s_new(struct h2c *h2c, int id)
|
||||
h2s->status = 0;
|
||||
h2s->body_len = 0;
|
||||
h2s->rxbuf = BUF_NULL;
|
||||
h2s->rx_tail = 0;
|
||||
h2s->rx_head = 0;
|
||||
h2s->rx_count = 0;
|
||||
memset(h2s->upgrade_protocol, 0, sizeof(h2s->upgrade_protocol));
|
||||
|
||||
h2s->by_id.key = h2s->id = id;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user