]> err.no Git - varnish/commitdiff
Pave more road for prefetch:
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 14 Jan 2008 10:42:56 +0000 (10:42 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 14 Jan 2008 10:42:56 +0000 (10:42 +0000)
Sanity-check values assigned to obj.prefetch from VCL: if before present
time or after ttl, SHM a VCL_info message and set obj.prefetch to zero
disabling prefetch.

Change objects/timer interaction:  We only keep track of the first timer for
each object (->timer_when) and add a field to remember what we intend to
do at that time (->timer_what).

Rename heap_idx to timer_idx to group the relevant fields (XXX: it should be
accessed through function outside cache_expire.c which should be called
cache_timer.c now).

Abolish the 30 second advance move to death-row.

When the prefetch timer expires, SHM a debug message and don't do anything.

Minor polishing and cleanup.

Add vcl_prefetch{} to default VCL and set prefetch 30 seconds before ttl.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2344 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_expire.c
varnish-cache/bin/varnishd/cache_hash.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/bin/varnishd/mgt_vcc.c

index a38821bbae6eb99864075246dea49f454c85da35..8d7af81b78e28de2737535252f1460ead07d4bf3 100644 (file)
@@ -232,7 +232,13 @@ struct object {
        struct ws               ws_o[1];
        unsigned char           *vary;
 
-       unsigned                heap_idx;
+       double                  timer_when;
+       enum {
+           TIMER_TTL,
+           TIMER_PREFETCH
+       }                       timer_what;
+       unsigned                timer_idx;
+
        unsigned                ban_seq;
 
        unsigned                pass;
index 3f8318a5277ebd35a172cf44155b5fb92da7cd7a..2bc616d5e8905a0be67bc3ea344c0ccc274a05ef 100644 (file)
@@ -50,7 +50,6 @@
 static pthread_t exp_thread;
 static struct binheap *exp_heap;
 static MTX exp_mtx;
-static unsigned expearly = 30;
 static VTAILQ_HEAD(,object) exp_deathrow = VTAILQ_HEAD_INITIALIZER(exp_deathrow);
 static VTAILQ_HEAD(,object) exp_lru = VTAILQ_HEAD_INITIALIZER(exp_lru);
 
@@ -61,6 +60,30 @@ static VTAILQ_HEAD(,object) exp_lru = VTAILQ_HEAD_INITIALIZER(exp_lru);
  */
 static const unsigned lru_target = (unsigned)(-3);
 
+/*--------------------------------------------------------------------
+ * Figure out which object timer fires next
+ */
+
+/* When does the timer fire for this object ? */
+static void
+update_object_when(struct object *o)
+{
+       double w;
+
+       w = o->ttl;
+       if (o->prefetch < 0.0) {
+               o->timer_when = o->ttl + o->prefetch;
+               o->timer_what = TIMER_PREFETCH;
+       } else if (o->prefetch > 0.0) {
+               assert(o->prefetch <= o->ttl);
+               o->timer_when = o->prefetch;
+               o->timer_what = TIMER_PREFETCH;
+       } else {
+               o->timer_when = o->ttl;
+               o->timer_what = TIMER_TTL;
+       }
+}
+
 /*--------------------------------------------------------------------*/
 
 void
@@ -68,7 +91,8 @@ EXP_Insert(struct object *o)
 {
 
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
-       assert(o->heap_idx == 0);
+       assert(o->timer_idx == 0);
+       update_object_when(o);
        LOCK(&exp_mtx);
        binheap_insert(exp_heap, o);
        VTAILQ_INSERT_TAIL(&exp_lru, o, deathrow);
@@ -82,7 +106,7 @@ EXP_Touch(struct object *o, double now)
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
        if (o->lru_stamp + params->lru_timeout < now) {
                LOCK(&exp_mtx); /* XXX: should be ..._TRY */
-               if (o->heap_idx != lru_target && o->heap_idx != 0) {
+               if (o->timer_idx != lru_target && o->timer_idx != 0) {
                        VTAILQ_REMOVE(&exp_lru, o, deathrow);
                        VTAILQ_INSERT_TAIL(&exp_lru, o, deathrow);
                        o->lru_stamp = now;
@@ -96,9 +120,10 @@ EXP_TTLchange(struct object *o)
 {
 
        LOCK(&exp_mtx);
-       if (o->heap_idx != lru_target) {
-               assert(o->heap_idx != 0);
-               binheap_delete(exp_heap, o->heap_idx);
+       if (o->timer_idx != lru_target) {
+               assert(o->timer_idx != 0);      /* XXX: symbolic zero ? */
+               update_object_when(o);
+               binheap_delete(exp_heap, o->timer_idx);
                binheap_insert(exp_heap, o);
        }
        UNLOCK(&exp_mtx);
@@ -185,40 +210,58 @@ exp_prefetch(void *arg)
                LOCK(&exp_mtx);
                o = binheap_root(exp_heap);
                CHECK_OBJ_ORNULL(o, OBJECT_MAGIC);
-               if (o == NULL || o->ttl > t + expearly) {
+               if (o == NULL || o->timer_when > t) {   /* XXX: >= ? */
                        UNLOCK(&exp_mtx);
+                       WSL_Flush(&ww);
                        AZ(sleep(1));
                        VCL_Refresh(&sp->vcl);
                        t = TIM_real();
                        continue;
                }
-               binheap_delete(exp_heap, o->heap_idx);
-               assert(o->heap_idx == 0);
+               binheap_delete(exp_heap, o->timer_idx);
+               assert(o->timer_idx == 0);
 
                /* Sanity check */
                o2 = binheap_root(exp_heap);
                if (o2 != NULL)
-                       assert(o2->ttl >= o->ttl);
+                       assert(o2->timer_when >= o->timer_when);
 
                UNLOCK(&exp_mtx);
-               WSL(&ww, SLT_ExpPick, 0, "%u", o->xid);
 
-               sp->obj = o;
-               VCL_timeout_method(sp);
+               WSL(&ww, SLT_ExpPick, 0, "%u %s", o->xid,
+                   o->timer_what == TIMER_PREFETCH ? "prefetch" : "ttl");
 
-               if (sp->handling == VCL_RET_DISCARD) {
+               if (o->timer_what == TIMER_PREFETCH) {
+                       o->prefetch = 0.0;
+                       update_object_when(o);
                        LOCK(&exp_mtx);
-                       VTAILQ_REMOVE(&exp_lru, o, deathrow);
-                       VTAILQ_INSERT_TAIL(&exp_deathrow, o, deathrow);
-                       VSL_stats->n_deathrow++;
+                       binheap_insert(exp_heap, o);
                        UNLOCK(&exp_mtx);
-                       continue;
+                       sp->obj = o;
+                       VCL_prefetch_method(sp);
+                       if (sp->handling == VCL_RET_FETCH) {
+                               WSL(&ww, SLT_Debug, 0, "Attempt Prefetch %u",
+                                   o->xid);
+                       }
+               } else { /* TIMER_TTL */
+                       sp->obj = o;
+                       VCL_timeout_method(sp);
+
+                       if (sp->handling == VCL_RET_DISCARD) {
+                               LOCK(&exp_mtx);
+                               VTAILQ_REMOVE(&exp_lru, o, deathrow);
+                               VTAILQ_INSERT_TAIL(&exp_deathrow, o, deathrow);
+                               VSL_stats->n_deathrow++;
+                               UNLOCK(&exp_mtx);
+                       }
+                       assert(sp->handling == VCL_RET_DISCARD);
                }
-               assert(sp->handling == VCL_RET_DISCARD);
        }
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * BinHeap helper functions for objects.
+ */
 
 static int
 object_cmp(void *priv, void *a, void *b)
@@ -226,19 +269,19 @@ object_cmp(void *priv, void *a, void *b)
        struct object *aa, *bb;
 
        (void)priv;
-
-       aa = a;
-       bb = b;
-       return (aa->ttl < bb->ttl);
+       CAST_OBJ_NOTNULL(aa, a, OBJECT_MAGIC);
+       CAST_OBJ_NOTNULL(bb, b, OBJECT_MAGIC);
+       return (aa->timer_when < bb->timer_when);
 }
 
 static void
 object_update(void *priv, void *p, unsigned u)
 {
-       struct object *o = p;
+       struct object *o;
 
        (void)priv;
-       o->heap_idx = u;
+       CAST_OBJ_NOTNULL(o, p, OBJECT_MAGIC);
+       o->timer_idx = u;
 }
 
 /*--------------------------------------------------------------------
@@ -263,9 +306,9 @@ EXP_NukeOne(struct sess *sp)
                 * means that we own the EXP refcnt on this object.
                 */
                VTAILQ_REMOVE(&exp_lru, o, deathrow);
-               binheap_delete(exp_heap, o->heap_idx);
-               assert(o->heap_idx == 0);
-               o->heap_idx = lru_target;
+               binheap_delete(exp_heap, o->timer_idx);
+               assert(o->timer_idx == 0);
+               o->timer_idx = lru_target;
                VSL_stats->n_lru_nuked++;       /* May be premature */
        }
        UNLOCK(&exp_mtx);
@@ -296,7 +339,7 @@ EXP_NukeOne(struct sess *sp)
        LOCK(&exp_mtx);
        VSL_stats->n_lru_nuked--;               /* It was premature */
        VSL_stats->n_lru_saved++;
-       o->heap_idx = 0;
+       o->timer_idx = 0;
        o->lru_stamp = sp->wrk->used;
        binheap_insert(exp_heap, o);
        VTAILQ_INSERT_TAIL(&exp_lru, o, deathrow);
index 26e44b3f6b89df67db95c01473256a3570835c2a..644f44147354d73b86c222031db14bb25590c2e9 100644 (file)
@@ -216,7 +216,7 @@ HSH_Lookup(struct sess *sp)
                    h->hd[HTTP_HDR_URL].b, oh->hash)) {
                        o->ttl = 0;
                        WSP(sp, SLT_ExpBan, "%u was banned", o->xid);
-                       if (o->heap_idx != 0)
+                       if (o->timer_idx != 0)
                                EXP_TTLchange(o);
                } else if (o->vary == NULL || VRY_Match(sp, o->vary))
                        break;
index 12cc68fb88af1e44642d23d00c33a119c68512c4..9e042fcdfff4b68d2b45cabac0048c99d4b0139d 100644 (file)
@@ -292,7 +292,7 @@ VRT_l_obj_ttl(const struct sess *sp, double a)
        if (a < 0)
                a = 0;
        sp->obj->ttl = sp->t_req + a;
-       if (sp->obj->heap_idx != 0)
+       if (sp->obj->timer_idx != 0)
                EXP_TTLchange(sp->obj);
 }
 
@@ -306,15 +306,31 @@ VRT_r_obj_ttl(const struct sess *sp)
 
 /*--------------------------------------------------------------------*/
 
+/* XXX: the VCL_info messages has unexpected fractions on the ttl */
+
 void
 VRT_l_obj_prefetch(const struct sess *sp, double a)
 {
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);       /* XXX */
-       sp->obj->prefetch = a;
-       if (a > 0.0)
-               sp->obj->prefetch += sp->t_req;
+       sp->obj->prefetch = 0.0;
+       if (a == 0.0)
+               sp->obj->prefetch = a;
+       else if (a > 0.0 && a + sp->t_req <= sp->obj->ttl)
+               sp->obj->prefetch = a + sp->t_req;
+       else if (a < 0.0 && a + sp->obj->ttl > sp->t_req)
+               sp->obj->prefetch = a;
+       else if (a > 0.0)
+               WSL(sp->wrk, SLT_VCL_info, sp->id,
+                   "XID %u: obj.prefetch (%g) after TTL (%g), ignored.",
+                   sp->obj->xid, a, sp->obj->ttl - sp->t_req);
+       else /* if (a < 0.0) */
+               WSL(sp->wrk, SLT_VCL_info, sp->id,
+                   "XID %u: obj.prefetch (%g) less than ttl (%g), ignored.",
+                   sp->obj->xid, a, sp->obj->ttl - sp->t_req);
+       if (sp->obj->timer_idx != 0)
+               EXP_TTLchange(sp->obj);
 }
 
 double
index 8720577270c3b49ca7ae08a0695a2c78514a4767..c6fd3185a7af7037670dcf9542360141c7df022b 100644 (file)
@@ -128,6 +128,7 @@ static const char *default_vcl =
     "    if (obj.http.Set-Cookie) {\n"
     "        pass;\n"
     "    }\n"
+    "   set obj.prefetch =  -30s;"
     "    insert;\n"
     "}\n"
     "sub vcl_deliver {\n"
@@ -136,6 +137,9 @@ static const char *default_vcl =
     "sub vcl_discard {\n"
     "    discard;\n"
     "}\n"
+    "sub vcl_prefetch {\n"
+    "    fetch;\n"
+    "}\n"
     "sub vcl_timeout {\n"
     "    discard;\n"
     "}\n";
@@ -278,7 +282,7 @@ mgt_run_cc(const char *source, struct vsb *sb)
        /* Next, try to load the object into the management process */
        if ((dlh = dlopen(of, RTLD_NOW | RTLD_LOCAL)) == NULL) {
                vsb_printf(sb,
-                   "%s(): failed to load compiled VCL program: %s",
+                   "%s(): failed to load compiled VCL program:\n  %s",
                    __func__, dlerror());
                unlink(of);
                free(of);
@@ -419,7 +423,7 @@ mgt_vcc_default(const char *b_arg, const char *f_arg, int f_fd, int C_flag)
        if (C_flag)
                return (0);
        if (vf == NULL) {
-               fprintf(stderr, "VCL compilation failed");
+               fprintf(stderr, "\nVCL compilation failed\n");
                return (1);
        }
        vp = mgt_vcc_add("boot", vf);