Commit b636e251 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@1498 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent f54ff6ba
...@@ -29,6 +29,7 @@ varnishd_SOURCES = \ ...@@ -29,6 +29,7 @@ varnishd_SOURCES = \
cache_vrt.c \ cache_vrt.c \
cache_vrt_acl.c \ cache_vrt_acl.c \
cache_vrt_re.c \ cache_vrt_re.c \
cache_ws.c \
hash_simple_list.c \ hash_simple_list.c \
hash_classic.c \ hash_classic.c \
mgt_child.c \ mgt_child.c \
......
...@@ -76,9 +76,30 @@ enum step { ...@@ -76,9 +76,30 @@ enum step {
#undef 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. * HTTP Request/Response/Header handling structure.
* RSN: struct worker and struct session will have one of these embedded.
*/ */
struct http_hdr { struct http_hdr {
...@@ -90,11 +111,9 @@ struct http { ...@@ -90,11 +111,9 @@ struct http {
unsigned magic; unsigned magic;
#define HTTP_MAGIC 0x6428b5c9 #define HTTP_MAGIC 0x6428b5c9
char *s; /* (S)tart of buffer */ struct ws ws[1];
char *t; /* start of (T)railing data */ char *rx_s, *rx_e; /* Received Request */
char *v; /* end of (V)alid bytes */ char *pl_s, *pl_e; /* Pipelined bytes */
char *f; /* first (F)ree byte */
char *e; /* (E)nd of buffer */
unsigned char conds; /* If-* headers present */ unsigned char conds; /* If-* headers present */
enum httpwhence { enum httpwhence {
......
...@@ -214,7 +214,7 @@ cnt_done(struct sess *sp) ...@@ -214,7 +214,7 @@ cnt_done(struct sess *sp)
sp->step = STP_RECV; sp->step = STP_RECV;
return (0); return (0);
} }
if (sp->http->t < sp->http->v) { if (sp->http->pl_s < sp->http->pl_e) {
VSL_stats->sess_readahead++; VSL_stats->sess_readahead++;
sp->step = STP_AGAIN; sp->step = STP_AGAIN;
return (0); return (0);
...@@ -426,13 +426,12 @@ cnt_lookup(struct sess *sp) ...@@ -426,13 +426,12 @@ cnt_lookup(struct sess *sp)
{ {
struct object *o; struct object *o;
assert(sp->http->f > sp->http->s);
assert(sp->http->f >= sp->http->t);
if (sp->obj == NULL) { 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; sp->hash_e = sp->hash_b;
VCL_hash_method(sp); /* XXX: no-op for now */ VCL_hash_method(sp); /* XXX: no-op for now */
WS_ReleaseP(sp->http->ws, sp->hash_e);
/* XXX check error */ /* XXX check error */
} }
...@@ -449,12 +448,7 @@ cnt_lookup(struct sess *sp) ...@@ -449,12 +448,7 @@ cnt_lookup(struct sess *sp)
return (1); return (1);
} }
xxxassert (sp->hash_e == sp->http->f); WS_Return(sp->http->ws, sp->hash_b, sp->hash_e);
if (sp->hash_e == sp->http->f) {
/* Nobody alloc'ed after us, free again */
sp->http->f = sp->hash_b;
}
sp->hash_b = sp->hash_e = NULL; sp->hash_b = sp->hash_e = NULL;
sp->obj = o; sp->obj = o;
......
...@@ -251,8 +251,8 @@ HSH_Deref(struct object *o) ...@@ -251,8 +251,8 @@ HSH_Deref(struct object *o)
if (r != 0) if (r != 0)
return; return;
if (o->http.s != NULL) if (o->http.ws->s != NULL)
free(o->http.s); free(o->http.ws->s);
HSH_Freestore(o); HSH_Freestore(o);
free(o); free(o);
......
This diff is collapsed.
...@@ -57,7 +57,6 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl) ...@@ -57,7 +57,6 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
const char *msg; const char *msg;
char date[40]; char date[40];
time_t now; time_t now;
size_t len;
int fd; int fd;
assert(status >= 100 && status <= 999); assert(status >= 100 && status <= 999);
...@@ -122,10 +121,8 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl) ...@@ -122,10 +121,8 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
vsb_delete(&vsb); vsb_delete(&vsb);
/* allocate space for header */ /* allocate space for header */
/* XXX what if the object already has a header? */
h->v = h->s = calloc(len = 1024, 1); WS_Init(h->ws, malloc(1024), 1024);
XXXAN(h->s);
h->e = h->s + len;
/* generate header */ /* generate header */
http_ClrHeader(h); http_ClrHeader(h);
......
...@@ -284,10 +284,8 @@ VRT_l_req_hash(struct sess *sp, const char *str) ...@@ -284,10 +284,8 @@ VRT_l_req_hash(struct sess *sp, const char *str)
if (str == NULL) if (str == NULL)
str = ""; str = "";
l = strlen(str); l = strlen(str);
xxxassert (sp->hash_e == sp->http->f); xxxassert (sp->hash_e + l + 1 <= sp->http->ws->e);
xxxassert (sp->hash_e + l + 1 <= sp->http->e);
memcpy(sp->hash_e, str, l); memcpy(sp->hash_e, str, l);
sp->hash_e[l] = '#'; sp->hash_e[l] = '#';
sp->hash_e += l + 1; sp->hash_e += l + 1;
sp->http->f += l + 1;
} }
/*-
* 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;
}
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