34 #if defined(LIBC_SCCS) && !defined(lint)
35 static char sccsid[] =
"@(#)mpool.c 8.5 (Berkeley) 7/26/94";
38 #include <sys/param.h>
39 #include <sys/queue.h>
48 #include "../include/db.h"
50 #define __MPOOLINTERFACE_PRIVATE
56 #define mpool_open __mpool_open
57 #define mpool_filter __mpool_filter
58 #define mpool_new __mpool_new
59 #define mpool_get __mpool_get
60 #define mpool_put __mpool_put
61 #define mpool_sync __mpool_sync
62 #define mpool_close __mpool_close
65 static BKT *mpool_bkt __P((
MPOOL *));
66 static BKT *mpool_look __P((
MPOOL *, pgno_t));
67 static int mpool_write __P((
MPOOL *,
BKT *));
74 mpool_open(key, fd, pagesize, maxcache)
77 pgno_t pagesize, maxcache;
91 if (!S_ISREG(sb.st_mode)) {
97 if ((mp = (
MPOOL *)calloc(1,
sizeof(
MPOOL))) == NULL)
99 CIRCLEQ_INIT(&mp->lqh);
100 for (entry = 0; entry < HASHSIZE; ++entry)
101 CIRCLEQ_INIT(&mp->hqh[entry]);
102 mp->maxcache = maxcache;
103 mp->npages = sb.st_size / pagesize;
104 mp->pagesize = pagesize;
114 mpool_filter(mp, pgin, pgout, pgcookie)
116 void (*pgin) __P((
void *, pgno_t,
void *));
117 void (*pgout) __P((
void *, pgno_t,
void *));
122 mp->pgcookie = pgcookie;
130 mpool_new(mp, pgnoaddr)
137 if (mp->npages == MAX_PAGE_NUMBER) {
138 (void)fprintf(stderr,
"mpool_new: page allocation overflow.\n");
149 if ((bp = mpool_bkt(mp)) == NULL)
151 *pgnoaddr = bp->pgno = mp->npages++;
152 bp->flags = MPOOL_PINNED;
154 head = &mp->hqh[HASHKEY(bp->pgno)];
155 CIRCLEQ_INSERT_HEAD(head, bp, hq);
156 CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
165 mpool_get(mp, pgno, flags)
176 if (pgno >= mp->npages) {
186 if ((bp = mpool_look(mp, pgno)) != NULL) {
188 if (bp->flags & MPOOL_PINNED) {
189 (void)fprintf(stderr,
190 "mpool_get: page %d already pinned\n", bp->pgno);
198 head = &mp->hqh[HASHKEY(bp->pgno)];
199 CIRCLEQ_REMOVE(head, bp, hq);
200 CIRCLEQ_INSERT_HEAD(head, bp, hq);
201 CIRCLEQ_REMOVE(&mp->lqh, bp, q);
202 CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
205 bp->flags |= MPOOL_PINNED;
210 if ((bp = mpool_bkt(mp)) == NULL)
217 off = mp->pagesize * pgno;
218 if (lseek(mp->fd, off, SEEK_SET) != off)
220 if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize))
229 bp->flags = MPOOL_PINNED;
235 head = &mp->hqh[HASHKEY(bp->pgno)];
236 CIRCLEQ_INSERT_HEAD(head, bp, hq);
237 CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q);
240 if (mp->pgin != NULL)
241 (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
251 mpool_put(mp, page, flags)
261 bp = (
BKT *)((
char *)page -
sizeof(
BKT));
263 if (!(bp->flags & MPOOL_PINNED)) {
264 (void)fprintf(stderr,
265 "mpool_put: page %d not pinned\n", bp->pgno);
269 bp->flags &= ~MPOOL_PINNED;
270 bp->flags |= flags & MPOOL_DIRTY;
271 return (RET_SUCCESS);
285 while ((bp = mp->lqh.cqh_first) != (
void *)&mp->lqh) {
286 CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q);
292 return (RET_SUCCESS);
306 for (bp = mp->lqh.cqh_first;
307 bp != (
void *)&mp->lqh; bp = bp->q.cqe_next)
308 if (bp->flags & MPOOL_DIRTY &&
309 mpool_write(mp, bp) == RET_ERROR)
313 return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
327 #define weak_alias(original, alias) \
328 asm (".weak " #alias "\n" #alias " = " #original);
329 weak_alias (__mpool_open, mpool_open)
330 weak_alias (__mpool_filter, mpool_filter)
331 weak_alias (__mpool_new, mpool_new)
332 weak_alias (__mpool_get, mpool_get)
333 weak_alias (__mpool_put, mpool_put)
334 weak_alias (__mpool_close, mpool_close)
335 weak_alias (__mpool_sync, mpool_sync)
350 if (mp->curcache < mp->maxcache)
359 for (bp = mp->lqh.cqh_first;
360 bp != (
void *)&mp->lqh; bp = bp->q.cqe_next)
361 if (!(bp->flags & MPOOL_PINNED)) {
363 if (bp->flags & MPOOL_DIRTY &&
364 mpool_write(mp, bp) == RET_ERROR)
370 head = &mp->hqh[HASHKEY(bp->pgno)];
371 CIRCLEQ_REMOVE(head, bp, hq);
372 CIRCLEQ_REMOVE(&mp->lqh, bp, q);
376 memset(bp, 0xff,
sizeof(
BKT) + mp->pagesize);
383 new:
if ((bp = (
BKT *) calloc(1,
sizeof(
BKT) + mp->pagesize)) == NULL)
388 #if defined(DEBUG) || defined(PURIFY)
389 memset(bp, 0xff,
sizeof(
BKT) + mp->pagesize);
391 bp->page = (
char *)bp +
sizeof(
BKT);
413 (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
415 off = mp->pagesize * bp->pgno;
416 if (lseek(mp->fd, off, SEEK_SET) != off)
418 if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
421 bp->flags &= ~MPOOL_DIRTY;
422 return (RET_SUCCESS);
437 head = &mp->hqh[HASHKEY(pgno)];
438 for (bp = head->cqh_first; bp != (
void *)head; bp = bp->hq.cqe_next)
439 if (bp->pgno == pgno) {
464 (void)fprintf(stderr,
"%lu pages in the file\n", mp->npages);
465 (void)fprintf(stderr,
466 "page size %lu, caching %lu pages of %lu page max cache\n",
467 mp->pagesize, mp->curcache, mp->maxcache);
468 (void)fprintf(stderr,
"%lu page puts, %lu page gets, %lu page new\n",
469 mp->pageput, mp->pageget, mp->pagenew);
470 (void)fprintf(stderr,
"%lu page allocs, %lu page flushes\n",
471 mp->pagealloc, mp->pageflush);
472 if (mp->cachehit + mp->cachemiss)
473 (void)fprintf(stderr,
474 "%.0f%% cache hit rate (%lu hits, %lu misses)\n",
475 ((
double)mp->cachehit / (mp->cachehit + mp->cachemiss))
476 * 100, mp->cachehit, mp->cachemiss);
477 (void)fprintf(stderr,
"%lu page reads, %lu page writes\n",
478 mp->pageread, mp->pagewrite);
482 for (bp = mp->lqh.cqh_first;
483 bp != (
void *)&mp->lqh; bp = bp->q.cqe_next) {
484 (void)fprintf(stderr,
"%s%d", sep, bp->pgno);
485 if (bp->flags & MPOOL_DIRTY)
486 (void)fprintf(stderr,
"d");
487 if (bp->flags & MPOOL_PINNED)
488 (void)fprintf(stderr,
"P");
496 (void)fprintf(stderr,
"\n");