[PATCH] Expire callback implementation

Martin Blix Grydeland martin at varnish-software.com
Mon May 26 15:05:07 CEST 2014


---
 bin/varnishd/cache/cache.h                     | 19 ++++++-
 bin/varnishd/cache/cache_expire.c              | 76 +++++++++++++++++++++++++-
 bin/varnishd/cache/cache_hash.c                |  2 +-
 bin/varnishd/storage/storage_persistent_silo.c |  2 +-
 4 files changed, 92 insertions(+), 7 deletions(-)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index c8d8d89..4c0196a 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -291,6 +291,18 @@ struct exp {
 
 /*--------------------------------------------------------------------*/
 
+typedef void exp_callback_f(struct dstat *ds, struct objcore *oc, void *priv);
+struct exp_callback {
+	unsigned			magic;
+#define EXP_CALLBACK_MAGIC		0xAB956EB1
+	exp_callback_f			*cb_insert;
+	exp_callback_f			*cb_remove;
+	void				*priv;
+	VTAILQ_ENTRY(exp_callback)	list;
+};
+
+/*--------------------------------------------------------------------*/
+
 struct vsl_log {
 	uint32_t		*wlb, *wlp, *wle;
 	unsigned		wlr;
@@ -919,14 +931,17 @@ extern pthread_t cli_thread;
 void EXP_Clr(struct exp *e);
 
 double EXP_Ttl(const struct req *, const struct object*);
-void EXP_Insert(struct objcore *oc);
-void EXP_Inject(struct objcore *oc, struct lru *lru, double when);
+void EXP_Insert(struct dstat *ds, struct objcore *oc);
+void EXP_Inject(struct dstat *ds, struct objcore *oc, struct lru *lru,
+    double when);
 void EXP_Init(void);
 void EXP_Rearm(struct object *o, double now, double ttl, double grace,
     double keep);
 void EXP_Touch(struct objcore *oc, double now);
 int EXP_NukeOne(struct busyobj *, struct lru *lru);
 void EXP_NukeLRU(struct worker *wrk, struct vsl_log *vsl, struct lru *lru);
+void EXP_Reg_Callback(struct exp_callback *cb);
+void EXP_Dereg_Callback(struct exp_callback *cb);
 
 /* cache_fetch.c */
 enum vbf_fetch_mode_e {
diff --git a/bin/varnishd/cache/cache_expire.c b/bin/varnishd/cache/cache_expire.c
index 8bd0707..e076fec 100644
--- a/bin/varnishd/cache/cache_expire.c
+++ b/bin/varnishd/cache/cache_expire.c
@@ -52,10 +52,47 @@ struct exp_priv {
 	VTAILQ_HEAD(,objcore)		inbox;
 	struct binheap			*heap;
 	pthread_cond_t			condvar;
+
+	VTAILQ_HEAD(,exp_callback)	cb_list;
+	pthread_rwlock_t		cb_mtx;
 };
 
 static struct exp_priv *exphdl;
 
+static void
+exp_insert_cb(struct dstat *ds, struct objcore *oc)
+{
+	struct exp_callback *cb;
+
+	if (VTAILQ_EMPTY(&exphdl->cb_list))
+		return;
+
+	AZ(pthread_rwlock_rdlock(&exphdl->cb_mtx));
+	VTAILQ_FOREACH(cb, &exphdl->cb_list, list) {
+		CHECK_OBJ_NOTNULL(cb, EXP_CALLBACK_MAGIC);
+		if (cb->cb_insert)
+			cb->cb_insert(ds, oc, cb->priv);
+	}
+	AZ(pthread_rwlock_unlock(&exphdl->cb_mtx));
+}
+
+static void
+exp_remove_cb(struct dstat *ds, struct objcore *oc)
+{
+	struct exp_callback *cb;
+
+	if (VTAILQ_EMPTY(&exphdl->cb_list))
+		return;
+
+	AZ(pthread_rwlock_rdlock(&exphdl->cb_mtx));
+	VTAILQ_FOREACH(cb, &exphdl->cb_list, list) {
+		CHECK_OBJ_NOTNULL(cb, EXP_CALLBACK_MAGIC);
+		if (cb->cb_remove)
+			cb->cb_remove(ds, oc, cb->priv);
+	}
+	AZ(pthread_rwlock_unlock(&exphdl->cb_mtx));
+}
+
 /*--------------------------------------------------------------------
  * struct exp manipulations
  */
@@ -130,7 +167,7 @@ exp_mail_it(struct objcore *oc)
  */
 
 void
-EXP_Inject(struct objcore *oc, struct lru *lru, double when)
+EXP_Inject(struct dstat *ds, struct objcore *oc, struct lru *lru, double when)
 {
 
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
@@ -152,6 +189,8 @@ EXP_Inject(struct objcore *oc, struct lru *lru, double when)
 		oc->timer_when = when;
 	Lck_Unlock(&lru->mtx);
 
+	exp_insert_cb(ds, oc);
+
 	exp_mail_it(oc);
 }
 
@@ -163,12 +202,12 @@ EXP_Inject(struct objcore *oc, struct lru *lru, double when)
  */
 
 void
-EXP_Insert(struct objcore *oc)
+EXP_Insert(struct dstat *ds, struct objcore *oc)
 {
 
 	CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
 	HSH_Ref(oc);
-	EXP_Inject(oc, NULL, -1);
+	EXP_Inject(ds, oc, NULL, -1);
 }
 
 /*--------------------------------------------------------------------
@@ -338,6 +377,7 @@ EXP_NukeOne(struct busyobj *bo, struct lru *lru)
 	    oc_getxid(bo->stats, oc) & VSL_IDENTMASK);
 	AN(bo->stats);
 	AN(oc);
+	exp_remove_cb(bo->stats, oc);
 	(void)HSH_DerefObjCore(bo->stats, &oc);
 	return (1);
 }
@@ -397,6 +437,7 @@ EXP_NukeLRU(struct worker *wrk, struct vsl_log *vsl, struct lru *lru)
 			    oc_getxid(&wrk->stats, oc) & VSL_IDENTMASK,
 			    EXP_Ttl(NULL, o) - t);
 			o->exp.ttl = 0.0;
+			exp_remove_cb(&wrk->stats, oc);
 			(void)HSH_DerefObjCore(&wrk->stats, &oc);
 		}
 
@@ -409,6 +450,31 @@ EXP_NukeLRU(struct worker *wrk, struct vsl_log *vsl, struct lru *lru)
 
 #endif
 
+void
+EXP_Reg_Callback(struct exp_callback *cb)
+{
+	CHECK_OBJ_NOTNULL(cb, EXP_CALLBACK_MAGIC);
+	AZ(pthread_rwlock_wrlock(&exphdl->cb_mtx));
+	VTAILQ_INSERT_TAIL(&exphdl->cb_list, cb, list);
+	AZ(pthread_rwlock_unlock(&exphdl->cb_mtx));
+}
+
+void
+EXP_Dereg_Callback(struct exp_callback *cb)
+{
+	struct exp_callback *cb2;
+
+	CHECK_OBJ_NOTNULL(cb, EXP_CALLBACK_MAGIC);
+	AZ(pthread_rwlock_wrlock(&exphdl->cb_mtx));
+	VTAILQ_FOREACH(cb2, &exphdl->cb_list, list) {
+		CHECK_OBJ_NOTNULL(cb2, EXP_CALLBACK_MAGIC);
+		if (cb2 == cb)
+			break;
+	}
+	AN(cb2);
+	VTAILQ_REMOVE(&exphdl->cb_list, cb2, list);
+	AZ(pthread_rwlock_unlock(&exphdl->cb_mtx));
+}
 
 /*--------------------------------------------------------------------
  * Handle stuff in the inbox
@@ -452,6 +518,7 @@ exp_inbox(struct exp_priv *ep, struct objcore *oc, double now)
 			binheap_delete(ep->heap, oc->timer_idx);
 		}
 		assert(oc->timer_idx == BINHEAP_NOIDX);
+		exp_remove_cb(&ep->wrk->stats, oc);
 		(void)HSH_DerefObjCore(&ep->wrk->stats, &oc);
 		return;
 	}
@@ -537,6 +604,7 @@ exp_expire(struct exp_priv *ep, double now)
 	VSLb(&ep->vsl, SLT_ExpKill, "EXP_Expired x=%u t=%.0f",
 	    oc_getxid(&ep->wrk->stats, oc) & VSL_IDENTMASK,
 	    EXP_Ttl(NULL, o) - now);
+	exp_remove_cb(&ep->wrk->stats, oc);
 	(void)HSH_DerefObjCore(&ep->wrk->stats, &oc);
 	return (0);
 }
@@ -618,6 +686,8 @@ EXP_Init(void)
 	Lck_New(&ep->mtx, lck_exp);
 	AZ(pthread_cond_init(&ep->condvar, NULL));
 	VTAILQ_INIT(&ep->inbox);
+	AZ(pthread_rwlock_init(&ep->cb_mtx, NULL));
+	VTAILQ_INIT(&ep->cb_list);
 	exphdl = ep;
 	WRK_BgThread(&pt, "cache-timeout", exp_thread, ep);
 }
diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index f4bbae0..ed269c6 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -683,7 +683,7 @@ HSH_Unbusy(struct dstat *ds, struct objcore *oc)
 
 	if (!(oc->flags & OC_F_PRIVATE)) {
 		BAN_NewObjCore(oc);
-		EXP_Insert(oc);
+		EXP_Insert(ds, oc);
 		AN(oc->exp_flags & OC_EF_EXP);
 		AN(oc->ban);
 	}
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index f27ccd9..dd93276 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -158,7 +158,7 @@ smp_load_seg(struct worker *wrk, const struct smp_sc *sc,
 		smp_init_oc(oc, sg, no);
 		oc->ban = BAN_RefBan(oc, so->ban, sc->tailban);
 		HSH_Insert(wrk, so->hash, oc);
-		EXP_Inject(oc, sg->lru, so->ttl);
+		EXP_Inject(&wrk->stats, oc, sg->lru, so->ttl);
 		sg->nobj++;
 	}
 	WRK_SumStat(wrk);
-- 
2.0.0.rc2




More information about the varnish-dev mailing list