]> err.no Git - varnish/commitdiff
Finish (the "easy") part of degraded mode:
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 28 Jan 2008 10:28:24 +0000 (10:28 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 28 Jan 2008 10:28:24 +0000 (10:28 +0000)
Add req.grace timer:  We only serve degraded mode objects if both the
request and the object's grace timers are satisfied.

Sort expiry list on obj.ttl + obj.grace and fiddle list if either changes.

In the hash lookup: record if any objects still in grace by obj.grace which
match our Vary: criteria (if any).

If no in-ttl object was found AND we have a graced object AND it is also
graced by req.grace AND it is being fetched: serve the graced object.

Otherwise, mark us as successor to the graced object while we fetch to
give others the chance.

When we unbusy the object, clean the magic pointers between the two
objects again.

To play with this you need at least:

sub vcl_recv {
set req.grace = 2m;
}
sub vcl_fetch {
set obj.grace = 2m;
}

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2392 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/cache_ws.c
varnish-cache/include/vrt_obj.h
varnish-cache/lib/libvcl/vcc_fixed_token.c
varnish-cache/lib/libvcl/vcc_gen_obj.tcl
varnish-cache/lib/libvcl/vcc_obj.c

index 9e0c854e27ca422c7c553fc754e49de95addc3bb..d00f4be730aabd98376460710100fab5881ea781 100644 (file)
@@ -220,7 +220,6 @@ struct storage {
 };
 
 /* -------------------------------------------------------------------*/
-
 enum e_objtimer {
        TIMER_TTL,
        TIMER_PREFETCH
@@ -271,6 +270,10 @@ struct object {
        VTAILQ_HEAD(, esi_bit)  esibits;
 
        double                  lru_stamp;
+
+       /* Prefetch */
+       struct object           *parent;
+       struct object           *child;
 };
 
 struct objhead {
@@ -326,6 +329,9 @@ struct sess {
        double                  t_resp;
        double                  t_end;
 
+       /* Acceptable grace period */
+       double                  grace;
+
        enum step               step;
        unsigned                cur_method;
        unsigned                handling;
index 2bc616d5e8905a0be67bc3ea344c0ccc274a05ef..2b93ae71f01df1daf3e6ad310ba0166149a897f2 100644 (file)
@@ -79,7 +79,7 @@ update_object_when(struct object *o)
                o->timer_when = o->prefetch;
                o->timer_what = TIMER_PREFETCH;
        } else {
-               o->timer_when = o->ttl;
+               o->timer_when = o->ttl + o->grace;
                o->timer_what = TIMER_TTL;
        }
 }
index eafa0852a03e79181fc4679b423460d97c2ce211..1703daec09e53a28824db2e2dfa1b5045f113007 100644 (file)
@@ -173,7 +173,7 @@ HSH_Lookup(struct sess *sp)
        struct worker *w;
        struct http *h;
        struct objhead *oh;
-       struct object *o, *busy_o;
+       struct object *o, *busy_o, *grace_o;
 
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
@@ -198,6 +198,7 @@ HSH_Lookup(struct sess *sp)
        }
 
        busy_o = NULL;
+       grace_o = NULL;
        VTAILQ_FOREACH(o, &oh->objects, list) {
                if (o->busy) {
                        busy_o = o;
@@ -207,8 +208,6 @@ HSH_Lookup(struct sess *sp)
                        continue;
                if (o->ttl == 0) 
                        continue;
-               if (o->ttl <= sp->t_req) 
-                       continue;
                if (BAN_CheckObject(o, h->hd[HTTP_HDR_URL].b, oh->hash)) {
                        o->ttl = 0;
                        WSP(sp, SLT_ExpBan, "%u was banned", o->xid);
@@ -216,9 +215,27 @@ HSH_Lookup(struct sess *sp)
                                EXP_TTLchange(o);
                        continue;
                }
-               if (o->vary == NULL || VRY_Match(sp, o->vary))
+               if (o->vary != NULL && !VRY_Match(sp, o->vary))
+                       continue;
+
+               /* If still valid, use it */
+               if (o->ttl >= sp->t_req)
                        break;
+
+               /* Remember any matching objects inside their grace period */
+               if (o->ttl + o->grace >= sp->t_req)
+                       grace_o = o;
        }
+
+       /*
+        * If we have a object in grace and being fetched,
+        * use it, if req.grace is also satisified.
+        */
+       if (o == NULL && grace_o != NULL &&
+           grace_o->child != NULL &&
+           grace_o->ttl + sp->grace >= sp->t_req)
+               o = grace_o;
+
        if (o != NULL) {
                /* We found an object we like */
                o->refcnt++;
@@ -239,8 +256,14 @@ HSH_Lookup(struct sess *sp)
        o = w->nobj;
        w->nobj = NULL;
        o->objhead = oh;
+       /* XXX: Should this not be ..._HEAD now ? */
        VTAILQ_INSERT_TAIL(&oh->objects, o, list);
        /* NB: do not deref objhead the new object inherits our reference */
+       if (grace_o != NULL) {
+               grace_o->child = o;
+               o->parent = grace_o;
+               grace_o->refcnt++;
+       }
        UNLOCK(&oh->mtx);
        BAN_NewObj(o);
        /*
@@ -271,6 +294,7 @@ void
 HSH_Unbusy(struct object *o)
 {
        struct objhead *oh;
+       struct object *parent;
 
        CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC);
        assert(o->busy);
@@ -284,8 +308,14 @@ HSH_Unbusy(struct object *o)
        }
        o->busy = 0;
        hsh_rush(oh);
+       parent = o->parent;
+       o->parent = NULL;
+       if (parent != NULL)
+               parent->child = NULL;
        if (oh != NULL)
                UNLOCK(&oh->mtx);
+       if (parent != NULL)
+               HSH_Deref(parent);
 }
 
 void
index d2e873f7b8fb0965396212aacad1695e88fb19e5..c43258ec23ff1b9e31e6f7f5781b12abdd20123f 100644 (file)
@@ -317,6 +317,8 @@ VRT_l_obj_grace(const struct sess *sp, double a)
        if (a < 0)
                a = 0;
        sp->obj->grace = a;
+       if (sp->obj->timer_idx != 0)
+               EXP_TTLchange(sp->obj);
 }
 
 double
@@ -427,6 +429,27 @@ VRT_r_req_restarts(const struct sess *sp)
        return (sp->restarts);
 }
 
+/*--------------------------------------------------------------------
+ * req.grace
+ */
+
+void
+VRT_l_req_grace(struct sess *sp, double a)
+{
+
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       if (a < 0)
+               a = 0;
+       sp->grace = a;
+}
+
+double
+VRT_r_req_grace(struct sess *sp)
+{
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       return (sp->grace);
+}
+
 /*--------------------------------------------------------------------*/
 
 const char *
index 8c7a9ccdf4aa3e662cf91d8eac718aac92084871..068cb0911506fc5a5978b5cdd8e96ae6e496b70f 100644 (file)
@@ -46,7 +46,7 @@
 #include "cache.h"
 
 /* Enable this to get detailed logging of WS usage */
-#ifdef DIAGNOSTICS
+#ifdef DIAGNOSTICS0
 #  define WS_DEBUG(fmt, ...)   VSL(SLT_Debug, 0, fmt, __VA_ARGS__)
 #else
 #  define WS_DEBUG(fmt, ...)   /* nothing */
index 8594d7754d99565628b75453daf03371cab75784..6c7cef88f6f8e3dd2f18f3740461e15a81f7ea99 100644 (file)
@@ -22,6 +22,8 @@ void VRT_l_req_hash(struct sess *, const char *);
 struct backend * VRT_r_req_backend(struct sess *);
 void VRT_l_req_backend(struct sess *, struct backend *);
 int VRT_r_req_restarts(const struct sess *);
+double VRT_r_req_grace(struct sess *);
+void VRT_l_req_grace(struct sess *, double);
 const char * VRT_r_bereq_request(const struct sess *);
 void VRT_l_bereq_request(const struct sess *, const char *, ...);
 const char * VRT_r_bereq_url(const struct sess *);
index 62ae6638c394fdf995951cf359647dd4c5ab67c7..9d4f2b3f445d8fb970fa49b5fc9e2c86bcf82230 100644 (file)
@@ -521,6 +521,8 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "struct backend * VRT_r_req_backend(struct sess *);\n");
        vsb_cat(sb, "void VRT_l_req_backend(struct sess *, struct backend *);\n");
        vsb_cat(sb, "int VRT_r_req_restarts(const struct sess *);\n");
+       vsb_cat(sb, "double VRT_r_req_grace(const struct sess *);\n");
+       vsb_cat(sb, "void VRT_l_req_grace(const struct sess *, double);\n");
        vsb_cat(sb, "const char * VRT_r_bereq_request(const struct sess *);\n");
        vsb_cat(sb, "void VRT_l_bereq_request(const struct sess *, const char *, ...);\n");
        vsb_cat(sb, "const char * VRT_r_bereq_url(const struct sess *);\n");
index ebc8b1d2745eea622d1dc037386e395549db83f1..7fcdafbb17b9a7a59651e6e6a3470724849ad597 100755 (executable)
@@ -97,6 +97,11 @@ set spobj {
                {recv pipe pass hash miss hit fetch deliver                }
                "const struct sess *"
        }
+       { req.grace
+               RW TIME
+               {recv pipe pass hash miss hit fetch deliver                }
+               "struct sess *"
+       }
 
        # Request sent to backend
        { bereq.request
index 4f0067976c9056ac241564444d815a2cb149d897..9bdca4db3a919658ffdfc3df650075e600efe679 100644 (file)
@@ -105,6 +105,13 @@ struct var vcc_vars[] = {
            0,
            VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
        },
+       { "req.grace", TIME, 9,
+           "VRT_r_req_grace(sp)",
+           "VRT_l_req_grace(sp, ",
+           V_RW,
+           0,
+           VCL_MET_RECV | VCL_MET_PIPE | VCL_MET_PASS | VCL_MET_HASH | VCL_MET_MISS | VCL_MET_HIT | VCL_MET_FETCH | VCL_MET_DELIVER
+       },
        { "bereq.request", STRING, 13,
            "VRT_r_bereq_request(sp)",
            "VRT_l_bereq_request(sp, ",