Commit 1a3b2cf3 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add http_Read() which reads from a socket but soaks up any prefeched

tail first and use it all the places where this logic was explicit
before.

Fix Refcounting on objects when we insert/deliver



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@485 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 65787f03
...@@ -260,6 +260,7 @@ int FetchHeaders(struct worker *w, struct sess *sp); ...@@ -260,6 +260,7 @@ int FetchHeaders(struct worker *w, struct sess *sp);
/* cache_hash.c */ /* cache_hash.c */
struct object *HSH_Lookup(struct sess *sp); struct object *HSH_Lookup(struct sess *sp);
void HSH_Unbusy(struct object *o); void HSH_Unbusy(struct object *o);
void HSH_Ref(struct object *o);
void HSH_Deref(struct object *o); void HSH_Deref(struct object *o);
void HSH_Init(void); void HSH_Init(void);
...@@ -270,6 +271,7 @@ int http_GetHdrField(struct http *hp, const char *hdr, const char *field, char * ...@@ -270,6 +271,7 @@ int http_GetHdrField(struct http *hp, const char *hdr, const char *field, char *
int http_GetStatus(struct http *hp); int http_GetStatus(struct http *hp);
int http_HdrIs(struct http *hp, const char *hdr, const char *val); int http_HdrIs(struct http *hp, const char *hdr, const char *val);
int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_GetTail(struct http *hp, unsigned len, char **b, char **e);
int http_Read(struct http *hp, int fd, char *b, unsigned len);
void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg);
int http_DissectRequest(struct http *sp, int fd); int http_DissectRequest(struct http *sp, int fd);
int http_DissectResponse(struct http *sp, int fd); int http_DissectResponse(struct http *sp, int fd);
......
...@@ -62,6 +62,8 @@ cnt_deliver(struct sess *sp) ...@@ -62,6 +62,8 @@ cnt_deliver(struct sess *sp)
{ {
vca_write_obj(sp->wrk, sp); vca_write_obj(sp->wrk, sp);
HSH_Deref(sp->obj);
sp->obj = NULL;
sp->step = STP_DONE; sp->step = STP_DONE;
return (0); return (0);
} }
...@@ -82,6 +84,7 @@ cnt_done(struct sess *sp) ...@@ -82,6 +84,7 @@ cnt_done(struct sess *sp)
{ {
char *b; char *b;
assert(sp->obj == NULL);
if (http_GetHdr(sp->http, "Connection", &b) && if (http_GetHdr(sp->http, "Connection", &b) &&
!strcmp(b, "close")) { !strcmp(b, "close")) {
vca_close_session(sp, "Connection header"); vca_close_session(sp, "Connection header");
...@@ -182,6 +185,7 @@ cnt_fetch(struct sess *sp) ...@@ -182,6 +185,7 @@ cnt_fetch(struct sess *sp)
sp->obj->pass = 1; sp->obj->pass = 1;
sp->obj->cacheable = 1; sp->obj->cacheable = 1;
HSH_Unbusy(sp->obj); HSH_Unbusy(sp->obj);
/* Don't HSH_Deref(sp->obj); we need the ref for storage */
sp->obj = NULL; sp->obj = NULL;
sp->step = STP_PASSBODY; sp->step = STP_PASSBODY;
return (0); return (0);
...@@ -189,6 +193,8 @@ cnt_fetch(struct sess *sp) ...@@ -189,6 +193,8 @@ cnt_fetch(struct sess *sp)
if (sp->handling == VCL_RET_INSERT) { if (sp->handling == VCL_RET_INSERT) {
sp->obj->cacheable = 1; sp->obj->cacheable = 1;
FetchBody(sp->wrk, sp); FetchBody(sp->wrk, sp);
HSH_Ref(sp->obj); /* get another, STP_DELIVER will deref */
HSH_Unbusy(sp->obj);
sp->step = STP_DELIVER; sp->step = STP_DELIVER;
return (0); return (0);
} }
...@@ -510,6 +516,8 @@ cnt_recv(struct sess *sp) ...@@ -510,6 +516,8 @@ cnt_recv(struct sess *sp)
sp->vcl = VCL_Get(); sp->vcl = VCL_Get();
SES_RefSrcAddr(sp); SES_RefSrcAddr(sp);
assert(sp->obj == NULL);
done = http_DissectRequest(sp->http, sp->fd); done = http_DissectRequest(sp->http, sp->fd);
if (done != 0) { if (done != 0) {
RES_Error(sp->wrk, sp, done, NULL); RES_Error(sp->wrk, sp, done, NULL);
......
...@@ -33,7 +33,6 @@ static int ...@@ -33,7 +33,6 @@ static int
fetch_straight(const struct sess *sp, int fd, struct http *hp, char *b) fetch_straight(const struct sess *sp, int fd, struct http *hp, char *b)
{ {
int i; int i;
char *e;
unsigned char *p; unsigned char *p;
off_t cl; off_t cl;
struct storage *st; struct storage *st;
...@@ -50,15 +49,8 @@ fetch_straight(const struct sess *sp, int fd, struct http *hp, char *b) ...@@ -50,15 +49,8 @@ fetch_straight(const struct sess *sp, int fd, struct http *hp, char *b)
i &= ~O_NONBLOCK; i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i); i = fcntl(fd, F_SETFL, i);
if (http_GetTail(hp, cl, &b, &e)) {
i = e - b;
memcpy(p, b, i);
p += i;
cl -= i;
}
while (cl != 0) { while (cl != 0) {
i = read(fd, p, cl); i = http_Read(hp, fd, p, cl);
assert(i > 0); /* XXX seen */ assert(i > 0); /* XXX seen */
p += i; p += i;
cl -= i; cl -= i;
...@@ -73,7 +65,7 @@ static int ...@@ -73,7 +65,7 @@ static int
fetch_chunked(const struct sess *sp, int fd, struct http *hp) fetch_chunked(const struct sess *sp, int fd, struct http *hp)
{ {
int i; int i;
char *b, *q, *e; char *q;
unsigned char *p; unsigned char *p;
struct storage *st; struct storage *st;
unsigned u, v; unsigned u, v;
...@@ -88,16 +80,10 @@ fetch_chunked(const struct sess *sp, int fd, struct http *hp) ...@@ -88,16 +80,10 @@ fetch_chunked(const struct sess *sp, int fd, struct http *hp)
bp = buf; bp = buf;
st = NULL; st = NULL;
while (1) { while (1) {
if (http_GetTail(hp, be - bp, &b, &e)) { i = http_Read(hp, fd, bp, be - bp);
memcpy(bp, b, e - b); assert(i >= 0);
bp += e - b; bp += i;
*bp = '\0'; *bp = '\0';
} else {
i = read(fd, bp, be - bp);
assert(i >= 0);
bp += i;
*bp = '\0';
}
u = strtoul(buf, &q, 16); u = strtoul(buf, &q, 16);
if (q == NULL || q == buf) if (q == NULL || q == buf)
continue; continue;
...@@ -151,15 +137,8 @@ fetch_chunked(const struct sess *sp, int fd, struct http *hp) ...@@ -151,15 +137,8 @@ fetch_chunked(const struct sess *sp, int fd, struct http *hp)
break; break;
if (v == 0) if (v == 0)
continue; continue;
if (http_GetTail(hp, v, &b, &e)) {
memcpy(p, b, e - b);
p += e - b;
st->len += e - b;
v -= e - b;
u -= e - b;
}
while (v > 0) { while (v > 0) {
i = read(fd, p, v); i = http_Read(hp, fd, p, v);
assert(i > 0); assert(i > 0);
st->len += i; st->len += i;
v -= i; v -= i;
...@@ -183,7 +162,6 @@ static int ...@@ -183,7 +162,6 @@ static int
fetch_eof(const struct sess *sp, int fd, struct http *hp) fetch_eof(const struct sess *sp, int fd, struct http *hp)
{ {
int i; int i;
char *b, *e;
unsigned char *p; unsigned char *p;
struct storage *st; struct storage *st;
unsigned v; unsigned v;
...@@ -204,15 +182,7 @@ fetch_eof(const struct sess *sp, int fd, struct http *hp) ...@@ -204,15 +182,7 @@ fetch_eof(const struct sess *sp, int fd, struct http *hp)
} }
assert(p != NULL); assert(p != NULL);
assert(st != NULL); assert(st != NULL);
if (http_GetTail(hp, v, &b, &e)) { i = http_Read(hp, fd, p, v);
memcpy(p, b, e - b);
p += e - b;
v -= e - b;
st->len += e - b;
sp->obj->len += e - b;
*p = '\0';
}
i = read(fd, p, v);
assert(i >= 0); assert(i >= 0);
if (i == 0) if (i == 0)
break; break;
......
...@@ -143,6 +143,17 @@ HSH_Unbusy(struct object *o) ...@@ -143,6 +143,17 @@ HSH_Unbusy(struct object *o)
} }
} }
void
HSH_Ref(struct object *o)
{
struct objhead *oh;
oh = o->objhead;
AZ(pthread_mutex_lock(&oh->mtx));
o->refcnt++;
AZ(pthread_mutex_unlock(&oh->mtx));
}
void void
HSH_Deref(struct object *o) HSH_Deref(struct object *o)
{ {
......
...@@ -120,6 +120,33 @@ http_GetTail(struct http *hp, unsigned len, char **b, char **e) ...@@ -120,6 +120,33 @@ http_GetTail(struct http *hp, unsigned len, char **b, char **e)
return (1); return (1);
} }
/* Read from fd, but soak up any tail first */
int
http_Read(struct http *hp, int fd, char *b, unsigned len)
{
int i;
unsigned u;
u = 0;
if (hp->t < hp->v) {
u = hp->v - hp->t;
if (u > len)
u = len;
memcpy(b, hp->t, u);
hp->t += u;
b += u;
len -= u;
}
if (len > 0) {
i = read(fd, b, len);
if (i < 0)
return (i);
u += i;
}
return (u);
}
int int
http_GetStatus(struct http *hp) http_GetStatus(struct http *hp)
{ {
......
...@@ -25,7 +25,6 @@ static int ...@@ -25,7 +25,6 @@ static int
pass_straight(struct sess *sp, int fd, struct http *hp, char *bi) pass_straight(struct sess *sp, int fd, struct http *hp, char *bi)
{ {
int i; int i;
char *b, *e;
off_t cl; off_t cl;
unsigned c; unsigned c;
char buf[PASS_BUFSIZ]; char buf[PASS_BUFSIZ];
...@@ -43,13 +42,7 @@ pass_straight(struct sess *sp, int fd, struct http *hp, char *bi) ...@@ -43,13 +42,7 @@ pass_straight(struct sess *sp, int fd, struct http *hp, char *bi)
c = cl; c = cl;
if (c > sizeof buf) if (c > sizeof buf)
c = sizeof buf; c = sizeof buf;
if (http_GetTail(hp, c, &b, &e)) { i = http_Read(hp, fd, buf, c);
i = e - b;
vca_write(sp, b, i);
cl -= i;
continue;
}
i = read(fd, buf, c);
if (i == 0 && bi == NULL) if (i == 0 && bi == NULL)
return (1); return (1);
assert(i > 0); assert(i > 0);
...@@ -81,15 +74,10 @@ pass_chunked(struct sess *sp, int fd, struct http *hp) ...@@ -81,15 +74,10 @@ pass_chunked(struct sess *sp, int fd, struct http *hp)
be = buf + sizeof buf; be = buf + sizeof buf;
p = buf; p = buf;
while (1) { while (1) {
if (http_GetTail(hp, be - bp, &b, &e)) { i = http_Read(hp, fd, bp, be - bp);
memcpy(bp, b, e - b); i = read(fd, bp, be - bp);
bp += e - b; assert(i > 0);
} else { bp += i;
/* XXX: must be safe from backend */
i = read(fd, bp, be - bp);
assert(i > 0);
bp += i;
}
/* buffer valid from p to bp */ /* buffer valid from p to bp */
u = strtoul(p, &q, 16); u = strtoul(p, &q, 16);
...@@ -159,7 +147,7 @@ PassBody(struct worker *w, struct sess *sp) ...@@ -159,7 +147,7 @@ PassBody(struct worker *w, struct sess *sp)
vc = sp->vbc; vc = sp->vbc;
assert(vc != NULL); assert(vc != NULL);
http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp); http_BuildSbuf(sp->fd, Build_Passreply, w->sb, hp);
sbuf_cat(w->sb, "\r\n"); sbuf_cat(w->sb, "\r\n");
sbuf_finish(w->sb); sbuf_finish(w->sb);
vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb)); vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb));
......
...@@ -59,7 +59,7 @@ PipeSession(struct worker *w, struct sess *sp) ...@@ -59,7 +59,7 @@ PipeSession(struct worker *w, struct sess *sp)
http_BuildSbuf(vc->fd, Build_Pipe, w->sb, sp->http); http_BuildSbuf(vc->fd, Build_Pipe, w->sb, sp->http);
i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb)); i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
assert(i == sbuf_len(w->sb)); assert(i == sbuf_len(w->sb));
if (http_GetTail(sp->http, 0, &b, &e) && b != e) { /* XXX */ if (http_GetTail(sp->http, 0, &b, &e) && b != e) {
i = write(vc->fd, b, e - b); i = write(vc->fd, b, e - b);
if (i != e - b) { if (i != e - b) {
close (vc->fd); close (vc->fd);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment