From: phk Date: Mon, 4 Jun 2007 19:10:16 +0000 (+0000) Subject: Wrap the management of the session workspace in functions, to prevent X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a36aac204f23cd3ccf0cb318f7c90a4ea32d4b2b;p=varnish Wrap the management of the session workspace in functions, to prevent 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 --- diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 96e6e225..d1a3b660 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -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 \ diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index d6104e0a..fa8272d4 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -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 { diff --git a/varnish-cache/bin/varnishd/cache_center.c b/varnish-cache/bin/varnishd/cache_center.c index 3bb930a0..309ae21c 100644 --- a/varnish-cache/bin/varnishd/cache_center.c +++ b/varnish-cache/bin/varnishd/cache_center.c @@ -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; diff --git a/varnish-cache/bin/varnishd/cache_hash.c b/varnish-cache/bin/varnishd/cache_hash.c index e9c6a5dc..b6d58e47 100644 --- a/varnish-cache/bin/varnishd/cache_hash.c +++ b/varnish-cache/bin/varnishd/cache_hash.c @@ -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); diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index fdbe23e6..ec3897e0 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -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++; } diff --git a/varnish-cache/bin/varnishd/cache_synthetic.c b/varnish-cache/bin/varnishd/cache_synthetic.c index b2dc4905..aa039ad7 100644 --- a/varnish-cache/bin/varnishd/cache_synthetic.c +++ b/varnish-cache/bin/varnishd/cache_synthetic.c @@ -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); diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 252d1b45..afcad24d 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -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 index 00000000..67255a79 --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_ws.c @@ -0,0 +1,138 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006 Linpro AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * 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 +#include + +#include +#include +#include +#include +#include + +#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; +}