MAJOR: buffers: replace buf->r with buf->p + buf->i
This change gets rid of buf->r which is always equal to buf->p + buf->i.
It removed some wrapping detection at a number of places, but required addition
of new relative offset computations at other locations. A large number of places
can be simplified now with extreme care, since most of the time, either the
pointer has to be computed once or we need a difference between the old ->w and
old ->r to compute free space. The cleanup will probably happen with the rewrite
of the buffer_input_* and buffer_output_* functions anyway.
buf->lr still has to move to the struct http_msg and be relative to buf->p
for the rework to be complete.
diff --git a/include/proto/buffers.h b/include/proto/buffers.h
index 0aa1ff3..2b2b2ac 100644
--- a/include/proto/buffers.h
+++ b/include/proto/buffers.h
@@ -62,7 +62,7 @@
buf->analysers = 0;
buf->cons = NULL;
buf->flags = BF_OUT_EMPTY;
- buf->r = buf->lr = buf->p = buf->data;
+ buf->lr = buf->p = buf->data;
}
/*****************************************************************/
@@ -158,63 +158,51 @@
}
/* Return the amount of bytes that can be written into the buffer at once,
- * including reserved space which may be overwritten. This version is optimized
- * to reduce the amount of operations but it's not easy to understand as it is.
- * Drawing a buffer with wrapping data on a paper helps a lot.
+ * including reserved space which may be overwritten.
*/
static inline int buffer_contig_space(const struct buffer *buf)
{
- int space_from_end = buffer_len(buf) - (buf->r - buf->data);
- if (space_from_end < 0) /* data does not wrap */
- space_from_end = buf->r - buf->data;
- return buf->size - space_from_end;
+ const char *left, *right;
+
+ if (buf->data + buf->o <= buf->p)
+ right = buf->data + buf->size;
+ else
+ right = buf->p + buf->size - buf->o;
+
+ left = buffer_wrap_add(buf, buf->p + buf->i);
+ return right - left;
}
+
/* Return the amount of bytes that can be written into the buffer at once,
- * excluding reserved space, which is preserved. Same comment as above for
- * the optimization leading to hardly understandable code.
+ * excluding the amount of reserved space passed in <res>, which is
+ * preserved.
*/
-static inline int buffer_contig_space_res(const struct buffer *buf)
+static inline int buffer_contig_space_with_res(const struct buffer *buf, int res)
{
/* Proceed differently if the buffer is full, partially used or empty.
* The hard situation is when it's partially used and either data or
* reserved space wraps at the end.
*/
- int res = buffer_reserved(buf);
int spare = buf->size - res;
if (buffer_len(buf) >= spare)
spare = 0;
else if (buffer_len(buf)) {
- spare = buffer_wrap_sub(buf, buf->p - buf->o) - res - buf->r;
- if (spare <= 0)
- spare += buf->size;
- spare = buffer_contig_area(buf, buf->r, spare);
+ spare = buffer_contig_space(buf) - res;
+ if (spare < 0)
+ spare = 0;
}
return spare;
}
-/* Same as above, but lets the caller pass the pre-computed value of
- * buffer_reserved() in <res> if it already knows it, to save some
- * computations.
+
+/* Return the amount of bytes that can be written into the buffer at once,
+ * excluding reserved space, which is preserved.
*/
-static inline int buffer_contig_space_with_res(const struct buffer *buf, int res)
+static inline int buffer_contig_space_res(const struct buffer *buf)
{
- /* Proceed differently if the buffer is full, partially used or empty.
- * The hard situation is when it's partially used and either data or
- * reserved space wraps at the end.
- */
- int spare = buf->size - res;
-
- if (buffer_len(buf) >= spare)
- spare = 0;
- else if (buffer_len(buf)) {
- spare = buffer_wrap_sub(buf, buf->p - buf->o) - res - buf->r;
- if (spare <= 0)
- spare += buf->size;
- spare = buffer_contig_area(buf, buf->r, spare);
- }
- return spare;
+ return buffer_contig_space_with_res(buf, buffer_reserved(buf));
}
/* Normalizes a pointer which is supposed to be relative to the beginning of a
@@ -260,7 +248,8 @@
static inline int buffer_work_area(const struct buffer *buf, const char *end)
{
end = buffer_pointer(buf, end);
- if (end == buf->r) /* pointer exactly at end, lets push forwards */
+ if (end == buffer_wrap_add(buf, buf->p + buf->i))
+ /* pointer exactly at end, lets push forwards */
end = buffer_wrap_sub(buf, buf->p - buf->o);
return buffer_count(buf, buf->p, end);
}
@@ -312,7 +301,7 @@
*/
static inline void buffer_flush(struct buffer *buf)
{
- buf->p = buf->r;
+ buf->p = buffer_wrap_add(buf, buf->p + buf->i);
buf->o += buf->i;
buf->i = 0;
if (buf->o)
@@ -328,7 +317,7 @@
buf->o = 0;
buf->i = 0;
buf->to_forward = 0;
- buf->r = buf->lr = buf->p = buf->data;
+ buf->lr = buf->p = buf->data;
buf->flags &= ~(BF_FULL | BF_OUT_EMPTY);
if (!buf->pipe)
buf->flags |= BF_OUT_EMPTY;
@@ -349,10 +338,7 @@
return;
buf->i = 0;
- buf->r = buf->p;
- if (buf->r >= buf->data + buf->size)
- buf->r -= buf->size;
- buf->lr = buf->r;
+ buf->lr = buf->p;
buf->flags &= ~BF_FULL;
if (buffer_len(buf) >= buffer_max_len(buf))
buf->flags |= BF_FULL;
@@ -456,7 +442,7 @@
{
if (!(buf->i | buf->o)) {
/* let's realign the buffer to optimize I/O */
- buf->r = buf->p = buf->lr = buf->data;
+ buf->p = buf->lr = buf->data;
}
return buffer_contig_space(buf);
}
@@ -471,7 +457,7 @@
{
buf->o -= len;
if (buffer_len(buf) == 0)
- buf->r = buf->p = buf->lr = buf->data;
+ buf->p = buf->lr = buf->data;
if (buffer_len(buf) < buffer_max_len(buf))
buf->flags &= ~BF_FULL;
diff --git a/include/types/buffers.h b/include/types/buffers.h
index f250532..5925455 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -180,7 +180,7 @@
int wex; /* expiration date for a write or connect, in ticks */
int rto; /* read timeout, in ticks */
int wto; /* write timeout, in ticks */
- char *r, *lr; /* read ptr, last read */
+ char *lr; /* last read read */
char *p; /* buffer's start pointer, separates in and out data */
unsigned int size; /* buffer size in bytes */
unsigned int i; /* number of input bytes pending for analysis in the buffer */
diff --git a/src/buffers.c b/src/buffers.c
index 41d3624..91a0cbb 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -96,6 +96,8 @@
* success, -2 if the message is larger than the buffer size, or the number of
* bytes available otherwise. The send limit is automatically adjusted with the
* amount of data written. FIXME-20060521: handle unaligned data.
+ * Note: this function appends data to the buffer's output and possibly overwrites
+ * any pending input data which are assumed not to exist.
*/
int buffer_write(struct buffer *buf, const char *msg, int len)
{
@@ -118,10 +120,9 @@
if (len > max)
return max;
- memcpy(buf->r, msg, len);
+ memcpy(buf->p, msg, len);
buf->o += len;
buf->p = buffer_wrap_add(buf, buf->p + len);
- buf->r = buffer_wrap_add(buf, buf->r + len);
buf->total += len;
buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
@@ -146,17 +147,13 @@
if (buf->flags & BF_FULL)
return -1;
- *buf->r = c;
+ *buffer_wrap_add(buf, buf->p + buf->i) = c;
buf->i++;
if (buffer_len(buf) >= buffer_max_len(buf))
buf->flags |= BF_FULL;
buf->flags |= BF_READ_PARTIAL;
- buf->r++;
- if (buf->r - buf->data == buf->size)
- buf->r -= buf->size;
-
if (buf->to_forward >= 1) {
if (buf->to_forward != BUF_INFINITE_FORWARD)
buf->to_forward--;
@@ -201,12 +198,11 @@
/* OK so the data fits in the buffer in one or two blocks */
max = buffer_contig_space_with_res(buf, buf->size - max);
- memcpy(buf->r, blk, MIN(len, max));
+ memcpy(buffer_wrap_add(buf, buf->p + buf->i), blk, MIN(len, max));
if (len > max)
memcpy(buf->data, blk + max, len - max);
buf->i += len;
- buf->r += len;
buf->total += len;
if (buf->to_forward) {
unsigned long fwd = len;
@@ -221,9 +217,6 @@
buf->flags &= ~BF_OUT_EMPTY;
}
- if (buf->r >= buf->data + buf->size)
- buf->r -= buf->size;
-
buf->flags &= ~BF_FULL;
if (buffer_len(buf) >= buffer_max_len(buf))
buf->flags |= BF_FULL;
@@ -335,28 +328,28 @@
delta = len - (end - pos);
- if (delta + b->r >= b->data + b->size)
+ if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size)
return 0; /* no space left */
- if (delta + b->r > buffer_wrap_sub(b, b->p - b->o) &&
- buffer_wrap_sub(b, b->p - b->o) >= b->r && buffer_not_empty(b))
+ if (buffer_not_empty(b) &&
+ delta + buffer_wrap_add(b, b->p + b->i) > buffer_wrap_sub(b, b->p - b->o) &&
+ buffer_wrap_sub(b, b->p - b->o) >= buffer_wrap_add(b, b->p + b->i))
return 0; /* no space left before wrapping data */
/* first, protect the end of the buffer */
- memmove(end + delta, end, b->r - end);
+ memmove(end + delta, end, buffer_wrap_add(b, b->p + b->i) - end);
/* now, copy str over pos */
if (len)
memcpy(pos, str, len);
/* we only move data after the displaced zone */
- if (b->r > pos) b->r += delta;
if (b->lr > pos) b->lr += delta;
b->i += delta;
b->flags &= ~BF_FULL;
if (buffer_len(b) == 0)
- b->r = b->p = b->lr = b->data;
+ b->p = b->lr = b->data;
if (buffer_len(b) >= buffer_max_len(b))
b->flags |= BF_FULL;
@@ -378,11 +371,11 @@
delta = len + 2;
- if (delta + b->r >= b->data + b->size)
+ if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size)
return 0; /* no space left */
/* first, protect the end of the buffer */
- memmove(pos + delta, pos, b->r - pos);
+ memmove(pos + delta, pos, buffer_wrap_add(b, b->p + b->i) - pos);
/* now, copy str over pos */
if (len && str) {
@@ -392,7 +385,6 @@
}
/* we only move data after the displaced zone */
- if (b->r > pos) b->r += delta;
if (b->lr > pos) b->lr += delta;
b->i += delta;
@@ -445,11 +437,11 @@
* empty area is either between buf->r and from or before from or
* after buf->r.
*/
- if (from > buf->r) {
- if (to >= buf->r && to < from)
+ if (from > buffer_wrap_add(buf, buf->p + buf->i)) {
+ if (to >= buffer_wrap_add(buf, buf->p + buf->i) && to < from)
break;
- } else if (from < buf->r) {
- if (to < from || to >= buf->r)
+ } else if (from < buffer_wrap_add(buf, buf->p + buf->i)) {
+ if (to < from || to >= buffer_wrap_add(buf, buf->p + buf->i))
break;
}
@@ -577,8 +569,8 @@
void buffer_dump(FILE *o, struct buffer *b, int from, int to)
{
fprintf(o, "Dumping buffer %p\n", b);
- fprintf(o, " data=%p o=%d i=%d r=%p p=%p lr=%p\n",
- b->data, b->o, b->i, b->r, b->p, b->lr);
+ fprintf(o, " data=%p o=%d i=%d p=%p lr=%p\n",
+ b->data, b->o, b->i, b->p, b->lr);
if (!to || to > buffer_len(b))
to = buffer_len(b);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index e9f9171..d0baa71 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3389,12 +3389,11 @@
chunk_printf(&msg,
" wex=%s\n"
- " data=%p r=%d p=%d lr=%d total=%lld\n",
+ " data=%p p=%d lr=%d total=%lld\n",
sess->req->wex ?
human_time(TICKS_TO_MS(sess->req->wex - now_ms),
TICKS_TO_MS(1000)) : "<NEVER>",
sess->req->data,
- (int)(sess->req->r - sess->req->data),
(int)(sess->req->p - sess->req->data),
(int)(sess->req->lr - sess->req->data),
sess->req->total);
@@ -3419,12 +3418,11 @@
chunk_printf(&msg,
" wex=%s\n"
- " data=%p r=%d p=%d lr=%d total=%lld\n",
+ " data=%p p=%d lr=%d total=%lld\n",
sess->rep->wex ?
human_time(TICKS_TO_MS(sess->rep->wex - now_ms),
TICKS_TO_MS(1000)) : "<NEVER>",
sess->rep->data,
- (int)(sess->rep->r - sess->rep->data),
(int)(sess->rep->p - sess->rep->data),
(int)(sess->rep->lr - sess->rep->data),
sess->rep->total);
diff --git a/src/proto_http.c b/src/proto_http.c
index 06f658e..aebca1b 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1279,7 +1279,7 @@
state = msg->msg_state;
ptr = buf->lr;
- end = buf->r;
+ end = buffer_wrap_add(buf, buf->p + buf->i);
if (unlikely(ptr >= end))
goto http_msg_ood;
@@ -1753,6 +1753,7 @@
{
char *ptr = buf->lr;
char *end = buf->data + buf->size;
+ char *stop = buffer_wrap_add(buf, buf->p + buf->i);
unsigned int chunk = 0;
/* The chunk size is in the following form, though we are only
@@ -1761,7 +1762,7 @@
*/
while (1) {
int c;
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
c = hex2i(*ptr);
if (c < 0) /* not a hex digit anymore */
@@ -1780,7 +1781,7 @@
while (http_is_spht[(unsigned char)*ptr]) {
if (++ptr >= end)
ptr = buf->data;
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
}
@@ -1793,7 +1794,7 @@
if (likely(*ptr == '\r')) {
if (++ptr >= end)
ptr = buf->data;
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
}
@@ -1808,13 +1809,13 @@
/* chunk extension, ends at next CRLF */
if (++ptr >= end)
ptr = buf->data;
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
while (!HTTP_IS_CRLF(*ptr)) {
if (++ptr >= end)
ptr = buf->data;
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
}
/* we have a CRLF now, loop above */
@@ -1860,11 +1861,12 @@
while (1) {
char *p1 = NULL, *p2 = NULL;
char *ptr = buf->lr;
+ char *stop = buffer_wrap_add(buf, buf->p + buf->i);
int bytes;
/* scan current line and stop at LF or CRLF */
while (1) {
- if (ptr == buf->r)
+ if (ptr == stop)
return 0;
if (*ptr == '\n') {
@@ -1974,10 +1976,10 @@
if (buf->i) {
int block1 = buf->i;
int block2 = 0;
- if (buf->r <= buf->p) {
+ if (buf->p + buf->i > buf->data + buf->size) {
/* non-contiguous block */
block1 = buf->data + buf->size - buf->p;
- block2 = buf->r - buf->data;
+ block2 = buf->p + buf->i - (buf->data + buf->size);
}
if (block2)
memcpy(swap_buffer, buf->data, block2);
@@ -1989,7 +1991,6 @@
/* adjust all known pointers */
buf->p = buf->data;
buf->lr += off; if (buf->lr >= end) buf->lr -= buf->size;
- buf->r += off; if (buf->r >= end) buf->r -= buf->size;
msg->sol += off; if (msg->sol >= end) msg->sol -= buf->size;
msg->eol += off; if (msg->eol >= end) msg->eol -= buf->size;
@@ -2066,8 +2067,8 @@
if (buffer_not_empty(req) && msg->msg_state < HTTP_MSG_ERROR) {
if ((txn->flags & TX_NOT_FIRST) &&
unlikely((req->flags & BF_FULL) ||
- req->r < req->lr ||
- req->r > req->data + req->size - global.tune.maxrewrite)) {
+ buffer_wrap_add(req, req->p + req->i) < req->lr ||
+ buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite)) {
if (req->o) {
if (req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
goto failed_keep_alive;
@@ -2076,7 +2077,8 @@
req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */
return 0;
}
- if (req->r < req->lr || req->r > req->data + req->size - global.tune.maxrewrite)
+ if (buffer_wrap_add(req, req->p + req->i) < req->lr ||
+ buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite)
http_buffer_heavy_realign(req, msg);
}
@@ -2089,8 +2091,8 @@
*/
if ((txn->flags & TX_NOT_FIRST) &&
unlikely((s->rep->flags & BF_FULL) ||
- s->rep->r < s->rep->lr ||
- s->rep->r > s->rep->data + s->rep->size - global.tune.maxrewrite)) {
+ buffer_wrap_add(s->rep, s->rep->p + s->rep->i) < s->rep->lr ||
+ buffer_wrap_add(s->rep, s->rep->p + s->rep->i) > s->rep->data + s->rep->size - global.tune.maxrewrite)) {
if (s->rep->o) {
if (s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
goto failed_keep_alive;
@@ -2102,7 +2104,7 @@
}
}
- if (likely(req->lr < req->r))
+ if (likely(req->lr < buffer_wrap_add(req, req->p + req->i)))
http_msg_analyzer(req, msg, &txn->hdr_idx);
}
@@ -2591,7 +2593,7 @@
si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
return 1;
}
- else if (end_params > req->data + req->i) {
+ else if (end_params > req->p + req->i) {
/* we need more data */
si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
return 0;
@@ -3823,7 +3825,7 @@
if (s->req->i) {
if (s->rep->o &&
!(s->rep->flags & BF_FULL) &&
- s->rep->r <= s->rep->data + s->rep->size - global.tune.maxrewrite)
+ buffer_wrap_add(s->rep, s->rep->p + s->rep->i) <= s->rep->data + s->rep->size - global.tune.maxrewrite)
s->rep->flags |= BF_EXPECT_MORE;
}
@@ -4483,8 +4485,8 @@
*/
if (buffer_not_empty(rep) && msg->msg_state < HTTP_MSG_ERROR) {
if (unlikely((rep->flags & BF_FULL) ||
- rep->r < rep->lr ||
- rep->r > rep->data + rep->size - global.tune.maxrewrite)) {
+ buffer_wrap_add(rep, rep->p + rep->i) < rep->lr ||
+ buffer_wrap_add(rep, rep->p + rep->i) > rep->data + rep->size - global.tune.maxrewrite)) {
if (rep->o) {
/* some data has still not left the buffer, wake us once that's done */
if (rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
@@ -4497,7 +4499,7 @@
http_buffer_heavy_realign(rep, msg);
}
- if (likely(rep->lr < rep->r))
+ if (likely(rep->lr < buffer_wrap_add(rep, rep->p + rep->i)))
http_msg_analyzer(rep, msg, &txn->hdr_idx);
}
@@ -7231,15 +7233,15 @@
struct buffer *buf, struct http_msg *msg,
int state, struct proxy *other_end)
{
- if (buf->r <= (buf->data + msg->som)) { /* message wraps */
+ if (buffer_wrap_add(buf, buf->p + buf->i) <= (buf->data + msg->som)) { /* message wraps */
int len1 = buf->size - msg->som;
- es->len = buf->r - (buf->data + msg->som) + buf->size;
+ es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->data + msg->som) + buf->size;
memcpy(es->buf, buf->data + msg->som, MIN(len1, sizeof(es->buf)));
if (es->len > len1 && len1 < sizeof(es->buf))
memcpy(es->buf, buf->data, MIN(es->len, sizeof(es->buf)) - len1);
}
else {
- es->len = buf->r - (buf->data + msg->som);
+ es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->data + msg->som);
memcpy(es->buf, buf->data + msg->som, MIN(es->len, sizeof(es->buf)));
}
@@ -7444,10 +7446,8 @@
* a HEAD with some data, or sending more than the advertised
* content-length.
*/
- if (unlikely(s->rep->i)) {
+ if (unlikely(s->rep->i))
s->rep->i = 0;
- s->rep->r = s->rep->p;
- }
s->req->rto = s->fe->timeout.client;
s->req->wto = TICK_ETERNITY;
@@ -8118,7 +8118,7 @@
}
/* Try to decode HTTP request */
- if (likely(req->lr < req->r))
+ if (likely(req->lr < buffer_wrap_add(req, req->p + req->i)))
http_msg_analyzer(req, msg, &txn->hdr_idx);
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 0d039eb..3d462ab 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -282,23 +282,22 @@
*/
if (buffer_empty(b)) {
/* let's realign the buffer to optimize I/O */
- b->r = b->p = b->lr = b->data;
+ b->p = b->lr = b->data;
}
else if (b->data + b->o < b->p &&
b->p + b->i < b->data + b->size) {
/* remaining space wraps at the end, with a moving limit */
- if (max > b->data + b->size - b->r)
- max = b->data + b->size - b->r;
+ if (max > b->data + b->size - (b->p + b->i))
+ max = b->data + b->size - (b->p + b->i);
}
/* else max is already OK */
/*
* 2. read the largest possible block
*/
- ret = recv(fd, b->r, max, 0);
+ ret = recv(fd, buffer_wrap_add(b, b->p + b->i), max, 0);
if (ret > 0) {
- b->r += ret;
b->i += ret;
cur_read += ret;
@@ -320,11 +319,6 @@
fdtab[fd].state = FD_STREADY;
b->flags |= BF_READ_PARTIAL;
-
- if (b->r == b->data + b->size) {
- b->r = b->data; /* wrap around the buffer */
- }
-
b->total += ret;
if (buffer_len(b) >= buffer_max_len(b)) {
@@ -653,7 +647,7 @@
b->o -= ret;
if (likely(!buffer_len(b)))
/* optimize data alignment in the buffer */
- b->r = b->p = b->lr = b->data;
+ b->lr = b->p = b->data;
if (likely(buffer_len(b) < buffer_max_len(b)))
b->flags &= ~BF_FULL;