[master] 3284aed Store VSC documentation in their own segments and only once, no matter how many instances of the VSC set there are.
Poul-Henning Kamp
phk at FreeBSD.org
Fri Dec 22 21:38:06 UTC 2017
commit 3284aed8679a176ba0e30b91055f6b074b279fd5
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Fri Dec 22 21:37:21 2017 +0000
Store VSC documentation in their own segments and only once, no matter
how many instances of the VSC set there are.
diff --git a/bin/varnishd/common/common_vsc.c b/bin/varnishd/common/common_vsc.c
index 1e8842d..3a719ed 100644
--- a/bin/varnishd/common/common_vsc.c
+++ b/bin/varnishd/common/common_vsc.c
@@ -53,11 +53,19 @@ struct vsc_seg {
unsigned magic;
#define VSC_SEG_MAGIC 0x9b355991
+ struct vsmw *vsm; // keep master/child sep.
const char *nm;
VTAILQ_ENTRY(vsc_seg) list;
void *seg;
+
+ /* VSC segments */
struct vsc_head *head;
void *ptr;
+ struct vsc_seg *doc;
+
+ /* DOC segments */
+ const unsigned char *jp;
+ int refs;
};
static VTAILQ_HEAD(,vsc_seg) vsc_seglist =
@@ -66,41 +74,86 @@ static VTAILQ_HEAD(,vsc_seg) vsc_seglist =
vsc_callback_f *vsc_lock;
vsc_callback_f *vsc_unlock;
+static struct vsc_seg *
+vrt_vsc_mksegv(const char *class, size_t payload, const char *fmt, va_list va)
+{
+ struct vsc_seg *vsg;
+ size_t co;
+
+ co = PRNDUP(sizeof(struct vsc_head));
+ ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
+ AN(vsg);
+ vsg->seg = VSMW_Allocv(heritage.proc_vsmw, class,
+ co + PRNDUP(payload), fmt, va);
+ AN(vsg->seg);
+ vsg->vsm = heritage.proc_vsmw;
+ vsg->head = (void*)vsg->seg;
+ vsg->head->body_offset = co;
+ vsg->ptr = (char*)vsg->seg + co;
+ return (vsg);
+}
+
+static struct vsc_seg *
+vrt_vsc_mksegf(const char *class, size_t payload, const char *fmt, ...)
+{
+ va_list ap;
+ struct vsc_seg *vsg;
+
+ va_start(ap, fmt);
+ vsg = vrt_vsc_mksegv(class, payload, fmt, ap);
+ va_end(ap);
+ return (vsg);
+}
+
void *
VRT_VSC_Alloc(struct vsc_seg **sg, const char *nm, size_t sd,
const unsigned char *jp, size_t sj, const char *fmt, va_list va)
{
- char *p;
- struct vsc_seg *vsg;
+ struct vsc_seg *vsg, *dvsg;
char buf[1024];
- uint64_t co, jo;
+ uintptr_t jjp;
if (vsc_lock != NULL)
vsc_lock();
+ jjp = (uintptr_t)jp;
+
+ VTAILQ_FOREACH(dvsg, &vsc_seglist, list) {
+ if (dvsg->vsm != heritage.proc_vsmw)
+ continue;
+ if (dvsg->jp == NULL || dvsg->jp == jp)
+ break;
+ }
+ if (dvsg == NULL || dvsg->jp == NULL) {
+ /* Create a new documentation segment */
+ dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj,
+ "%jx", (uintmax_t)jjp);
+ AN(dvsg);
+ dvsg->jp = jp;
+ dvsg->head->doc_id = jjp;
+ memcpy(dvsg->ptr, jp, sj);
+ VWMB();
+ dvsg->head->ready = 1;
+ VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list);
+ }
+ AN(dvsg);
+ dvsg->refs++;
+
if (*fmt == '\0')
bprintf(buf, "%s", nm);
else
bprintf(buf, "%s.%s", nm, fmt);
- co = PRNDUP(sizeof(struct vsc_head));
- jo = co + PRNDUP(sd);
AN(heritage.proc_vsmw);
- p = VSMW_Allocv(heritage.proc_vsmw, VSC_CLASS,
- jo + PRNDUP(sj), buf, va);
- AN(p);
- ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
+ vsg = vrt_vsc_mksegv(VSC_CLASS, sd, buf, va);
AN(vsg);
- vsg->seg = p;
- vsg->head = (void*)p;
- vsg->head->ctr_offset = co;
- vsg->ptr = p + co;
+ vsg->nm = nm;
+ vsg->doc = dvsg;
+ vsg->head->doc_id = jjp;
VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list);
- memcpy(p + jo, jp, sj);
VWMB();
- vsg->head->json_offset = jo;
- vsg->nm = nm;
+ vsg->head->ready = 1;
if (vsc_unlock != NULL)
vsc_unlock();
if (sg != NULL)
@@ -111,16 +164,27 @@ VRT_VSC_Alloc(struct vsc_seg **sg, const char *nm, size_t sd,
void
VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg)
{
+ struct vsc_seg *dvsg;
if (vsc_lock != NULL)
vsc_lock();
AN(heritage.proc_vsmw);
CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
+ AZ(vsg->jp);
+ CHECK_OBJ_NOTNULL(vsg->doc, VSC_SEG_MAGIC);
+ assert(vsg->vsm == heritage.proc_vsmw);
assert(vsg->nm == nm);
+
+ dvsg = vsg->doc;
VSMW_Free(heritage.proc_vsmw, &vsg->seg);
VTAILQ_REMOVE(&vsc_seglist, vsg, list);
FREE_OBJ(vsg);
+ if (--dvsg->refs == 0) {
+ VSMW_Free(heritage.proc_vsmw, &dvsg->seg);
+ VTAILQ_REMOVE(&vsc_seglist, dvsg, list);
+ FREE_OBJ(dvsg);
+ }
if (vsc_unlock != NULL)
vsc_unlock();
}
diff --git a/include/vsc_priv.h b/include/vsc_priv.h
index e0d9f2e..88f55dd 100644
--- a/include/vsc_priv.h
+++ b/include/vsc_priv.h
@@ -37,8 +37,10 @@
#define VSC_PRIV_H_INCLUDED
#define VSC_CLASS "Stat"
+#define VSC_DOC_CLASS "StatDoc"
struct vsc_head {
- volatile uint64_t json_offset;
- uint64_t ctr_offset;
+ volatile int ready;
+ uint64_t body_offset;
+ uintptr_t doc_id;
};
diff --git a/lib/libvarnishapi/vsc.c b/lib/libvarnishapi/vsc.c
index 92a4939..8f7c2df 100644
--- a/lib/libvarnishapi/vsc.c
+++ b/lib/libvarnishapi/vsc.c
@@ -69,8 +69,11 @@ struct vsc_seg {
#define VSC_SEG_MAGIC 0x801177d4
VTAILQ_ENTRY(vsc_seg) list;
struct vsm_fantom fantom[1];
- struct vjsn *vj;
struct vsc_head *head;
+ char *body;
+
+ struct vjsn *vj;
+
unsigned npoints;
struct vsc_pt *points;
};
@@ -205,7 +208,7 @@ vsc_clean_point(struct vsc_pt *point)
}
static int
-vsc_fill_point(const struct vsc *vsc, struct vsc_seg *seg,
+vsc_fill_point(const struct vsc *vsc, const struct vsc_seg *seg,
const struct vjsn_val *vv, struct vsb *vsb, struct vsc_pt *point)
{
struct vjsn_val *vt;
@@ -285,9 +288,7 @@ vsc_fill_point(const struct vsc *vsc, struct vsc_seg *seg,
vt = vjsn_child(vv, "index");
AN(vt);
- point->point.ptr = (volatile void*)
- ((volatile char*)seg->fantom->b +
- seg->head->ctr_offset + atoi(vt->value));
+ point->point.ptr = (volatile void*)(seg->body + atoi(vt->value));
return (1);
}
@@ -301,22 +302,24 @@ vsc_del_seg(const struct vsc *vsc, struct vsm *vsm, struct vsc_seg *sp)
AN(vsm);
CHECK_OBJ_NOTNULL(sp, VSC_SEG_MAGIC);
AZ(VSM_Unmap(vsm, sp->fantom));
- vjsn_delete(&sp->vj);
- pp = sp->points;
- for (u = 0; u < sp->npoints; u++, pp++) {
- if (vsc->fdestroy != NULL)
- vsc->fdestroy(vsc->priv, &pp->point);
- vsc_clean_point(pp);
+ if (sp->vj != NULL) {
+ vjsn_delete(&sp->vj);
+ } else {
+ pp = sp->points;
+ for (u = 0; u < sp->npoints; u++, pp++) {
+ if (vsc->fdestroy != NULL)
+ vsc->fdestroy(vsc->priv, &pp->point);
+ vsc_clean_point(pp);
+ }
+ free(sp->points);
}
- free(sp->points);
FREE_OBJ(sp);
}
static struct vsc_seg *
vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp)
{
- struct vsc_seg *sp;
- const char *p;
+ struct vsc_seg *sp, *spd;
const char *e;
struct vjsn_val *vv, *vve;
struct vsb *vsb;
@@ -336,34 +339,43 @@ vsc_add_seg(const struct vsc *vsc, struct vsm *vsm, const struct vsm_fantom *fp)
FREE_OBJ(sp);
return (NULL);
}
-
sp->head = sp->fantom->b;
- if (sp->head->json_offset == 0) {
+ if (sp->head->ready == 0) {
VRMB();
usleep(100000);
}
- assert(sp->head->json_offset > 0);
- p = (char*)sp->fantom->b + sp->head->json_offset;
- assert (p < (char*)sp->fantom->e);
- sp->vj = vjsn_parse(p, &e);
- XXXAZ(e);
- vve = vjsn_child(sp->vj->value, "elements");
- AN(vve);
- sp->npoints = strtoul(vve->value, NULL, 0);
- sp->points = calloc(sp->npoints, sizeof *sp->points);
- AN(sp->points);
- vsb = VSB_new_auto();
- AN(vsb);
- vve = vjsn_child(sp->vj->value, "elem");
- AN(vve);
- pp = sp->points;
- VTAILQ_FOREACH(vv, &vve->children, list) {
- if (vsc_fill_point(vsc, sp, vv, vsb, pp) &&
- vsc->fnew != NULL)
- pp->point.priv = vsc->fnew(vsc->priv, &pp->point);
- pp++;
+ assert(sp->head->ready > 0);
+ sp->body = (char*)sp->fantom->b + sp->head->body_offset;
+
+ if (!strcmp(fp->class, VSC_CLASS)) {
+ VTAILQ_FOREACH(spd, &vsc->segs, list)
+ if (spd->head->doc_id == sp->head->doc_id)
+ break;
+ AN(spd);
+ // XXX: Refcount ?
+ vve = vjsn_child(spd->vj->value, "elements");
+ AN(vve);
+ sp->npoints = strtoul(vve->value, NULL, 0);
+ sp->points = calloc(sp->npoints, sizeof *sp->points);
+ AN(sp->points);
+ vsb = VSB_new_auto();
+ AN(vsb);
+ vve = vjsn_child(spd->vj->value, "elem");
+ AN(vve);
+ pp = sp->points;
+ VTAILQ_FOREACH(vv, &vve->children, list) {
+ if (vsc_fill_point(vsc, sp, vv, vsb, pp) &&
+ vsc->fnew != NULL)
+ pp->point.priv =
+ vsc->fnew(vsc->priv, &pp->point);
+ pp++;
+ }
+ VSB_destroy(&vsb);
+ return (sp);
}
- VSB_destroy(&vsb);
+ assert(!strcmp(fp->class, VSC_DOC_CLASS));
+ sp->vj = vjsn_parse(sp->body, &e);
+ XXXAZ(e);
AN(sp->vj);
return (sp);
}
@@ -398,8 +410,10 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv)
AN(vsm);
sp = VTAILQ_FIRST(&vsc->segs);
VSM_FOREACH(&ifantom, vsm) {
- if (strcmp(ifantom.class, VSC_CLASS))
+ if (strcmp(ifantom.class, VSC_CLASS) &&
+ strcmp(ifantom.class, VSC_DOC_CLASS))
continue;
+ sp2 = sp;
while (sp != NULL &&
(strcmp(ifantom.ident, sp->fantom->ident) ||
VSM_StillValid(vsm, sp->fantom) != VSM_valid)) {
@@ -408,19 +422,18 @@ VSC_Iter(struct vsc *vsc, struct vsm *vsm, VSC_iter_f *fiter, void *priv)
VTAILQ_REMOVE(&vsc->segs, sp2, list);
vsc_del_seg(vsc, vsm, sp2);
}
- if (sp != NULL) {
- if (fiter != NULL)
- i = vsc_iter_seg(vsc, sp, fiter, priv);
- sp = VTAILQ_NEXT(sp, list);
- } else {
+ if (sp == NULL) {
sp = vsc_add_seg(vsc, vsm, &ifantom);
if (sp != NULL) {
VTAILQ_INSERT_TAIL(&vsc->segs, sp, list);
- if (fiter != NULL)
- i = vsc_iter_seg(vsc, sp, fiter, priv);
- sp = NULL;
+ sp2 = NULL;
}
+ } else {
+ sp2 = VTAILQ_NEXT(sp, list);
}
+ if (sp != NULL && fiter != NULL)
+ i = vsc_iter_seg(vsc, sp, fiter, priv);
+ sp = sp2;
if (i)
break;
}
More information about the varnish-commit
mailing list