mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-09 08:37:04 +02:00
MEDIUM: channel: implement a zero-copy buffer transfer
bi_swpbuf() swaps the buffer passed in argument with the one attached to the channel, but only if this last one is empty. The idea is to avoid a copy when buffers can simply be swapped.
This commit is contained in:
parent
33cb065348
commit
b034b2598d
@ -43,6 +43,7 @@ unsigned long long __channel_forward(struct channel *chn, unsigned long long byt
|
|||||||
|
|
||||||
/* SI-to-channel functions working with buffers */
|
/* SI-to-channel functions working with buffers */
|
||||||
int bi_putblk(struct channel *chn, const char *str, int len);
|
int bi_putblk(struct channel *chn, const char *str, int len);
|
||||||
|
struct buffer *bi_swpbuf(struct channel *chn, struct buffer *buf);
|
||||||
int bi_putchr(struct channel *chn, char c);
|
int bi_putchr(struct channel *chn, char c);
|
||||||
int bo_inject(struct channel *chn, const char *msg, int len);
|
int bo_inject(struct channel *chn, const char *msg, int len);
|
||||||
int bo_getline(struct channel *chn, char *str, int len);
|
int bo_getline(struct channel *chn, char *str, int len);
|
||||||
|
@ -196,6 +196,51 @@ int bi_putblk(struct channel *chn, const char *blk, int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tries to copy the whole buffer <buf> into the channel's buffer after length
|
||||||
|
* controls. It will only succeed if the target buffer is empty, in which case
|
||||||
|
* it will simply swap the buffers. The buffer not attached to the channel is
|
||||||
|
* returned so that the caller can store it locally. The chn->buf->o and
|
||||||
|
* to_forward pointers are updated. If the output buffer is a dummy buffer or
|
||||||
|
* if it still contains data <buf> is returned, indicating that nothing could
|
||||||
|
* be done. Channel flag READ_PARTIAL is updated if some data can be transferred.
|
||||||
|
* The chunk's length is updated with the number of bytes sent. On errors, NULL
|
||||||
|
* is returned. Note that only buf->i is considered.
|
||||||
|
*/
|
||||||
|
struct buffer *bi_swpbuf(struct channel *chn, struct buffer *buf)
|
||||||
|
{
|
||||||
|
struct buffer *old;
|
||||||
|
|
||||||
|
if (unlikely(channel_input_closed(chn)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!chn->buf->size || !buffer_empty(chn->buf)) {
|
||||||
|
chn->flags |= CF_WAKE_WRITE;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
old = chn->buf;
|
||||||
|
chn->buf = buf;
|
||||||
|
|
||||||
|
if (!buf->i)
|
||||||
|
return old;
|
||||||
|
|
||||||
|
chn->total += buf->i;
|
||||||
|
|
||||||
|
if (chn->to_forward) {
|
||||||
|
unsigned long fwd = buf->i;
|
||||||
|
if (chn->to_forward != CHN_INFINITE_FORWARD) {
|
||||||
|
if (fwd > chn->to_forward)
|
||||||
|
fwd = chn->to_forward;
|
||||||
|
chn->to_forward -= fwd;
|
||||||
|
}
|
||||||
|
b_adv(chn->buf, fwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* notify that some data was read from the SI into the buffer */
|
||||||
|
chn->flags |= CF_READ_PARTIAL;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
/* Gets one text line out of a channel's buffer from a stream interface.
|
/* Gets one text line out of a channel's buffer from a stream interface.
|
||||||
* Return values :
|
* Return values :
|
||||||
* >0 : number of bytes read. Includes the \n if present before len or end.
|
* >0 : number of bytes read. Includes the \n if present before len or end.
|
||||||
|
Loading…
Reference in New Issue
Block a user