146367Sbostic /*- 246367Sbostic * Copyright (c) 1990 The Regents of the University of California. 346367Sbostic * All rights reserved. 446367Sbostic * 546367Sbostic * This code is derived from software contributed to Berkeley by 646367Sbostic * Margo Seltzer. 746367Sbostic * 846367Sbostic * %sccs.include.redist.c% 946367Sbostic * 10*50997Sbostic * @(#)hash.h 5.5 (Berkeley) 09/04/91 1146367Sbostic */ 1246367Sbostic 1346367Sbostic /* Operations */ 14*50997Sbostic typedef enum { 15*50997Sbostic HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT 16*50997Sbostic } ACTION; 1746367Sbostic 1846367Sbostic /* Buffer Management structures */ 1946367Sbostic typedef struct _bufhead BUFHEAD; 2046367Sbostic 2146367Sbostic struct _bufhead { 22*50997Sbostic BUFHEAD *prev; /* LRU links */ 23*50997Sbostic BUFHEAD *next; /* LRU links */ 24*50997Sbostic BUFHEAD *ovfl; /* Overflow page buffer header */ 25*50997Sbostic u_int addr; /* Address of this page */ 26*50997Sbostic char *page; /* Actual page data */ 27*50997Sbostic char flags; 2846367Sbostic #define BUF_MOD 0x0001 2946367Sbostic #define BUF_DISK 0x0002 3046367Sbostic #define BUF_BUCKET 0x0004 3146458Sbostic #define BUF_PIN 0x0008 3246458Sbostic }; 3346367Sbostic 34*50997Sbostic #define IS_BUCKET(X) ((X) & BUF_BUCKET) 3546458Sbostic 36*50997Sbostic typedef BUFHEAD **SEGMENT; 3746367Sbostic 3846367Sbostic /* Hash Table Information */ 3946367Sbostic typedef struct hashhdr { /* Disk resident portion */ 40*50997Sbostic int magic; /* Magic NO for hash tables */ 41*50997Sbostic int version; /* Version ID */ 42*50997Sbostic long lorder; /* Byte Order */ 43*50997Sbostic int bsize; /* Bucket/Page Size */ 44*50997Sbostic int bshift; /* Bucket shift */ 45*50997Sbostic int dsize; /* Directory Size */ 46*50997Sbostic int ssize; /* Segment Size */ 47*50997Sbostic int sshift; /* Segment shift */ 48*50997Sbostic int max_bucket; /* ID of Maximum bucket in use */ 49*50997Sbostic int high_mask; /* Mask to modulo into entire table */ 50*50997Sbostic int low_mask; /* Mask to modulo into lower half of table */ 51*50997Sbostic int ffactor; /* Fill factor */ 52*50997Sbostic int nkeys; /* Number of keys in hash table */ 53*50997Sbostic int hdrpages; /* Size of table header */ 54*50997Sbostic int h_charkey; /* value of hash(CHARKEY) */ 55*50997Sbostic #define NCACHED 32 /* number of bit maps and spare points */ 56*50997Sbostic int spares[NCACHED];/* spare pages for overflow */ 57*50997Sbostic u_short bitmaps[NCACHED]; /* address of overflow page bitmaps */ 5846367Sbostic } HASHHDR; 5946367Sbostic 60*50997Sbostic typedef struct htab { /* Memory resident data structure */ 61*50997Sbostic HASHHDR hdr; /* Header */ 62*50997Sbostic int nsegs; /* Number of allocated segments */ 63*50997Sbostic int exsegs; /* Number of extra allocated segments */ 64*50997Sbostic int (*hash) (); /* Hash Function */ 65*50997Sbostic int flags; /* Flag values */ 66*50997Sbostic int fp; /* File pointer */ 67*50997Sbostic char *tmp_buf; /* Temporary Buffer for BIG data */ 68*50997Sbostic char *tmp_key; /* Temporary Buffer for BIG keys */ 69*50997Sbostic BUFHEAD *cpage; /* Current page */ 70*50997Sbostic int cbucket; /* Current bucket */ 71*50997Sbostic int cndx; /* Index of next item on cpage */ 72*50997Sbostic int errno; /* Error Number -- for DBM compatability */ 73*50997Sbostic int new_file; /* Indicates if fd is backing store or no */ 74*50997Sbostic int save_file; /* Indicates whether we need to flush file at 75*50997Sbostic * exit */ 7646367Sbostic u_long *mapp[NCACHED]; /* Pointers to page maps */ 77*50997Sbostic int nmaps; /* Initial number of bitmaps */ 78*50997Sbostic int nbufs; /* Number of buffers left to allocate */ 79*50997Sbostic BUFHEAD bufhead; /* Header of buffer lru list */ 80*50997Sbostic SEGMENT *dir; /* Hash Bucket directory */ 8146367Sbostic } HTAB; 8246367Sbostic 8346367Sbostic /* 8446367Sbostic * Constants 8546367Sbostic */ 86*50997Sbostic #define MAX_BSIZE 65536 /* 2^16 */ 8746367Sbostic #define MIN_BUFFERS 6 8846367Sbostic #define MINHDRSIZE 512 89*50997Sbostic #define DEF_BUFSIZE 65536 /* 64 K */ 90*50997Sbostic #define DEF_BUCKET_SIZE 256 91*50997Sbostic #define DEF_BUCKET_SHIFT 8 /* log2(BUCKET) */ 9246367Sbostic #define DEF_SEGSIZE 256 93*50997Sbostic #define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ 9446367Sbostic #define DEF_DIRSIZE 256 9546367Sbostic #define DEF_FFACTOR 5 96*50997Sbostic #define SPLTMAX 8 97*50997Sbostic #define CHARKEY "%$sniglet^&" 9846367Sbostic #define NUMKEY 1038583 9946367Sbostic #define VERSION_NO 3 10046367Sbostic #define BYTE_SHIFT 3 10146367Sbostic #define INT_TO_BYTE 2 10246367Sbostic #define INT_BYTE_SHIFT 5 103*50997Sbostic #define ALL_SET ((u_int)0xFFFFFFFF) 10446367Sbostic #define ALL_CLEAR 0 10546367Sbostic 106*50997Sbostic #define PTROF(X) ((BUFHEAD *)((u_int)(X)&~0x3)) 107*50997Sbostic #define ISMOD(X) ((u_int)(X)&0x1) 108*50997Sbostic #define DOMOD(X) ((X) = (char *)((u_int)(X)|0x1)) 109*50997Sbostic #define ISDISK(X) ((u_int)(X)&0x2) 110*50997Sbostic #define DODISK(X) ((X) = (char *)((u_int)(X)|0x2)) 11146367Sbostic 112*50997Sbostic #define BITS_PER_MAP 32 11346367Sbostic 11446367Sbostic /* Given the address of the beginning of a big map, clear/set the nth bit */ 115*50997Sbostic #define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) 116*50997Sbostic #define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) 117*50997Sbostic #define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) 11846367Sbostic 11946367Sbostic /* Overflow management */ 12046367Sbostic /* 121*50997Sbostic * Overflow page numbers are allocated per split point. At each doubling of 122*50997Sbostic * the table, we can allocate extra pages. So, an overflow page number has 123*50997Sbostic * the top 5 bits indicate which split point and the lower 11 bits indicate 124*50997Sbostic * which page at that split point is indicated (pages within split points are 125*50997Sbostic * numberered starting with 1). 126*50997Sbostic */ 12746367Sbostic 12846367Sbostic #define SPLITSHIFT 11 12946367Sbostic #define SPLITMASK 0x7FF 130*50997Sbostic #define SPLITNUM(N) (((u_int)(N)) >> SPLITSHIFT) 131*50997Sbostic #define OPAGENUM(N) ((N) & SPLITMASK) 132*50997Sbostic #define OADDR_OF(S,O) ((u_int)((u_int)(S) << SPLITSHIFT) + (O)) 13346367Sbostic 13446367Sbostic #define BUCKET_TO_PAGE(B) \ 135*50997Sbostic (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0) 13646367Sbostic #define OADDR_TO_PAGE(B) \ 137*50997Sbostic BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); 13846367Sbostic 13946367Sbostic /* 140*50997Sbostic * page.h contains a detailed description of the page format. 141*50997Sbostic * 142*50997Sbostic * Normally, keys and data are accessed from offset tables in the top of 143*50997Sbostic * each page which point to the beginning of the key and data. There are 144*50997Sbostic * four flag values which may be stored in these offset tables which indicate 145*50997Sbostic * the following: 146*50997Sbostic * 147*50997Sbostic * 148*50997Sbostic * OVFLPAGE Rather than a key data pair, this pair contains 149*50997Sbostic * the address of an overflow page. The format of 150*50997Sbostic * the pair is: 151*50997Sbostic * OVERFLOW_PAGE_NUMBER OVFLPAGE 152*50997Sbostic * 153*50997Sbostic * PARTIAL_KEY This must be the first key/data pair on a page 154*50997Sbostic * and implies that page contains only a partial key. 155*50997Sbostic * That is, the key is too big to fit on a single page 156*50997Sbostic * so it starts on this page and continues on the next. 157*50997Sbostic * The format of the page is: 158*50997Sbostic * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE 159*50997Sbostic * 160*50997Sbostic * KEY_OFF -- offset of the beginning of the key 161*50997Sbostic * PARTIAL_KEY -- 1 162*50997Sbostic * OVFL_PAGENO - page number of the next overflow page 163*50997Sbostic * OVFLPAGE -- 0 164*50997Sbostic * 165*50997Sbostic * FULL_KEY This must be the first key/data pair on the page. It 166*50997Sbostic * is used in two cases. 167*50997Sbostic * 168*50997Sbostic * Case 1: 169*50997Sbostic * There is a complete key on the page but no data 170*50997Sbostic * (because it wouldn't fit). The next page contains 171*50997Sbostic * the data. 172*50997Sbostic * 173*50997Sbostic * Page format it: 174*50997Sbostic * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 175*50997Sbostic * 176*50997Sbostic * KEY_OFF -- offset of the beginning of the key 177*50997Sbostic * FULL_KEY -- 2 178*50997Sbostic * OVFL_PAGENO - page number of the next overflow page 179*50997Sbostic * OVFLPAGE -- 0 180*50997Sbostic * 181*50997Sbostic * Case 2: 182*50997Sbostic * This page contains no key, but part of a large 183*50997Sbostic * data field, which is continued on the next page. 184*50997Sbostic * 185*50997Sbostic * Page format it: 186*50997Sbostic * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 187*50997Sbostic * 188*50997Sbostic * KEY_OFF -- offset of the beginning of the data on 189*50997Sbostic * this page 190*50997Sbostic * FULL_KEY -- 2 191*50997Sbostic * OVFL_PAGENO - page number of the next overflow page 192*50997Sbostic * OVFLPAGE -- 0 193*50997Sbostic * 194*50997Sbostic * FULL_KEY_DATA 195*50997Sbostic * This must be the first key/data pair on the page. 196*50997Sbostic * There are two cases: 197*50997Sbostic * 198*50997Sbostic * Case 1: 199*50997Sbostic * This page contains a key and the beginning of the 200*50997Sbostic * data field, but the data field is continued on the 201*50997Sbostic * next page. 202*50997Sbostic * 203*50997Sbostic * Page format is: 204*50997Sbostic * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF 205*50997Sbostic * 206*50997Sbostic * KEY_OFF -- offset of the beginning of the key 207*50997Sbostic * FULL_KEY_DATA -- 3 208*50997Sbostic * OVFL_PAGENO - page number of the next overflow page 209*50997Sbostic * DATA_OFF -- offset of the beginning of the data 210*50997Sbostic * 211*50997Sbostic * Case 2: 212*50997Sbostic * This page contains the last page of a big data pair. 213*50997Sbostic * There is no key, only the tail end of the data 214*50997Sbostic * on this page. 215*50997Sbostic * 216*50997Sbostic * Page format is: 217*50997Sbostic * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE> 218*50997Sbostic * 219*50997Sbostic * DATA_OFF -- offset of the beginning of the data on 220*50997Sbostic * this page 221*50997Sbostic * FULL_KEY_DATA -- 3 222*50997Sbostic * OVFL_PAGENO - page number of the next overflow page 223*50997Sbostic * OVFLPAGE -- 0 224*50997Sbostic * 225*50997Sbostic * OVFL_PAGENO and OVFLPAGE are optional (they are 226*50997Sbostic * not present if there is no next page). 227*50997Sbostic */ 22846367Sbostic 22946367Sbostic #define OVFLPAGE 0 23046367Sbostic #define PARTIAL_KEY 1 23146367Sbostic #define FULL_KEY 2 23246367Sbostic #define FULL_KEY_DATA 3 23346367Sbostic #define REAL_KEY 4 234*50997Sbostic 23546367Sbostic /* Short hands for accessing structure */ 236*50997Sbostic #define BSIZE hdr.bsize 237*50997Sbostic #define BSHIFT hdr.bshift 238*50997Sbostic #define DSIZE hdr.dsize 239*50997Sbostic #define SGSIZE hdr.ssize 240*50997Sbostic #define SSHIFT hdr.sshift 241*50997Sbostic #define LORDER hdr.lorder 24246367Sbostic #define MAX_BUCKET hdr.max_bucket 24346367Sbostic #define FFACTOR hdr.ffactor 24446367Sbostic #define HIGH_MASK hdr.high_mask 24546367Sbostic #define LOW_MASK hdr.low_mask 24646367Sbostic #define NKEYS hdr.nkeys 24746367Sbostic #define HDRPAGES hdr.hdrpages 24846367Sbostic #define SPARES hdr.spares 24946367Sbostic #define BITMAPS hdr.bitmaps 25046367Sbostic #define VERSION hdr.version 25146367Sbostic #define MAGIC hdr.magic 25246367Sbostic #define NEXT_FREE hdr.next_free 25346367Sbostic #define H_CHARKEY hdr.h_charkey 254