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