]> err.no Git - varnish/commitdiff
Wrap the management of the session workspace in functions, to prevent
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 4 Jun 2007 19:10:16 +0000 (19:10 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 4 Jun 2007 19:10:16 +0000 (19:10 +0000)
pointer gymnastics getting out of hand.

In addition to the obvious alloc/return primitives there are also
reserve/release primitives for when we don't know the length yet.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1498 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/Makefile.am
varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_hash.c
varnish-cache/bin/varnishd/cache_http.c
varnish-cache/bin/varnishd/cache_synthetic.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/bin/varnishd/cache_ws.c [new file with mode: 0644]

index 96e6e2252402ba28397c51cc38880aefcc428212..d1a3b660d3e5a89ba2a9f62255a90b7e0a5a9dfd 100644 (file)
@@ -29,6 +29,7 @@ varnishd_SOURCES = \
        cache_vrt.c \
        cache_vrt_acl.c \
        cache_vrt_re.c \
+       cache_ws.c \
        hash_simple_list.c \
        hash_classic.c \
        mgt_child.c \
index d6104e0a1d1ffeadccdf529724c954cc26524a43..fa8272d4c8acd59cdb2b061fd2ef506d5f9ee07c 100644 (file)
@@ -76,9 +76,30 @@ enum step {
 #undef STEP
 };
 
+/*--------------------------------------------------------------------
+ * Workspace structure for quick memory allocation.
+ */
+
+struct ws {
+       char                    *s;             /* (S)tart of buffer */
+       char                    *e;             /* (E)nd of buffer */
+       char                    *f;             /* (F)ree pointer */
+       char                    *r;             /* (R)eserved length */
+};
+
+void WS_Init(struct ws *ws, void *space, unsigned len);
+unsigned WS_Reserve(struct ws *ws, unsigned bytes);
+void WS_Release(struct ws *ws, unsigned bytes);
+void WS_ReleaseP(struct ws *ws, char *ptr);
+void WS_Assert(struct ws *ws);
+void WS_Reset(struct ws *ws);
+char *WS_Alloc(struct ws *ws, unsigned bytes);
+void WS_Return(struct ws *ws, char *b, char *e);
+
+
+
 /*--------------------------------------------------------------------
  * HTTP Request/Response/Header handling structure.
- * RSN: struct worker and struct session will have one of these embedded.
  */
 
 struct http_hdr {
@@ -90,11 +111,9 @@ struct http {
        unsigned                magic;
 #define HTTP_MAGIC             0x6428b5c9
 
-       char                    *s;             /* (S)tart of buffer */
-       char                    *t;             /* start of (T)railing data */
-       char                    *v;             /* end of (V)alid bytes */
-       char                    *f;             /* first (F)ree byte */
-       char                    *e;             /* (E)nd of buffer */
+       struct ws               ws[1];
+       char                    *rx_s, *rx_e;   /* Received Request */
+       char                    *pl_s, *pl_e;   /* Pipelined bytes */
 
        unsigned char           conds;          /* If-* headers present */
        enum httpwhence {
index 3bb930a0cc84e66ed3e4039a78d51172eb0d2ba7..309ae21c1acbaf8f6ccbc3f991f48e3a8dda5752 100644 (file)
@@ -214,7 +214,7 @@ cnt_done(struct sess *sp)
                sp->step = STP_RECV;
                return (0);
        }
-       if (sp->http->t < sp->http->v) {
+       if (sp->http->pl_s < sp->http->pl_e) {
                VSL_stats->sess_readahead++;
                sp->step = STP_AGAIN;
                return (0);
@@ -426,13 +426,12 @@ cnt_lookup(struct sess *sp)
 {
        struct object *o;
 
-       assert(sp->http->f > sp->http->s);
-       assert(sp->http->f >= sp->http->t);
        if (sp->obj == NULL) {
-               sp->hash_b = sp->http->f;
+               WS_Reserve(sp->http->ws, 0);
+               sp->hash_b = sp->http->ws->f;
                sp->hash_e = sp->hash_b;
                VCL_hash_method(sp);            /* XXX: no-op for now */
-
+               WS_ReleaseP(sp->http->ws, sp->hash_e);
                /* XXX check error */
        }
 
@@ -449,12 +448,7 @@ cnt_lookup(struct sess *sp)
                return (1);
        }
 
-       xxxassert (sp->hash_e == sp->http->f);
-       if (sp->hash_e == sp->http->f) {
-               /* Nobody alloc'ed after us, free again */
-               sp->http->f = sp->hash_b;
-       }
-
+       WS_Return(sp->http->ws, sp->hash_b, sp->hash_e);
        sp->hash_b = sp->hash_e = NULL;
 
        sp->obj = o;
index e9c6a5dcf1d9f9194a265c99d344a97966e07412..b6d58e478ece763068e72769205129c7cb7f4660 100644 (file)
@@ -251,8 +251,8 @@ HSH_Deref(struct object *o)
        if (r != 0)
                return;
 
-       if (o->http.s != NULL)
-               free(o->http.s);
+       if (o->http.ws->s != NULL)
+               free(o->http.ws->s);
 
        HSH_Freestore(o);
        free(o);
index fdbe23e63377e1b9c3df9708bd005454cc28ba6f..ec3897e01bea865ff0c0da5826e25e23a21153ac 100644 (file)
@@ -164,16 +164,11 @@ http_StatusMessage(int status)
 void
 http_Setup(struct http *hp, void *space, unsigned len)
 {
-       char *sp = space;
 
        assert(len > 0);
        memset(hp, 0, sizeof *hp);
        hp->magic = HTTP_MAGIC;
-       hp->s = sp;
-       hp->t = sp;
-       hp->v = sp;
-       hp->f = sp;
-       hp->e = sp + len;
+       WS_Init(hp->ws, space, len);
        hp->nhd = HTTP_HDR_FIRST;
 }
 
@@ -329,20 +324,20 @@ int
 http_GetTail(struct http *hp, unsigned len, char **b, char **e)
 {
 
-       if (hp->t >= hp->v)
+       if (hp->pl_s >= hp->pl_e)
                return (0);
 
        if (len == 0)
-               len = hp->v - hp->t;
+               len = hp->pl_e - hp->pl_e;
 
-       if (hp->t + len > hp->v)
-               len = hp->v - hp->t;
+       if (hp->pl_s + len > hp->pl_e)
+               len = hp->pl_e - hp->pl_s;
        if (len == 0)
                return (0);
-       *b = hp->t;
-       *e = hp->t + len;
-       hp->t += len;
-       assert(hp->t <= hp->v);
+       *b = hp->pl_s;
+       *e = hp->pl_s + len;
+       hp->pl_s += len;
+       assert(hp->pl_s <= hp->pl_e);
        return (1);
 }
 
@@ -357,15 +352,16 @@ http_Read(struct http *hp, int fd, void *p, unsigned len)
        char *b = p;
 
        u = 0;
-       if (hp->t < hp->v) {
-               u = hp->v - hp->t;
+       if (hp->pl_s < hp->pl_e) {
+               u = hp->pl_e - hp->pl_s;
                if (u > len)
                        u = len;
-               memcpy(b, hp->t, u);
-               hp->t += u;
+               memcpy(b, hp->pl_s, u);
+               hp->pl_s += u;
                b += u;
                len -= u;
        }
+       hp->pl_s = hp->pl_e = NULL;
        if (len > 0) {
                i = read(fd, b, len);
                if (i < 0)
@@ -417,8 +413,8 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
        hp->nhd = HTTP_HDR_FIRST;
        hp->conds = 0;
        r = NULL;               /* For FlexeLint */
-       assert(p < hp->v);      /* http_header_complete() guarantees this */
-       for (; p < hp->v; p = r) {
+       assert(p < hp->rx_e);   /* http_header_complete() guarantees this */
+       for (; p < hp->rx_e; p = r) {
                /* XXX: handle continuation lines */
                q = strchr(p, '\n');
                assert(q != NULL);
@@ -445,8 +441,6 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
                        WSLR(w, http2shmlog(hp, HTTP_T_LostHeader), fd, p, q);
                }
        }
-       assert(hp->t <= hp->v);
-       assert(hp->t == r);
        return (0);
 }
 
@@ -458,12 +452,11 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
        char *p;
 
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-       AN(hp->t);
-       assert(hp->s < hp->t);
-       assert(hp->t <= hp->v);
+       /* Assert a NUL at rx_e */
+       assert(hp->rx_s < hp->rx_e);
        hp->logtag = HTTP_Rx;
 
-       for (p = hp->s ; isspace(*p); p++)
+       for (p = hp->rx_s ; isspace(*p); p++)
                continue;
 
        /* First, the request type (GET/HEAD etc) */
@@ -478,7 +471,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
        while (isspace(*p) && *p != '\n')
                p++;
        if (*p == '\n') {
-               WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v);
+               WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
                return (400);
        }
        hp->hd[HTTP_HDR_URL].b = p;
@@ -487,7 +480,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
        hp->hd[HTTP_HDR_URL].e = p;
        WSLH(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL);
        if (*p == '\n') {
-               WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v);
+               WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
                return (400);
        }
        *p++ = '\0';
@@ -496,7 +489,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
        while (isspace(*p) && *p != '\n')
                p++;
        if (*p == '\n') {
-               WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v);
+               WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
                return (400);
        }
        hp->hd[HTTP_HDR_PROTO].b = p;
@@ -509,7 +502,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
        while (isspace(*p) && *p != '\n')
                p++;
        if (*p != '\n') {
-               WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v);
+               WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
                return (400);
        }
        *p++ = '\0';
@@ -525,16 +518,15 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
        char *p, *q;
 
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-       AN(hp->t);
-       assert(hp->s < hp->t);
-       assert(hp->t <= hp->v);
+       /* Assert a NUL at rx_e */
+       assert(hp->rx_s < hp->rx_e);
        hp->logtag = HTTP_Rx;
 
-       for (p = hp->s ; isspace(*p); p++)
+       for (p = hp->rx_s ; isspace(*p); p++)
                continue;
 
        if (memcmp(p, "HTTP/1.", 7)) {
-               WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v);
+               WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
                return (400);
        }
        /* First, protocol */
@@ -572,7 +564,9 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
        return (http_dissect_hdrs(w, hp, fd, p));
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * Return nonzero if we have a complete HTTP request.
+ */
 
 static int
 http_header_complete(struct http *hp)
@@ -580,33 +574,33 @@ http_header_complete(struct http *hp)
        char *p;
 
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-       assert(hp->v <= hp->e);
-       assert(*hp->v == '\0');
+       assert(*hp->rx_e == '\0');
        /* Skip any leading white space */
-       for (p = hp->s ; p < hp->v && isspace(*p); p++)
+       for (p = hp->rx_s ; p < hp->rx_e && isspace(*p); p++)
                continue;
-       if (p >= hp->v) {
-               hp->v = hp->s;
+       if (p >= hp->rx_e) {
+               hp->rx_e = hp->rx_s;
                return (0);
        }
        while (1) {
                /* XXX: we could save location of all linebreaks for later */
                p = strchr(p, '\n');
                if (p == NULL)
-                       return (0);
+                       return (0);     /* XXX: Could cache p */
                p++;
                if (*p == '\r')
                        p++;
-               if (*p != '\n')
-                       continue;
-               break;
+               if (*p == '\n')
+                       break;
        }
-       if (++p > hp->v)
-               return (0);
-       hp->t = p;
-       assert(hp->t > hp->s);
-       assert(hp->t <= hp->v);
-       hp->f = hp->v;
+       p++;
+       WS_ReleaseP(hp->ws, hp->rx_e);
+       if (p != hp->rx_e) {
+               hp->pl_s = p;
+               hp->pl_e = hp->rx_e;
+               hp->rx_e = p;
+       }
+       /* XXX: Check this stuff... */
        return (1);
 }
 
@@ -618,25 +612,26 @@ http_RecvPrep(struct http *hp)
        unsigned l;
 
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
-       assert(hp->v <= hp->e);
-       assert(hp->t <= hp->v);
-       if (hp->t > hp->s && hp->t < hp->v) {
-               l = hp->v - hp->t;
-               memmove(hp->s, hp->t, l);
-               hp->v = hp->s + l;
-               hp->t = hp->s;
-               *hp->v = '\0';
-       } else  {
-               hp->v = hp->s;
-               hp->t = hp->s;
+       WS_Assert(hp->ws);
+       WS_Reset(hp->ws);
+       WS_Reserve(hp->ws, 0);
+       hp->rx_s = hp->ws->f;
+       hp->rx_e = hp->rx_s;
+       if (hp->pl_s != NULL) {
+               assert(hp->pl_s < hp->pl_e);
+               l = hp->pl_e - hp->pl_s;
+               memmove(hp->rx_s, hp->pl_s, l);
+               hp->rx_e = hp->rx_s + l;
+               hp->pl_s = hp->pl_e = NULL;
        }
+       *hp->rx_e = '\0';
 }
 
 int
 http_RecvPrepAgain(struct http *hp)
 {
        http_RecvPrep(hp);
-       if (hp->v == hp->s)
+       if (hp->rx_s == hp->rx_e)
                return (0);
        return (http_header_complete(hp));
 }
@@ -649,38 +644,35 @@ http_RecvSome(int fd, struct http *hp)
        unsigned l;
        int i;
 
-       l = (hp->e - hp->s) / 2;
-       if (l < hp->v - hp->s)
-               l = 0;
-       else
-               l -= hp->v - hp->s;
+       l = (hp->ws->e - hp->rx_e) - 1;
        if (l <= 1) {
                VSL(SLT_HttpError, fd, "Received too much");
-               VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
-               hp->t = NULL;
+               VSLR(SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
+               hp->rx_s = hp->rx_e = NULL;
+               WS_Release(hp->ws, 0);
                return (1);
        }
        errno = 0;
-       i = read(fd, hp->v, l - 1);
+       i = read(fd, hp->rx_e, l - 1);
        if (i > 0) {
-               hp->v += i;
-               *hp->v = '\0';
+               hp->rx_e += i;
+               *hp->rx_e = '\0';
                if (http_header_complete(hp))
                        return(0);
                return (-1);
        }
 
-       if (hp->v != hp->s) {
+       if (hp->rx_e != hp->rx_s) {
                VSL(SLT_HttpError, fd,
                    "Received (only) %d bytes, errno %d",
-                   hp->v - hp->s, errno);
-               VSLR(SLT_Debug, fd, hp->s, hp->v);
+                   hp->rx_e - hp->rx_s, errno);
+               VSLR(SLT_Debug, fd, hp->rx_s, hp->rx_e);
        } else if (errno == 0)
                VSL(SLT_HttpError, fd, "Received nothing");
        else
-               VSL(SLT_HttpError, fd,
-                   "Received errno %d", errno);
-       hp->t = NULL;
+               VSL(SLT_HttpError, fd, "Received errno %d", errno);
+       hp->rx_s = hp->rx_e = NULL;
+       WS_Release(hp->ws, 0);
        return(2);
 }
 
@@ -707,6 +699,7 @@ void
 http_CopyHttp(struct http *to, struct http *fm)
 {
        unsigned u, l;
+       char *p;
 
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
@@ -717,10 +710,10 @@ http_CopyHttp(struct http *to, struct http *fm)
                AN(fm->hd[u].e);
                l += (fm->hd[u].e - fm->hd[u].b) + 1;
        }
-       to->s = malloc(l);
-       XXXAN(to->s);
-       to->e = to->s + l;
-       to->f = to->s;
+       p = malloc(l);
+       XXXAN(p);
+       WS_Init(to->ws, p, l);
+       WS_Reserve(to->ws, 0);
        for (u = 0; u < fm->nhd; u++) {
                if (fm->hd[u].b == NULL)
                        continue;
@@ -728,12 +721,13 @@ http_CopyHttp(struct http *to, struct http *fm)
                assert(*fm->hd[u].e == '\0');
                l = fm->hd[u].e - fm->hd[u].b;
                assert(l == strlen(fm->hd[u].b));
-               memcpy(to->f, fm->hd[u].b, l);
-               to->hd[u].b = to->f;
-               to->hd[u].e = to->f + l;
+               memcpy(p, fm->hd[u].b, l);
+               to->hd[u].b = p;
+               to->hd[u].e = p + l;
                *to->hd[u].e = '\0';
-               to->f += l + 1;
+               p += l + 1;
        }
+       /* XXX: Leave to->ws reserved for now */
        to->nhd = fm->nhd;
 }
 
@@ -860,7 +854,7 @@ http_ClrHeader(struct http *to)
 {
 
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-       to->f = to->v;
+       /* XXX ??? to->f = to->v;  Not sure this is valid */
        to->nhd = HTTP_HDR_FIRST;
        memset(to->hd, 0, sizeof to->hd);
 }
@@ -882,46 +876,45 @@ http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
 
 /*--------------------------------------------------------------------*/
 
-void
-http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol)
+static void
+http_PutField(struct http *to, int field, const char *string)
 {
+       char *e, *p;
        int l;
 
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-       l = strlcpy(to->f, protocol, to->e - to->f);
-       xxxassert(to->f + l < to->e);
-       to->hd[HTTP_HDR_PROTO].b = to->f;
-       to->hd[HTTP_HDR_PROTO].e = to->f + l;
-       to->f += l + 1;
+       e = strchr(string, '\0');
+       l = (e - string);
+       p = WS_Alloc(to->ws, l + 1);
+       memcpy(p, string, l + 1);
+       to->hd[field].b = p;
+       to->hd[field].e = p + l;
+}
+
+void
+http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol)
+{
+
+       http_PutField(to, HTTP_HDR_PROTO, protocol);
        WSLH(w, HTTP_T_Protocol, fd, to, HTTP_HDR_PROTO);
 }
 
 void
 http_PutStatus(struct worker *w, int fd, struct http *to, int status)
 {
-       int l;
+       char stat[4];
 
-       CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-       assert(status >= 100 && status <= 999);
-       l = snprintf(to->f, to->e - to->f, "%d", status);
-       xxxassert(to->f + l < to->e);
-       to->hd[HTTP_HDR_STATUS].b = to->f;
-       to->hd[HTTP_HDR_STATUS].e = to->f + l;
-       to->f += l + 1;
+       assert(status >= 0 && status <= 999);
+       sprintf(stat, "%d", status);
+       http_PutField(to, HTTP_HDR_STATUS, stat);
        WSLH(w, HTTP_T_Status, fd, to, HTTP_HDR_STATUS);
 }
 
 void
 http_PutResponse(struct worker *w, int fd, struct http *to, const char *response)
 {
-       int l;
 
-       CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-       l = strlcpy(to->f, response, to->e - to->f);
-       xxxassert(to->f + l < to->e);
-       to->hd[HTTP_HDR_RESPONSE].b = to->f;
-       to->hd[HTTP_HDR_RESPONSE].e = to->f + l;
-       to->f += l + 1;
+       http_PutField(to, HTTP_HDR_RESPONSE, response);
        WSLH(w, HTTP_T_Response, fd, to, HTTP_HDR_RESPONSE);
 }
 
@@ -932,18 +925,18 @@ http_PrintfHeader(struct worker *w, int fd, struct http *to, const char *fmt, ..
        unsigned l, n;
 
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
-       l = to->e - to->f;
+       l = WS_Reserve(to->ws, 0);
        va_start(ap, fmt);
-       n = vsnprintf(to->f, l, fmt, ap);
+       n = vsnprintf(to->ws->f, l, fmt, ap);
        va_end(ap);
-       if (n >= l || to->nhd >= HTTP_HDR_MAX) {
+       if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) {
                VSL_stats->losthdr++;
-               WSL(w, http2shmlog(to, HTTP_T_LostHeader), fd, "%s", to->f);
+               WSL(w, http2shmlog(to, HTTP_T_LostHeader), fd, "%s", to->ws->f);
+               WS_Release(to->ws, 0);
        } else {
-               assert(to->f < to->e);
-               to->hd[to->nhd].b = to->f;
-               to->hd[to->nhd].e = to->f + n;
-               to->f += n + 1;
+               to->hd[to->nhd].b = to->ws->f;
+               to->hd[to->nhd].e = to->ws->f + n;
+               WS_Release(to->ws, n + 1);
                WSLH(w, HTTP_T_Header, fd, to, to->nhd);
                to->nhd++;
        }
index b2dc4905e8613631c41d77ba9eb3670ce558385b..aa039ad739a81bed3d8beecf06625e217600b36b 100644 (file)
@@ -57,7 +57,6 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
        const char *msg;
        char date[40];
        time_t now;
-       size_t len;
        int fd;
 
        assert(status >= 100 && status <= 999);
@@ -122,10 +121,8 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
        vsb_delete(&vsb);
 
        /* allocate space for header */
-       /* XXX what if the object already has a header? */
-       h->v = h->s = calloc(len = 1024, 1);
-       XXXAN(h->s);
-       h->e = h->s + len;
+
+       WS_Init(h->ws, malloc(1024), 1024);
 
        /* generate header */
        http_ClrHeader(h);
index 252d1b451b5dc49bf54b35d64393bb25b848ed7f..afcad24d295f9198205a3302bc4909ff26d5bd2e 100644 (file)
@@ -284,10 +284,8 @@ VRT_l_req_hash(struct sess *sp, const char *str)
        if (str == NULL)
                str = "";
        l = strlen(str);
-       xxxassert (sp->hash_e == sp->http->f);
-       xxxassert (sp->hash_e + l + 1 <= sp->http->e);
+       xxxassert (sp->hash_e + l + 1 <= sp->http->ws->e);
        memcpy(sp->hash_e, str, l);
        sp->hash_e[l] = '#';
        sp->hash_e += l + 1;
-       sp->http->f += l + 1;
 }
diff --git a/varnish-cache/bin/varnishd/cache_ws.c b/varnish-cache/bin/varnishd/cache_ws.c
new file mode 100644 (file)
index 0000000..67255a7
--- /dev/null
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "heritage.h"
+#include "shmlog.h"
+#include "vcl.h"
+#include "cli_priv.h"
+#include "cache.h"
+
+void
+WS_Assert(struct ws *ws)
+{
+
+       assert(ws != NULL);
+       assert(ws->s != NULL);
+       assert(ws->e != NULL);
+       assert(ws->s < ws->e);
+       assert(ws->f >= ws->s);
+       assert(ws->f <= ws->e);
+       if (ws->r) {
+               assert(ws->r > ws->s);
+               assert(ws->r <= ws->e);
+       }
+}
+
+void
+WS_Init(struct ws *ws, void *space, unsigned len)
+{
+
+       assert(space != NULL);
+       memset(ws, 0, sizeof *ws);
+       ws->s = space;
+       ws->e = ws->s + len;
+       ws->f = ws->s;
+       WS_Assert(ws);
+}
+
+void
+WS_Reset(struct ws *ws)
+{
+
+       WS_Assert(ws);
+       assert(ws->r == NULL);
+       ws->f = ws->s;
+}
+
+char *
+WS_Alloc(struct ws *ws, unsigned bytes)
+{
+       char *r;
+
+       WS_Assert(ws);
+       assert(ws->r == NULL);
+       xxxassert(ws->f + bytes <= ws->e);
+       r = ws->f;
+       ws->f += bytes;
+       return (r);
+}
+
+unsigned
+WS_Reserve(struct ws *ws, unsigned bytes)
+{
+       WS_Assert(ws);
+       assert(ws->r == NULL);
+       if (bytes == 0)
+               bytes = ws->e - ws->f;
+       xxxassert(ws->f + bytes <= ws->e);
+       ws->r = ws->f + bytes;
+       return (ws->r - ws->f);
+}
+
+void
+WS_Release(struct ws *ws, unsigned bytes)
+{
+       WS_Assert(ws);
+       assert(ws->r != NULL);
+       assert(ws->f + bytes <= ws->r);
+       ws->f += bytes;
+       ws->r = NULL;
+}
+
+void
+WS_ReleaseP(struct ws *ws, char *ptr)
+{
+       WS_Assert(ws);
+       assert(ws->r != NULL);
+       assert(ptr >= ws->f);
+       assert(ptr <= ws->r);
+       ws->f = ptr;
+       ws->r = NULL;
+}
+
+void
+WS_Return(struct ws *ws, char *s, char *e)
+{
+
+       WS_Assert(ws);
+       if (e == ws->f)
+               ws->f = s;
+}