Commit 9831187e authored by Lasse Karstensen's avatar Lasse Karstensen
parents d96e763c 7b255309
......@@ -108,7 +108,6 @@ struct poolparam;
struct sess;
struct sesspool;
struct vbc;
struct vbo;
struct vef_priv;
struct vrt_backend;
struct vsb;
......@@ -298,7 +297,7 @@ struct worker {
struct objhead *nobjhead;
struct objcore *nobjcore;
struct waitinglist *nwaitinglist;
struct vbo *nvbo;
struct busyobj *nbo;
void *nhashpriv;
struct dstat stats;
......@@ -459,7 +458,14 @@ enum busyobj_state_e {
struct busyobj {
unsigned magic;
#define BUSYOBJ_MAGIC 0x23b95567
struct vbo *vbo;
struct lock mtx;
char *end;
/*
* All fields from refcount and down are zeroed when the busyobj
* is recycled.
*/
unsigned refcount;
uint8_t *vary;
unsigned is_gzip;
......@@ -479,7 +485,7 @@ struct busyobj {
struct http_conn htc;
enum body_status body_status;
struct pool_task task;
struct pool_task fetch_task;
struct vef_priv *vef_priv;
......@@ -719,9 +725,9 @@ double BAN_Time(const struct ban *ban);
/* cache_busyobj.c */
void VBO_Init(void);
struct busyobj *VBO_GetBusyObj(struct worker *wrk);
void VBO_RefBusyObj(const struct busyobj *busyobj);
void VBO_RefBusyObj(struct busyobj *busyobj);
void VBO_DerefBusyObj(struct worker *wrk, struct busyobj **busyobj);
void VBO_Free(struct vbo **vbo);
void VBO_Free(struct busyobj **vbo);
/* cache_center.c [CNT] */
void CNT_Session(struct sess *sp);
......
......@@ -40,15 +40,6 @@
static struct mempool *vbopool;
struct vbo {
unsigned magic;
#define VBO_MAGIC 0xde3d8223
struct lock mtx;
unsigned refcount;
char *end;
struct busyobj bo;
};
/*--------------------------------------------------------------------
*/
......@@ -56,7 +47,7 @@ void
VBO_Init(void)
{
vbopool = MPL_New("vbo", &cache_param->vbo_pool,
vbopool = MPL_New("busyobj", &cache_param->vbo_pool,
&cache_param->workspace_backend);
AN(vbopool);
}
......@@ -65,130 +56,122 @@ VBO_Init(void)
* BusyObj handling
*/
static struct vbo *
static struct busyobj *
vbo_New(void)
{
struct vbo *vbo;
struct busyobj *bo;
unsigned sz;
vbo = MPL_Get(vbopool, &sz);
AN(vbo);
vbo->magic = VBO_MAGIC;
vbo->end = (char *)vbo + sz;
Lck_New(&vbo->mtx, lck_busyobj);
return (vbo);
bo = MPL_Get(vbopool, &sz);
XXXAN(bo);
bo->magic = BUSYOBJ_MAGIC;
bo->end = (char *)bo + sz;
Lck_New(&bo->mtx, lck_busyobj);
return (bo);
}
void
VBO_Free(struct vbo **vbop)
VBO_Free(struct busyobj **bop)
{
struct vbo *vbo;
AN(vbop);
vbo = *vbop;
*vbop = NULL;
CHECK_OBJ_NOTNULL(vbo, VBO_MAGIC);
AZ(vbo->refcount);
Lck_Delete(&vbo->mtx);
MPL_Free(vbopool, vbo);
struct busyobj *bo;
AN(bop);
bo = *bop;
*bop = NULL;
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
AZ(bo->refcount);
Lck_Delete(&bo->mtx);
MPL_Free(vbopool, bo);
}
struct busyobj *
VBO_GetBusyObj(struct worker *wrk)
{
struct vbo *vbo = NULL;
struct busyobj *bo = NULL;
uint16_t nhttp;
unsigned sz;
char *p;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
if (wrk->nvbo != NULL) {
vbo = wrk->nvbo;
wrk->nvbo = NULL;
if (wrk->nbo != NULL) {
bo = wrk->nbo;
wrk->nbo = NULL;
}
if (vbo == NULL)
vbo = vbo_New();
if (bo == NULL)
bo = vbo_New();
CHECK_OBJ_NOTNULL(vbo, VBO_MAGIC);
AZ(vbo->refcount);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
AZ(bo->refcount);
AZ(vbo->bo.magic);
vbo->refcount = 1;
vbo->bo.magic = BUSYOBJ_MAGIC;
vbo->bo.vbo = vbo;
bo->refcount = 1;
p = (void*)(vbo + 1);
p = (void*)(bo + 1);
p = (void*)PRNDUP(p);
assert(p < vbo->end);
assert(p < bo->end);
nhttp = (uint16_t)cache_param->http_max_hdr;
sz = HTTP_estimate(nhttp);
vbo->bo.bereq = HTTP_create(p, nhttp);
bo->bereq = HTTP_create(p, nhttp);
p += sz;
p = (void*)PRNDUP(p);
assert(p < vbo->end);
assert(p < bo->end);
vbo->bo.beresp = HTTP_create(p, nhttp);
bo->beresp = HTTP_create(p, nhttp);
p += sz;
p = (void*)PRNDUP(p);
assert(p < vbo->end);
assert(p < bo->end);
sz = cache_param->vsl_buffer;
VSL_Setup(vbo->bo.vsl, p, sz);
VSL_Setup(bo->vsl, p, sz);
p += sz;
p = (void*)PRNDUP(p);
assert(p < vbo->end);
assert(p < bo->end);
WS_Init(vbo->bo.ws, "bo", p, vbo->end - p);
WS_Init(bo->ws, "bo", p, bo->end - p);
return (&vbo->bo);
return (bo);
}
void
VBO_RefBusyObj(const struct busyobj *busyobj)
VBO_RefBusyObj(struct busyobj *bo)
{
struct vbo *vbo;
CHECK_OBJ_NOTNULL(busyobj, BUSYOBJ_MAGIC);
vbo = busyobj->vbo;
CHECK_OBJ_NOTNULL(vbo, VBO_MAGIC);
Lck_Lock(&vbo->mtx);
assert(vbo->refcount > 0);
vbo->refcount++;
Lck_Unlock(&vbo->mtx);
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
Lck_Lock(&bo->mtx);
assert(bo->refcount > 0);
bo->refcount++;
Lck_Unlock(&bo->mtx);
}
void
VBO_DerefBusyObj(struct worker *wrk, struct busyobj **pbo)
{
struct busyobj *bo;
struct vbo *vbo;
unsigned r;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_ORNULL(wrk, WORKER_MAGIC);
AN(pbo);
bo = *pbo;
*pbo = NULL;
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
vbo = bo->vbo;
CHECK_OBJ_NOTNULL(vbo, VBO_MAGIC);
Lck_Lock(&vbo->mtx);
assert(vbo->refcount > 0);
r = --vbo->refcount;
Lck_Unlock(&vbo->mtx);
Lck_Lock(&bo->mtx);
assert(bo->refcount > 0);
r = --bo->refcount;
Lck_Unlock(&bo->mtx);
if (r)
return;
VSL_Flush(vbo->bo.vsl, 0);
/* XXX: Sanity checks & cleanup */
memset(&vbo->bo, 0, sizeof vbo->bo);
VSL_Flush(bo->vsl, 0);
memset(&bo->refcount, 0,
sizeof *bo - offsetof(struct busyobj, refcount));
if (cache_param->bo_cache && wrk->nvbo == NULL)
wrk->nvbo = vbo;
if (cache_param->bo_cache && wrk != NULL && wrk->nbo == NULL)
wrk->nbo = bo;
else
VBO_Free(&vbo);
VBO_Free(&bo);
}
......@@ -903,23 +903,19 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
bo = req->busyobj;
CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
#if 1
FetchBody(wrk, bo);
#else
bo->task.func = FetchBody;
bo->task.priv = bo;
if (Pool_Task(wrk->pool, &bo->task, POOL_NO_QUEUE)) {
bo->fetch_task.func = FetchBody;
bo->fetch_task.priv = bo;
/* Gain a reference for FetchBody() */
VBO_RefBusyObj(bo);
if (Pool_Task(wrk->pool, &bo->fetch_task, POOL_NO_QUEUE))
FetchBody(wrk, bo);
} else {
while (bo->state < BOS_FAILED)
(void)usleep(10000);
}
#endif
while (bo->state < BOS_FAILED)
(void)usleep(10000);
assert(bo->state >= BOS_FAILED);
http_Teardown(bo->bereq);
http_Teardown(bo->beresp);
bo->vfp = NULL;
assert(WRW_IsReleased(wrk));
AZ(bo->vbc);
AN(req->director);
......@@ -938,7 +934,7 @@ cnt_fetchbody(struct sess *sp, struct worker *wrk, struct req *req)
AN(req->obj->objcore);
AN(req->obj->objcore->ban);
AZ(req->obj->ws_o->overflow);
HSH_Unbusy(req->obj->objcore);
HSH_Unbusy(&wrk->stats, req->obj->objcore);
}
VBO_DerefBusyObj(wrk, &req->busyobj);
wrk->acct_tmp.fetch++;
......
......@@ -298,7 +298,7 @@ fetch_chunked(struct busyobj *bo, struct http_conn *htc)
do {
/* Skip leading whitespace */
do {
if (HTC_Read(htc, buf, 1) <= 0)
if (HTC_Read(htc, buf, 1) <= 0)
return (FetchError(bo, "chunked read err"));
} while (vct_islws(buf[0]));
......@@ -527,7 +527,13 @@ FetchHdr(struct sess *sp, int need_host_hdr, int sendbody)
return (0);
}
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------
* This function is either called by the requesting thread OR by a
* dedicated body-fetch work-thread.
*
* We get passed the busyobj in the priv arg, and we inherit a
* refcount on it, which we must release, when done fetching.
*/
void
FetchBody(struct worker *wrk, void *priv)
......@@ -619,53 +625,58 @@ FetchBody(struct worker *wrk, void *priv)
*/
AZ(vfp_nop_end(bo));
bo->vfp = NULL;
VSLb(bo->vsl, SLT_Fetch_Body, "%u(%s) cls %d mklen %d",
bo->body_status, body_status(bo->body_status),
cls, mklen);
http_Teardown(bo->bereq);
http_Teardown(bo->beresp);
if (bo->state == BOS_FAILED) {
wrk->stats.fetch_failed++;
VDI_CloseFd(&bo->vbc);
obj->len = 0;
bo->stats = NULL;
return;
}
} else {
assert(bo->state == BOS_FETCHING);
assert(bo->state == BOS_FETCHING);
if (cls == 0 && bo->should_close)
cls = 1;
if (cls == 0 && bo->should_close)
cls = 1;
VSLb(bo->vsl, SLT_Length, "%zd", obj->len);
VSLb(bo->vsl, SLT_Length, "%zd", obj->len);
{
/* Sanity check fetch methods accounting */
ssize_t uu;
{
/* Sanity check fetch methods accounting */
ssize_t uu;
uu = 0;
VTAILQ_FOREACH(st, &obj->store, list)
uu += st->len;
if (bo->do_stream)
/* Streaming might have started freeing stuff */
assert (uu <= obj->len);
uu = 0;
VTAILQ_FOREACH(st, &obj->store, list)
uu += st->len;
if (bo->do_stream)
/* Streaming might have started freeing stuff */
assert (uu <= obj->len);
else
assert(uu == obj->len);
}
else
assert(uu == obj->len);
}
if (mklen > 0) {
http_Unset(obj->http, H_Content_Length);
http_PrintfHeader(obj->http, "Content-Length: %zd", obj->len);
}
if (mklen > 0) {
http_Unset(obj->http, H_Content_Length);
http_PrintfHeader(obj->http,
"Content-Length: %zd", obj->len);
}
bo->state = BOS_FINISHED;
bo->state = BOS_FINISHED;
if (cls)
VDI_CloseFd(&bo->vbc);
else
VDI_RecycleFd(&bo->vbc);
if (cls)
VDI_CloseFd(&bo->vbc);
else
VDI_RecycleFd(&bo->vbc);
}
bo->stats = NULL;
VBO_DerefBusyObj(wrk, &bo);
}
/*--------------------------------------------------------------------
......
......@@ -125,14 +125,13 @@ HSH_Cleanup(struct worker *wrk)
if (wrk->nwaitinglist != NULL) {
FREE_OBJ(wrk->nwaitinglist);
wrk->nwaitinglist = NULL;
wrk->stats.n_waitinglist--;
}
if (wrk->nhashpriv != NULL) {
/* XXX: If needed, add slinger method for this */
free(wrk->nhashpriv);
wrk->nhashpriv = NULL;
}
if (wrk->nvbo != NULL)
VBO_Free(&wrk->nvbo);
}
void
......@@ -470,7 +469,7 @@ HSH_Lookup(struct sess *sp, struct objhead **poh)
*/
static void
hsh_rush(struct objhead *oh)
hsh_rush(struct dstat *ds, struct objhead *oh)
{
unsigned u;
struct sess *sp;
......@@ -499,6 +498,7 @@ hsh_rush(struct objhead *oh)
if (VTAILQ_EMPTY(&wl->list)) {
oh->waitinglist = NULL;
FREE_OBJ(wl);
ds->n_waitinglist--;
}
}
......@@ -578,12 +578,12 @@ HSH_Drop(struct worker *wrk, struct object **oo)
AssertObjCorePassOrBusy((*oo)->objcore);
(*oo)->exp.ttl = -1.;
if ((*oo)->objcore != NULL) /* Pass has no objcore */
HSH_Unbusy((*oo)->objcore);
HSH_Unbusy(&wrk->stats, (*oo)->objcore);
(void)HSH_Deref(&wrk->stats, NULL, oo);
}
void
HSH_Unbusy(struct objcore *oc)
HSH_Unbusy(struct dstat *ds, struct objcore *oc)
{
struct objhead *oh;
......@@ -605,7 +605,7 @@ HSH_Unbusy(struct objcore *oc)
oc->flags &= ~OC_F_BUSY;
oc->busyobj = NULL;
if (oh->waitinglist != NULL)
hsh_rush(oh);
hsh_rush(ds, oh);
AN(oc->ban);
Lck_Unlock(&oh->mtx);
}
......@@ -682,7 +682,7 @@ HSH_Deref(struct dstat *ds, struct objcore *oc, struct object **oo)
AN(oc->methods);
}
if (oh->waitinglist != NULL)
hsh_rush(oh);
hsh_rush(ds, oh);
Lck_Unlock(&oh->mtx);
if (r != 0)
return (r);
......
......@@ -128,6 +128,7 @@ RES_BuildHttp(const struct sess *sp)
if (req->res_mode & RES_CHUNKED)
http_SetHeader(req->resp, "Transfer-Encoding: chunked");
http_Unset(req->resp, H_Date);
VTIM_format(VTIM_real(), time_str);
http_PrintfHeader(req->resp, "Date: %s", time_str);
......
......@@ -147,8 +147,8 @@ wrk_thread_real(void *priv, unsigned thread_workspace)
if (w->vcl != NULL)
VCL_Rel(&w->vcl);
AZ(pthread_cond_destroy(&w->cond));
if (w->nvbo != NULL)
VBO_Free(&w->nvbo);
if (w->nbo != NULL)
VBO_Free(&w->nbo);
HSH_Cleanup(w);
WRK_SumStat(w);
return (NULL);
......
......@@ -53,7 +53,6 @@ struct hash_slinger {
/* cache_hash.c */
void HSH_Cleanup(struct worker *w);
struct objcore *HSH_Lookup(struct sess *sp, struct objhead **poh);
void HSH_Unbusy(struct objcore *);
void HSH_Ref(struct objcore *o);
void HSH_Drop(struct worker *, struct object **);
void HSH_Init(const struct hash_slinger *slinger);
......@@ -94,6 +93,7 @@ struct objhead {
#define hoh_head _u.n.u_n_hoh_head
};
void HSH_Unbusy(struct dstat *, struct objcore *);
void HSH_DeleteObjHead(struct dstat *, struct objhead *oh);
int HSH_Deref(struct dstat *, struct objcore *oc, struct object **o);
#endif /* VARNISH_CACHE_CHILD */
......
......@@ -9,7 +9,11 @@ server s1 {
send "Baba\n"
} -start
varnish v1 -vcl+backend {} -start
varnish v1 -vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
}
} -start
varnish v1 -cliok "param.set between_bytes_timeout 1"
client c1 {
......
......@@ -13,6 +13,9 @@ varnish v1 -vcl+backend {
sub vcl_miss {
set bereq.between_bytes_timeout = 2s;
}
sub vcl_fetch {
set beresp.do_stream = false;
}
} -start
client c1 {
......
......@@ -15,6 +15,9 @@ varnish v1 -vcl {
.port = "${s1_port}";
.between_bytes_timeout = 1s;
}
sub vcl_fetch {
set beresp.do_stream = false;
}
} -start
client c1 {
......
......@@ -11,7 +11,11 @@ server s1 {
send "\n"
} -start
varnish v1 -vcl+backend {} -start
varnish v1 -vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
}
} -start
client c1 {
txreq -url /foo
......
......@@ -21,6 +21,8 @@ varnish v1 \
-arg {-p diag_bitmap=0x00010000} \
-vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
if (req.url == "/gunzip") {
set beresp.do_gunzip = true;
}
......
......@@ -11,7 +11,11 @@ server s1 {
send "\r\n"
} -start
varnish v1 -vcl+backend {} -start
varnish v1 -vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
}
} -start
client c1 {
txreq
......
......@@ -26,7 +26,11 @@ server s1 {
varnish v1 \
-arg {-p diag_bitmap=0x00010000} \
-vcl+backend {}
-vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
}
}
varnish v1 -start
......
......@@ -9,6 +9,7 @@ server s1 {
varnish v1 -arg "-smalloc,1M" -arg "-pgzip_level=0" -vcl+backend {
sub vcl_fetch {
set beresp.do_stream = false;
set beresp.do_gzip = true;
}
} -start
......
......@@ -50,7 +50,7 @@ Description
Example
set beresp.http.x-nice = std.tolower("VerY");
set_up_tos
set_ip_tos
----------
Prototype
set_ip_tos(INT i)
......
......@@ -9,7 +9,7 @@ memory segment. When the end of the segment is reached we start over,
overwriting old data. This is much, much faster then logging to a file
and it doesn't require disk space.
The flip side is that if you forget to have program actually write the
The flip side is that if you forget to have a program actually write the
logs to disk they will disappear.
varnishlog is one of the programs you can use to look at what Varnish
......
......@@ -135,7 +135,7 @@ down for, uhm, examples.
Example 1 - manipulating headers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Lets say we want to remove the cookie for all objects in the /static
Lets say we want to remove the cookie for all objects in the /images
directory of our web server::
sub vcl_recv {
......
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