1*0a6a1f1dSLionel Sambuc /* $NetBSD: mpool.c,v 1.21 2013/12/14 18:04:00 christos Exp $ */
22639ae9bSBen Gras
32639ae9bSBen Gras /*-
42639ae9bSBen Gras * Copyright (c) 1990, 1993, 1994
52639ae9bSBen Gras * The Regents of the University of California. All rights reserved.
62639ae9bSBen Gras *
72639ae9bSBen Gras * Redistribution and use in source and binary forms, with or without
82639ae9bSBen Gras * modification, are permitted provided that the following conditions
92639ae9bSBen Gras * are met:
102639ae9bSBen Gras * 1. Redistributions of source code must retain the above copyright
112639ae9bSBen Gras * notice, this list of conditions and the following disclaimer.
122639ae9bSBen Gras * 2. Redistributions in binary form must reproduce the above copyright
132639ae9bSBen Gras * notice, this list of conditions and the following disclaimer in the
142639ae9bSBen Gras * documentation and/or other materials provided with the distribution.
152639ae9bSBen Gras * 3. Neither the name of the University nor the names of its contributors
162639ae9bSBen Gras * may be used to endorse or promote products derived from this software
172639ae9bSBen Gras * without specific prior written permission.
182639ae9bSBen Gras *
192639ae9bSBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
202639ae9bSBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212639ae9bSBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222639ae9bSBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
232639ae9bSBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242639ae9bSBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
252639ae9bSBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262639ae9bSBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
272639ae9bSBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
282639ae9bSBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
292639ae9bSBen Gras * SUCH DAMAGE.
302639ae9bSBen Gras */
312639ae9bSBen Gras
322639ae9bSBen Gras #if HAVE_NBTOOL_CONFIG_H
332639ae9bSBen Gras #include "nbtool_config.h"
342639ae9bSBen Gras #endif
352639ae9bSBen Gras
362639ae9bSBen Gras #include <sys/cdefs.h>
37*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: mpool.c,v 1.21 2013/12/14 18:04:00 christos Exp $");
382639ae9bSBen Gras
392639ae9bSBen Gras #include "namespace.h"
402639ae9bSBen Gras #include <sys/queue.h>
412639ae9bSBen Gras #include <sys/stat.h>
422639ae9bSBen Gras
432639ae9bSBen Gras #include <errno.h>
442639ae9bSBen Gras #include <stdio.h>
452639ae9bSBen Gras #include <stdlib.h>
462639ae9bSBen Gras #include <string.h>
472639ae9bSBen Gras #include <unistd.h>
482639ae9bSBen Gras
492639ae9bSBen Gras #include <db.h>
502639ae9bSBen Gras
512639ae9bSBen Gras #define __MPOOLINTERFACE_PRIVATE
522639ae9bSBen Gras #include <mpool.h>
532639ae9bSBen Gras
542639ae9bSBen Gras #ifdef __weak_alias
552639ae9bSBen Gras __weak_alias(mpool_close,_mpool_close)
562639ae9bSBen Gras __weak_alias(mpool_filter,_mpool_filter)
572639ae9bSBen Gras __weak_alias(mpool_get,_mpool_get)
582639ae9bSBen Gras __weak_alias(mpool_new,_mpool_new)
592639ae9bSBen Gras __weak_alias(mpool_open,_mpool_open)
602639ae9bSBen Gras __weak_alias(mpool_put,_mpool_put)
612639ae9bSBen Gras __weak_alias(mpool_sync,_mpool_sync)
622639ae9bSBen Gras #endif
632639ae9bSBen Gras
642639ae9bSBen Gras static BKT *mpool_bkt(MPOOL *);
652639ae9bSBen Gras static BKT *mpool_look(MPOOL *, pgno_t);
662639ae9bSBen Gras static int mpool_write(MPOOL *, BKT *);
672639ae9bSBen Gras
682639ae9bSBen Gras /*
692639ae9bSBen Gras * mpool_open --
702639ae9bSBen Gras * Initialize a memory pool.
712639ae9bSBen Gras */
722639ae9bSBen Gras /*ARGSUSED*/
732639ae9bSBen Gras MPOOL *
mpool_open(void * key,int fd,pgno_t pagesize,pgno_t maxcache)742639ae9bSBen Gras mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache)
752639ae9bSBen Gras {
762639ae9bSBen Gras struct stat sb;
772639ae9bSBen Gras MPOOL *mp;
782639ae9bSBen Gras int entry;
792639ae9bSBen Gras
802639ae9bSBen Gras /*
812639ae9bSBen Gras * Get information about the file.
822639ae9bSBen Gras *
832639ae9bSBen Gras * XXX
842639ae9bSBen Gras * We don't currently handle pipes, although we should.
852639ae9bSBen Gras */
862639ae9bSBen Gras if (fstat(fd, &sb))
87*0a6a1f1dSLionel Sambuc return NULL;
882639ae9bSBen Gras if (!S_ISREG(sb.st_mode)) {
892639ae9bSBen Gras errno = ESPIPE;
90*0a6a1f1dSLionel Sambuc return NULL;
912639ae9bSBen Gras }
922639ae9bSBen Gras
932639ae9bSBen Gras /* Allocate and initialize the MPOOL cookie. */
94*0a6a1f1dSLionel Sambuc if ((mp = calloc(1, sizeof(*mp))) == NULL)
952639ae9bSBen Gras return (NULL);
9684d9c625SLionel Sambuc TAILQ_INIT(&mp->lqh);
972639ae9bSBen Gras for (entry = 0; entry < HASHSIZE; ++entry)
9884d9c625SLionel Sambuc TAILQ_INIT(&mp->hqh[entry]);
992639ae9bSBen Gras mp->maxcache = maxcache;
1002639ae9bSBen Gras mp->npages = (pgno_t)(sb.st_size / pagesize);
1012639ae9bSBen Gras mp->pagesize = pagesize;
1022639ae9bSBen Gras mp->fd = fd;
103*0a6a1f1dSLionel Sambuc return mp;
1042639ae9bSBen Gras }
1052639ae9bSBen Gras
1062639ae9bSBen Gras /*
1072639ae9bSBen Gras * mpool_filter --
1082639ae9bSBen Gras * Initialize input/output filters.
1092639ae9bSBen Gras */
1102639ae9bSBen Gras void
mpool_filter(MPOOL * mp,void (* pgin)(void *,pgno_t,void *),void (* pgout)(void *,pgno_t,void *),void * pgcookie)1112639ae9bSBen Gras mpool_filter(MPOOL *mp, void (*pgin)(void *, pgno_t, void *),
1122639ae9bSBen Gras void (*pgout)(void *, pgno_t, void *), void *pgcookie)
1132639ae9bSBen Gras {
1142639ae9bSBen Gras mp->pgin = pgin;
1152639ae9bSBen Gras mp->pgout = pgout;
1162639ae9bSBen Gras mp->pgcookie = pgcookie;
1172639ae9bSBen Gras }
1182639ae9bSBen Gras
1192639ae9bSBen Gras /*
1202639ae9bSBen Gras * mpool_new --
1212639ae9bSBen Gras * Get a new page of memory.
1222639ae9bSBen Gras */
1232639ae9bSBen Gras void *
mpool_new(MPOOL * mp,pgno_t * pgnoaddr)1242639ae9bSBen Gras mpool_new( MPOOL *mp, pgno_t *pgnoaddr)
1252639ae9bSBen Gras {
1262639ae9bSBen Gras struct _hqh *head;
1272639ae9bSBen Gras BKT *bp;
1282639ae9bSBen Gras
1292639ae9bSBen Gras if (mp->npages == MAX_PAGE_NUMBER) {
1302639ae9bSBen Gras (void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
1312639ae9bSBen Gras abort();
1322639ae9bSBen Gras }
1332639ae9bSBen Gras #ifdef STATISTICS
1342639ae9bSBen Gras ++mp->pagenew;
1352639ae9bSBen Gras #endif
1362639ae9bSBen Gras /*
1372639ae9bSBen Gras * Get a BKT from the cache. Assign a new page number, attach
1382639ae9bSBen Gras * it to the head of the hash chain, the tail of the lru chain,
1392639ae9bSBen Gras * and return.
1402639ae9bSBen Gras */
1412639ae9bSBen Gras if ((bp = mpool_bkt(mp)) == NULL)
142*0a6a1f1dSLionel Sambuc return NULL;
1432639ae9bSBen Gras *pgnoaddr = bp->pgno = mp->npages++;
1442639ae9bSBen Gras bp->flags = MPOOL_PINNED;
1452639ae9bSBen Gras
1462639ae9bSBen Gras head = &mp->hqh[HASHKEY(bp->pgno)];
14784d9c625SLionel Sambuc TAILQ_INSERT_HEAD(head, bp, hq);
14884d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
149*0a6a1f1dSLionel Sambuc return bp->page;
1502639ae9bSBen Gras }
1512639ae9bSBen Gras
1522639ae9bSBen Gras /*
1532639ae9bSBen Gras * mpool_get
1542639ae9bSBen Gras * Get a page.
1552639ae9bSBen Gras */
1562639ae9bSBen Gras /*ARGSUSED*/
1572639ae9bSBen Gras void *
mpool_get(MPOOL * mp,pgno_t pgno,u_int flags)1582639ae9bSBen Gras mpool_get(MPOOL *mp, pgno_t pgno, u_int flags)
1592639ae9bSBen Gras {
1602639ae9bSBen Gras struct _hqh *head;
1612639ae9bSBen Gras BKT *bp;
1622639ae9bSBen Gras off_t off;
1632639ae9bSBen Gras ssize_t nr;
1642639ae9bSBen Gras
1652639ae9bSBen Gras /* Check for attempt to retrieve a non-existent page. */
1662639ae9bSBen Gras if (pgno >= mp->npages) {
1672639ae9bSBen Gras errno = EINVAL;
168*0a6a1f1dSLionel Sambuc return NULL;
1692639ae9bSBen Gras }
1702639ae9bSBen Gras
1712639ae9bSBen Gras #ifdef STATISTICS
1722639ae9bSBen Gras ++mp->pageget;
1732639ae9bSBen Gras #endif
1742639ae9bSBen Gras
1752639ae9bSBen Gras /* Check for a page that is cached. */
1762639ae9bSBen Gras if ((bp = mpool_look(mp, pgno)) != NULL) {
1772639ae9bSBen Gras #ifdef DEBUG
1782639ae9bSBen Gras if (bp->flags & MPOOL_PINNED) {
1792639ae9bSBen Gras (void)fprintf(stderr,
1802639ae9bSBen Gras "mpool_get: page %d already pinned\n", bp->pgno);
1812639ae9bSBen Gras abort();
1822639ae9bSBen Gras }
1832639ae9bSBen Gras #endif
1842639ae9bSBen Gras /*
1852639ae9bSBen Gras * Move the page to the head of the hash chain and the tail
1862639ae9bSBen Gras * of the lru chain.
1872639ae9bSBen Gras */
1882639ae9bSBen Gras head = &mp->hqh[HASHKEY(bp->pgno)];
18984d9c625SLionel Sambuc TAILQ_REMOVE(head, bp, hq);
19084d9c625SLionel Sambuc TAILQ_INSERT_HEAD(head, bp, hq);
19184d9c625SLionel Sambuc TAILQ_REMOVE(&mp->lqh, bp, q);
19284d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
1932639ae9bSBen Gras
1942639ae9bSBen Gras /* Return a pinned page. */
1952639ae9bSBen Gras bp->flags |= MPOOL_PINNED;
196*0a6a1f1dSLionel Sambuc return bp->page;
1972639ae9bSBen Gras }
1982639ae9bSBen Gras
1992639ae9bSBen Gras /* Get a page from the cache. */
2002639ae9bSBen Gras if ((bp = mpool_bkt(mp)) == NULL)
201*0a6a1f1dSLionel Sambuc return NULL;
2022639ae9bSBen Gras
2032639ae9bSBen Gras /* Read in the contents. */
2042639ae9bSBen Gras #ifdef STATISTICS
2052639ae9bSBen Gras ++mp->pageread;
2062639ae9bSBen Gras #endif
2072639ae9bSBen Gras off = mp->pagesize * pgno;
2082639ae9bSBen Gras if ((nr = pread(mp->fd, bp->page, (size_t)mp->pagesize, off)) != (int)mp->pagesize) {
2092639ae9bSBen Gras if (nr >= 0)
2102639ae9bSBen Gras errno = EFTYPE;
211*0a6a1f1dSLionel Sambuc return NULL;
2122639ae9bSBen Gras }
2132639ae9bSBen Gras
2142639ae9bSBen Gras /* Set the page number, pin the page. */
2152639ae9bSBen Gras bp->pgno = pgno;
2162639ae9bSBen Gras bp->flags = MPOOL_PINNED;
2172639ae9bSBen Gras
2182639ae9bSBen Gras /*
2192639ae9bSBen Gras * Add the page to the head of the hash chain and the tail
2202639ae9bSBen Gras * of the lru chain.
2212639ae9bSBen Gras */
2222639ae9bSBen Gras head = &mp->hqh[HASHKEY(bp->pgno)];
22384d9c625SLionel Sambuc TAILQ_INSERT_HEAD(head, bp, hq);
22484d9c625SLionel Sambuc TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
2252639ae9bSBen Gras
2262639ae9bSBen Gras /* Run through the user's filter. */
2272639ae9bSBen Gras if (mp->pgin != NULL)
2282639ae9bSBen Gras (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
2292639ae9bSBen Gras
230*0a6a1f1dSLionel Sambuc return bp->page;
2312639ae9bSBen Gras }
2322639ae9bSBen Gras
2332639ae9bSBen Gras /*
2342639ae9bSBen Gras * mpool_put
2352639ae9bSBen Gras * Return a page.
2362639ae9bSBen Gras */
2372639ae9bSBen Gras /*ARGSUSED*/
2382639ae9bSBen Gras int
mpool_put(MPOOL * mp,void * page,u_int flags)2392639ae9bSBen Gras mpool_put(MPOOL *mp, void *page, u_int flags)
2402639ae9bSBen Gras {
2412639ae9bSBen Gras BKT *bp;
2422639ae9bSBen Gras
2432639ae9bSBen Gras #ifdef STATISTICS
2442639ae9bSBen Gras ++mp->pageput;
2452639ae9bSBen Gras #endif
246*0a6a1f1dSLionel Sambuc bp = (void *)((intptr_t)page - sizeof(BKT));
2472639ae9bSBen Gras #ifdef DEBUG
2482639ae9bSBen Gras if (!(bp->flags & MPOOL_PINNED)) {
2492639ae9bSBen Gras (void)fprintf(stderr,
2502639ae9bSBen Gras "mpool_put: page %d not pinned\n", bp->pgno);
2512639ae9bSBen Gras abort();
2522639ae9bSBen Gras }
2532639ae9bSBen Gras #endif
2542639ae9bSBen Gras bp->flags &= ~MPOOL_PINNED;
2552639ae9bSBen Gras bp->flags |= flags & MPOOL_DIRTY;
2562639ae9bSBen Gras return (RET_SUCCESS);
2572639ae9bSBen Gras }
2582639ae9bSBen Gras
2592639ae9bSBen Gras /*
2602639ae9bSBen Gras * mpool_close
2612639ae9bSBen Gras * Close the buffer pool.
2622639ae9bSBen Gras */
2632639ae9bSBen Gras int
mpool_close(MPOOL * mp)2642639ae9bSBen Gras mpool_close(MPOOL *mp)
2652639ae9bSBen Gras {
2662639ae9bSBen Gras BKT *bp;
2672639ae9bSBen Gras
2682639ae9bSBen Gras /* Free up any space allocated to the lru pages. */
26984d9c625SLionel Sambuc while (!TAILQ_EMPTY(&mp->lqh)) {
27084d9c625SLionel Sambuc bp = TAILQ_FIRST(&mp->lqh);
27184d9c625SLionel Sambuc TAILQ_REMOVE(&mp->lqh, bp, q);
2722639ae9bSBen Gras free(bp);
2732639ae9bSBen Gras }
2742639ae9bSBen Gras
2752639ae9bSBen Gras /* Free the MPOOL cookie. */
2762639ae9bSBen Gras free(mp);
277*0a6a1f1dSLionel Sambuc return RET_SUCCESS;
2782639ae9bSBen Gras }
2792639ae9bSBen Gras
2802639ae9bSBen Gras /*
2812639ae9bSBen Gras * mpool_sync
2822639ae9bSBen Gras * Sync the pool to disk.
2832639ae9bSBen Gras */
2842639ae9bSBen Gras int
mpool_sync(MPOOL * mp)2852639ae9bSBen Gras mpool_sync(MPOOL *mp)
2862639ae9bSBen Gras {
2872639ae9bSBen Gras BKT *bp;
2882639ae9bSBen Gras
2892639ae9bSBen Gras /* Walk the lru chain, flushing any dirty pages to disk. */
29084d9c625SLionel Sambuc TAILQ_FOREACH(bp, &mp->lqh, q)
2912639ae9bSBen Gras if (bp->flags & MPOOL_DIRTY &&
2922639ae9bSBen Gras mpool_write(mp, bp) == RET_ERROR)
293*0a6a1f1dSLionel Sambuc return RET_ERROR;
2942639ae9bSBen Gras
2952639ae9bSBen Gras /* Sync the file descriptor. */
296*0a6a1f1dSLionel Sambuc return fsync(mp->fd) ? RET_ERROR : RET_SUCCESS;
2972639ae9bSBen Gras }
2982639ae9bSBen Gras
2992639ae9bSBen Gras /*
3002639ae9bSBen Gras * mpool_bkt
3012639ae9bSBen Gras * Get a page from the cache (or create one).
3022639ae9bSBen Gras */
3032639ae9bSBen Gras static BKT *
mpool_bkt(MPOOL * mp)3042639ae9bSBen Gras mpool_bkt(MPOOL *mp)
3052639ae9bSBen Gras {
3062639ae9bSBen Gras struct _hqh *head;
3072639ae9bSBen Gras BKT *bp;
3082639ae9bSBen Gras
3092639ae9bSBen Gras /* If under the max cached, always create a new page. */
3102639ae9bSBen Gras if (mp->curcache < mp->maxcache)
3112639ae9bSBen Gras goto new;
3122639ae9bSBen Gras
3132639ae9bSBen Gras /*
3142639ae9bSBen Gras * If the cache is max'd out, walk the lru list for a buffer we
3152639ae9bSBen Gras * can flush. If we find one, write it (if necessary) and take it
3162639ae9bSBen Gras * off any lists. If we don't find anything we grow the cache anyway.
3172639ae9bSBen Gras * The cache never shrinks.
3182639ae9bSBen Gras */
31984d9c625SLionel Sambuc TAILQ_FOREACH(bp, &mp->lqh, q)
3202639ae9bSBen Gras if (!(bp->flags & MPOOL_PINNED)) {
3212639ae9bSBen Gras /* Flush if dirty. */
3222639ae9bSBen Gras if (bp->flags & MPOOL_DIRTY &&
3232639ae9bSBen Gras mpool_write(mp, bp) == RET_ERROR)
324*0a6a1f1dSLionel Sambuc return NULL;
3252639ae9bSBen Gras #ifdef STATISTICS
3262639ae9bSBen Gras ++mp->pageflush;
3272639ae9bSBen Gras #endif
3282639ae9bSBen Gras /* Remove from the hash and lru queues. */
3292639ae9bSBen Gras head = &mp->hqh[HASHKEY(bp->pgno)];
33084d9c625SLionel Sambuc TAILQ_REMOVE(head, bp, hq);
33184d9c625SLionel Sambuc TAILQ_REMOVE(&mp->lqh, bp, q);
3322639ae9bSBen Gras #ifdef DEBUG
3332639ae9bSBen Gras {
3342639ae9bSBen Gras void *spage = bp->page;
3352639ae9bSBen Gras (void)memset(bp, 0xff,
3362639ae9bSBen Gras (size_t)(sizeof(BKT) + mp->pagesize));
3372639ae9bSBen Gras bp->page = spage;
3382639ae9bSBen Gras }
3392639ae9bSBen Gras #endif
340*0a6a1f1dSLionel Sambuc return bp;
3412639ae9bSBen Gras }
3422639ae9bSBen Gras
3432639ae9bSBen Gras new: if ((bp = calloc(1, (size_t)(sizeof(BKT) + mp->pagesize))) == NULL)
344*0a6a1f1dSLionel Sambuc return NULL;
3452639ae9bSBen Gras #ifdef STATISTICS
3462639ae9bSBen Gras ++mp->pagealloc;
3472639ae9bSBen Gras #endif
3482639ae9bSBen Gras #if defined(DEBUG) || defined(PURIFY)
3492639ae9bSBen Gras (void)memset(bp, 0xff, (size_t)(sizeof(BKT) + mp->pagesize));
3502639ae9bSBen Gras #endif
351*0a6a1f1dSLionel Sambuc bp->page = (void *)((intptr_t)bp + sizeof(BKT));
3522639ae9bSBen Gras ++mp->curcache;
353*0a6a1f1dSLionel Sambuc return bp;
3542639ae9bSBen Gras }
3552639ae9bSBen Gras
3562639ae9bSBen Gras /*
3572639ae9bSBen Gras * mpool_write
3582639ae9bSBen Gras * Write a page to disk.
3592639ae9bSBen Gras */
3602639ae9bSBen Gras static int
mpool_write(MPOOL * mp,BKT * bp)3612639ae9bSBen Gras mpool_write(MPOOL *mp, BKT *bp)
3622639ae9bSBen Gras {
3632639ae9bSBen Gras off_t off;
3642639ae9bSBen Gras
3652639ae9bSBen Gras #ifdef STATISTICS
3662639ae9bSBen Gras ++mp->pagewrite;
3672639ae9bSBen Gras #endif
3682639ae9bSBen Gras
3692639ae9bSBen Gras /* Run through the user's filter. */
3702639ae9bSBen Gras if (mp->pgout)
3712639ae9bSBen Gras (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
3722639ae9bSBen Gras
3732639ae9bSBen Gras off = mp->pagesize * bp->pgno;
374*0a6a1f1dSLionel Sambuc if (pwrite(mp->fd, bp->page, (size_t)mp->pagesize, off) !=
375*0a6a1f1dSLionel Sambuc (ssize_t)mp->pagesize)
376*0a6a1f1dSLionel Sambuc return RET_ERROR;
3772639ae9bSBen Gras
3782639ae9bSBen Gras /*
3792639ae9bSBen Gras * Re-run through the input filter since this page may soon be
3802639ae9bSBen Gras * accessed via the cache, and whatever the user's output filter
3812639ae9bSBen Gras * did may screw things up if we don't let the input filter
3822639ae9bSBen Gras * restore the in-core copy.
3832639ae9bSBen Gras */
3842639ae9bSBen Gras if (mp->pgin)
3852639ae9bSBen Gras (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
3862639ae9bSBen Gras
3872639ae9bSBen Gras bp->flags &= ~MPOOL_DIRTY;
388*0a6a1f1dSLionel Sambuc return RET_SUCCESS;
3892639ae9bSBen Gras }
3902639ae9bSBen Gras
3912639ae9bSBen Gras /*
3922639ae9bSBen Gras * mpool_look
3932639ae9bSBen Gras * Lookup a page in the cache.
3942639ae9bSBen Gras */
3952639ae9bSBen Gras static BKT *
mpool_look(MPOOL * mp,pgno_t pgno)3962639ae9bSBen Gras mpool_look(MPOOL *mp, pgno_t pgno)
3972639ae9bSBen Gras {
3982639ae9bSBen Gras struct _hqh *head;
3992639ae9bSBen Gras BKT *bp;
4002639ae9bSBen Gras
4012639ae9bSBen Gras head = &mp->hqh[HASHKEY(pgno)];
40284d9c625SLionel Sambuc TAILQ_FOREACH(bp, head, hq)
4032639ae9bSBen Gras if (bp->pgno == pgno) {
4042639ae9bSBen Gras #ifdef STATISTICS
4052639ae9bSBen Gras ++mp->cachehit;
4062639ae9bSBen Gras #endif
407*0a6a1f1dSLionel Sambuc return bp;
4082639ae9bSBen Gras }
4092639ae9bSBen Gras #ifdef STATISTICS
4102639ae9bSBen Gras ++mp->cachemiss;
4112639ae9bSBen Gras #endif
412*0a6a1f1dSLionel Sambuc return NULL;
4132639ae9bSBen Gras }
4142639ae9bSBen Gras
4152639ae9bSBen Gras #ifdef STATISTICS
4162639ae9bSBen Gras /*
4172639ae9bSBen Gras * mpool_stat
4182639ae9bSBen Gras * Print out cache statistics.
4192639ae9bSBen Gras */
4202639ae9bSBen Gras void
mpool_stat(mp)4212639ae9bSBen Gras mpool_stat(mp)
4222639ae9bSBen Gras MPOOL *mp;
4232639ae9bSBen Gras {
4242639ae9bSBen Gras BKT *bp;
4252639ae9bSBen Gras int cnt;
4262639ae9bSBen Gras const char *sep;
4272639ae9bSBen Gras
4282639ae9bSBen Gras (void)fprintf(stderr, "%lu pages in the file\n", (u_long)mp->npages);
4292639ae9bSBen Gras (void)fprintf(stderr,
4302639ae9bSBen Gras "page size %lu, cacheing %lu pages of %lu page max cache\n",
4312639ae9bSBen Gras (u_long)mp->pagesize, (u_long)mp->curcache, (u_long)mp->maxcache);
4322639ae9bSBen Gras (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
4332639ae9bSBen Gras mp->pageput, mp->pageget, mp->pagenew);
4342639ae9bSBen Gras (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
4352639ae9bSBen Gras mp->pagealloc, mp->pageflush);
4362639ae9bSBen Gras if (mp->cachehit + mp->cachemiss)
4372639ae9bSBen Gras (void)fprintf(stderr,
4382639ae9bSBen Gras "%.0f%% cache hit rate (%lu hits, %lu misses)\n",
4392639ae9bSBen Gras ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
4402639ae9bSBen Gras * 100, mp->cachehit, mp->cachemiss);
4412639ae9bSBen Gras (void)fprintf(stderr, "%lu page reads, %lu page writes\n",
4422639ae9bSBen Gras mp->pageread, mp->pagewrite);
4432639ae9bSBen Gras
4442639ae9bSBen Gras sep = "";
4452639ae9bSBen Gras cnt = 0;
44684d9c625SLionel Sambuc TAILQ_FOREACH(bp, &mp->lqh, q) {
4472639ae9bSBen Gras (void)fprintf(stderr, "%s%d", sep, bp->pgno);
4482639ae9bSBen Gras if (bp->flags & MPOOL_DIRTY)
4492639ae9bSBen Gras (void)fprintf(stderr, "d");
4502639ae9bSBen Gras if (bp->flags & MPOOL_PINNED)
4512639ae9bSBen Gras (void)fprintf(stderr, "P");
4522639ae9bSBen Gras if (++cnt == 10) {
4532639ae9bSBen Gras sep = "\n";
4542639ae9bSBen Gras cnt = 0;
4552639ae9bSBen Gras } else
4562639ae9bSBen Gras sep = ", ";
4572639ae9bSBen Gras
4582639ae9bSBen Gras }
4592639ae9bSBen Gras (void)fprintf(stderr, "\n");
4602639ae9bSBen Gras }
4612639ae9bSBen Gras #endif
462