1*ef5d438eSPaul Traina/****************************************************************************** 2*ef5d438eSPaul Traina 3*ef5d438eSPaul TrainaPACKAGE: User Level Shared Memory Manager 4*ef5d438eSPaul Traina 5*ef5d438eSPaul TrainaDESCRIPTION: 6*ef5d438eSPaul Traina This package provides a buffer pool interface implemented as 7*ef5d438eSPaul Traina a collection of file pages mapped into shared memory. 8*ef5d438eSPaul Traina 9*ef5d438eSPaul Traina Based on Mark's buffer manager 10*ef5d438eSPaul Traina 11*ef5d438eSPaul TrainaROUTINES: 12*ef5d438eSPaul Traina External 13*ef5d438eSPaul Traina buf_alloc 14*ef5d438eSPaul Traina buf_flags 15*ef5d438eSPaul Traina buf_get 16*ef5d438eSPaul Traina buf_init 17*ef5d438eSPaul Traina buf_last 18*ef5d438eSPaul Traina buf_open 19*ef5d438eSPaul Traina buf_pin 20*ef5d438eSPaul Traina buf_sync 21*ef5d438eSPaul Traina buf_unpin 22*ef5d438eSPaul Traina Internal 23*ef5d438eSPaul Traina bf_assign_buf 24*ef5d438eSPaul Traina bf_fid_to_fd 25*ef5d438eSPaul Traina bf_newbuf 26*ef5d438eSPaul Traina bf_put_page 27*ef5d438eSPaul Traina 28*ef5d438eSPaul Traina 29*ef5d438eSPaul Traina******************************************************************************/ 30*ef5d438eSPaul Traina#include <sys/types.h> 31*ef5d438eSPaul Traina#include <assert.h> 32*ef5d438eSPaul Traina#include <sys/file.h> 33*ef5d438eSPaul Traina#include <sys/stat.h> 34*ef5d438eSPaul Traina#include <stdio.h> 35*ef5d438eSPaul Traina#include <errno.h> 36*ef5d438eSPaul Traina#include "list.h" 37*ef5d438eSPaul Traina#include "user.h" 38*ef5d438eSPaul Traina#include "txn_sys.h" 39*ef5d438eSPaul Traina#include "buf.h" 40*ef5d438eSPaul Traina#include "semkeys.h" 41*ef5d438eSPaul Traina#include "error.h" 42*ef5d438eSPaul Traina 43*ef5d438eSPaul Traina/* 44*ef5d438eSPaul Traina we need to translate between some type of file id that the user 45*ef5d438eSPaul Traina process passes and a file descriptor. For now, it's a nop. 46*ef5d438eSPaul Traina*/ 47*ef5d438eSPaul Traina#define GET_MASTER get_sem ( buf_spinlock ) 48*ef5d438eSPaul Traina#define RELEASE_MASTER release_sem ( buf_spinlock ) 49*ef5d438eSPaul Traina 50*ef5d438eSPaul Traina#define LRUID *buf_lru 51*ef5d438eSPaul Traina#define LRUP (bufhdr_table+*buf_lru) 52*ef5d438eSPaul Traina#define MRU bufhdr_table[*buf_lru].lru.prev 53*ef5d438eSPaul Traina 54*ef5d438eSPaul Traina/* Global indicator that you have started reusing buffers */ 55*ef5d438eSPaul Trainaint do_statistics = 0; 56*ef5d438eSPaul Traina/* 57*ef5d438eSPaul Traina Process Statics (pointers into shared memory) 58*ef5d438eSPaul Traina*/ 59*ef5d438eSPaul Trainastatic BUF_T *buf_table = 0; 60*ef5d438eSPaul Trainastatic BUFHDR_T *bufhdr_table; 61*ef5d438eSPaul Trainastatic int *buf_hash_table; 62*ef5d438eSPaul Trainastatic int *buf_lru; /* LRU is the free list */ 63*ef5d438eSPaul Trainastatic int buf_spinlock; 64*ef5d438eSPaul Trainastatic FINFO_T *buf_fids; 65*ef5d438eSPaul Trainastatic int *buf_sp; /* Pointer to string free space */ 66*ef5d438eSPaul Trainastatic char *buf_strings; 67*ef5d438eSPaul Traina 68*ef5d438eSPaul Traina/* Process Local FID->FD table */ 69*ef5d438eSPaul Trainastatic int fds[NUM_FILE_ENTRIES]; 70*ef5d438eSPaul Traina 71*ef5d438eSPaul Traina/* Static routines */ 72*ef5d438eSPaul Trainastatic BUFHDR_T *bf_assign_buf(); 73*ef5d438eSPaul Trainastatic int bf_fid_to_fd(); 74*ef5d438eSPaul Trainastatic BUFHDR_T *bf_newbuf(); 75*ef5d438eSPaul Trainastatic int bf_put_page(); 76*ef5d438eSPaul Traina 77*ef5d438eSPaul Traina/* 78*ef5d438eSPaul Traina Return 0 on success 79*ef5d438eSPaul Traina 1 on failure 80*ef5d438eSPaul Traina*/ 81*ef5d438eSPaul Trainaextern int 82*ef5d438eSPaul Trainabuf_init ( ) 83*ef5d438eSPaul Traina{ 84*ef5d438eSPaul Traina ADDR_T buf_region; 85*ef5d438eSPaul Traina BUFHDR_T *bhp; 86*ef5d438eSPaul Traina int i; 87*ef5d438eSPaul Traina int ref_count; 88*ef5d438eSPaul Traina int *spinlockp; 89*ef5d438eSPaul Traina 90*ef5d438eSPaul Traina /* 91*ef5d438eSPaul Traina Initialize Process local structures 92*ef5d438eSPaul Traina */ 93*ef5d438eSPaul Traina for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { 94*ef5d438eSPaul Traina fds[i] = -1; 95*ef5d438eSPaul Traina } 96*ef5d438eSPaul Traina 97*ef5d438eSPaul Traina buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM, 98*ef5d438eSPaul Traina BUF_REGION_SIZE, &ref_count ); 99*ef5d438eSPaul Traina if ( !buf_region ) { 100*ef5d438eSPaul Traina return (1); 101*ef5d438eSPaul Traina } 102*ef5d438eSPaul Traina error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region, 103*ef5d438eSPaul Traina BUF_REGION_NUM, BUF_REGION_SIZE ); 104*ef5d438eSPaul Traina 105*ef5d438eSPaul Traina buf_table = (BUF_T *)buf_region; 106*ef5d438eSPaul Traina bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS); 107*ef5d438eSPaul Traina buf_hash_table = (int *)(bufhdr_table + NUM_BUFS); 108*ef5d438eSPaul Traina buf_lru = buf_hash_table + NUMTABLE_ENTRIES; 109*ef5d438eSPaul Traina spinlockp = buf_lru + 1; 110*ef5d438eSPaul Traina buf_fids = (FINFO_T *)(spinlockp+1); 111*ef5d438eSPaul Traina buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES); 112*ef5d438eSPaul Traina buf_strings = (char *)(buf_sp + 1); 113*ef5d438eSPaul Traina 114*ef5d438eSPaul Traina /* Create locking spinlock (gets creating holding the lock) */ 115*ef5d438eSPaul Traina buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 ); 116*ef5d438eSPaul Traina if ( buf_spinlock < 0 ) { 117*ef5d438eSPaul Traina return(1); 118*ef5d438eSPaul Traina } 119*ef5d438eSPaul Traina if ( ref_count <= 1 ) { 120*ef5d438eSPaul Traina *spinlockp = buf_spinlock; 121*ef5d438eSPaul Traina 122*ef5d438eSPaul Traina /* Now initialize the buffer manager */ 123*ef5d438eSPaul Traina 124*ef5d438eSPaul Traina /* 1. Free list */ 125*ef5d438eSPaul Traina *buf_lru = 0; 126*ef5d438eSPaul Traina 127*ef5d438eSPaul Traina /* 2. Buffer headers */ 128*ef5d438eSPaul Traina for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) { 129*ef5d438eSPaul Traina bhp->lru.next = i+1; 130*ef5d438eSPaul Traina bhp->lru.prev = i-1; 131*ef5d438eSPaul Traina bhp->flags = 0; /* All Flags off */ 132*ef5d438eSPaul Traina bhp->refcount = 0; 133*ef5d438eSPaul Traina bhp->wait_proc = -1; /* No sleepers */ 134*ef5d438eSPaul Traina LISTPE_INIT ( hash, bhp, i ); /* Hash chains */ 135*ef5d438eSPaul Traina } 136*ef5d438eSPaul Traina bufhdr_table[0].lru.prev = NUM_BUFS-1; 137*ef5d438eSPaul Traina bufhdr_table[NUM_BUFS-1].lru.next = 0; 138*ef5d438eSPaul Traina 139*ef5d438eSPaul Traina /* 3. Hash Table */ 140*ef5d438eSPaul Traina for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) { 141*ef5d438eSPaul Traina buf_hash_table[i] = NUM_BUFS; 142*ef5d438eSPaul Traina } 143*ef5d438eSPaul Traina 144*ef5d438eSPaul Traina /* 4. File ID Table */ 145*ef5d438eSPaul Traina for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { 146*ef5d438eSPaul Traina buf_fids[i].offset = -1; 147*ef5d438eSPaul Traina buf_fids[i].npages = -1; 148*ef5d438eSPaul Traina buf_fids[i].refcount = 0; 149*ef5d438eSPaul Traina } 150*ef5d438eSPaul Traina 151*ef5d438eSPaul Traina /* 5. Free String Pointer */ 152*ef5d438eSPaul Traina *buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES); 153*ef5d438eSPaul Traina if (RELEASE_MASTER) { 154*ef5d438eSPaul Traina return(1); 155*ef5d438eSPaul Traina } 156*ef5d438eSPaul Traina error_log0 ( "Initialized buffer region\n" ); 157*ef5d438eSPaul Traina } 158*ef5d438eSPaul Traina return (0); 159*ef5d438eSPaul Traina} 160*ef5d438eSPaul Traina 161*ef5d438eSPaul Trainaextern void 162*ef5d438eSPaul Trainabuf_exit() 163*ef5d438eSPaul Traina{ 164*ef5d438eSPaul Traina int ref; 165*ef5d438eSPaul Traina int i; 166*ef5d438eSPaul Traina 167*ef5d438eSPaul Traina /* Flush Buffer Pool on Exit */ 168*ef5d438eSPaul Traina for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { 169*ef5d438eSPaul Traina if ( fds[i] != -1 ) { 170*ef5d438eSPaul Traina close ( fds[i] ); 171*ef5d438eSPaul Traina } 172*ef5d438eSPaul Traina } 173*ef5d438eSPaul Traina if ( buf_table ) { 174*ef5d438eSPaul Traina detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref ); 175*ef5d438eSPaul Traina } 176*ef5d438eSPaul Traina return; 177*ef5d438eSPaul Traina} 178*ef5d438eSPaul Traina 179*ef5d438eSPaul Traina/* 180*ef5d438eSPaul Traina We need an empty buffer. Find the LRU unpinned NON-Dirty page. 181*ef5d438eSPaul Traina*/ 182*ef5d438eSPaul Trainastatic BUFHDR_T * 183*ef5d438eSPaul Trainabf_newbuf() 184*ef5d438eSPaul Traina{ 185*ef5d438eSPaul Traina int fd; 186*ef5d438eSPaul Traina int lruid; 187*ef5d438eSPaul Traina int nbytes; 188*ef5d438eSPaul Traina int ndx; 189*ef5d438eSPaul Traina BUFHDR_T *bhp; 190*ef5d438eSPaul Traina 191*ef5d438eSPaul Traina lruid = LRUID; 192*ef5d438eSPaul Traina for ( bhp = LRUP; 193*ef5d438eSPaul Traina bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS); 194*ef5d438eSPaul Traina bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) { 195*ef5d438eSPaul Traina 196*ef5d438eSPaul Traina if ( bhp->lru.next == lruid ) { 197*ef5d438eSPaul Traina /* OUT OF BUFFERS */ 198*ef5d438eSPaul Traina error_log1 ( "All buffers are pinned. %s\n", 199*ef5d438eSPaul Traina "Unable to grant buffer request" ); 200*ef5d438eSPaul Traina return(NULL); 201*ef5d438eSPaul Traina } 202*ef5d438eSPaul Traina } 203*ef5d438eSPaul Traina /* BHP can be used */ 204*ef5d438eSPaul Traina if ( bhp->flags & BUF_DIRTY ) { 205*ef5d438eSPaul Traina do_statistics = 1; 206*ef5d438eSPaul Traina /* 207*ef5d438eSPaul Traina MIS Check for log flushed appropriately 208*ef5d438eSPaul Traina */ 209*ef5d438eSPaul Traina fd = bf_fid_to_fd(bhp->id.file_id); 210*ef5d438eSPaul Traina if ( fd == -1 ) { 211*ef5d438eSPaul Traina error_log1 ("Invalid fid %d\n", bhp->id.file_id); 212*ef5d438eSPaul Traina return(NULL); 213*ef5d438eSPaul Traina } 214*ef5d438eSPaul Traina if ( bf_put_page(fd, bhp) < 0 ) { 215*ef5d438eSPaul Traina return(NULL); 216*ef5d438eSPaul Traina } 217*ef5d438eSPaul Traina } 218*ef5d438eSPaul Traina /* Update Hash Pointers */ 219*ef5d438eSPaul Traina ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id ); 220*ef5d438eSPaul Traina LISTP_REMOVE(bufhdr_table, hash, bhp); 221*ef5d438eSPaul Traina if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) { 222*ef5d438eSPaul Traina if ( bhp->hash.next != (bhp-bufhdr_table) ) { 223*ef5d438eSPaul Traina buf_hash_table[ndx] = bhp->hash.next; 224*ef5d438eSPaul Traina } else { 225*ef5d438eSPaul Traina buf_hash_table[ndx] = NUM_BUFS; 226*ef5d438eSPaul Traina } 227*ef5d438eSPaul Traina } 228*ef5d438eSPaul Traina INIT_BUF(bhp); 229*ef5d438eSPaul Traina 230*ef5d438eSPaul Traina return(bhp); 231*ef5d438eSPaul Traina} 232*ef5d438eSPaul Traina/* 233*ef5d438eSPaul Traina buf_alloc 234*ef5d438eSPaul Traina 235*ef5d438eSPaul Traina Add a page to a file and return a buffer for it. 236*ef5d438eSPaul Traina 237*ef5d438eSPaul Traina*/ 238*ef5d438eSPaul TrainaADDR_T 239*ef5d438eSPaul Trainabuf_alloc ( fid, new_pageno ) 240*ef5d438eSPaul Trainaint fid; 241*ef5d438eSPaul Trainaint *new_pageno; 242*ef5d438eSPaul Traina{ 243*ef5d438eSPaul Traina BUFHDR_T *bhp; 244*ef5d438eSPaul Traina int fd; 245*ef5d438eSPaul Traina int len; 246*ef5d438eSPaul Traina int ndx; 247*ef5d438eSPaul Traina OBJ_T fobj; 248*ef5d438eSPaul Traina 249*ef5d438eSPaul Traina if (GET_MASTER) { 250*ef5d438eSPaul Traina return(NULL); 251*ef5d438eSPaul Traina } 252*ef5d438eSPaul Traina if ( buf_fids[fid].npages == -1 ) { 253*ef5d438eSPaul Traina /* initialize npages field */ 254*ef5d438eSPaul Traina fd = bf_fid_to_fd ( fid ); 255*ef5d438eSPaul Traina } 256*ef5d438eSPaul Traina assert (fid < NUM_FILE_ENTRIES); 257*ef5d438eSPaul Traina 258*ef5d438eSPaul Traina *new_pageno = buf_fids[fid].npages; 259*ef5d438eSPaul Traina if ( *new_pageno == -1 ) { 260*ef5d438eSPaul Traina RELEASE_MASTER; 261*ef5d438eSPaul Traina return ( NULL ); 262*ef5d438eSPaul Traina } 263*ef5d438eSPaul Traina buf_fids[fid].npages++; 264*ef5d438eSPaul Traina ndx = BUF_HASH ( fid, *new_pageno ); 265*ef5d438eSPaul Traina fobj.file_id = fid; 266*ef5d438eSPaul Traina fobj.obj_id = *new_pageno; 267*ef5d438eSPaul Traina bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len ); 268*ef5d438eSPaul Traina if ( RELEASE_MASTER ) { 269*ef5d438eSPaul Traina /* Memory leak */ 270*ef5d438eSPaul Traina return(NULL); 271*ef5d438eSPaul Traina } 272*ef5d438eSPaul Traina if ( bhp ) { 273*ef5d438eSPaul Traina return ((ADDR_T)(buf_table+(bhp-bufhdr_table))); 274*ef5d438eSPaul Traina } else { 275*ef5d438eSPaul Traina return ( NULL ); 276*ef5d438eSPaul Traina } 277*ef5d438eSPaul Traina} 278*ef5d438eSPaul Traina 279*ef5d438eSPaul Traina 280*ef5d438eSPaul Traina/* 281*ef5d438eSPaul Traina Buffer Flags 282*ef5d438eSPaul Traina BF_DIRTY Mark page as dirty 283*ef5d438eSPaul Traina BF_EMPTY Don't initialize page, just get buffer 284*ef5d438eSPaul Traina BF_PIN Retrieve with pin 285*ef5d438eSPaul Traina 286*ef5d438eSPaul TrainaMIS 287*ef5d438eSPaul TrainaMight want to add a flag that sets an LSN for this buffer is the 288*ef5d438eSPaul TrainaDIRTY flag is set 289*ef5d438eSPaul Traina 290*ef5d438eSPaul TrainaEventually, you may want a flag that indicates the I/O and lock 291*ef5d438eSPaul Trainarequest should be shipped off together, but not for now. 292*ef5d438eSPaul Traina*/ 293*ef5d438eSPaul Trainaextern ADDR_T 294*ef5d438eSPaul Trainabuf_get ( file_id, page_id, flags, len ) 295*ef5d438eSPaul Trainaint file_id; 296*ef5d438eSPaul Trainaint page_id; 297*ef5d438eSPaul Trainau_long flags; 298*ef5d438eSPaul Trainaint *len; /* Number of bytes read into buffer */ 299*ef5d438eSPaul Traina{ 300*ef5d438eSPaul Traina BUFHDR_T *bhp; 301*ef5d438eSPaul Traina int bufid; 302*ef5d438eSPaul Traina int fd; 303*ef5d438eSPaul Traina int ndx; 304*ef5d438eSPaul Traina int next_bufid; 305*ef5d438eSPaul Traina int stat; 306*ef5d438eSPaul Traina OBJ_T fobj; 307*ef5d438eSPaul Traina 308*ef5d438eSPaul Traina ndx = BUF_HASH ( file_id, page_id ); 309*ef5d438eSPaul Traina fobj.file_id = (long) file_id; 310*ef5d438eSPaul Traina fobj.obj_id = (long) page_id; 311*ef5d438eSPaul Traina if ( GET_MASTER ) { 312*ef5d438eSPaul Traina return(NULL); 313*ef5d438eSPaul Traina } 314*ef5d438eSPaul Traina /* 315*ef5d438eSPaul Traina This could be a for loop, but we lose speed 316*ef5d438eSPaul Traina by making all the cases general purpose so we 317*ef5d438eSPaul Traina optimize for the no-collision case. 318*ef5d438eSPaul Traina */ 319*ef5d438eSPaul Traina bufid = buf_hash_table[ndx]; 320*ef5d438eSPaul Traina if ( bufid < NUM_BUFS ) { 321*ef5d438eSPaul Traina for ( bhp = bufhdr_table+bufid; 322*ef5d438eSPaul Traina !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID); 323*ef5d438eSPaul Traina bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) { 324*ef5d438eSPaul Traina 325*ef5d438eSPaul Traina if ( bhp->hash.next == bufid ) { 326*ef5d438eSPaul Traina goto not_found; 327*ef5d438eSPaul Traina } 328*ef5d438eSPaul Traina } 329*ef5d438eSPaul Traina/* found */ 330*ef5d438eSPaul Traina if ( flags & BF_PIN ) { 331*ef5d438eSPaul Traina bhp->flags |= BUF_PINNED; 332*ef5d438eSPaul Traina bhp->refcount++; 333*ef5d438eSPaul Traina#ifdef PIN_DEBUG 334*ef5d438eSPaul Traina fprintf(stderr, "buf_get: %X PINNED (%d)\n", 335*ef5d438eSPaul Traina buf_table + (bhp-bufhdr_table), bhp->refcount); 336*ef5d438eSPaul Traina#endif 337*ef5d438eSPaul Traina } 338*ef5d438eSPaul Traina if ( flags & BF_DIRTY ) { 339*ef5d438eSPaul Traina bhp->flags |= BUF_DIRTY; 340*ef5d438eSPaul Traina } 341*ef5d438eSPaul Traina 342*ef5d438eSPaul Traina while ( bhp->flags & BUF_IO_IN_PROGRESS ) { 343*ef5d438eSPaul Traina /* MIS -- eventually err check here */ 344*ef5d438eSPaul Traina#ifdef DEBUG 345*ef5d438eSPaul Traina printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc, 346*ef5d438eSPaul Traina my_txnp - txn_table); 347*ef5d438eSPaul Traina#endif 348*ef5d438eSPaul Traina#ifdef WAIT_STATS 349*ef5d438eSPaul Traina buf_waits++; 350*ef5d438eSPaul Traina#endif 351*ef5d438eSPaul Traina stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock ); 352*ef5d438eSPaul Traina if ( stat ) { 353*ef5d438eSPaul Traina /* Memory leak */ 354*ef5d438eSPaul Traina return(NULL); 355*ef5d438eSPaul Traina } 356*ef5d438eSPaul Traina if (!( bhp->flags & BUF_IO_IN_PROGRESS) && 357*ef5d438eSPaul Traina (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) { 358*ef5d438eSPaul Traina if (RELEASE_MASTER) 359*ef5d438eSPaul Traina return(NULL); 360*ef5d438eSPaul Traina return(buf_get ( file_id, page_id, flags, len )); 361*ef5d438eSPaul Traina } 362*ef5d438eSPaul Traina } 363*ef5d438eSPaul Traina MAKE_MRU( bhp ); 364*ef5d438eSPaul Traina *len = BUFSIZE; 365*ef5d438eSPaul Traina } else { 366*ef5d438eSPaul Trainanot_found: 367*ef5d438eSPaul Traina /* If you get here, the page isn't in the hash table */ 368*ef5d438eSPaul Traina bhp = bf_assign_buf ( ndx, &fobj, flags, len ); 369*ef5d438eSPaul Traina } 370*ef5d438eSPaul Traina /* Common code between found and not found */ 371*ef5d438eSPaul Traina 372*ef5d438eSPaul Traina if ( bhp && bhp->flags & BUF_NEWPAGE ) { 373*ef5d438eSPaul Traina *len = 0; 374*ef5d438eSPaul Traina } 375*ef5d438eSPaul Traina if (RELEASE_MASTER){ 376*ef5d438eSPaul Traina /* Memory leak */ 377*ef5d438eSPaul Traina return(NULL); 378*ef5d438eSPaul Traina } 379*ef5d438eSPaul Traina if ( bhp ) { 380*ef5d438eSPaul Traina return ((ADDR_T)(buf_table+(bhp-bufhdr_table))); 381*ef5d438eSPaul Traina } else { 382*ef5d438eSPaul Traina return ( NULL ); 383*ef5d438eSPaul Traina } 384*ef5d438eSPaul Traina} 385*ef5d438eSPaul Traina 386*ef5d438eSPaul Traina/* 387*ef5d438eSPaul Traina MIS - do I want to add file links to buffer pool? 388*ef5d438eSPaul Traina*/ 389*ef5d438eSPaul Trainaextern int 390*ef5d438eSPaul Trainabuf_sync ( fid, close ) 391*ef5d438eSPaul Trainaint fid; 392*ef5d438eSPaul Trainaint close; /* should we dec refcount and possibly 393*ef5d438eSPaul Traina invalidate all the buffers */ 394*ef5d438eSPaul Traina{ 395*ef5d438eSPaul Traina int i; 396*ef5d438eSPaul Traina int fd; 397*ef5d438eSPaul Traina int invalidate; 398*ef5d438eSPaul Traina BUFHDR_T *bhp; 399*ef5d438eSPaul Traina 400*ef5d438eSPaul Traina if ( (fd = bf_fid_to_fd ( fid )) < 0 ) { 401*ef5d438eSPaul Traina return(1); 402*ef5d438eSPaul Traina } 403*ef5d438eSPaul Traina if (GET_MASTER) { 404*ef5d438eSPaul Traina return(1); 405*ef5d438eSPaul Traina } 406*ef5d438eSPaul Traina invalidate = (buf_fids[fid].refcount == 1 && close); 407*ef5d438eSPaul Traina if ( invalidate ) 408*ef5d438eSPaul Traina for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) { 409*ef5d438eSPaul Traina if (bhp->id.file_id == fid) { 410*ef5d438eSPaul Traina if ((bhp->flags & BF_DIRTY) && (bf_put_page( fd, bhp ) < 0)) { 411*ef5d438eSPaul Traina return(1); 412*ef5d438eSPaul Traina } 413*ef5d438eSPaul Traina bhp->id.file_id = -1; 414*ef5d438eSPaul Traina } 415*ef5d438eSPaul Traina } 416*ef5d438eSPaul Traina if (invalidate || close) 417*ef5d438eSPaul Traina buf_fids[fid].refcount--; 418*ef5d438eSPaul Traina 419*ef5d438eSPaul Traina if (RELEASE_MASTER) { 420*ef5d438eSPaul Traina return(1); 421*ef5d438eSPaul Traina } 422*ef5d438eSPaul Traina return(0); 423*ef5d438eSPaul Traina 424*ef5d438eSPaul Traina 425*ef5d438eSPaul Traina} 426*ef5d438eSPaul Traina 427*ef5d438eSPaul Trainaextern int 428*ef5d438eSPaul Trainabuf_flags ( addr, set_flags, unset_flags ) 429*ef5d438eSPaul TrainaADDR_T addr; 430*ef5d438eSPaul Trainau_long set_flags; 431*ef5d438eSPaul Trainau_long unset_flags; 432*ef5d438eSPaul Traina{ 433*ef5d438eSPaul Traina int bufid; 434*ef5d438eSPaul Traina BUFHDR_T *bhp; 435*ef5d438eSPaul Traina 436*ef5d438eSPaul Traina#ifdef PIN_DEBUG 437*ef5d438eSPaul Traina fprintf(stderr, "buf_flags: %X setting %s%s%s%s%s releasing %s%s%s%s%s\n", 438*ef5d438eSPaul Traina addr, 439*ef5d438eSPaul Traina set_flags&BUF_DIRTY ? "DIRTY " : "", 440*ef5d438eSPaul Traina set_flags&BUF_VALID ? "VALID " : "", 441*ef5d438eSPaul Traina set_flags&BUF_PINNED ? "PINNED " : "", 442*ef5d438eSPaul Traina set_flags&BUF_IO_ERROR ? "IO_ERROR " : "", 443*ef5d438eSPaul Traina set_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", 444*ef5d438eSPaul Traina set_flags&BUF_NEWPAGE ? "NEWPAGE " : "", 445*ef5d438eSPaul Traina unset_flags&BUF_DIRTY ? "DIRTY " : "", 446*ef5d438eSPaul Traina unset_flags&BUF_VALID ? "VALID " : "", 447*ef5d438eSPaul Traina unset_flags&BUF_PINNED ? "PINNED " : "", 448*ef5d438eSPaul Traina unset_flags&BUF_IO_ERROR ? "IO_ERROR " : "", 449*ef5d438eSPaul Traina unset_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "", 450*ef5d438eSPaul Traina unset_flags&BUF_NEWPAGE ? "NEWPAGE " : "" ); 451*ef5d438eSPaul Traina#endif 452*ef5d438eSPaul Traina if (!ADDR_OK(addr)) { 453*ef5d438eSPaul Traina error_log1 ( "buf_pin: Invalid Buffer Address %x\n", addr ); 454*ef5d438eSPaul Traina return(1); 455*ef5d438eSPaul Traina } 456*ef5d438eSPaul Traina bufid = ((BUF_T *)addr) - buf_table; 457*ef5d438eSPaul Traina assert ( bufid < NUM_BUFS); 458*ef5d438eSPaul Traina bhp = &bufhdr_table[bufid]; 459*ef5d438eSPaul Traina if (GET_MASTER) { 460*ef5d438eSPaul Traina return(1); 461*ef5d438eSPaul Traina } 462*ef5d438eSPaul Traina bhp->flags |= set_flags; 463*ef5d438eSPaul Traina if ( set_flags & BUF_PINNED ) { 464*ef5d438eSPaul Traina bhp->refcount++; 465*ef5d438eSPaul Traina } 466*ef5d438eSPaul Traina if ( set_flags & BUF_DIRTY ) { 467*ef5d438eSPaul Traina unset_flags |= BUF_NEWPAGE; 468*ef5d438eSPaul Traina } 469*ef5d438eSPaul Traina 470*ef5d438eSPaul Traina if ( unset_flags & BUF_PINNED ) { 471*ef5d438eSPaul Traina bhp->refcount--; 472*ef5d438eSPaul Traina if ( bhp->refcount ) { 473*ef5d438eSPaul Traina /* Turn off pin bit so it doesn't get unset */ 474*ef5d438eSPaul Traina unset_flags &= ~BUF_PINNED; 475*ef5d438eSPaul Traina } 476*ef5d438eSPaul Traina } 477*ef5d438eSPaul Traina bhp->flags &= ~unset_flags; 478*ef5d438eSPaul Traina MAKE_MRU(bhp); 479*ef5d438eSPaul Traina if (RELEASE_MASTER) { 480*ef5d438eSPaul Traina return(1); 481*ef5d438eSPaul Traina } 482*ef5d438eSPaul Traina return(0); 483*ef5d438eSPaul Traina} 484*ef5d438eSPaul Traina 485*ef5d438eSPaul Traina/* 486*ef5d438eSPaul Traina Take a string name and produce an fid. 487*ef5d438eSPaul Traina 488*ef5d438eSPaul Traina returns -1 on error 489*ef5d438eSPaul Traina 490*ef5d438eSPaul Traina MIS -- this is a potential problem -- you keep actual names 491*ef5d438eSPaul Traina here -- what if people run from different directories? 492*ef5d438eSPaul Traina*/ 493*ef5d438eSPaul Trainaextern int 494*ef5d438eSPaul Trainabuf_name_lookup ( fname ) 495*ef5d438eSPaul Trainachar *fname; 496*ef5d438eSPaul Traina{ 497*ef5d438eSPaul Traina int i; 498*ef5d438eSPaul Traina int fid; 499*ef5d438eSPaul Traina int ndx; 500*ef5d438eSPaul Traina 501*ef5d438eSPaul Traina fid = -1; 502*ef5d438eSPaul Traina if (GET_MASTER) { 503*ef5d438eSPaul Traina return(-1); 504*ef5d438eSPaul Traina } 505*ef5d438eSPaul Traina for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) { 506*ef5d438eSPaul Traina if ( buf_fids[i].offset == -1 ) { 507*ef5d438eSPaul Traina fid = i; 508*ef5d438eSPaul Traina } else { 509*ef5d438eSPaul Traina if (!strcmp (fname, buf_strings+buf_fids[i].offset)) { 510*ef5d438eSPaul Traina if (RELEASE_MASTER) { 511*ef5d438eSPaul Traina return(-1); 512*ef5d438eSPaul Traina } 513*ef5d438eSPaul Traina buf_fids[i].refcount++; 514*ef5d438eSPaul Traina return(i); 515*ef5d438eSPaul Traina } 516*ef5d438eSPaul Traina } 517*ef5d438eSPaul Traina } 518*ef5d438eSPaul Traina if ( fid == -1 ) { 519*ef5d438eSPaul Traina error_log0 ( "No more file ID's\n" ); 520*ef5d438eSPaul Traina } else { 521*ef5d438eSPaul Traina ndx = *buf_sp - strlen(fname) - 1; 522*ef5d438eSPaul Traina if ( ndx < 0 ) { 523*ef5d438eSPaul Traina error_log0 ( "Out of string space\n" ); 524*ef5d438eSPaul Traina fid = -1; 525*ef5d438eSPaul Traina } else { 526*ef5d438eSPaul Traina *buf_sp = ndx; 527*ef5d438eSPaul Traina strcpy ( buf_strings+ndx, fname ); 528*ef5d438eSPaul Traina buf_fids[fid].offset = ndx; 529*ef5d438eSPaul Traina } 530*ef5d438eSPaul Traina buf_fids[fid].refcount = 1; 531*ef5d438eSPaul Traina } 532*ef5d438eSPaul Traina if (RELEASE_MASTER) { 533*ef5d438eSPaul Traina return(-1); 534*ef5d438eSPaul Traina } 535*ef5d438eSPaul Traina return(fid); 536*ef5d438eSPaul Traina} 537*ef5d438eSPaul Traina 538*ef5d438eSPaul Trainastatic int 539*ef5d438eSPaul Trainabf_fid_to_fd ( fid ) 540*ef5d438eSPaul Trainaint fid; 541*ef5d438eSPaul Traina{ 542*ef5d438eSPaul Traina struct stat sbuf; 543*ef5d438eSPaul Traina 544*ef5d438eSPaul Traina assert ( (fid < NUM_FILE_ENTRIES) && (buf_fids[fid].offset != -1) ); 545*ef5d438eSPaul Traina if ( fds[fid] != -1 ) { 546*ef5d438eSPaul Traina return(fds[fid]); 547*ef5d438eSPaul Traina 548*ef5d438eSPaul Traina } 549*ef5d438eSPaul Traina fds[fid] = open ( buf_strings+buf_fids[fid].offset, O_RDWR|O_CREAT, 550*ef5d438eSPaul Traina 0666 ); 551*ef5d438eSPaul Traina if ( fds[fid] < 0 ) { 552*ef5d438eSPaul Traina error_log3 ( "Error Opening File %s FID: %d FD: %d. Errno = %d\n", 553*ef5d438eSPaul Traina buf_strings+buf_fids[fid].offset, fid, fds[fid], 554*ef5d438eSPaul Traina errno ); 555*ef5d438eSPaul Traina return(-1); 556*ef5d438eSPaul Traina } 557*ef5d438eSPaul Traina error_log3 ( "Opening File %s FID: %d FD: %d\n", 558*ef5d438eSPaul Traina buf_strings+buf_fids[fid].offset, fid, fds[fid] ); 559*ef5d438eSPaul Traina if ( buf_fids[fid].npages == -1 ) { 560*ef5d438eSPaul Traina /* Initialize the npages field */ 561*ef5d438eSPaul Traina if ( fstat ( fds[fid], &sbuf ) ) { 562*ef5d438eSPaul Traina error_log3 ( "Error Fstating %s FID: %d. Errno = %d\n", 563*ef5d438eSPaul Traina buf_strings+buf_fids[fid].offset, fid, errno ); 564*ef5d438eSPaul Traina } else { 565*ef5d438eSPaul Traina buf_fids[fid].npages = ( sbuf.st_size / BUFSIZE ); 566*ef5d438eSPaul Traina } 567*ef5d438eSPaul Traina } 568*ef5d438eSPaul Traina 569*ef5d438eSPaul Traina return ( fds[fid] ); 570*ef5d438eSPaul Traina} 571*ef5d438eSPaul Traina 572*ef5d438eSPaul Trainastatic int 573*ef5d438eSPaul Trainabf_put_page ( fd, bhp ) 574*ef5d438eSPaul Trainaint fd; 575*ef5d438eSPaul TrainaBUFHDR_T *bhp; 576*ef5d438eSPaul Traina{ 577*ef5d438eSPaul Traina int nbytes; 578*ef5d438eSPaul Traina 579*ef5d438eSPaul Traina assert ( (bhp-bufhdr_table) < NUM_BUFS ); 580*ef5d438eSPaul Traina if ( lseek ( fd, bhp->id.obj_id << BUFSHIFT, L_SET ) < 0 ) { 581*ef5d438eSPaul Traina return(-1); 582*ef5d438eSPaul Traina } 583*ef5d438eSPaul Traina bhp->flags |= BUF_IO_IN_PROGRESS; 584*ef5d438eSPaul Traina if (RELEASE_MASTER) { 585*ef5d438eSPaul Traina return(-1); 586*ef5d438eSPaul Traina } 587*ef5d438eSPaul Traina nbytes = write(fd, buf_table[bhp-bufhdr_table], BUFSIZE); 588*ef5d438eSPaul Traina if (GET_MASTER) { 589*ef5d438eSPaul Traina return(-2); 590*ef5d438eSPaul Traina } 591*ef5d438eSPaul Traina if ( nbytes < 0 ) { 592*ef5d438eSPaul Traina error_log1 ("Write failed with error code %d\n", errno); 593*ef5d438eSPaul Traina return(-1); 594*ef5d438eSPaul Traina } else if ( nbytes != BUFSIZE ) { 595*ef5d438eSPaul Traina error_log1 ("Short write: %d bytes of %d\n", nbytes, BUFSIZE ); 596*ef5d438eSPaul Traina } 597*ef5d438eSPaul Traina bhp->flags &= ~(BUF_DIRTY|BUF_IO_IN_PROGRESS); 598*ef5d438eSPaul Traina return (0); 599*ef5d438eSPaul Traina} 600*ef5d438eSPaul Traina 601*ef5d438eSPaul Trainastatic BUFHDR_T * 602*ef5d438eSPaul Trainabf_assign_buf ( ndx, obj, flags, len ) 603*ef5d438eSPaul Trainaint ndx; 604*ef5d438eSPaul TrainaOBJ_T *obj; 605*ef5d438eSPaul Trainau_long flags; 606*ef5d438eSPaul Trainaint *len; /* Number of bytes read */ 607*ef5d438eSPaul Traina{ 608*ef5d438eSPaul Traina BUFHDR_T *bhp; 609*ef5d438eSPaul Traina int fd; 610*ef5d438eSPaul Traina 611*ef5d438eSPaul Traina assert ( obj->file_id < NUM_FILE_ENTRIES ); 612*ef5d438eSPaul Traina bhp = bf_newbuf(); 613*ef5d438eSPaul Traina if ( !bhp ) { 614*ef5d438eSPaul Traina return(NULL); 615*ef5d438eSPaul Traina } 616*ef5d438eSPaul Traina OBJ_ASSIGN ( (*obj), bhp->id ); 617*ef5d438eSPaul Traina if ( buf_hash_table[ndx] >= NUM_BUFS ) { 618*ef5d438eSPaul Traina buf_hash_table[ndx] = bhp-bufhdr_table; 619*ef5d438eSPaul Traina } else { 620*ef5d438eSPaul Traina LISTPE_INSERT ( bufhdr_table, hash, bhp, buf_hash_table[ndx] ); 621*ef5d438eSPaul Traina } 622*ef5d438eSPaul Traina 623*ef5d438eSPaul Traina bhp->flags |= BUF_VALID; 624*ef5d438eSPaul Traina if ( flags & BF_PIN ) { 625*ef5d438eSPaul Traina bhp->flags |= BUF_PINNED; 626*ef5d438eSPaul Traina bhp->refcount++; 627*ef5d438eSPaul Traina#ifdef PIN_DEBUG 628*ef5d438eSPaul Traina fprintf(stderr, "bf_assign_buf: %X PINNED (%d)\n", 629*ef5d438eSPaul Traina buf_table + (bhp-bufhdr_table), bhp->refcount); 630*ef5d438eSPaul Traina#endif 631*ef5d438eSPaul Traina } 632*ef5d438eSPaul Traina fd = bf_fid_to_fd(obj->file_id); 633*ef5d438eSPaul Traina if ( fd == -1 ) { 634*ef5d438eSPaul Traina error_log1 ("Invalid fid %d\n", obj->file_id); 635*ef5d438eSPaul Traina bhp->flags |= ~BUF_IO_ERROR; 636*ef5d438eSPaul Traina return(NULL); 637*ef5d438eSPaul Traina } 638*ef5d438eSPaul Traina if ( obj->obj_id >= buf_fids[obj->file_id].npages) { 639*ef5d438eSPaul Traina buf_fids[obj->file_id].npages = obj->obj_id+1; 640*ef5d438eSPaul Traina *len = 0; 641*ef5d438eSPaul Traina } else if ( flags & BF_EMPTY ) { 642*ef5d438eSPaul Traina *len = 0; 643*ef5d438eSPaul Traina } else { 644*ef5d438eSPaul Traina bhp->flags |= BUF_IO_IN_PROGRESS; 645*ef5d438eSPaul Traina if (RELEASE_MASTER) { 646*ef5d438eSPaul Traina return(NULL); 647*ef5d438eSPaul Traina } 648*ef5d438eSPaul Traina if ( lseek ( fd, obj->obj_id << BUFSHIFT, L_SET ) < -1 ) { 649*ef5d438eSPaul Traina error_log2 ("Unable to perform seek on file: %d to page %d", 650*ef5d438eSPaul Traina obj->file_id, obj->obj_id ); 651*ef5d438eSPaul Traina bhp->flags &= ~BUF_IO_IN_PROGRESS; 652*ef5d438eSPaul Traina bhp->flags |= ~BUF_IO_ERROR; 653*ef5d438eSPaul Traina return(NULL); 654*ef5d438eSPaul Traina } 655*ef5d438eSPaul Traina *len = read(fd, buf_table[bhp-bufhdr_table], BUFSIZE); 656*ef5d438eSPaul Traina if ( *len < 0 ) { 657*ef5d438eSPaul Traina error_log2 ("Unable to perform read on file: %d to page %d", 658*ef5d438eSPaul Traina obj->file_id, obj->obj_id ); 659*ef5d438eSPaul Traina bhp->flags &= ~BUF_IO_IN_PROGRESS; 660*ef5d438eSPaul Traina bhp->flags |= ~BUF_IO_ERROR; 661*ef5d438eSPaul Traina return(NULL); 662*ef5d438eSPaul Traina } 663*ef5d438eSPaul Traina if (GET_MASTER) { 664*ef5d438eSPaul Traina return(NULL); 665*ef5d438eSPaul Traina } 666*ef5d438eSPaul Traina bhp->flags &= ~BUF_IO_IN_PROGRESS; 667*ef5d438eSPaul Traina if ( bhp->wait_proc != -1 ) { 668*ef5d438eSPaul Traina /* wake up waiter and anyone waiting on it */ 669*ef5d438eSPaul Traina#ifdef DEBUG 670*ef5d438eSPaul Traina printf("Waking transaction %d due to completed I/O\n", 671*ef5d438eSPaul Traina bhp->wait_proc); 672*ef5d438eSPaul Traina#endif 673*ef5d438eSPaul Traina proc_wake_id ( bhp->wait_proc ); 674*ef5d438eSPaul Traina bhp->wait_proc = -1; 675*ef5d438eSPaul Traina } 676*ef5d438eSPaul Traina MAKE_MRU(bhp); 677*ef5d438eSPaul Traina } 678*ef5d438eSPaul Traina 679*ef5d438eSPaul Traina if ( flags & BF_DIRTY ) { 680*ef5d438eSPaul Traina bhp->flags |= BUF_DIRTY; 681*ef5d438eSPaul Traina } else if ( *len < BUFSIZE ) { 682*ef5d438eSPaul Traina bhp->flags |= BUF_NEWPAGE; 683*ef5d438eSPaul Traina } 684*ef5d438eSPaul Traina return ( bhp ); 685*ef5d438eSPaul Traina} 686*ef5d438eSPaul Traina 687*ef5d438eSPaul Trainaint 688*ef5d438eSPaul Trainabuf_last ( fid ) 689*ef5d438eSPaul Trainaint fid; 690*ef5d438eSPaul Traina{ 691*ef5d438eSPaul Traina int val; 692*ef5d438eSPaul Traina 693*ef5d438eSPaul Traina if (GET_MASTER) { 694*ef5d438eSPaul Traina return(-1); 695*ef5d438eSPaul Traina } 696*ef5d438eSPaul Traina assert ( fid < NUM_FILE_ENTRIES ); 697*ef5d438eSPaul Traina if ( buf_fids[fid].npages == -1 ) { 698*ef5d438eSPaul Traina /* initialize npages field */ 699*ef5d438eSPaul Traina (void) bf_fid_to_fd ( fid ); 700*ef5d438eSPaul Traina } 701*ef5d438eSPaul Traina val = buf_fids[fid].npages; 702*ef5d438eSPaul Traina if ( val ) { 703*ef5d438eSPaul Traina val--; /* Convert to page number */ 704*ef5d438eSPaul Traina } 705*ef5d438eSPaul Traina if (RELEASE_MASTER) { 706*ef5d438eSPaul Traina return(-1); 707*ef5d438eSPaul Traina } 708*ef5d438eSPaul Traina return(val); 709*ef5d438eSPaul Traina} 710*ef5d438eSPaul Traina 711*ef5d438eSPaul Traina#ifdef DEBUG 712*ef5d438eSPaul Trainaextern void 713*ef5d438eSPaul Trainabuf_dump ( id, all ) 714*ef5d438eSPaul Trainaint id; 715*ef5d438eSPaul Trainaint all; 716*ef5d438eSPaul Traina{ 717*ef5d438eSPaul Traina int i; 718*ef5d438eSPaul Traina BUFHDR_T *bhp; 719*ef5d438eSPaul Traina 720*ef5d438eSPaul Traina printf ( "LRU + %d\n", *buf_lru ); 721*ef5d438eSPaul Traina if ( all ) { 722*ef5d438eSPaul Traina printf("ID\tFID\tPID\tLNEXT\tLPREV\tHNEXT\tHPREV\tSLEEP\tFLAG\tREFS\n"); 723*ef5d438eSPaul Traina for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) { 724*ef5d438eSPaul Traina printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i, 725*ef5d438eSPaul Traina bhp->id.file_id, bhp->id.obj_id, 726*ef5d438eSPaul Traina bhp->lru.next, bhp->lru.prev, 727*ef5d438eSPaul Traina bhp->hash.next, bhp->hash.prev, 728*ef5d438eSPaul Traina bhp->wait_proc, bhp->flags, bhp->refcount ); 729*ef5d438eSPaul Traina } 730*ef5d438eSPaul Traina } else { 731*ef5d438eSPaul Traina if ( id >= NUM_BUFS ) { 732*ef5d438eSPaul Traina printf ( "Buffer ID (%d) too high\n", id ); 733*ef5d438eSPaul Traina return; 734*ef5d438eSPaul Traina } 735*ef5d438eSPaul Traina bhp = bufhdr_table+id; 736*ef5d438eSPaul Traina printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i, 737*ef5d438eSPaul Traina bhp->id.file_id, bhp->id.obj_id, 738*ef5d438eSPaul Traina bhp->lru.next, bhp->lru.prev, 739*ef5d438eSPaul Traina bhp->hash.next, bhp->hash.prev, 740*ef5d438eSPaul Traina bhp->wait_proc, bhp->flags, bhp->refcount ); 741*ef5d438eSPaul Traina } 742*ef5d438eSPaul Traina return; 743*ef5d438eSPaul Traina} 744*ef5d438eSPaul Traina#endif 745*ef5d438eSPaul Traina 746