diff options
Diffstat (limited to 'lib/libc/db/mpool')
-rw-r--r-- | lib/libc/db/mpool/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/db/mpool/README | 7 | ||||
-rw-r--r-- | lib/libc/db/mpool/mpool.c | 463 | ||||
-rw-r--r-- | lib/libc/db/mpool/mpool.libtp | 746 |
4 files changed, 0 insertions, 1222 deletions
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc deleted file mode 100644 index c8f2949..0000000 --- a/lib/libc/db/mpool/Makefile.inc +++ /dev/null @@ -1,6 +0,0 @@ -# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 -# $Id$ - -.PATH: ${.CURDIR}/../libc/db/mpool - -SRCS+= mpool.c diff --git a/lib/libc/db/mpool/README b/lib/libc/db/mpool/README deleted file mode 100644 index 0f01fbc..0000000 --- a/lib/libc/db/mpool/README +++ /dev/null @@ -1,7 +0,0 @@ -# @(#)README 8.1 (Berkeley) 6/4/93 - -These are the current memory pool routines. -They aren't ready for prime time, yet, and -the interface is expected to change. - ---keith diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c deleted file mode 100644 index a61041e..0000000 --- a/lib/libc/db/mpool/mpool.c +++ /dev/null @@ -1,463 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/stat.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <db.h> - -#define __MPOOLINTERFACE_PRIVATE -#include <mpool.h> - -static BKT *mpool_bkt __P((MPOOL *)); -static BKT *mpool_look __P((MPOOL *, pgno_t)); -static int mpool_write __P((MPOOL *, BKT *)); - -/* - * mpool_open -- - * Initialize a memory pool. - */ -MPOOL * -mpool_open(key, fd, pagesize, maxcache) - void *key; - int fd; - pgno_t pagesize, maxcache; -{ - struct stat sb; - MPOOL *mp; - int entry; - - /* - * Get information about the file. - * - * XXX - * We don't currently handle pipes, although we should. - */ - if (fstat(fd, &sb)) - return (NULL); - if (!S_ISREG(sb.st_mode)) { - errno = ESPIPE; - return (NULL); - } - - /* Allocate and initialize the MPOOL cookie. */ - if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) - return (NULL); - CIRCLEQ_INIT(&mp->lqh); - for (entry = 0; entry < HASHSIZE; ++entry) - CIRCLEQ_INIT(&mp->hqh[entry]); - mp->maxcache = maxcache; - mp->npages = sb.st_size / pagesize; - mp->pagesize = pagesize; - mp->fd = fd; - return (mp); -} - -/* - * mpool_filter -- - * Initialize input/output filters. - */ -void -mpool_filter(mp, pgin, pgout, pgcookie) - MPOOL *mp; - void (*pgin) __P((void *, pgno_t, void *)); - void (*pgout) __P((void *, pgno_t, void *)); - void *pgcookie; -{ - mp->pgin = pgin; - mp->pgout = pgout; - mp->pgcookie = pgcookie; -} - -/* - * mpool_new -- - * Get a new page of memory. - */ -void * -mpool_new(mp, pgnoaddr) - MPOOL *mp; - pgno_t *pgnoaddr; -{ - struct _hqh *head; - BKT *bp; - - if (mp->npages == MAX_PAGE_NUMBER) { - (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); - abort(); - } -#ifdef STATISTICS - ++mp->pagenew; -#endif - /* - * Get a BKT from the cache. Assign a new page number, attach - * it to the head of the hash chain, the tail of the lru chain, - * and return. - */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - *pgnoaddr = bp->pgno = mp->npages++; - bp->flags = MPOOL_PINNED; - - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - return (bp->page); -} - -/* - * mpool_get - * Get a page. - */ -void * -mpool_get(mp, pgno, flags) - MPOOL *mp; - pgno_t pgno; - u_int flags; /* XXX not used? */ -{ - struct _hqh *head; - BKT *bp; - off_t off; - int nr; - - /* Check for attempt to retrieve a non-existent page. */ - if (pgno >= mp->npages) { - errno = EINVAL; - return (NULL); - } - -#ifdef STATISTICS - ++mp->pageget; -#endif - - /* Check for a page that is cached. */ - if ((bp = mpool_look(mp, pgno)) != NULL) { -#ifdef DEBUG - if (bp->flags & MPOOL_PINNED) { - (void)fprintf(stderr, - "mpool_get: page %d already pinned\n", bp->pgno); - abort(); - } -#endif - /* - * Move the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Return a pinned page. */ - bp->flags |= MPOOL_PINNED; - return (bp->page); - } - - /* Get a page from the cache. */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - - /* Read in the contents. */ -#ifdef STATISTICS - ++mp->pageread; -#endif - off = mp->pagesize * pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (NULL); - if ((nr = read(mp->fd, bp->page, mp->pagesize)) != mp->pagesize) { - if (nr >= 0) - errno = EFTYPE; - return (NULL); - } - - /* Set the page number, pin the page. */ - bp->pgno = pgno; - bp->flags = MPOOL_PINNED; - - /* - * Add the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Run through the user's filter. */ - if (mp->pgin != NULL) - (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); - - return (bp->page); -} - -/* - * mpool_put - * Return a page. - */ -int -mpool_put(mp, page, flags) - MPOOL *mp; - void *page; - u_int flags; -{ - BKT *bp; - -#ifdef STATISTICS - ++mp->pageput; -#endif - bp = (BKT *)((char *)page - sizeof(BKT)); -#ifdef DEBUG - if (!(bp->flags & MPOOL_PINNED)) { - (void)fprintf(stderr, - "mpool_put: page %d not pinned\n", bp->pgno); - abort(); - } -#endif - bp->flags &= ~MPOOL_PINNED; - bp->flags |= flags & MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_close - * Close the buffer pool. - */ -int -mpool_close(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Free up any space allocated to the lru pages. */ - while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) { - CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q); - free(bp); - } - - /* Free the MPOOL cookie. */ - free(mp); - return (RET_SUCCESS); -} - -/* - * mpool_sync - * Sync the pool to disk. - */ -int -mpool_sync(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Walk the lru chain, flushing any dirty pages to disk. */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (RET_ERROR); - - /* Sync the file descriptor. */ - return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); -} - -/* - * mpool_bkt - * Get a page from the cache (or create one). - */ -static BKT * -mpool_bkt(mp) - MPOOL *mp; -{ - struct _hqh *head; - BKT *bp; - - /* If under the max cached, always create a new page. */ - if (mp->curcache < mp->maxcache) - goto new; - - /* - * If the cache is max'd out, walk the lru list for a buffer we - * can flush. If we find one, write it (if necessary) and take it - * off any lists. If we don't find anything we grow the cache anyway. - * The cache never shrinks. - */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (!(bp->flags & MPOOL_PINNED)) { - /* Flush if dirty. */ - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (NULL); -#ifdef STATISTICS - ++mp->pageflush; -#endif - /* Remove from the hash and lru queues. */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); -#ifdef DEBUG - { void *spage; - spage = bp->page; - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); - bp->page = spage; - } -#endif - return (bp); - } - -new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL) - return (NULL); -#ifdef STATISTICS - ++mp->pagealloc; -#endif -#if defined(DEBUG) || defined(PURIFY) - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); -#endif - bp->page = (char *)bp + sizeof(BKT); - ++mp->curcache; - return (bp); -} - -/* - * mpool_write - * Write a page to disk. - */ -static int -mpool_write(mp, bp) - MPOOL *mp; - BKT *bp; -{ - off_t off; - -#ifdef STATISTICS - ++mp->pagewrite; -#endif - - /* Run through the user's filter. */ - if (mp->pgout) - (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); - - off = mp->pagesize * bp->pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (RET_ERROR); - if (write(mp->fd, bp->page, mp->pagesize) != mp->pagesize) - return (RET_ERROR); - - bp->flags &= ~MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_look - * Lookup a page in the cache. - */ -static BKT * -mpool_look(mp, pgno) - MPOOL *mp; - pgno_t pgno; -{ - struct _hqh *head; - BKT *bp; - - head = &mp->hqh[HASHKEY(pgno)]; - for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) - if (bp->pgno == pgno) { -#ifdef STATISTICS - ++mp->cachehit; -#endif - return (bp); - } -#ifdef STATISTICS - ++mp->cachemiss; -#endif - return (NULL); -} - -#ifdef STATISTICS -/* - * mpool_stat - * Print out cache statistics. - */ -void -mpool_stat(mp) - MPOOL *mp; -{ - BKT *bp; - int cnt; - char *sep; - - (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); - (void)fprintf(stderr, - "page size %lu, cacheing %lu pages of %lu page max cache\n", - mp->pagesize, mp->curcache, mp->maxcache); - (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", - mp->pageput, mp->pageget, mp->pagenew); - (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", - mp->pagealloc, mp->pageflush); - if (mp->cachehit + mp->cachemiss) - (void)fprintf(stderr, - "%.0f%% cache hit rate (%lu hits, %lu misses)\n", - ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) - * 100, mp->cachehit, mp->cachemiss); - (void)fprintf(stderr, "%lu page reads, %lu page writes\n", - mp->pageread, mp->pagewrite); - - sep = ""; - cnt = 0; - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) { - (void)fprintf(stderr, "%s%d", sep, bp->pgno); - if (bp->flags & MPOOL_DIRTY) - (void)fprintf(stderr, "d"); - if (bp->flags & MPOOL_PINNED) - (void)fprintf(stderr, "P"); - if (++cnt == 10) { - sep = "\n"; - cnt = 0; - } else - sep = ", "; - - } - (void)fprintf(stderr, "\n"); -} -#endif diff --git a/lib/libc/db/mpool/mpool.libtp b/lib/libc/db/mpool/mpool.libtp deleted file mode 100644 index dbb0469..0000000 --- a/lib/libc/db/mpool/mpool.libtp +++ /dev/null @@ -1,746 +0,0 @@ -/****************************************************************************** - -VERSION $Id$ -PACKAGE: User Level Shared Memory Manager - -DESCRIPTION: - This package provides a buffer pool interface implemented as - a collection of file pages mapped into shared memory. - - Based on Mark's buffer manager - -ROUTINES: - External - buf_alloc - buf_flags - buf_get - buf_init - buf_last - buf_open - buf_pin - buf_sync - buf_unpin - Internal - bf_assign_buf - bf_fid_to_fd - bf_newbuf - bf_put_page - - -******************************************************************************/ -#include <sys/types.h> -#include <assert.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <stdio.h> -#include <errno.h> -#include "list.h" -#include "user.h" -#include "txn_sys.h" -#include "buf.h" -#include "semkeys.h" -#include "error.h" - -/* - we need to translate between some type of file id that the user - process passes and a file descriptor. For now, it's a nop. -*/ -#define GET_MASTER get_sem ( buf_spinlock ) -#define RELEASE_MASTER release_sem ( buf_spinlock ) - -#define LRUID *buf_lru -#define LRUP (bufhdr_table+*buf_lru) -#define MRU bufhdr_table[*buf_lru].lru.prev - -/* Global indicator that you have started reusing buffers */ -int do_statistics = 0; -/* - Process Statics (pointers into shared memory) -*/ -static BUF_T *buf_table = 0; -static BUFHDR_T *bufhdr_table; -static int *buf_hash_table; -static int *buf_lru; /* LRU is the free list */ -static int buf_spinlock; -static FINFO_T *buf_fids; -static int *buf_sp; /* Pointer to string free space */ -static char *buf_strings; - -/* Process Local FID->FD table */ -static int fds[NUM_FILE_ENTRIES]; - -/* Static routines */ -static BUFHDR_T *bf_assign_buf(); -static int bf_fid_to_fd(); -static BUFHDR_T *bf_newbuf(); -static int bf_put_page(); - -/* - Return 0 on success - 1 on failure -*/ -extern int -buf_init ( ) -{ - ADDR_T buf_region; - BUFHDR_T *bhp; - int i; - int ref_count; - int *spinlockp; - - /* - Initialize Process local structures - */ - for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { - fds[i] = -1; - } - - buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM, - BUF_REGION_SIZE, &ref_count ); - if ( !buf_region ) { - return (1); - } - error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region, - BUF_REGION_NUM, BUF_REGION_SIZE ); - - buf_table = (BUF_T *)buf_region; - bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS); - buf_hash_table = (int *)(bufhdr_table + NUM_BUFS); - buf_lru = buf_hash_table + NUMTABLE_ENTRIES; - spinlockp = buf_lru + 1; - buf_fids = (FINFO_T *)(spinlockp+1); - buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES); - buf_strings = (char *)(buf_sp + 1); - - /* Create locking spinlock (gets creating holding the lock) */ - buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 ); - if ( buf_spinlock < 0 ) { - return(1); - } - if ( ref_count <= 1 ) { - *spinlockp = buf_spinlock; - - /* Now initialize the buffer manager */ - - /* 1. Free list */ - *buf_lru = 0; - - /* 2. Buffer headers */ - for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) { - bhp->lru.next = i+1; - bhp->lru.prev = i-1; - bhp->flags = 0; /* All Flags off */ - bhp->refcount = 0; - bhp->wait_proc = -1; /* No sleepers */ - LISTPE_INIT ( hash, bhp, i ); /* Hash chains */ - } - bufhdr_table[0].lru.prev = NUM_BUFS-1; - bufhdr_table[NUM_BUFS-1].lru.next = 0; - - /* 3. Hash Table */ - for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) { - buf_hash_table[i] = NUM_BUFS; - } - - /* 4. File ID Table */ - for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { - buf_fids[i].offset = -1; - buf_fids[i].npages = -1; - buf_fids[i].refcount = 0; - } - - /* 5. Free String Pointer */ - *buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES); - if (RELEASE_MASTER) { - return(1); - } - error_log0 ( "Initialized buffer region\n" ); - } - return (0); -} - -extern void -buf_exit() -{ - int ref; - int i; - - /* Flush Buffer Pool on Exit */ - for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { - if ( fds[i] != -1 ) { - close ( fds[i] ); - } - } - if ( buf_table ) { - detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref ); - } - return; -} - -/* - We need an empty buffer. Find the LRU unpinned NON-Dirty page. -*/ -static BUFHDR_T * -bf_newbuf() -{ - int fd; - int lruid; - int nbytes; - int ndx; - BUFHDR_T *bhp; - - lruid = LRUID; - for ( bhp = LRUP; - bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS); - bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) { - - if ( bhp->lru.next == lruid ) { - /* OUT OF BUFFERS */ - error_log1 ( "All buffers are pinned. %s\n", - "Unable to grant buffer request" ); - return(NULL); - } - } - /* BHP can be used */ - if ( bhp->flags & BUF_DIRTY ) { - do_statistics = 1; - /* - MIS Check for log flushed appropriately - */ - fd = bf_fid_to_fd(bhp->id.file_id); - if ( fd == -1 ) { - error_log1 ("Invalid fid %d\n", bhp->id.file_id); - return(NULL); - } - if ( bf_put_page(fd, bhp) < 0 ) { - return(NULL); - } - } - /* Update Hash Pointers */ - ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id ); - LISTP_REMOVE(bufhdr_table, hash, bhp); - if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) { - if ( bhp->hash.next != (bhp-bufhdr_table) ) { - buf_hash_table[ndx] = bhp->hash.next; - } else { - buf_hash_table[ndx] = NUM_BUFS; - } - } - INIT_BUF(bhp); - - return(bhp); -} -/* - buf_alloc - - Add a page to a file and return a buffer for it. - -*/ -ADDR_T -buf_alloc ( fid, new_pageno ) -int fid; -int *new_pageno; -{ - BUFHDR_T *bhp; - int fd; - int len; - int ndx; - OBJ_T fobj; - - if (GET_MASTER) { - return(NULL); - } - if ( buf_fids[fid].npages == -1 ) { - /* initialize npages field */ - fd = bf_fid_to_fd ( fid ); - } - assert (fid < NUM_FILE_ENTRIES); - - *new_pageno = buf_fids[fid].npages; - if ( *new_pageno == -1 ) { - RELEASE_MASTER; - return ( NULL ); - } - buf_fids[fid].npages++; - ndx = BUF_HASH ( fid, *new_pageno ); - fobj.file_id = fid; - fobj.obj_id = *new_pageno; - bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len ); - if ( RELEASE_MASTER ) { - /* Memory leak */ - return(NULL); - } - if ( bhp ) { - return ((ADDR_T)(buf_table+(bhp-bufhdr_table))); - } else { - return ( NULL ); - } -} - - -/* - Buffer Flags - BF_DIRTY Mark page as dirty - BF_EMPTY Don't initialize page, just get buffer - BF_PIN Retrieve with pin - -MIS -Might want to add a flag that sets an LSN for this buffer is the -DIRTY flag is set - -Eventually, you may want a flag that indicates the I/O and lock -request should be shipped off together, but not for now. -*/ -extern ADDR_T -buf_get ( file_id, page_id, flags, len ) -int file_id; -int page_id; -u_long flags; -int *len; /* Number of bytes read into buffer */ -{ - BUFHDR_T *bhp; - int bufid; - int fd; - int ndx; - int next_bufid; - int stat; - OBJ_T fobj; - - ndx = BUF_HASH ( file_id, page_id ); - fobj.file_id = (long) file_id; - fobj.obj_id = (long) page_id; - if ( GET_MASTER ) { - return(NULL); - } - /* - This could be a for loop, but we lose speed - by making all the cases general purpose so we - optimize for the no-collision case. - */ - bufid = buf_hash_table[ndx]; - if ( bufid < NUM_BUFS ) { - for ( bhp = bufhdr_table+bufid; - !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID); - bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) { - - if ( bhp->hash.next == bufid ) { - goto not_found; - } - } -/* found */ - if ( flags & BF_PIN ) { - bhp->flags |= BUF_PINNED; - bhp->refcount++; -#ifdef PIN_DEBUG - fprintf(stderr, "buf_get: %X PINNED (%d)\n", - buf_table + (bhp-bufhdr_table), bhp->refcount); -#endif - } - if ( flags & BF_DIRTY ) { - bhp->flags |= BUF_DIRTY; - } - - while ( bhp->flags & BUF_IO_IN_PROGRESS ) { - /* MIS -- eventually err check here */ -#ifdef DEBUG - printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc, - my_txnp - txn_table); -#endif -#ifdef WAIT_STATS - buf_waits++; -#endif - stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock ); - if ( stat ) { - /* Memory leak */ - return(NULL); - } - if (!( bhp->flags & BUF_IO_IN_PROGRESS) && - (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) { - if (RELEASE_MASTER) - return(NULL); - return(buf_get ( file_id, page_id, flags, len )); - } - } - MAKE_MRU( bhp ); - *len = BUFSIZE; - } else { -not_found: - /* If you get here, the page isn't in the hash table */ - bhp = bf_assign_buf ( ndx, &fobj, flags, len ); - } - /* Common code between found and not found */ - - if ( bhp && bhp->flags & BUF_NEWPAGE ) { - *len = 0; - } - if (RELEASE_MASTER){ - /* Memory leak */ - return(NULL); - } - if ( bhp ) { - return ((ADDR_T)(buf_table+(bhp-bufhdr_table))); - } else { - return ( NULL ); - } -} - -/* - MIS - do I want to add file links to buffer pool? -*/ -extern int -buf_sync ( fid, close ) -int fid; -int close; /* should we dec refcount and possibly - invalidate all the buffers */ -{ - int i; - int fd; - int invalidate; - BUFHDR_T *bhp; - - if ( (fd = bf_fid_to_fd ( fid )) < 0 ) { - return(1); - } - if (GET_MASTER) { - return(1); - } - invalidate = (buf_fids[fid].refcount == 1 && close); - if ( invalidate ) - for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) { - if (bhp->id.file_id == fid) { - if ((bhp->flags & BF_DIRTY) && (bf_put_page( fd, bhp ) < 0)) { - return(1); - } - bhp->id.file_id = -1; - } - } - if (invalidate || close) - buf_fids[fid].refcount--; - - if (RELEASE_MASTER) { - return(1); - } - return(0); - - -} - -extern int -buf_flags ( addr, set_flags, unset_flags ) -ADDR_T addr; -u_long set_flags; -u_long unset_flags; -{ - int bufid; - BUFHDR_T *bhp; - -#ifdef PIN_DEBUG - fprintf(stderr, "buf_flags: %X setting %s%s%s%s%s releasing %s%s%s%s%s\n", - addr, - set_flags&BUF_DIRTY ? "DIRTY " : "", - set_flags&BUF_VALID ? "VALID " : "", - set_flags&BUF_PINNED ? "PINNED " : "", - set_flags&BUF_IO_ERROR ? "IO_ERROR " : "", - set_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", - set_flags&BUF_NEWPAGE ? "NEWPAGE " : "", - unset_flags&BUF_DIRTY ? "DIRTY " : "", - unset_flags&BUF_VALID ? "VALID " : "", - unset_flags&BUF_PINNED ? "PINNED " : "", - unset_flags&BUF_IO_ERROR ? "IO_ERROR " : "", - unset_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", - unset_flags&BUF_NEWPAGE ? "NEWPAGE " : "" ); -#endif - if (!ADDR_OK(addr)) { - error_log1 ( "buf_pin: Invalid Buffer Address %x\n", addr ); - return(1); - } - bufid = ((BUF_T *)addr) - buf_table; - assert ( bufid < NUM_BUFS); - bhp = &bufhdr_table[bufid]; - if (GET_MASTER) { - return(1); - } - bhp->flags |= set_flags; - if ( set_flags & BUF_PINNED ) { - bhp->refcount++; - } - if ( set_flags & BUF_DIRTY ) { - unset_flags |= BUF_NEWPAGE; - } - - if ( unset_flags & BUF_PINNED ) { - bhp->refcount--; - if ( bhp->refcount ) { - /* Turn off pin bit so it doesn't get unset */ - unset_flags &= ~BUF_PINNED; - } - } - bhp->flags &= ~unset_flags; - MAKE_MRU(bhp); - if (RELEASE_MASTER) { - return(1); - } - return(0); -} - -/* - Take a string name and produce an fid. - - returns -1 on error - - MIS -- this is a potential problem -- you keep actual names - here -- what if people run from different directories? -*/ -extern int -buf_name_lookup ( fname ) -char *fname; -{ - int i; - int fid; - int ndx; - - fid = -1; - if (GET_MASTER) { - return(-1); - } - for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { - if ( buf_fids[i].offset == -1 ) { - fid = i; - } else { - if (!strcmp (fname, buf_strings+buf_fids[i].offset)) { - if (RELEASE_MASTER) { - return(-1); - } - buf_fids[i].refcount++; - return(i); - } - } - } - if ( fid == -1 ) { - error_log0 ( "No more file ID's\n" ); - } else { - ndx = *buf_sp - strlen(fname) - 1; - if ( ndx < 0 ) { - error_log0 ( "Out of string space\n" ); - fid = -1; - } else { - *buf_sp = ndx; - strcpy ( buf_strings+ndx, fname ); - buf_fids[fid].offset = ndx; - } - buf_fids[fid].refcount = 1; - } - if (RELEASE_MASTER) { - return(-1); - } - return(fid); -} - -static int -bf_fid_to_fd ( fid ) -int fid; -{ - struct stat sbuf; - - assert ( (fid < NUM_FILE_ENTRIES) && (buf_fids[fid].offset != -1) ); - if ( fds[fid] != -1 ) { - return(fds[fid]); - - } - fds[fid] = open ( buf_strings+buf_fids[fid].offset, O_RDWR|O_CREAT, - 0666 ); - if ( fds[fid] < 0 ) { - error_log3 ( "Error Opening File %s FID: %d FD: %d. Errno = %d\n", - buf_strings+buf_fids[fid].offset, fid, fds[fid], - errno ); - return(-1); - } - error_log3 ( "Opening File %s FID: %d FD: %d\n", - buf_strings+buf_fids[fid].offset, fid, fds[fid] ); - if ( buf_fids[fid].npages == -1 ) { - /* Initialize the npages field */ - if ( fstat ( fds[fid], &sbuf ) ) { - error_log3 ( "Error Fstating %s FID: %d. Errno = %d\n", - buf_strings+buf_fids[fid].offset, fid, errno ); - } else { - buf_fids[fid].npages = ( sbuf.st_size / BUFSIZE ); - } - } - - return ( fds[fid] ); -} - -static int -bf_put_page ( fd, bhp ) -int fd; -BUFHDR_T *bhp; -{ - int nbytes; - - assert ( (bhp-bufhdr_table) < NUM_BUFS ); - if ( lseek ( fd, bhp->id.obj_id << BUFSHIFT, L_SET ) < 0 ) { - return(-1); - } - bhp->flags |= BUF_IO_IN_PROGRESS; - if (RELEASE_MASTER) { - return(-1); - } - nbytes = write(fd, buf_table[bhp-bufhdr_table], BUFSIZE); - if (GET_MASTER) { - return(-2); - } - if ( nbytes < 0 ) { - error_log1 ("Write failed with error code %d\n", errno); - return(-1); - } else if ( nbytes != BUFSIZE ) { - error_log1 ("Short write: %d bytes of %d\n", nbytes, BUFSIZE ); - } - bhp->flags &= ~(BUF_DIRTY|BUF_IO_IN_PROGRESS); - return (0); -} - -static BUFHDR_T * -bf_assign_buf ( ndx, obj, flags, len ) -int ndx; -OBJ_T *obj; -u_long flags; -int *len; /* Number of bytes read */ -{ - BUFHDR_T *bhp; - int fd; - - assert ( obj->file_id < NUM_FILE_ENTRIES ); - bhp = bf_newbuf(); - if ( !bhp ) { - return(NULL); - } - OBJ_ASSIGN ( (*obj), bhp->id ); - if ( buf_hash_table[ndx] >= NUM_BUFS ) { - buf_hash_table[ndx] = bhp-bufhdr_table; - } else { - LISTPE_INSERT ( bufhdr_table, hash, bhp, buf_hash_table[ndx] ); - } - - bhp->flags |= BUF_VALID; - if ( flags & BF_PIN ) { - bhp->flags |= BUF_PINNED; - bhp->refcount++; -#ifdef PIN_DEBUG - fprintf(stderr, "bf_assign_buf: %X PINNED (%d)\n", - buf_table + (bhp-bufhdr_table), bhp->refcount); -#endif - } - fd = bf_fid_to_fd(obj->file_id); - if ( fd == -1 ) { - error_log1 ("Invalid fid %d\n", obj->file_id); - bhp->flags |= ~BUF_IO_ERROR; - return(NULL); - } - if ( obj->obj_id >= buf_fids[obj->file_id].npages) { - buf_fids[obj->file_id].npages = obj->obj_id+1; - *len = 0; - } else if ( flags & BF_EMPTY ) { - *len = 0; - } else { - bhp->flags |= BUF_IO_IN_PROGRESS; - if (RELEASE_MASTER) { - return(NULL); - } - if ( lseek ( fd, obj->obj_id << BUFSHIFT, L_SET ) < -1 ) { - error_log2 ("Unable to perform seek on file: %d to page %d", - obj->file_id, obj->obj_id ); - bhp->flags &= ~BUF_IO_IN_PROGRESS; - bhp->flags |= ~BUF_IO_ERROR; - return(NULL); - } - *len = read(fd, buf_table[bhp-bufhdr_table], BUFSIZE); - if ( *len < 0 ) { - error_log2 ("Unable to perform read on file: %d to page %d", - obj->file_id, obj->obj_id ); - bhp->flags &= ~BUF_IO_IN_PROGRESS; - bhp->flags |= ~BUF_IO_ERROR; - return(NULL); - } - if (GET_MASTER) { - return(NULL); - } - bhp->flags &= ~BUF_IO_IN_PROGRESS; - if ( bhp->wait_proc != -1 ) { - /* wake up waiter and anyone waiting on it */ -#ifdef DEBUG - printf("Waking transaction %d due to completed I/O\n", - bhp->wait_proc); -#endif - proc_wake_id ( bhp->wait_proc ); - bhp->wait_proc = -1; - } - MAKE_MRU(bhp); - } - - if ( flags & BF_DIRTY ) { - bhp->flags |= BUF_DIRTY; - } else if ( *len < BUFSIZE ) { - bhp->flags |= BUF_NEWPAGE; - } - return ( bhp ); -} - -int -buf_last ( fid ) -int fid; -{ - int val; - - if (GET_MASTER) { - return(-1); - } - assert ( fid < NUM_FILE_ENTRIES ); - if ( buf_fids[fid].npages == -1 ) { - /* initialize npages field */ - (void) bf_fid_to_fd ( fid ); - } - val = buf_fids[fid].npages; - if ( val ) { - val--; /* Convert to page number */ - } - if (RELEASE_MASTER) { - return(-1); - } - return(val); -} - -#ifdef DEBUG -extern void -buf_dump ( id, all ) -int id; -int all; -{ - int i; - BUFHDR_T *bhp; - - printf ( "LRU + %d\n", *buf_lru ); - if ( all ) { - printf("ID\tFID\tPID\tLNEXT\tLPREV\tHNEXT\tHPREV\tSLEEP\tFLAG\tREFS\n"); - for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) { - printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i, - bhp->id.file_id, bhp->id.obj_id, - bhp->lru.next, bhp->lru.prev, - bhp->hash.next, bhp->hash.prev, - bhp->wait_proc, bhp->flags, bhp->refcount ); - } - } else { - if ( id >= NUM_BUFS ) { - printf ( "Buffer ID (%d) too high\n", id ); - return; - } - bhp = bufhdr_table+id; - printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i, - bhp->id.file_id, bhp->id.obj_id, - bhp->lru.next, bhp->lru.prev, - bhp->hash.next, bhp->hash.prev, - bhp->wait_proc, bhp->flags, bhp->refcount ); - } - return; -} -#endif - |