xref: /freebsd-14.2/lib/libc/db/mpool/mpool.libtp (revision be6151e4)
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