]> err.no Git - varnish/commitdiff
Complete the storage_file method.
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 14 Jun 2006 06:58:55 +0000 (06:58 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 14 Jun 2006 06:58:55 +0000 (06:58 +0000)
git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@179 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/storage_file.c

index 23c86fe50bb8bc479c2abe131a12c0395650d6a6..d81461a636a8031b7264832dac394f3a2b5ffd80 100644 (file)
 
 /*--------------------------------------------------------------------*/
 
+struct smf {
+       struct storage          s;
+       struct smf_sc           *sc;
+
+       int                     alloc;
+       time_t                  age;
+
+       off_t                   size;
+       off_t                   offset;
+       unsigned char           *ptr;
+
+       TAILQ_ENTRY(smf)        order;
+       TAILQ_ENTRY(smf)        status;
+};
+
+TAILQ_HEAD(smfhead, smf);
+
 struct smf_sc {
        char                    *filename;
        int                     fd;
+       int                     pagesize;
        uintmax_t               filesize;
-};
-
-struct smf {
-       struct storage          s;
+       struct smfhead          order;
+       struct smfhead          free;
+       struct smfhead          used;
 };
 
 /*--------------------------------------------------------------------*/
@@ -55,7 +72,7 @@ smf_calcsize(struct smf_sc *sc, const char *size, int newfile)
        AZ(fstatfs(sc->fd, &fsst));
 
        /* We use units of the larger of filesystem blocksize and pagesize */
-       bs = getpagesize();
+       bs = sc->pagesize;
        if (bs < fsst.f_bsize)
                bs = fsst.f_bsize;
 
@@ -127,15 +144,15 @@ smf_calcsize(struct smf_sc *sc, const char *size, int newfile)
        /* round down to of filesystem blocksize or pagesize */
        l -= (l % bs);
 
-       if (l < MINPAGES * getpagesize()) {
+       if (l < MINPAGES * sc->pagesize) {
                fprintf(stderr,
                    "Error: size too small, at least %ju needed\n",
-                   (uintmax_t)MINPAGES * getpagesize());
+                   (uintmax_t)MINPAGES * sc->pagesize);
                exit (2);
        }
 
        printf("file %s size %ju bytes (%ju fs-blocks, %ju pages)\n",
-           sc->filename, l, l / fsst.f_bsize, l / getpagesize());
+           sc->filename, l, l / fsst.f_bsize, l / sc->pagesize);
 
        sc->filesize = l;
 }
@@ -160,6 +177,11 @@ smf_init(struct stevedore *parent, const char *spec)
 
        sc = calloc(sizeof *sc, 1);
        assert(sc != NULL);
+       TAILQ_INIT(&sc->order);
+       TAILQ_INIT(&sc->free);
+       TAILQ_INIT(&sc->used);
+       sc->pagesize = getpagesize();
+
        parent->priv = sc;
 
        /* If no size specified, use 50% of filesystem free space */
@@ -236,6 +258,137 @@ smf_init(struct stevedore *parent, const char *spec)
        smf_initfile(sc, size, 1);
 }
 
+/*--------------------------------------------------------------------
+ * Allocate a range from the first free range that is large enough.
+ */
+
+static struct smf *
+alloc_smf(struct smf_sc *sc, size_t bytes)
+{
+       struct smf *sp, *sp2;
+
+       bytes += (sc->pagesize - 1);
+       bytes &= ~(sc->pagesize - 1);
+       TAILQ_FOREACH(sp, &sc->free, status) {
+               if (sp->size >= bytes)
+                       break;
+       }
+       if (sp == NULL)
+               return (sp);
+
+       if (sp->size == bytes) {
+               TAILQ_REMOVE(&sc->free, sp, status);
+               sp->alloc = 1;
+               TAILQ_INSERT_TAIL(&sc->used, sp, status);
+               printf("ALLOC   %12p  %12p %12jx %12jx\n", (void*)sp, (void*)sp->ptr, (uintmax_t)sp->offset, (uintmax_t)sp->size);
+               return (sp);
+       }
+
+       /* Split from front */
+       sp2 = malloc(sizeof *sp2);
+       assert(sp2 != NULL);
+       *sp2 = *sp;
+
+       sp->offset += bytes;
+       sp->ptr += bytes;
+       sp->size -= bytes;
+
+       sp2->size = bytes;
+       sp2->alloc = 1;
+       TAILQ_INSERT_BEFORE(sp, sp2, order);
+       TAILQ_INSERT_TAIL(&sc->used, sp2, status);
+       printf("SPLIT   %12p  %12p %12jx %12jx\n", (void*)sp, (void*)sp->ptr, (uintmax_t)sp->offset, (uintmax_t)sp->size);
+       printf("ALLOC   %12p  %12p %12jx %12jx\n", (void*)sp2, (void*)sp2->ptr, (uintmax_t)sp2->offset, (uintmax_t)sp2->size);
+       return (sp2);
+}
+
+/*--------------------------------------------------------------------
+ * Free a range.  Attemt merge forward and backward, then sort into 
+ * free list according to age.
+ */
+
+static void
+free_smf(struct smf *sp)
+{
+       struct smf *sp2;
+       struct smf_sc *sc = sp->sc;
+
+       printf("FREE   %12p  %12p %12jx %12jx\n", (void*)sp, (void*)sp->ptr, (uintmax_t)sp->offset, (uintmax_t)sp->size);
+       TAILQ_REMOVE(&sc->used, sp, status);
+       sp->alloc = 0;
+
+       sp2 = TAILQ_NEXT(sp, order);
+       if (sp2 != NULL &&
+           sp2->alloc == 0 &&
+           (sp2->ptr == sp->ptr + sp->size) &&
+           (sp2->offset == sp->offset + sp->size)) {
+               sp->size += sp2->size;
+               TAILQ_REMOVE(&sc->order, sp2, order);
+               TAILQ_REMOVE(&sc->free, sp2, status);
+               free(sp2);
+               printf("MERGEN %12p  %12p %12jx %12jx\n", (void*)sp, (void*)sp->ptr, (uintmax_t)sp->offset, (uintmax_t)sp->size);
+       }
+
+       sp2 = TAILQ_PREV(sp, smfhead, order);
+       if (sp2 != NULL &&
+           sp2->alloc == 0 &&
+           (sp->ptr == sp2->ptr + sp2->size) &&
+           (sp->offset == sp2->offset + sp2->size)) {
+               sp2->size += sp->size;
+               sp2->age = sp->age;
+               TAILQ_REMOVE(&sc->order, sp, order);
+               free(sp);
+               TAILQ_REMOVE(&sc->free, sp2, status);
+               sp = sp2;
+               printf("MERGEP %12p  %12p %12jx %12jx\n", (void*)sp, (void*)sp->ptr, (uintmax_t)sp->offset, (uintmax_t)sp->size);
+       }
+
+       TAILQ_FOREACH(sp2, &sc->free, status) {
+               if (sp->age > sp2->age ||
+                   (sp->age == sp2->age && sp->offset < sp2->offset)) {
+                       TAILQ_INSERT_BEFORE(sp2, sp, order);
+                       break;
+               }
+       }
+       if (sp2 == NULL)
+               TAILQ_INSERT_TAIL(&sc->free, sp, status);
+}
+
+/*--------------------------------------------------------------------
+ * Insert a newly created range as busy, then free it to do any collapses
+ */
+
+static void
+new_smf(struct smf_sc *sc, unsigned char *ptr, off_t off, size_t len)
+{
+       struct smf *sp, *sp2;
+
+       sp = calloc(sizeof *sp, 1);
+       assert(sp != NULL);
+       printf("NEW    %12p  %12p %12jx %12jx\n", (void*)sp, (void*)ptr, (uintmax_t)off, (uintmax_t)len);
+
+       sp->sc = sc;
+
+       sp->size = len;
+       sp->ptr = ptr;
+       sp->offset = off;
+
+       sp->alloc = 1;
+
+       TAILQ_FOREACH(sp2, &sc->order, order) {
+               if (sp->ptr < sp2->ptr) {
+                       TAILQ_INSERT_BEFORE(sp2, sp, order);
+                       break;
+               }
+       }
+       if (sp2 == NULL)
+               TAILQ_INSERT_TAIL(&sc->order, sp, order);
+
+       TAILQ_INSERT_HEAD(&sc->used, sp, status);
+
+       free_smf(sp);
+}
+
 /*--------------------------------------------------------------------*/
 
 /*
@@ -251,17 +404,15 @@ smf_open_chunk(struct smf_sc *sc, off_t sz, off_t off, off_t *fail, off_t *sum)
        void *p;
        off_t h;
 
-       if (*fail < getpagesize() * MINPAGES)
+       if (*fail < sc->pagesize * MINPAGES)
                return;
 
        if (sz < *fail && sz < SIZE_T_MAX) {
                p = mmap(NULL, sz, PROT_READ|PROT_WRITE,
                    MAP_NOCORE | MAP_NOSYNC | MAP_PRIVATE, sc->fd, off);
                if (p != MAP_FAILED) {
-                       printf("%12p...%12p  %12jx...%12jx %12jx\n",
-                           p, (u_char *)p + sz,
-                           off, off + sz, sz);
                        (*sum) += sz;
+                       new_smf(sc, p, off, sz);
                        return;
                }
        }
@@ -272,7 +423,7 @@ smf_open_chunk(struct smf_sc *sc, off_t sz, off_t off, off_t *fail, off_t *sum)
        h = sz / 2;
        if (h > SIZE_T_MAX)
                h = SIZE_T_MAX;
-       h -= (h % getpagesize());
+       h -= (h % sc->pagesize);
 
        smf_open_chunk(sc, h, off, fail, sum);
        smf_open_chunk(sc, sz - h, off + h, fail, sum);
@@ -299,15 +450,14 @@ smf_open(struct stevedore *st)
 /*--------------------------------------------------------------------*/
 
 static struct storage *
-smf_alloc(struct stevedore *st __unused, unsigned size)
+smf_alloc(struct stevedore *st, unsigned size)
 {
        struct smf *smf;
 
-       smf = calloc(sizeof *smf, 1);
+       smf = alloc_smf(st->priv, size);
        assert(smf != NULL);
        smf->s.priv = smf;
-       smf->s.ptr = malloc(size);
-       assert(smf->s.ptr != NULL);
+       smf->s.ptr = smf->ptr;
        smf->s.len = size;
        return (&smf->s);
 }
@@ -318,8 +468,7 @@ smf_free(struct storage *s)
        struct smf *smf;
 
        smf = s->priv;
-       free(smf->s.ptr);
-       free(smf);
+       free_smf(smf);
 }
 
 struct stevedore smf_stevedore = {