---
 bin/varnishd/storage/storage_persistent.c      |   47 +++++++++++++++++++++++-
 bin/varnishd/storage/storage_persistent.h      |    5 +++
 bin/varnishd/storage/storage_persistent_mgt.c  |    4 +-
 bin/varnishd/storage/storage_persistent_silo.c |   27 ++++++++++++++
 4 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/bin/varnishd/storage/storage_persistent.c 
b/bin/varnishd/storage/storage_persistent.c
index 00bd940..4306e4d 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -371,6 +371,10 @@ smp_save_segs(struct smp_sc *sc)
                if (sg->flags & SMP_SEG_NEW)
                        break;
                VTAILQ_REMOVE(&sc->segments, sg, list);
+               if (sg->flags & SMP_SEG_NUKED) {
+                       assert(sc->free_pending >= sg->p.length);
+                       sc->free_pending -= sg->p.length;
+               }
                LRU_Free(sg->lru);
                FREE_OBJ(sg);
        }
@@ -406,6 +410,10 @@ smp_save_segs(struct smp_sc *sc)
        VTAILQ_FOREACH(sg, &sc->segments, list) {
                assert(sg->p.offset < sc->mediasize);
                assert(sg->p.offset + sg->p.length <= sc->mediasize);
+               if (sg->flags & SMP_SEG_NUKED) {
+                       AZ(length);
+                       continue;
+               }
                if (sg->flags & SMP_SEG_NEW)
                        break;
                *ss = sg->p;
@@ -421,6 +429,39 @@ smp_save_segs(struct smp_sc *sc)
        smp_sync_sign(&sc->seg2.ctx);
        Lck_Lock(&sc->mtx);
 }
+
+/*
+ * Raise the free_reserve by nuking segments
+ */
+
+static void
+smp_raise_reserve(struct worker *wrk, struct vsl_log *vsl, struct smp_sc *sc)
+{
+       struct smp_seg *sg;
+
+       Lck_AssertHeld(&sc->mtx);
+
+       VTAILQ_FOREACH(sg, &sc->segments, list) {
+               if (sg == sc->cur_seg)
+                       break;
+               if (smp_silospaceleft(sc) + sc->free_pending > sc->free_reserve)
+                       break;
+               if (sg->flags & SMP_SEG_NEW)
+                       break;
+               if (sg->flags & SMP_SEG_NUKED)
+                       continue;
+
+               /* Nuke this segment */
+               Lck_Unlock(&sc->mtx);
+               EXP_NukeLRU(wrk, vsl, sg->lru);
+               Lck_Lock(&sc->mtx);
+               sg->flags |= SMP_SEG_NUKED;
+               sc->free_pending += sg->p.length;
+       }
+       assert(smp_silospaceleft(sc) + sc->free_pending > sc->free_reserve);
+       sc->flags &= ~SMP_SC_LOW;
+}
+
 /*--------------------------------------------------------------------
  * Silo worker thread
  */
@@ -430,10 +471,12 @@ smp_thread(struct worker *wrk, void *priv)
 {
        struct smp_sc   *sc;
        struct smp_seg *sg;
+       struct vsl_log vsl;
 
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
        CAST_OBJ_NOTNULL(sc, priv, SMP_SC_MAGIC);
        sc->thread = pthread_self();
+       VSL_Setup(&vsl, NULL, 0);
 
        /* First, load all the objects from all segments */
        VTAILQ_FOREACH(sg, &sc->segments, list)
@@ -448,10 +491,12 @@ smp_thread(struct worker *wrk, void *priv)
        /* Housekeeping loop */
        Lck_Lock(&sc->mtx);
        while (!(sc->flags & SMP_SC_STOP)) {
+               if (sc->flags & SMP_SC_LOW)
+                       smp_raise_reserve(wrk, &vsl, sc);
                if (sc->flags & SMP_SC_SYNC)
                        smp_save_segs(sc);
 
-               if (!(sc->flags & (SMP_SC_SYNC | SMP_SC_STOP)))
+               if (!(sc->flags & (SMP_SC_LOW | SMP_SC_SYNC | SMP_SC_STOP)))
                        /* Wait for something to do */
                        (void)Lck_CondWait(&sc->cond, &sc->mtx, NULL);
        }
diff --git a/bin/varnishd/storage/storage_persistent.h 
b/bin/varnishd/storage/storage_persistent.h
index 93ec45e..9e0642d 100644
--- a/bin/varnishd/storage/storage_persistent.h
+++ b/bin/varnishd/storage/storage_persistent.h
@@ -89,6 +89,7 @@ struct smp_seg {
 #define SMP_SEG_LOADED         (1 << 1)
 #define SMP_SEG_NEW            (1 << 2)
 #define SMP_SEG_SYNCSIGNS      (1 << 3)
+#define SMP_SEG_NUKED          (1 << 4)
 
        uint32_t                nobj;           /* Number of objects */
        uint32_t                nalloc;         /* Allocations */
@@ -114,6 +115,7 @@ struct smp_sc {
 #define SMP_SC_LOADED          (1 << 0)
 #define SMP_SC_STOP            (1 << 1)
 #define SMP_SC_SYNC            (1 << 2)
+#define SMP_SC_LOW             (1 << 3)
 
        const struct stevedore  *stevedore;
        int                     fd;
@@ -133,6 +135,7 @@ struct smp_sc {
        uint64_t                next_top;       /* next alloc address top */
 
        uint64_t                free_offset;
+       uint64_t                free_pending;
 
        pthread_t               thread;
 
@@ -224,6 +227,8 @@ void smp_msync(void *addr, size_t length);
 
 void smp_newsilo(struct smp_sc *sc);
 int smp_valid_silo(struct smp_sc *sc);
+uint64_t smp_silospaceleft(struct smp_sc *sc);
+void smp_check_reserve(struct smp_sc *sc);
 
 /*--------------------------------------------------------------------
  * Caculate payload of some stuff
diff --git a/bin/varnishd/storage/storage_persistent_mgt.c 
b/bin/varnishd/storage/storage_persistent_mgt.c
index c5b1dfd..26c9d36 100644
--- a/bin/varnishd/storage/storage_persistent_mgt.c
+++ b/bin/varnishd/storage/storage_persistent_mgt.c
@@ -114,9 +114,7 @@ smp_metrics(struct smp_sc *sc)
        fprintf(stderr, "aim_nseg = %u, aim_segl = %ju\n",
            sc->aim_nseg, (uintmax_t)sc->aim_segl);
 
-       /*
-        * How much space in the free reserve pool ?
-        */
+       /* XXX: Random number larger than 1 */
        sc->free_reserve = sc->aim_segl * 10;
 
        fprintf(stderr, "free_reserve = %ju\n", (uintmax_t)sc->free_reserve);
diff --git a/bin/varnishd/storage/storage_persistent_silo.c 
b/bin/varnishd/storage/storage_persistent_silo.c
index addb836..e432302 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -184,6 +184,7 @@ smp_new_seg(struct smp_sc *sc)
        sc->free_offset = sg->p.offset + sg->p.length;
 
        VTAILQ_INSERT_TAIL(&sc->segments, sg, list);
+       smp_check_reserve(sc);
 
        /* Set up our allocation points */
        sc->cur_seg = sg;
@@ -270,6 +271,32 @@ smp_close_seg(struct smp_sc *sc, struct smp_seg *sg)
        smp_sync_segs(sc);
 }
 
+uint64_t
+smp_silospaceleft(struct smp_sc *sc)
+{
+       struct smp_seg *sg;
+
+       Lck_AssertHeld(&sc->mtx);
+
+       sg = VTAILQ_FIRST(&sc->segments);
+       if (sg == NULL)
+               return (sc->mediasize - sc->free_offset);
+       if (sg->p.offset < sc->free_offset) {
+               return ((sc->mediasize - sc->free_offset) +
+                       (sg->p.offset - sc->ident->stuff[SMP_SPC_STUFF]));
+       }
+       return (sg->p.offset - sc->free_offset);
+}
+
+void
+smp_check_reserve(struct smp_sc *sc)
+{
+       Lck_AssertHeld(&sc->mtx);
+
+       if (smp_silospaceleft(sc) + sc->free_pending < sc->free_reserve)
+               sc->flags |= SMP_SC_LOW;
+}
+
 /*---------------------------------------------------------------------
  */
 
-- 
1.7.9.5


_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to