/*--------------------------------------------------------------------*/
+#define L0(n)
+#define L1(n) int n;
+#define MAC_STAT(n, t, l, f, e) L##l(n)
+struct dstat {
+#include "stat_field.h"
+};
+#undef MAC_STAT
+#undef L0
+#undef L1
+
+/*--------------------------------------------------------------------*/
+
struct worker {
unsigned magic;
#define WORKER_MAGIC 0x6391adcf
struct objhead *nobjhead;
struct object *nobj;
struct objcore *nobjcore;
+ struct dstat *stats;
double lastused;
void WRK_Init(void);
int WRK_Queue(struct workreq *wrq);
void WRK_QueueSession(struct sess *sp);
+void WRK_SumStat(struct worker *w);
void WRW_Reserve(struct worker *w, int *fd);
void WRW_Release(struct worker *w);
RES_WriteObj(sp);
AZ(sp->wrk->wfd);
- HSH_Deref(&sp->obj);
+ HSH_Deref(sp->wrk, &sp->obj);
sp->step = STP_DONE;
return (0);
}
}
/* Drop our object, we won't need it */
- HSH_Deref(&sp->obj);
+ HSH_Deref(sp->wrk, &sp->obj);
switch(sp->handling) {
case VCL_RET_PASS:
if (sp->obj->objcore->flags & OC_F_PASS) {
VSL_stats->cache_hitpass++;
WSP(sp, SLT_HitPass, "%u", sp->obj->xid);
- HSH_Deref(&sp->obj);
+ HSH_Deref(sp->wrk, &sp->obj);
sp->step = STP_PASS;
return (0);
}
double t;
struct sess *sp;
unsigned char logbuf[1024]; /* XXX size ? */
+ struct dstat stats;
THR_SetName("cache-timeout");
(void)arg;
sp = SES_New(NULL, 0);
XXXAN(sp);
+ memset(&ww, 0, sizeof ww);
+ memset(&stats, 0, sizeof stats);
sp->wrk = &ww;
ww.magic = WORKER_MAGIC;
ww.wlp = ww.wlb = logbuf;
ww.wle = logbuf + sizeof logbuf;
+ ww.stats = &stats;
AZ(sleep(10)); /* XXX: Takes time for VCL to arrive */
VCL_Get(&sp->vcl);
if (oc == NULL || oc->timer_when > t) { /* XXX: > or >= ? */
Lck_Unlock(&exp_mtx);
WSL_Flush(&ww, 0);
+ WRK_SumStat(&ww);
AZ(sleep(1));
VCL_Refresh(&sp->vcl);
t = TIM_real();
oc->flags &= ~OC_F_ONLRU;
VSL_stats->n_expired++;
Lck_Unlock(&exp_mtx);
- HSH_Deref(&o);
+ HSH_Deref(&ww, &o);
}
}
if (sp->handling == VCL_RET_DISCARD) {
WSL(sp->wrk, SLT_ExpKill, 0, "%u LRU", o->xid);
- HSH_Deref(&o);
+ HSH_Deref(sp->wrk, &o);
return (1);
}
VTAILQ_INIT(&oh->waitinglist);
Lck_New(&oh->mtx);
w->nobjhead = oh;
- VSL_stats->n_objecthead++;
+ w->stats->n_objecthead++;
}
CHECK_OBJ_NOTNULL(w->nobjhead, OBJHEAD_MAGIC);
VTAILQ_INIT(&o->store);
VTAILQ_INIT(&o->esibits);
w->nobj = o;
- VSL_stats->n_object++;
+ w->stats->n_object++;
}
CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
}
void
-HSH_DeleteObjHead(struct objhead *oh)
+HSH_DeleteObjHead(struct worker *w, struct objhead *oh)
{
AZ(oh->refcnt);
assert(VTAILQ_EMPTY(&oh->objcs));
Lck_Delete(&oh->mtx);
- VSL_stats->n_objecthead--;
+ w->stats->n_objecthead--;
free(oh->hash);
FREE_OBJ(oh);
}
o->cacheable = 0;
if (o->objcore != NULL) /* Pass has no objcore */
HSH_Unbusy(sp);
- HSH_Deref(&sp->obj);
+ HSH_Deref(sp->wrk, &sp->obj);
}
void
if (oh != NULL)
Lck_Unlock(&oh->mtx);
if (parent != NULL)
- HSH_Deref(&parent);
+ HSH_Deref(sp->wrk, &parent);
}
void
}
void
-HSH_Deref(struct object **oo)
+HSH_Deref(struct worker *w, struct object **oo)
{
struct object *o;
struct objhead *oh;
ESI_Destroy(o);
HSH_Freestore(o);
STV_free(o->objstore);
- VSL_stats->n_object--;
+ w->stats->n_object--;
if (oh == NULL) {
AZ(oc);
assert(oh->refcnt > 0);
if (hash->deref(oh))
return;
- HSH_DeleteObjHead(oh);
+ HSH_DeleteObjHead(w, oh);
}
void
static pthread_cond_t herder_cond;
static struct lock herder_mtx;
+static struct lock wstat_mtx;
/*--------------------------------------------------------------------
* Write data to fd
/*--------------------------------------------------------------------*/
+static void
+wrk_sumstat(struct worker *w)
+{
+
+ Lck_AssertHeld(&wstat_mtx);
+#define L0(n)
+#define L1(n) VSL_stats->n += w->stats->n
+#define MAC_STAT(n, t, l, f, d) L##l(n);
+#include "stat_field.h"
+#undef MAC_STAT
+#undef L0
+#undef L1
+ memset(w->stats, 0, sizeof *w->stats);
+}
+
+void
+WRK_SumStat(struct worker *w)
+{
+ Lck_Lock(&wstat_mtx);
+ wrk_sumstat(w);
+ Lck_Unlock(&wstat_mtx);
+}
+
+/*--------------------------------------------------------------------*/
+
static void *
wrk_thread(void *priv)
{
struct wq *qp;
unsigned char wlog[params->shm_workspace];
struct SHA256Context sha256;
+ struct dstat stats;
+ unsigned stats_clean = 0;
THR_SetName("cache-worker");
w = &ww;
CAST_OBJ_NOTNULL(qp, priv, WQ_MAGIC);
memset(w, 0, sizeof *w);
+ memset(&stats, 0, sizeof stats);
w->magic = WORKER_MAGIC;
+ w->stats = &stats;
w->lastused = NAN;
w->wlb = w->wlp = wlog;
w->wle = wlog + sizeof wlog;
if (isnan(w->lastused))
w->lastused = TIM_real();
VTAILQ_INSERT_HEAD(&qp->idle, w, list);
+ if (!stats_clean) {
+ Lck_Lock(&wstat_mtx);
+ wrk_sumstat(w);
+ stats_clean = 1;
+ Lck_Unlock(&wstat_mtx);
+ }
Lck_CondWait(&w->cond, &qp->mtx);
}
if (w->wrq == NULL)
AN(w->wrq);
AN(w->wrq->func);
w->lastused = NAN;
+ stats_clean = 0;
w->wrq->func(w, w->wrq->priv);
AZ(w->wfd);
assert(w->wlp == w->wlb);
w->wrq = NULL;
+ if (!Lck_Trylock(&wstat_mtx)) {
+ wrk_sumstat(w);
+ stats_clean = 1;
+ Lck_Unlock(&wstat_mtx);
+ }
Lck_Lock(&qp->mtx);
}
qp->nthr--;
Lck_Unlock(&qp->mtx);
+ AN(stats_clean);
VSL(SLT_WorkThread, 0, "%p end", w);
if (w->vcl != NULL)
AZ(pthread_cond_init(&herder_cond, NULL));
Lck_New(&herder_mtx);
+ Lck_New(&wstat_mtx);
wrk_addpools(params->wthread_pools);
AZ(pthread_create(&tp, NULL, wrk_herdtimer_thread, NULL));
{
struct objhead *oh, *oh2;
struct hcb_y *y;
+ struct worker ww;
+ struct dstat stats;
+
+ memset(&ww, 0, sizeof ww);
+ memset(&stats, 0, sizeof stats);
+ ww.magic = WORKER_MAGIC;
+ ww.stats = &stats;
THR_SetName("hcb_cleaner");
(void)priv;
fprintf(stderr, "OH %p is cold enough\n", oh);
#endif
oh->refcnt = 0;
- HSH_DeleteObjHead(oh);
+ HSH_DeleteObjHead(&ww, oh);
}
}
Lck_Unlock(&hcb_mtx);
+ WRK_SumStat(&ww);
}
}
/* cache_hash.c */
void HSH_Prealloc(struct sess *sp);
-void HSH_DeleteObjHead(struct objhead *oh);
void HSH_Freestore(struct object *o);
void HSH_Copy(const struct sess *sp, struct objhead *o);
struct object *HSH_Lookup(struct sess *sp);
void HSH_Unbusy(const struct sess *sp);
void HSH_Ref(struct object *o);
-void HSH_Deref(struct object **o);
void HSH_Drop(struct sess *sp);
double HSH_Grace(double g);
void HSH_Init(void);
};
extern unsigned save_hash;
+void HSH_DeleteObjHead(struct worker *w, struct objhead *oh);
+void HSH_Deref(struct worker *w, struct object **o);
#endif /* VARNISH_CACHE_CHILD */
MAC_STAT(n_srcaddr_act, uint64_t, 0, 'i', "N active struct srcaddr")
MAC_STAT(n_sess_mem, uint64_t, 0, 'i', "N struct sess_mem")
MAC_STAT(n_sess, uint64_t, 0, 'i', "N struct sess")
-MAC_STAT(n_object, uint64_t, 0, 'i', "N struct object")
-MAC_STAT(n_objecthead, uint64_t, 0, 'i', "N struct objecthead")
+MAC_STAT(n_object, uint64_t, 1, 'i', "N struct object")
+MAC_STAT(n_objecthead, uint64_t, 1, 'i', "N struct objecthead")
MAC_STAT(n_smf, uint64_t, 0, 'i', "N struct smf")
MAC_STAT(n_smf_frag, uint64_t, 0, 'i', "N small free smf")
MAC_STAT(n_smf_large, uint64_t, 0, 'i', "N large free smf")