146367Sbostic /*- 2*61202Sbostic * Copyright (c) 1990, 1993 3*61202Sbostic * The Regents of the University of California. 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*61202Sbostic * @(#)hash.h 8.1 (Berkeley) 06/04/93 1146367Sbostic */ 1246367Sbostic 1346367Sbostic /* Operations */ 1450997Sbostic typedef enum { 1550997Sbostic HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT 1650997Sbostic } ACTION; 1746367Sbostic 1846367Sbostic /* Buffer Management structures */ 1946367Sbostic typedef struct _bufhead BUFHEAD; 2046367Sbostic 2146367Sbostic struct _bufhead { 2250997Sbostic BUFHEAD *prev; /* LRU links */ 2350997Sbostic BUFHEAD *next; /* LRU links */ 2450997Sbostic BUFHEAD *ovfl; /* Overflow page buffer header */ 2550997Sbostic u_int addr; /* Address of this page */ 2650997Sbostic char *page; /* Actual page data */ 2750997Sbostic char flags; 2846367Sbostic #define BUF_MOD 0x0001 2946367Sbostic #define BUF_DISK 0x0002 3046367Sbostic #define BUF_BUCKET 0x0004 3146458Sbostic #define BUF_PIN 0x0008 3246458Sbostic }; 3346367Sbostic 3450997Sbostic #define IS_BUCKET(X) ((X) & BUF_BUCKET) 3546458Sbostic 3650997Sbostic typedef BUFHEAD **SEGMENT; 3746367Sbostic 3846367Sbostic /* Hash Table Information */ 3946367Sbostic typedef struct hashhdr { /* Disk resident portion */ 4050997Sbostic int magic; /* Magic NO for hash tables */ 4150997Sbostic int version; /* Version ID */ 4250997Sbostic long lorder; /* Byte Order */ 4350997Sbostic int bsize; /* Bucket/Page Size */ 4450997Sbostic int bshift; /* Bucket shift */ 4550997Sbostic int dsize; /* Directory Size */ 4650997Sbostic int ssize; /* Segment Size */ 4750997Sbostic int sshift; /* Segment shift */ 4851061Sbostic int ovfl_point; /* Where overflow pages are being allocated */ 4951061Sbostic int last_freed; /* Last overflow page freed */ 5050997Sbostic int max_bucket; /* ID of Maximum bucket in use */ 5150997Sbostic int high_mask; /* Mask to modulo into entire table */ 5250997Sbostic int low_mask; /* Mask to modulo into lower half of table */ 5350997Sbostic int ffactor; /* Fill factor */ 5450997Sbostic int nkeys; /* Number of keys in hash table */ 5550997Sbostic int hdrpages; /* Size of table header */ 5650997Sbostic int h_charkey; /* value of hash(CHARKEY) */ 5750997Sbostic #define NCACHED 32 /* number of bit maps and spare points */ 5850997Sbostic int spares[NCACHED];/* spare pages for overflow */ 5950997Sbostic u_short bitmaps[NCACHED]; /* address of overflow page bitmaps */ 6046367Sbostic } HASHHDR; 6146367Sbostic 6250997Sbostic typedef struct htab { /* Memory resident data structure */ 6350997Sbostic HASHHDR hdr; /* Header */ 6450997Sbostic int nsegs; /* Number of allocated segments */ 6550997Sbostic int exsegs; /* Number of extra allocated segments */ 6650997Sbostic int (*hash) (); /* Hash Function */ 6750997Sbostic int flags; /* Flag values */ 6850997Sbostic int fp; /* File pointer */ 6950997Sbostic char *tmp_buf; /* Temporary Buffer for BIG data */ 7050997Sbostic char *tmp_key; /* Temporary Buffer for BIG keys */ 7150997Sbostic BUFHEAD *cpage; /* Current page */ 7250997Sbostic int cbucket; /* Current bucket */ 7350997Sbostic int cndx; /* Index of next item on cpage */ 7450997Sbostic int errno; /* Error Number -- for DBM compatability */ 7550997Sbostic int new_file; /* Indicates if fd is backing store or no */ 7650997Sbostic int save_file; /* Indicates whether we need to flush file at 7750997Sbostic * exit */ 7846367Sbostic u_long *mapp[NCACHED]; /* Pointers to page maps */ 7950997Sbostic int nmaps; /* Initial number of bitmaps */ 8050997Sbostic int nbufs; /* Number of buffers left to allocate */ 8150997Sbostic BUFHEAD bufhead; /* Header of buffer lru list */ 8250997Sbostic SEGMENT *dir; /* Hash Bucket directory */ 8346367Sbostic } HTAB; 8446367Sbostic 8546367Sbostic /* 8646367Sbostic * Constants 8746367Sbostic */ 8850997Sbostic #define MAX_BSIZE 65536 /* 2^16 */ 8946367Sbostic #define MIN_BUFFERS 6 9046367Sbostic #define MINHDRSIZE 512 9150997Sbostic #define DEF_BUFSIZE 65536 /* 64 K */ 9260244Sbostic #define DEF_BUCKET_SIZE 4096 9360244Sbostic #define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ 9446367Sbostic #define DEF_SEGSIZE 256 9550997Sbostic #define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ 9646367Sbostic #define DEF_DIRSIZE 256 9760244Sbostic #define DEF_FFACTOR 65536 9860244Sbostic #define MIN_FFACTOR 4 9950997Sbostic #define SPLTMAX 8 10050997Sbostic #define CHARKEY "%$sniglet^&" 10146367Sbostic #define NUMKEY 1038583 10246367Sbostic #define BYTE_SHIFT 3 10346367Sbostic #define INT_TO_BYTE 2 10446367Sbostic #define INT_BYTE_SHIFT 5 10550997Sbostic #define ALL_SET ((u_int)0xFFFFFFFF) 10646367Sbostic #define ALL_CLEAR 0 10746367Sbostic 10850997Sbostic #define PTROF(X) ((BUFHEAD *)((u_int)(X)&~0x3)) 10950997Sbostic #define ISMOD(X) ((u_int)(X)&0x1) 11050997Sbostic #define DOMOD(X) ((X) = (char *)((u_int)(X)|0x1)) 11150997Sbostic #define ISDISK(X) ((u_int)(X)&0x2) 11250997Sbostic #define DODISK(X) ((X) = (char *)((u_int)(X)|0x2)) 11346367Sbostic 11450997Sbostic #define BITS_PER_MAP 32 11546367Sbostic 11646367Sbostic /* Given the address of the beginning of a big map, clear/set the nth bit */ 11750997Sbostic #define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) 11850997Sbostic #define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) 11950997Sbostic #define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) 12046367Sbostic 12146367Sbostic /* Overflow management */ 12246367Sbostic /* 12350997Sbostic * Overflow page numbers are allocated per split point. At each doubling of 12450997Sbostic * the table, we can allocate extra pages. So, an overflow page number has 12550997Sbostic * the top 5 bits indicate which split point and the lower 11 bits indicate 12650997Sbostic * which page at that split point is indicated (pages within split points are 12750997Sbostic * numberered starting with 1). 12850997Sbostic */ 12946367Sbostic 13046367Sbostic #define SPLITSHIFT 11 13146367Sbostic #define SPLITMASK 0x7FF 13250997Sbostic #define SPLITNUM(N) (((u_int)(N)) >> SPLITSHIFT) 13350997Sbostic #define OPAGENUM(N) ((N) & SPLITMASK) 13450997Sbostic #define OADDR_OF(S,O) ((u_int)((u_int)(S) << SPLITSHIFT) + (O)) 13546367Sbostic 13646367Sbostic #define BUCKET_TO_PAGE(B) \ 13750997Sbostic (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0) 13846367Sbostic #define OADDR_TO_PAGE(B) \ 13950997Sbostic BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); 14046367Sbostic 14146367Sbostic /* 14250997Sbostic * page.h contains a detailed description of the page format. 14350997Sbostic * 14450997Sbostic * Normally, keys and data are accessed from offset tables in the top of 14550997Sbostic * each page which point to the beginning of the key and data. There are 14650997Sbostic * four flag values which may be stored in these offset tables which indicate 14750997Sbostic * the following: 14850997Sbostic * 14950997Sbostic * 15050997Sbostic * OVFLPAGE Rather than a key data pair, this pair contains 15150997Sbostic * the address of an overflow page. The format of 15250997Sbostic * the pair is: 15350997Sbostic * OVERFLOW_PAGE_NUMBER OVFLPAGE 15450997Sbostic * 15550997Sbostic * PARTIAL_KEY This must be the first key/data pair on a page 15650997Sbostic * and implies that page contains only a partial key. 15750997Sbostic * That is, the key is too big to fit on a single page 15850997Sbostic * so it starts on this page and continues on the next. 15950997Sbostic * The format of the page is: 16050997Sbostic * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE 16150997Sbostic * 16250997Sbostic * KEY_OFF -- offset of the beginning of the key 16350997Sbostic * PARTIAL_KEY -- 1 16450997Sbostic * OVFL_PAGENO - page number of the next overflow page 16550997Sbostic * OVFLPAGE -- 0 16650997Sbostic * 16750997Sbostic * FULL_KEY This must be the first key/data pair on the page. It 16850997Sbostic * is used in two cases. 16950997Sbostic * 17050997Sbostic * Case 1: 17150997Sbostic * There is a complete key on the page but no data 17250997Sbostic * (because it wouldn't fit). The next page contains 17350997Sbostic * the data. 17450997Sbostic * 17550997Sbostic * Page format it: 17650997Sbostic * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 17750997Sbostic * 17850997Sbostic * KEY_OFF -- offset of the beginning of the key 17950997Sbostic * FULL_KEY -- 2 18050997Sbostic * OVFL_PAGENO - page number of the next overflow page 18150997Sbostic * OVFLPAGE -- 0 18250997Sbostic * 18350997Sbostic * Case 2: 18450997Sbostic * This page contains no key, but part of a large 18550997Sbostic * data field, which is continued on the next page. 18650997Sbostic * 18750997Sbostic * Page format it: 18850997Sbostic * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 18950997Sbostic * 19050997Sbostic * KEY_OFF -- offset of the beginning of the data on 19150997Sbostic * this page 19250997Sbostic * FULL_KEY -- 2 19350997Sbostic * OVFL_PAGENO - page number of the next overflow page 19450997Sbostic * OVFLPAGE -- 0 19550997Sbostic * 19650997Sbostic * FULL_KEY_DATA 19750997Sbostic * This must be the first key/data pair on the page. 19850997Sbostic * There are two cases: 19950997Sbostic * 20050997Sbostic * Case 1: 20150997Sbostic * This page contains a key and the beginning of the 20250997Sbostic * data field, but the data field is continued on the 20350997Sbostic * next page. 20450997Sbostic * 20550997Sbostic * Page format is: 20650997Sbostic * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF 20750997Sbostic * 20850997Sbostic * KEY_OFF -- offset of the beginning of the key 20950997Sbostic * FULL_KEY_DATA -- 3 21050997Sbostic * OVFL_PAGENO - page number of the next overflow page 21150997Sbostic * DATA_OFF -- offset of the beginning of the data 21250997Sbostic * 21350997Sbostic * Case 2: 21450997Sbostic * This page contains the last page of a big data pair. 21550997Sbostic * There is no key, only the tail end of the data 21650997Sbostic * on this page. 21750997Sbostic * 21850997Sbostic * Page format is: 21950997Sbostic * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE> 22050997Sbostic * 22150997Sbostic * DATA_OFF -- offset of the beginning of the data on 22250997Sbostic * this page 22350997Sbostic * FULL_KEY_DATA -- 3 22450997Sbostic * OVFL_PAGENO - page number of the next overflow page 22550997Sbostic * OVFLPAGE -- 0 22650997Sbostic * 22750997Sbostic * OVFL_PAGENO and OVFLPAGE are optional (they are 22850997Sbostic * not present if there is no next page). 22950997Sbostic */ 23046367Sbostic 23146367Sbostic #define OVFLPAGE 0 23246367Sbostic #define PARTIAL_KEY 1 23346367Sbostic #define FULL_KEY 2 23446367Sbostic #define FULL_KEY_DATA 3 23546367Sbostic #define REAL_KEY 4 23650997Sbostic 23746367Sbostic /* Short hands for accessing structure */ 23850997Sbostic #define BSIZE hdr.bsize 23950997Sbostic #define BSHIFT hdr.bshift 24050997Sbostic #define DSIZE hdr.dsize 24150997Sbostic #define SGSIZE hdr.ssize 24250997Sbostic #define SSHIFT hdr.sshift 24350997Sbostic #define LORDER hdr.lorder 24451061Sbostic #define OVFL_POINT hdr.ovfl_point 24551061Sbostic #define LAST_FREED hdr.last_freed 24646367Sbostic #define MAX_BUCKET hdr.max_bucket 24746367Sbostic #define FFACTOR hdr.ffactor 24846367Sbostic #define HIGH_MASK hdr.high_mask 24946367Sbostic #define LOW_MASK hdr.low_mask 25046367Sbostic #define NKEYS hdr.nkeys 25146367Sbostic #define HDRPAGES hdr.hdrpages 25246367Sbostic #define SPARES hdr.spares 25346367Sbostic #define BITMAPS hdr.bitmaps 25446367Sbostic #define VERSION hdr.version 25546367Sbostic #define MAGIC hdr.magic 25646367Sbostic #define NEXT_FREE hdr.next_free 25746367Sbostic #define H_CHARKEY hdr.h_charkey 258