source: vendor/FreeBSD-libc/current/db/mpool/mpool.libtp

Last change on this file was 961, checked in by bird, 22 years ago

Initial revision

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