[BUG] http: analyser optimizations broke pipelining

HTTP pipelining currently needs to monitor the response buffer to wait
for some free space to be able to send a response. It was not possible
for the HTTP analyser to be called based on response buffer activity.
Now we introduce a new buffer flag BF_WAKE_ONCE which is set when the
HTTP request analyser is set on the response buffer and some activity
is detected. This is not clean at all but once of the only ways to fix
the issue before we make it possible to register events for analysers.

Also it appeared that one realign condition did not cover all cases.
This commit is contained in:
Willy Tarreau 2010-12-17 07:13:42 +01:00
parent 35ed8019e3
commit 0499e3575c
3 changed files with 21 additions and 2 deletions

View File

@ -115,13 +115,15 @@
#define BF_EXPECT_MORE 0x2000000 /* more data expected to be sent very soon (one-shoot) */
#define BF_SEND_DONTWAIT 0x4000000 /* don't wait for sending data (one-shoot) */
#define BF_WAKE_ONCE 0x8000000 /* pretend there is activity on this buffer (one-shoot) */
/* Use these masks to clear the flags before going back to lower layers */
#define BF_CLEAR_READ (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED))
#define BF_CLEAR_WRITE (~(BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR))
#define BF_CLEAR_TIMEOUT (~(BF_READ_TIMEOUT|BF_WRITE_TIMEOUT|BF_ANA_TIMEOUT))
/* Masks which define input events for stream analysers */
#define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY)
#define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY|BF_WAKE_ONCE)
/* Mask for static flags which cause analysers to be woken up when they change */
#define BF_MASK_STATIC (BF_OUT_EMPTY|BF_FULL|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW)

View File

@ -2390,7 +2390,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */
return 0;
}
if (req->l <= req->size - global.tune.maxrewrite)
if (req->r < req->lr || req->r > req->data + req->size - global.tune.maxrewrite)
http_buffer_heavy_realign(req, msg);
}
@ -2411,6 +2411,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
/* don't let a connection request be initiated */
buffer_dont_connect(req);
s->rep->flags &= ~BF_EXPECT_MORE; /* speed up sending a previous response */
s->rep->analysers |= an_bit; /* wake us up once it changes */
return 0;
}
}

View File

@ -1506,6 +1506,7 @@ struct task *process_session(struct task *t)
rq_prod_last = s->si[0].state;
rq_cons_last = s->si[1].state;
s->req->flags &= ~BF_WAKE_ONCE;
rqf_last = s->req->flags;
if ((s->req->flags ^ flags) & BF_MASK_STATIC)
@ -1543,6 +1544,18 @@ struct task *process_session(struct task *t)
s->si[1].state != rp_prod_last) {
unsigned int flags = s->rep->flags;
if ((s->rep->flags & BF_MASK_ANALYSER) &&
(s->rep->analysers & AN_REQ_WAIT_HTTP)) {
/* Due to HTTP pipelining, the HTTP request analyser might be waiting
* for some free space in the response buffer, so we might need to call
* it when something changes in the response buffer, but still we pass
* it the request buffer. Note that the SI state might very well still
* be zero due to us returning a flow of redirects!
*/
s->rep->analysers &= ~AN_REQ_WAIT_HTTP;
s->req->flags |= BF_WAKE_ONCE;
}
if (s->rep->prod->state >= SI_ST_EST) {
int max_loops = global.tune.maxpollevents;
unsigned int ana_list;
@ -1617,6 +1630,9 @@ struct task *process_session(struct task *t)
if (s->req->analysers & ~req_ana_back)
goto resync_request;
if ((s->req->flags & ~rqf_last) & BF_MASK_ANALYSER)
goto resync_request;
/* FIXME: here we should call protocol handlers which rely on
* both buffers.
*/