]> mj.ucw.cz Git - libucw.git/commitdiff
Move pagecache from libucw to libsherlock
authorMichal Vaner <vorner@ucw.cz>
Thu, 17 Jul 2008 09:23:16 +0000 (11:23 +0200)
committerMartin Mares <mj@ucw.cz>
Thu, 17 Jul 2008 17:25:39 +0000 (19:25 +0200)
ucw/Makefile
ucw/pagecache.c [deleted file]
ucw/pagecache.h [deleted file]

index 39d69957e5f49d4bf5b40ebe3e563e1e3f6fbbac..b803e7d4391def7d555d7dc1e981bcd201199b15 100644 (file)
@@ -8,7 +8,7 @@ PROGS+=$(o)/ucw/basecode
 LIBUCW_MODS= \
        threads \
        alloc alloc_str realloc bigalloc mempool mempool-str mempool-fmt eltpool \
-       mmap pagecache partmap hashfunc \
+       mmap partmap hashfunc \
        lists slists simple-lists bitsig \
        log log-file proctitle \
        conf-alloc conf-dump conf-input conf-intr conf-journal conf-parse conf-section \
@@ -33,7 +33,7 @@ LIBUCW_MODS= \
 
 LIBUCW_INCLUDES= \
        lib.h config.h threads.h \
-       mempool.h pagecache.h \
+       mempool.h \
        arraysort.h \
        lists.h clists.h slists.h simple-lists.h \
        string.h stkstring.h unicode.h chartype.h regex.h \
diff --git a/ucw/pagecache.c b/ucw/pagecache.c
deleted file mode 100644 (file)
index 4f135a4..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- *     UCW Library -- File Page Cache
- *
- *     (c) 1999--2002 Martin Mares <mj@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#include "ucw/lib.h"
-#include "ucw/pagecache.h"
-#include "ucw/lfs.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <alloca.h>
-
-struct page_cache {
-  list free_pages;                     /* LRU queue of free non-dirty pages */
-  list locked_pages;                   /* List of locked pages (starts with dirty ones) */
-  list dirty_pages;                    /* List of free dirty pages */
-  uns page_size;                       /* Bytes per page (must be a power of two) */
-  uns free_count;                      /* Number of free / dirty pages */
-  uns total_count;                     /* Total number of pages */
-  uns max_pages;                       /* Maximum number of free pages */
-  uns hash_size;                       /* Hash table size */
-  uns stat_hit;                                /* Number of cache hits */
-  uns stat_miss;                       /* Number of cache misses */
-  uns stat_write;                      /* Number of writes */
-  list *hash_table;                    /* List heads corresponding to hash buckets */
-#ifndef HAVE_PREAD
-  sh_off_t pos;                                /* Current position in the file */
-  int pos_fd;                          /* FD the position corresponds to */
-#endif
-};
-
-#define PAGE_NUMBER(pos) ((pos) & ~(sh_off_t)(c->page_size - 1))
-#define PAGE_OFFSET(pos) ((pos) & (c->page_size - 1))
-
-struct page_cache *
-pgc_open(uns page_size, uns max_pages)
-{
-  struct page_cache *c = xmalloc_zero(sizeof(struct page_cache));
-  uns i;
-
-  init_list(&c->free_pages);
-  init_list(&c->locked_pages);
-  init_list(&c->dirty_pages);
-  c->page_size = page_size;
-  c->max_pages = max_pages;
-  c->hash_size = nextprime(c->max_pages);
-  c->hash_table = xmalloc(sizeof(list) * c->hash_size);
-  for(i=0; i<c->hash_size; i++)
-    init_list(&c->hash_table[i]);
-#ifndef HAVE_PREAD
-  c->pos_fd = -1;
-#endif
-  return c;
-}
-
-void
-pgc_close(struct page_cache *c)
-{
-  pgc_cleanup(c);
-  ASSERT(EMPTY_LIST(c->locked_pages));
-  ASSERT(EMPTY_LIST(c->dirty_pages));
-  ASSERT(EMPTY_LIST(c->free_pages));
-  xfree(c->hash_table);
-  xfree(c);
-}
-
-static void
-pgc_debug_page(struct page *p)
-{
-  printf("\tp=%08x d=%d f=%x c=%d\n", (uns) p->pos, p->fd, p->flags, p->lock_count);
-}
-
-void
-pgc_debug(struct page_cache *c, int mode)
-{
-  struct page *p;
-
-  printf(">> Page cache dump: pgsize=%d, pages=%d, freepages=%d of %d, hash=%d\n", c->page_size, c->total_count, c->free_count, c->max_pages, c->hash_size);
-  printf(">> stats: %d hits, %d misses, %d writes\n", c->stat_hit, c->stat_miss, c->stat_write);
-  if (mode)
-    {
-      puts("LRU list:");
-      WALK_LIST(p, c->free_pages)
-       pgc_debug_page(p);
-      puts("Locked list:");
-      WALK_LIST(p, c->locked_pages)
-       pgc_debug_page(p);
-      puts("Dirty list:");
-      WALK_LIST(p, c->dirty_pages)
-       pgc_debug_page(p);
-    }
-}
-
-static void
-flush_page(struct page_cache *c, struct page *p)
-{
-  int s;
-
-  ASSERT(p->flags & PG_FLAG_DIRTY);
-#ifdef HAVE_PREAD
-  s = sh_pwrite(p->fd, p->data, c->page_size, p->pos);
-#else
-  if (c->pos != p->pos || c->pos_fd != (int) p->fd)
-    sh_seek(p->fd, p->pos, SEEK_SET);
-  s = write(p->fd, p->data, c->page_size);
-  c->pos = p->pos + s;
-  c->pos_fd = p->fd;
-#endif
-  if (s < 0)
-    die("pgc_write(%d): %m", p->fd);
-  if (s != (int) c->page_size)
-    die("pgc_write(%d): incomplete page (only %d of %d)", p->fd, s, c->page_size);
-  p->flags &= ~PG_FLAG_DIRTY;
-  c->stat_write++;
-}
-
-static int
-flush_cmp(const void *X, const void *Y)
-{
-  struct page *x = *((struct page **)X);
-  struct page *y = *((struct page **)Y);
-
-  if (x->fd < y->fd)
-    return -1;
-  if (x->fd > y->fd)
-    return 1;
-  if (x->pos < y->pos)
-    return -1;
-  if (x->pos > y->pos)
-    return 1;
-  return 0;
-}
-
-static void
-flush_pages(struct page_cache *c, uns force)
-{
-  uns cnt = 0;
-  uns max = force ? ~0U : c->free_count / 2;
-  uns i;
-  struct page *p, *q, **req, **rr;
-
-  WALK_LIST(p, c->dirty_pages)
-    {
-      cnt++;
-      if (cnt >= max)
-       break;
-    }
-  req = rr = alloca(cnt * sizeof(struct page *));
-  i = cnt;
-  p = HEAD(c->dirty_pages);
-  while ((q = (struct page *) p->n.next) && i--)
-    {
-      rem_node(&p->n);
-      add_tail(&c->free_pages, &p->n);
-      *rr++ = p;
-      p = q;
-    }
-  qsort(req, cnt, sizeof(struct page *), flush_cmp);
-  for(i=0; i<cnt; i++)
-    flush_page(c, req[i]);
-}
-
-static inline uns
-hash_page(struct page_cache *c, sh_off_t pos, uns fd)
-{
-  return (pos + fd) % c->hash_size;
-}
-
-static struct page *
-get_page(struct page_cache *c, sh_off_t pos, uns fd)
-{
-  node *n;
-  struct page *p;
-  uns hash = hash_page(c, pos, fd);
-
-  /*
-   *  Return locked buffer for given page.
-   */
-
-  WALK_LIST(n, c->hash_table[hash])
-    {
-      p = SKIP_BACK(struct page, hn, n);
-      if (p->pos == pos && p->fd == fd)
-       {
-         /* Found in the cache */
-         rem_node(&p->n);
-         if (!p->lock_count)
-           c->free_count--;
-         return p;
-       }
-    }
-  if (c->total_count < c->max_pages || !c->free_count)
-    {
-      /* Enough free space, expand the cache */
-      p = xmalloc(sizeof(struct page) + c->page_size);
-      c->total_count++;
-    }
-  else
-    {
-      /* Discard the oldest unlocked page */
-      p = HEAD(c->free_pages);
-      if (!p->n.next)
-       {
-         /* There are only dirty pages here */
-         flush_pages(c, 0);
-         p = HEAD(c->free_pages);
-         ASSERT(p->n.next);
-       }
-      ASSERT(!p->lock_count);
-      rem_node(&p->n);
-      rem_node(&p->hn);
-      c->free_count--;
-    }
-  p->pos = pos;
-  p->fd = fd;
-  p->flags = 0;
-  p->lock_count = 0;
-  add_tail(&c->hash_table[hash], &p->hn);
-  return p;
-}
-
-void
-pgc_flush(struct page_cache *c)
-{
-  struct page *p;
-
-  flush_pages(c, 1);
-  WALK_LIST(p, c->locked_pages)
-    if (p->flags & PG_FLAG_DIRTY)
-      flush_page(c, p);
-    else
-      break;
-}
-
-void
-pgc_cleanup(struct page_cache *c)
-{
-  struct page *p;
-  node *n;
-
-  pgc_flush(c);
-  WALK_LIST_DELSAFE(p, n, c->free_pages)
-    {
-      ASSERT(!(p->flags & PG_FLAG_DIRTY) && !p->lock_count);
-      rem_node(&p->n);
-      rem_node(&p->hn);
-      c->free_count--;
-      c->total_count--;
-      xfree(p);
-    }
-  ASSERT(!c->free_count);
-}
-
-static inline struct page *
-get_and_lock_page(struct page_cache *c, sh_off_t pos, uns fd)
-{
-  struct page *p = get_page(c, pos, fd);
-
-  add_tail(&c->locked_pages, &p->n);
-  p->lock_count++;
-  return p;
-}
-
-struct page *
-pgc_read(struct page_cache *c, int fd, sh_off_t pos)
-{
-  struct page *p;
-  int s;
-
-  ASSERT(!PAGE_OFFSET(pos));
-  p = get_and_lock_page(c, pos, fd);
-  if (p->flags & PG_FLAG_VALID)
-    c->stat_hit++;
-  else
-    {
-      c->stat_miss++;
-#ifdef HAVE_PREAD
-      s = sh_pread(fd, p->data, c->page_size, pos);
-#else
-      if (c->pos != pos || c->pos_fd != (int)fd)
-       sh_seek(fd, pos, SEEK_SET);
-      s = read(fd, p->data, c->page_size);
-      c->pos = pos + s;
-      c->pos_fd = fd;
-#endif
-      if (s < 0)
-       die("pgc_read(%d): %m", fd);
-      if (s != (int) c->page_size)
-       die("pgc_read(%d): incomplete page (only %d of %d)", p->fd, s, c->page_size);
-      p->flags |= PG_FLAG_VALID;
-    }
-  return p;
-}
-
-struct page *
-pgc_get(struct page_cache *c, int fd, sh_off_t pos)
-{
-  struct page *p;
-
-  ASSERT(!PAGE_OFFSET(pos));
-  p = get_and_lock_page(c, pos, fd);
-  p->flags |= PG_FLAG_VALID | PG_FLAG_DIRTY;
-  return p;
-}
-
-struct page *
-pgc_get_zero(struct page_cache *c, int fd, sh_off_t pos)
-{
-  struct page *p;
-
-  ASSERT(!PAGE_OFFSET(pos));
-  p = get_and_lock_page(c, pos, fd);
-  bzero(p->data, c->page_size);
-  p->flags |= PG_FLAG_VALID | PG_FLAG_DIRTY;
-  return p;
-}
-
-void
-pgc_put(struct page_cache *c, struct page *p)
-{
-  ASSERT(p->lock_count);
-  if (--p->lock_count)
-    return;
-  rem_node(&p->n);
-  if (p->flags & PG_FLAG_DIRTY)
-    {
-      add_tail(&c->dirty_pages, &p->n);
-      c->free_count++;
-    }
-  else if (c->free_count < c->max_pages)
-    {
-      add_tail(&c->free_pages, &p->n);
-      c->free_count++;
-    }
-  else
-    {
-      rem_node(&p->hn);
-      xfree(p);
-      c->total_count--;
-    }
-}
-
-void
-pgc_mark_dirty(struct page_cache *c, struct page *p)
-{
-  ASSERT(p->lock_count);
-  if (!(p->flags & PG_FLAG_DIRTY))
-    {
-      p->flags |= PG_FLAG_DIRTY;
-      rem_node(&p->n);
-      add_head(&c->locked_pages, &p->n);
-    }
-}
-
-byte *
-pgc_read_data(struct page_cache *c, int fd, sh_off_t pos, uns *len)
-{
-  struct page *p;
-  sh_off_t page = PAGE_NUMBER(pos);
-  uns offset = PAGE_OFFSET(pos);
-
-  p = pgc_read(c, fd, page);
-  pgc_put(c, p);
-  *len = c->page_size - offset;
-  return p->data + offset;
-}
-
-#ifdef TEST
-
-int main(int argc, char **argv)
-{
-  struct page_cache *c = pgc_open(1024, 2);
-  struct page *p, *q, *r;
-  int fd = open("test", O_RDWR | O_CREAT | O_TRUNC, 0666);
-  if (fd < 0)
-    die("open: %m");
-  pgc_debug(c, 1);
-  p = pgc_get(c, fd, 0);
-  pgc_debug(c, 1);
-  strcpy(p->data, "one");
-  pgc_put(c, p);
-  pgc_debug(c, 1);
-  p = pgc_get(c, fd, 1024);
-  pgc_debug(c, 1);
-  strcpy(p->data, "two");
-  pgc_put(c, p);
-  pgc_debug(c, 1);
-  p = pgc_get(c, fd, 2048);
-  pgc_debug(c, 1);
-  strcpy(p->data, "three");
-  pgc_put(c, p);
-  pgc_debug(c, 1);
-  pgc_flush(c);
-  pgc_debug(c, 1);
-  p = pgc_read(c, fd, 0);
-  pgc_debug(c, 1);
-  strcpy(p->data, "odin");
-  pgc_mark_dirty(c, p);
-  pgc_debug(c, 1);
-  pgc_flush(c);
-  pgc_debug(c, 1);
-  q = pgc_read(c, fd, 1024);
-  pgc_debug(c, 1);
-  r = pgc_read(c, fd, 2048);
-  pgc_debug(c, 1);
-  pgc_put(c, p);
-  pgc_put(c, q);
-  pgc_put(c, r);
-  pgc_debug(c, 1);
-  p = pgc_get(c, fd, 3072);
-  pgc_debug(c, 1);
-  strcpy(p->data, "four");
-  pgc_put(c, p);
-  pgc_debug(c, 1);
-  pgc_cleanup(c);
-  pgc_debug(c, 1);
-  pgc_close(c);
-  return 0;
-}
-
-#endif
diff --git a/ucw/pagecache.h b/ucw/pagecache.h
deleted file mode 100644 (file)
index 36251a5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *     UCW Library -- File Page Cache
- *
- *     (c) 1999--2002 Martin Mares <mj@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#ifndef _UCW_PAGECACHE_H
-#define _UCW_PAGECACHE_H
-
-#include "ucw/lists.h"
-
-struct page_cache;
-
-struct page {
-  node n;                              /* Node in page list */
-  node hn;                             /* Node in hash table */
-  sh_off_t pos;
-  uns fd;
-  uns flags;
-  uns lock_count;
-  byte data[0];
-};
-
-#define PG_FLAG_DIRTY          1
-#define PG_FLAG_VALID          2
-
-struct page_cache *pgc_open(uns page_size, uns max_pages);
-void pgc_close(struct page_cache *);
-void pgc_debug(struct page_cache *, int mode);
-void pgc_flush(struct page_cache *);                           /* Write all unwritten pages */
-void pgc_cleanup(struct page_cache *);                         /* Deallocate all unused buffers */
-struct page *pgc_read(struct page_cache *, int fd, sh_off_t);  /* Read page and lock it */
-struct page *pgc_get(struct page_cache *, int fd, sh_off_t);   /* Get page for writing */
-struct page *pgc_get_zero(struct page_cache *, int fd, sh_off_t); /* ... and clear it */
-void pgc_put(struct page_cache *, struct page *);              /* Release page */
-void pgc_mark_dirty(struct page_cache *, struct page *);       /* Mark locked page as dirty */
-byte *pgc_read_data(struct page_cache *, int fd, sh_off_t, uns *);     /* Partial reading */
-
-#endif