Commit 573c98a7 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Make the number of HTTP headers a parameter, and allocate only as

many as we need for the objects.

This passes the tests, but performance tests have not been performed
and there may be alignment issues on platforms with strict alignment.

If this works out, the benefits will include:

A) no need to recompile if you need more than 64 HTTP headers.

B) You do not waste a kilobyte per object, on space for headers you do not have.

Reports very welcome!



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4456 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 3a61b691
...@@ -71,16 +71,8 @@ enum { ...@@ -71,16 +71,8 @@ enum {
HTTP_HDR_RESPONSE, HTTP_HDR_RESPONSE,
/* HTTP header lines */ /* HTTP header lines */
HTTP_HDR_FIRST, HTTP_HDR_FIRST,
HTTP_HDR_MAX = HTTP_HDR_MAX_VAL
}; };
/* Note: intentionally not IOV_MAX unless it has to be */
#if (IOV_MAX < (HTTP_HDR_MAX_VAL * 2))
# define MAX_IOVS IOV_MAX
#else
# define MAX_IOVS (HTTP_HDR_MAX_VAL * 2)
#endif
struct cli; struct cli;
struct vsb; struct vsb;
struct sess; struct sess;
...@@ -154,11 +146,12 @@ struct http { ...@@ -154,11 +146,12 @@ struct http {
int status; int status;
double protover; double protover;
txt hd[HTTP_HDR_MAX]; unsigned shd; /* Size of hd space */
unsigned char hdf[HTTP_HDR_MAX]; txt *hd;
unsigned char *hdf;
#define HDF_FILTER (1 << 0) /* Filtered by Connection */ #define HDF_FILTER (1 << 0) /* Filtered by Connection */
#define HDF_COPY (1 << 1) /* Copy this field */ #define HDF_COPY (1 << 1) /* Copy this field */
unsigned nhd; unsigned nhd; /* Next free hd */
}; };
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -214,8 +207,9 @@ struct worker { ...@@ -214,8 +207,9 @@ struct worker {
int *wfd; int *wfd;
unsigned werr; /* valid after WRK_Flush() */ unsigned werr; /* valid after WRK_Flush() */
struct iovec iov[MAX_IOVS]; struct iovec *iov;
int niov; unsigned siov;
unsigned niov;
ssize_t liov; ssize_t liov;
struct VCL_conf *vcl; struct VCL_conf *vcl;
...@@ -227,7 +221,7 @@ struct worker { ...@@ -227,7 +221,7 @@ struct worker {
struct http_conn htc[1]; struct http_conn htc[1];
struct ws ws[1]; struct ws ws[1];
struct http http[3]; struct http *http[3];
struct http *bereq; struct http *bereq;
struct http *beresp1; struct http *beresp1;
struct http *beresp; struct http *beresp;
...@@ -341,7 +335,7 @@ struct object { ...@@ -341,7 +335,7 @@ struct object {
double last_modified; double last_modified;
double last_lru; double last_lru;
struct http http[1]; struct http *http;
VTAILQ_HEAD(, storage) store; VTAILQ_HEAD(, storage) store;
...@@ -513,8 +507,10 @@ int FetchReqBody(struct sess *sp); ...@@ -513,8 +507,10 @@ int FetchReqBody(struct sess *sp);
void Fetch_Init(void); void Fetch_Init(void);
/* cache_http.c */ /* cache_http.c */
unsigned HTTP_estimate(unsigned nhttp);
struct http *HTTP_create(void *p, unsigned nhttp);
const char *http_StatusMessage(unsigned); const char *http_StatusMessage(unsigned);
unsigned http_EstimateWS(const struct http *fm, unsigned how); unsigned http_EstimateWS(const struct http *fm, unsigned how, unsigned *nhd);
void HTTP_Init(void); void HTTP_Init(void);
void http_ClrHeader(struct http *to); void http_ClrHeader(struct http *to);
unsigned http_Write(struct worker *w, const struct http *hp, int resp); unsigned http_Write(struct worker *w, const struct http *hp, int resp);
......
...@@ -184,7 +184,7 @@ cnt_deliver(struct sess *sp) ...@@ -184,7 +184,7 @@ cnt_deliver(struct sess *sp)
sp->obj->last_lru = sp->t_resp; /* XXX: locking ? */ sp->obj->last_lru = sp->t_resp; /* XXX: locking ? */
sp->obj->last_use = sp->t_resp; /* XXX: locking ? */ sp->obj->last_use = sp->t_resp; /* XXX: locking ? */
} }
sp->wrk->resp = &sp->wrk->http[2]; sp->wrk->resp = sp->wrk->http[2];
http_Setup(sp->wrk->resp, sp->wrk->ws); http_Setup(sp->wrk->resp, sp->wrk->ws);
RES_BuildHttp(sp); RES_BuildHttp(sp);
VCL_deliver_method(sp); VCL_deliver_method(sp);
...@@ -336,7 +336,7 @@ cnt_error(struct sess *sp) ...@@ -336,7 +336,7 @@ cnt_error(struct sess *sp)
if (sp->obj == NULL) { if (sp->obj == NULL) {
HSH_Prealloc(sp); HSH_Prealloc(sp);
sp->wrk->cacheable = 0; sp->wrk->cacheable = 0;
sp->obj = STV_NewObject(sp, 0, 0); sp->obj = STV_NewObject(sp, 0, 0, params->http_headers);
sp->obj->xid = sp->xid; sp->obj->xid = sp->xid;
sp->obj->entered = sp->t_req; sp->obj->entered = sp->t_req;
} else { } else {
...@@ -421,7 +421,7 @@ cnt_fetch(struct sess *sp) ...@@ -421,7 +421,7 @@ cnt_fetch(struct sess *sp)
int i; int i;
struct http *hp, *hp2; struct http *hp, *hp2;
char *b; char *b;
unsigned handling, l; unsigned handling, l, nhttp;
int varyl = 0; int varyl = 0;
struct vsb *vary = NULL; struct vsb *vary = NULL;
...@@ -432,7 +432,7 @@ cnt_fetch(struct sess *sp) ...@@ -432,7 +432,7 @@ cnt_fetch(struct sess *sp)
AZ(sp->vbe); AZ(sp->vbe);
/* sp->wrk->http[0] is (still) bereq */ /* sp->wrk->http[0] is (still) bereq */
sp->wrk->beresp = &sp->wrk->http[1]; sp->wrk->beresp = sp->wrk->http[1];
http_Setup(sp->wrk->beresp, sp->wrk->ws); http_Setup(sp->wrk->beresp, sp->wrk->ws);
i = FetchHdr(sp); i = FetchHdr(sp);
...@@ -441,7 +441,7 @@ cnt_fetch(struct sess *sp) ...@@ -441,7 +441,7 @@ cnt_fetch(struct sess *sp)
* Save a copy before it might get mangled in VCL. When it comes to * Save a copy before it might get mangled in VCL. When it comes to
* dealing with the body, we want to see the unadultered headers. * dealing with the body, we want to see the unadultered headers.
*/ */
sp->wrk->beresp1 = &sp->wrk->http[2]; sp->wrk->beresp1 = sp->wrk->http[2];
*sp->wrk->beresp1 = *sp->wrk->beresp; *sp->wrk->beresp1 = *sp->wrk->beresp;
if (i) { if (i) {
...@@ -529,7 +529,7 @@ cnt_fetch(struct sess *sp) ...@@ -529,7 +529,7 @@ cnt_fetch(struct sess *sp)
AZ(sp->objcore); AZ(sp->objcore);
} }
l = http_EstimateWS(sp->wrk->beresp, HTTPH_A_INS); l = http_EstimateWS(sp->wrk->beresp, HTTPH_A_INS, &nhttp);
if (vary != NULL) if (vary != NULL)
l += varyl; l += varyl;
...@@ -542,7 +542,7 @@ cnt_fetch(struct sess *sp) ...@@ -542,7 +542,7 @@ cnt_fetch(struct sess *sp)
* XXX: also. * XXX: also.
*/ */
sp->obj = STV_NewObject(sp, l, sp->wrk->ttl); sp->obj = STV_NewObject(sp, l, sp->wrk->ttl, nhttp);
if (sp->objhead != NULL) { if (sp->objhead != NULL) {
CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC); CHECK_OBJ_NOTNULL(sp->objhead, OBJHEAD_MAGIC);
...@@ -861,7 +861,7 @@ cnt_miss(struct sess *sp) ...@@ -861,7 +861,7 @@ cnt_miss(struct sess *sp)
AN(sp->objcore); AN(sp->objcore);
AN(sp->objhead); AN(sp->objhead);
WS_Reset(sp->wrk->ws, NULL); WS_Reset(sp->wrk->ws, NULL);
sp->wrk->bereq = &sp->wrk->http[0]; sp->wrk->bereq = sp->wrk->http[0];
http_Setup(sp->wrk->bereq, sp->wrk->ws); http_Setup(sp->wrk->bereq, sp->wrk->ws);
http_FilterHeader(sp, HTTPH_R_FETCH); http_FilterHeader(sp, HTTPH_R_FETCH);
VCL_miss_method(sp); VCL_miss_method(sp);
...@@ -926,7 +926,7 @@ cnt_pass(struct sess *sp) ...@@ -926,7 +926,7 @@ cnt_pass(struct sess *sp)
AZ(sp->obj); AZ(sp->obj);
WS_Reset(sp->wrk->ws, NULL); WS_Reset(sp->wrk->ws, NULL);
sp->wrk->bereq = &sp->wrk->http[0]; sp->wrk->bereq = sp->wrk->http[0];
http_Setup(sp->wrk->bereq, sp->wrk->ws); http_Setup(sp->wrk->bereq, sp->wrk->ws);
http_FilterHeader(sp, HTTPH_R_PASS); http_FilterHeader(sp, HTTPH_R_PASS);
...@@ -976,7 +976,7 @@ cnt_pipe(struct sess *sp) ...@@ -976,7 +976,7 @@ cnt_pipe(struct sess *sp)
sp->acct_req.pipe++; sp->acct_req.pipe++;
WS_Reset(sp->wrk->ws, NULL); WS_Reset(sp->wrk->ws, NULL);
sp->wrk->bereq = &sp->wrk->http[0]; sp->wrk->bereq = sp->wrk->http[0];
http_Setup(sp->wrk->bereq, sp->wrk->ws); http_Setup(sp->wrk->bereq, sp->wrk->ws);
http_FilterHeader(sp, HTTPH_R_PIPE); http_FilterHeader(sp, HTTPH_R_PIPE);
......
...@@ -117,14 +117,49 @@ http_StatusMessage(unsigned status) ...@@ -117,14 +117,49 @@ http_StatusMessage(unsigned status)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
unsigned
HTTP_estimate(unsigned nhttp)
{
/* XXX: We trust the structs to size-aligned as necessary */
return (sizeof (struct http) + (sizeof (txt) + 1) * nhttp);
}
struct http *
HTTP_create(void *p, unsigned nhttp)
{
struct http *hp;
hp = p;
hp->magic = HTTP_MAGIC;
hp->hd = (void*)(hp + 1);
hp->shd = nhttp;
hp->hdf = (void*)(hp->hd + nhttp);
return (hp);
}
/*--------------------------------------------------------------------*/
void void
http_Setup(struct http *hp, struct ws *ws) http_Setup(struct http *hp, struct ws *ws)
{ {
unsigned shd;
txt *hd;
unsigned char *hdf;
/* XXX: This is not elegant, is it efficient ? */
shd = hp->shd;
hd = hp->hd;
hdf = hp->hdf;
memset(hp, 0, sizeof *hp); memset(hp, 0, sizeof *hp);
memset(hd, 0, sizeof *hd * shd);
memset(hdf, 0, sizeof *hdf * shd);
hp->magic = HTTP_MAGIC; hp->magic = HTTP_MAGIC;
hp->ws = ws; hp->ws = ws;
hp->nhd = HTTP_HDR_FIRST; hp->nhd = HTTP_HDR_FIRST;
hp->shd = shd;
hp->hd = hd;
hp->hdf = hdf;
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
...@@ -367,7 +402,7 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p, txt t) ...@@ -367,7 +402,7 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p, txt t)
q--; q--;
*q = '\0'; *q = '\0';
if (hp->nhd < HTTP_HDR_MAX) { if (hp->nhd < hp->shd) {
hp->hdf[hp->nhd] = 0; hp->hdf[hp->nhd] = 0;
hp->hd[hp->nhd].b = p; hp->hd[hp->nhd].b = p;
hp->hd[hp->nhd].e = q; hp->hd[hp->nhd].e = q;
...@@ -556,7 +591,7 @@ void ...@@ -556,7 +591,7 @@ void
http_SetH(struct http *to, unsigned n, const char *fm) http_SetH(struct http *to, unsigned n, const char *fm)
{ {
assert(n < HTTP_HDR_MAX); assert(n < to->shd);
AN(fm); AN(fm);
to->hd[n].b = TRUST_ME(fm); to->hd[n].b = TRUST_ME(fm);
to->hd[n].e = strchr(to->hd[n].b, '\0'); to->hd[n].e = strchr(to->hd[n].b, '\0');
...@@ -567,7 +602,7 @@ static void ...@@ -567,7 +602,7 @@ static void
http_copyh(struct http *to, const struct http *fm, unsigned n) http_copyh(struct http *to, const struct http *fm, unsigned n)
{ {
assert(n < HTTP_HDR_MAX); assert(n < to->shd);
Tcheck(fm->hd[n]); Tcheck(fm->hd[n]);
to->hd[n] = fm->hd[n]; to->hd[n] = fm->hd[n];
to->hdf[n] = fm->hdf[n]; to->hdf[n] = fm->hdf[n];
...@@ -612,9 +647,9 @@ http_copyheader(struct worker *w, int fd, struct http *to, ...@@ -612,9 +647,9 @@ http_copyheader(struct worker *w, int fd, struct http *to,
CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC); CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
assert(n < HTTP_HDR_MAX); assert(n < to->shd);
Tcheck(fm->hd[n]); Tcheck(fm->hd[n]);
if (to->nhd < HTTP_HDR_MAX) { if (to->nhd < to->shd) {
to->hd[to->nhd] = fm->hd[n]; to->hd[to->nhd] = fm->hd[n];
to->hdf[to->nhd] = 0; to->hdf[to->nhd] = 0;
to->nhd++; to->nhd++;
...@@ -630,11 +665,12 @@ http_copyheader(struct worker *w, int fd, struct http *to, ...@@ -630,11 +665,12 @@ http_copyheader(struct worker *w, int fd, struct http *to,
*/ */
unsigned unsigned
http_EstimateWS(const struct http *fm, unsigned how) http_EstimateWS(const struct http *fm, unsigned how, unsigned *nhd)
{ {
unsigned u, l; unsigned u, l;
l = 0; l = 0;
*nhd = HTTP_HDR_FIRST;
CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC); CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
for (u = 0; u < fm->nhd; u++) { for (u = 0; u < fm->nhd; u++) {
if (fm->hd[u].b == NULL) if (fm->hd[u].b == NULL)
...@@ -647,6 +683,7 @@ http_EstimateWS(const struct http *fm, unsigned how) ...@@ -647,6 +683,7 @@ http_EstimateWS(const struct http *fm, unsigned how)
#include "http_headers.h" #include "http_headers.h"
#undef HTTPH #undef HTTPH
l += Tlen(fm->hd[u]) + 1; l += Tlen(fm->hd[u]) + 1;
(*nhd)++;
// fm->hdf[u] |= HDF_COPY; // fm->hdf[u] |= HDF_COPY;
} }
return (l); return (l);
...@@ -755,7 +792,7 @@ http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr) ...@@ -755,7 +792,7 @@ http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
{ {
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
if (to->nhd >= HTTP_HDR_MAX) { if (to->nhd >= to->shd) {
VSL_stats->losthdr++; VSL_stats->losthdr++;
WSL(w, SLT_LostHeader, fd, "%s", hdr); WSL(w, SLT_LostHeader, fd, "%s", hdr);
return; return;
...@@ -827,7 +864,7 @@ http_PrintfHeader(struct worker *w, int fd, struct http *to, ...@@ -827,7 +864,7 @@ http_PrintfHeader(struct worker *w, int fd, struct http *to,
va_start(ap, fmt); va_start(ap, fmt);
n = vsnprintf(to->ws->f, l, fmt, ap); n = vsnprintf(to->ws->f, l, fmt, ap);
va_end(ap); va_end(ap);
if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) { if (n + 1 >= l || to->nhd >= to->shd) {
VSL_stats->losthdr++; VSL_stats->losthdr++;
WSL(w, SLT_LostHeader, fd, "%s", to->ws->f); WSL(w, SLT_LostHeader, fd, "%s", to->ws->f);
WS_Release(to->ws, 0); WS_Release(to->ws, 0);
......
...@@ -117,11 +117,16 @@ WRK_SumStat(struct worker *w) ...@@ -117,11 +117,16 @@ WRK_SumStat(struct worker *w)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void * static void *
wrk_thread_real(struct wq *qp, unsigned shm_workspace, unsigned sess_workspace) wrk_thread_real(struct wq *qp, unsigned shm_workspace, unsigned sess_workspace,
unsigned nhttp, unsigned http_space, unsigned siov)
{ {
struct worker *w, ww; struct worker *w, ww;
unsigned char wlog[shm_workspace]; unsigned char wlog[shm_workspace];
unsigned char ws[sess_workspace]; unsigned char ws[sess_workspace];
unsigned char http0[http_space];
unsigned char http1[http_space];
unsigned char http2[http_space];
struct iovec iov[siov];
struct SHA256Context sha256; struct SHA256Context sha256;
int stats_clean; int stats_clean;
...@@ -133,6 +138,11 @@ wrk_thread_real(struct wq *qp, unsigned shm_workspace, unsigned sess_workspace) ...@@ -133,6 +138,11 @@ wrk_thread_real(struct wq *qp, unsigned shm_workspace, unsigned sess_workspace)
w->wlb = w->wlp = wlog; w->wlb = w->wlp = wlog;
w->wle = wlog + sizeof wlog; w->wle = wlog + sizeof wlog;
w->sha256ctx = &sha256; w->sha256ctx = &sha256;
w->http[0] = HTTP_create(http0, nhttp);
w->http[1] = HTTP_create(http1, nhttp);
w->http[2] = HTTP_create(http2, nhttp);
w->iov = iov;
w->siov = siov;
AZ(pthread_cond_init(&w->cond, NULL)); AZ(pthread_cond_init(&w->cond, NULL));
WS_Init(w->ws, "wrk", ws, sess_workspace); WS_Init(w->ws, "wrk", ws, sess_workspace);
...@@ -202,12 +212,19 @@ static void * ...@@ -202,12 +212,19 @@ static void *
wrk_thread(void *priv) wrk_thread(void *priv)
{ {
struct wq *qp; struct wq *qp;
volatile unsigned nhttp;
unsigned siov;
CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC); CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC);
/* We need to snapshot these two for consistency */ /* We need to snapshot these two for consistency */
nhttp = params->http_headers;
siov = nhttp * 2; /* XXX param ? */
if (siov > IOV_MAX)
siov = IOV_MAX;
return (wrk_thread_real(qp, return (wrk_thread_real(qp,
params->shm_workspace, params->shm_workspace,
params->sess_workspace)); params->sess_workspace,
nhttp, HTTP_estimate(nhttp), siov));
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
......
...@@ -60,8 +60,9 @@ struct sessmem { ...@@ -60,8 +60,9 @@ struct sessmem {
#define SESSMEM_MAGIC 0x555859c5 #define SESSMEM_MAGIC 0x555859c5
struct sess sess; struct sess sess;
struct http http[2];
unsigned workspace; unsigned workspace;
void *wsp;
struct http *http[2];
VTAILQ_ENTRY(sessmem) list; VTAILQ_ENTRY(sessmem) list;
struct sockaddr_storage sockaddr[2]; struct sockaddr_storage sockaddr[2];
}; };
...@@ -99,25 +100,40 @@ static struct sess * ...@@ -99,25 +100,40 @@ static struct sess *
ses_setup(struct sessmem *sm, const struct sockaddr *addr, unsigned len) ses_setup(struct sessmem *sm, const struct sockaddr *addr, unsigned len)
{ {
struct sess *sp; struct sess *sp;
volatile unsigned u; unsigned char *p;
volatile unsigned nws;
volatile unsigned nhttp;
unsigned l, hl;
if (sm == NULL) { if (sm == NULL) {
if (VSL_stats->n_sess_mem >= params->max_sess) if (VSL_stats->n_sess_mem >= params->max_sess)
return (NULL); return (NULL);
/* /*
* It is not necessary to lock mem_workspace, but we * It is not necessary to lock these, but we need to
* need to cache it locally, to make sure we get a * cache them locally, to make sure we get a consistent
* consistent view of it. * view of the value.
*/ */
u = params->sess_workspace; nws = params->sess_workspace;
sm = malloc(sizeof *sm + u); nhttp = params->http_headers;
if (sm == NULL) hl = HTTP_estimate(nhttp);
l = sizeof *sm + nws + 2 * hl;
p = malloc(l);
if (p == NULL)
return (NULL); return (NULL);
/* Don't waste time zeroing the workspace */ /* Don't waste time zeroing the workspace */
memset(sm, 0, sizeof *sm); memset(p, 0, l - nws);
sm = (void*)p;
p += sizeof *sm;
sm->magic = SESSMEM_MAGIC; sm->magic = SESSMEM_MAGIC;
sm->workspace = u; sm->workspace = nws;
VSL_stats->n_sess_mem++; VSL_stats->n_sess_mem++;
sm->http[0] = HTTP_create(p, nhttp);
p += hl;
sm->http[1] = HTTP_create(p, nhttp);
p += hl;
sm->wsp = p;
} }
CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC); CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC);
VSL_stats->n_sess++; VSL_stats->n_sess++;
...@@ -142,9 +158,9 @@ ses_setup(struct sessmem *sm, const struct sockaddr *addr, unsigned len) ...@@ -142,9 +158,9 @@ ses_setup(struct sessmem *sm, const struct sockaddr *addr, unsigned len)
sp->sockaddrlen = len; sp->sockaddrlen = len;
} }
WS_Init(sp->ws, "sess", (void *)(sm + 1), sm->workspace); WS_Init(sp->ws, "sess", sm->wsp, sm->workspace);
sp->http = &sm->http[0]; sp->http = sm->http[0];
sp->http0 = &sm->http[1]; sp->http0 = sm->http[1];
SES_ResetBackendTimeouts(sp); SES_ResetBackendTimeouts(sp);
...@@ -193,7 +209,7 @@ SES_Delete(struct sess *sp) ...@@ -193,7 +209,7 @@ SES_Delete(struct sess *sp)
{ {
struct acct *b = &sp->acct; struct acct *b = &sp->acct;
struct sessmem *sm; struct sessmem *sm;
unsigned workspace; // unsigned workspace;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
sm = sp->mem; sm = sp->mem;
...@@ -213,10 +229,10 @@ SES_Delete(struct sess *sp) ...@@ -213,10 +229,10 @@ SES_Delete(struct sess *sp)
free(sm); free(sm);
} else { } else {
/* Clean and prepare for reuse */ /* Clean and prepare for reuse */
workspace = sm->workspace; // workspace = sm->workspace;
memset(sm, 0, sizeof *sm); // memset(sm, 0, sizeof *sm);
sm->magic = SESSMEM_MAGIC; // sm->magic = SESSMEM_MAGIC;
sm->workspace = workspace; // sm->workspace = workspace;
Lck_Lock(&ses_mem_mtx); Lck_Lock(&ses_mem_mtx);
VTAILQ_INSERT_HEAD(&ses_free_mem[1 - ses_qp], sm, list); VTAILQ_INSERT_HEAD(&ses_free_mem[1 - ses_qp], sm, list);
......
...@@ -153,7 +153,7 @@ WRW_Write(struct worker *w, const void *ptr, int len) ...@@ -153,7 +153,7 @@ WRW_Write(struct worker *w, const void *ptr, int len)
return (0); return (0);
if (len == -1) if (len == -1)
len = strlen(ptr); len = strlen(ptr);
if (w->niov == MAX_IOVS) if (w->niov == w->siov)
(void)WRW_Flush(w); (void)WRW_Flush(w);
w->iov[w->niov].iov_base = TRUST_ME(ptr); w->iov[w->niov].iov_base = TRUST_ME(ptr);
w->iov[w->niov].iov_len = len; w->iov[w->niov].iov_len = len;
...@@ -193,7 +193,7 @@ WRW_Sendfile(struct worker *w, int fd, off_t off, unsigned len) ...@@ -193,7 +193,7 @@ WRW_Sendfile(struct worker *w, int fd, off_t off, unsigned len)
} while (0); } while (0);
#elif defined(__sun) && defined(HAVE_SENDFILEV) #elif defined(__sun) && defined(HAVE_SENDFILEV)
do { do {
sendfilevec_t svvec[HTTP_HDR_MAX * 2 + 1]; sendfilevec_t svvec[params->http_headers * 2 + 1];
size_t xferred = 0, expected = 0; size_t xferred = 0, expected = 0;
int i; int i;
for (i = 0; i < w->niov; i++) { for (i = 0; i < w->niov; i++) {
......
...@@ -101,6 +101,7 @@ struct params { ...@@ -101,6 +101,7 @@ struct params {
unsigned sess_workspace; unsigned sess_workspace;
unsigned obj_workspace; unsigned obj_workspace;
unsigned shm_workspace; unsigned shm_workspace;
unsigned http_headers;
unsigned shm_reclen; unsigned shm_reclen;
......
...@@ -493,6 +493,12 @@ static const struct parspec input_parspec[] = { ...@@ -493,6 +493,12 @@ static const struct parspec input_parspec[] = {
"Minimum is 1024 bytes.", "Minimum is 1024 bytes.",
DELAYED_EFFECT, DELAYED_EFFECT,
"16384", "bytes" }, "16384", "bytes" },
{ "http_headers", tweak_uint, &master.http_headers, 32, UINT_MAX,
"Maximum number of HTTP headers we will deal with.\n"
"This space is preallocated in sessions and workthreads only "
"objects allocate only space for the headers they store.\n",
0,
"64", "header lines" },
{ "obj_workspace", tweak_uint, &master.obj_workspace, 0, UINT_MAX, { "obj_workspace", tweak_uint, &master.obj_workspace, 0, UINT_MAX,
"Bytes of HTTP protocol workspace allocated for objects. " "Bytes of HTTP protocol workspace allocated for objects. "
"This space must be big enough for the entire HTTP protocol " "This space must be big enough for the entire HTTP protocol "
......
...@@ -88,13 +88,15 @@ stv_pick_stevedore(void) ...@@ -88,13 +88,15 @@ stv_pick_stevedore(void)
/*********************************************************************/ /*********************************************************************/
static void static void
STV_InitObj(struct sess *sp, struct object *o, unsigned wsl) STV_InitObj(struct sess *sp, struct object *o, unsigned wsl, unsigned lhttp,
unsigned nhttp)
{ {
memset(o, 0, sizeof *o); memset(o, 0, sizeof *o);
o->magic = OBJECT_MAGIC; o->magic = OBJECT_MAGIC;
WS_Init(o->ws_o, "obj", (o + 1), wsl); o->http = HTTP_create(o + 1, nhttp);
WS_Init(o->ws_o, "obj", (char *)(o + 1) + lhttp, wsl);
WS_Assert(o->ws_o); WS_Assert(o->ws_o);
http_Setup(o->http, o->ws_o); http_Setup(o->http, o->ws_o);
...@@ -109,10 +111,11 @@ STV_InitObj(struct sess *sp, struct object *o, unsigned wsl) ...@@ -109,10 +111,11 @@ STV_InitObj(struct sess *sp, struct object *o, unsigned wsl)
/*********************************************************************/ /*********************************************************************/
struct object * struct object *
STV_NewObject(struct sess *sp, unsigned l, double ttl) STV_NewObject(struct sess *sp, unsigned l, double ttl, unsigned nhttp)
{ {
struct object *o; struct object *o;
struct storage *st; struct storage *st;
unsigned lh;
(void)ttl; (void)ttl;
if (l == 0) if (l == 0)
...@@ -120,21 +123,23 @@ STV_NewObject(struct sess *sp, unsigned l, double ttl) ...@@ -120,21 +123,23 @@ STV_NewObject(struct sess *sp, unsigned l, double ttl)
if (params->obj_workspace > 0 && params->obj_workspace > l) if (params->obj_workspace > 0 && params->obj_workspace > l)
l = params->obj_workspace; l = params->obj_workspace;
lh = HTTP_estimate(nhttp);
if (!sp->wrk->cacheable) { if (!sp->wrk->cacheable) {
o = malloc(sizeof *o + l); o = malloc(sizeof *o + l + lh);
XXXAN(o); XXXAN(o);
STV_InitObj(sp, o, l); STV_InitObj(sp, o, l, lh, nhttp);
return (o); return (o);
} }
st = STV_alloc(sp, sizeof *o + l, sp->objcore); st = STV_alloc(sp, sizeof *o + l + lh, sp->objcore);
XXXAN(st); XXXAN(st);
xxxassert(st->space >= (sizeof *o + l)); xxxassert(st->space >= (sizeof *o + l + lh));
st->len = st->space; st->len = st->space;
o = (void *)st->ptr; /* XXX: align ? */ o = (void *)st->ptr; /* XXX: align ? */
STV_InitObj(sp, o, st->space - sizeof *o); STV_InitObj(sp, o, st->space - (sizeof *o + lh), lh, nhttp);
o->objstore = st; o->objstore = st;
return (o); return (o);
} }
......
...@@ -68,7 +68,8 @@ struct stevedore { ...@@ -68,7 +68,8 @@ struct stevedore {
VTAILQ_ENTRY(stevedore) list; VTAILQ_ENTRY(stevedore) list;
}; };
struct object *STV_NewObject(struct sess *sp, unsigned len, double ttl); struct object *STV_NewObject(struct sess *sp, unsigned len, double ttl,
unsigned nhttp);
struct storage *STV_alloc(struct sess *sp, size_t size, struct objcore *oc); struct storage *STV_alloc(struct sess *sp, size_t size, struct objcore *oc);
void STV_trim(struct storage *st, size_t size); void STV_trim(struct storage *st, size_t size);
void STV_free(struct storage *st); void STV_free(struct storage *st);
......
...@@ -9,7 +9,7 @@ server s1 { ...@@ -9,7 +9,7 @@ server s1 {
txresp -body "012345\n" txresp -body "012345\n"
} -start } -start
varnish v1 -vcl+backend {} -start varnish v1 -arg "-smalloc,1m" -vcl+backend {} -start
varnish v1 -expect n_object == 0 varnish v1 -expect n_object == 0
varnish v1 -expect client_conn == 0 varnish v1 -expect client_conn == 0
......
...@@ -415,13 +415,6 @@ else ...@@ -415,13 +415,6 @@ else
fi fi
AC_DEFINE_UNQUOTED([VCC_CC],"$VCC_CC",[C compiler command line for VCL code]) AC_DEFINE_UNQUOTED([VCC_CC],"$VCC_CC",[C compiler command line for VCL code])
# Define HTTP_HDR_MAX_VAL
AC_ARG_WITH(max-header-fields,
AS_HELP_STRING([--with-max-header-fields=NUM],
[How many header fields to support (default=64)]),
[],
[with_max_header_fields=64])
AC_DEFINE_UNQUOTED(HTTP_HDR_MAX_VAL, $with_max_header_fields, [Define maximum number of header fields supported by varnish ]) AC_DEFINE_UNQUOTED(HTTP_HDR_MAX_VAL, $with_max_header_fields, [Define maximum number of header fields supported by varnish ])
# Use jemalloc on Linux # Use jemalloc on Linux
......
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