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*46458Sbostic * @(#)hash.h 5.2 (Berkeley) 02/19/91 1146367Sbostic */ 1246367Sbostic 1346367Sbostic /* Operations */ 1446367Sbostic typedef enum { HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, 1546367Sbostic HASH_FIRST, HASH_NEXT } ACTION; 1646367Sbostic 1746367Sbostic /* Buffer Management structures */ 1846367Sbostic typedef struct _bufhead BUFHEAD; 1946367Sbostic 2046367Sbostic struct _bufhead { 2146367Sbostic BUFHEAD *prev; /* LRU links */ 2246367Sbostic BUFHEAD *next; /* LRU links */ 2346367Sbostic BUFHEAD *ovfl; /* Overflow page buffer header */ 2446367Sbostic int addr; /* Address of this page */ 2546367Sbostic char *page; /* Actual page data */ 26*46458Sbostic char flags; 2746367Sbostic #define BUF_MOD 0x0001 2846367Sbostic #define BUF_DISK 0x0002 2946367Sbostic #define BUF_BUCKET 0x0004 30*46458Sbostic #define BUF_PIN 0x0008 31*46458Sbostic }; 3246367Sbostic 33*46458Sbostic 3446367Sbostic #define IS_BUCKET(X) (X & BUF_BUCKET) 3546367Sbostic 3646367Sbostic typedef BUFHEAD **SEGMENT; 3746367Sbostic 3846367Sbostic /* Hash Table Information */ 3946367Sbostic typedef struct hashhdr { /* Disk resident portion */ 4046367Sbostic int magic; /* Magic NO for hash tables */ 4146367Sbostic int version; /* Version ID */ 4246367Sbostic long lorder; /* Byte Order */ 4346367Sbostic int bsize; /* Bucket/Page Size */ 4446367Sbostic int bshift; /* Bucket shift */ 4546367Sbostic int dsize; /* Directory Size */ 4646367Sbostic int ssize; /* Segment Size */ 4746367Sbostic int sshift; /* Segment shift */ 4846367Sbostic int max_bucket; /* ID of Maximum bucket in use */ 4946367Sbostic int high_mask; /* Mask to modulo into entire table */ 5046367Sbostic int low_mask; /* Mask to modulo into lower half of table */ 5146367Sbostic int ffactor; /* Fill factor */ 5246367Sbostic int nkeys; /* Number of keys in hash table */ 5346367Sbostic int hdrpages; /* Size of table header */ 5446367Sbostic int h_charkey; /* value of hash(CHARKEY) */ 5546367Sbostic # define NCACHED 32 /* number of bit maps and spare points*/ 5646367Sbostic int spares[NCACHED]; /* spare pages for overflow */ 5746367Sbostic u_short bitmaps[NCACHED]; /* address of overflow page bitmaps */ 5846367Sbostic } HASHHDR; 5946367Sbostic 6046367Sbostic typedef struct htab { /* Memory resident data structure */ 6146367Sbostic HASHHDR hdr; /* Header */ 6246367Sbostic int nsegs; /* Number of allocated segments */ 6346367Sbostic int exsegs; /* Number of extra allocated segments */ 6446367Sbostic int (*hash)(); /* Hash Function */ 6546367Sbostic int flags; /* Flag values */ 6646367Sbostic int fp; /* File pointer */ 6746367Sbostic char *tmp_buf; /* Temporary Buffer for BIG data */ 6846367Sbostic char *tmp_key; /* Temporary Buffer for BIG keys */ 6946367Sbostic BUFHEAD *cpage; /* Current page */ 7046367Sbostic int cbucket; /* Current bucket */ 7146367Sbostic int cndx; /* Index of next item on cpage */ 7246367Sbostic int errno; /* Error Number -- for DBM compatability */ 7346367Sbostic int new_file; /* Indicates whether fd is backing store or no */ 7446367Sbostic int save_file; /* Indicates whether we need to flush file at exit */ 7546367Sbostic u_long *mapp[NCACHED]; /* Pointers to page maps */ 7646367Sbostic int nbufs; /* Number of buffers left to allocate */ 7746367Sbostic BUFHEAD bufhead; /* Header of buffer lru list */ 7846367Sbostic SEGMENT *dir; /* Hash Bucket directory */ 7946367Sbostic } HTAB; 8046367Sbostic 8146367Sbostic 8246367Sbostic /* 8346367Sbostic * Constants 8446367Sbostic */ 8546367Sbostic #define MAX_BSIZE 65536 /* 2^16 */ 8646367Sbostic #define MIN_BUFFERS 6 8746367Sbostic #define MINHDRSIZE 512 8846367Sbostic #define DEF_BUFSIZE 65536 /* 64 K */ 8946367Sbostic #define DEF_BUCKET_SIZE 256 9046367Sbostic #define DEF_BUCKET_SHIFT 8 /* log2(BUCKET) */ 9146367Sbostic #define DEF_SEGSIZE 256 9246367Sbostic #define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ 9346367Sbostic #define DEF_DIRSIZE 256 9446367Sbostic #define DEF_FFACTOR 5 9546367Sbostic #define SPLTMAX 8 9646367Sbostic #define CHARKEY "%$sniglet^&" 9746367Sbostic #define NUMKEY 1038583 9846367Sbostic #define VERSION_NO 3 9946367Sbostic #define BYTE_SHIFT 3 10046367Sbostic #define INT_TO_BYTE 2 10146367Sbostic #define INT_BYTE_SHIFT 5 10246367Sbostic #define ALL_SET ((unsigned)0xFFFFFFFF) 10346367Sbostic #define ALL_CLEAR 0 10446367Sbostic 10546367Sbostic 10646367Sbostic #define PTROF(X) ((BUFHEAD *)((unsigned)(X)&~0x3)) 10746367Sbostic #define ISMOD(X) ((unsigned)(X)&0x1) 10846367Sbostic #define DOMOD(X) (X = (char *)( (unsigned)X | 0x1)) 10946367Sbostic #define ISDISK(X) ((unsigned)(X)&0x2) 11046367Sbostic #define DODISK(X) (X = (char *)( (unsigned)X | 0x2)) 11146367Sbostic 11246367Sbostic #define BITS_PER_MAP 32 11346367Sbostic 11446367Sbostic /* Given the address of the beginning of a big map, clear/set the nth bit */ 11546367Sbostic 11646367Sbostic #define CLRBIT(A,N) ((A)[N/BITS_PER_MAP] &= ~(1<<(N%BITS_PER_MAP))) 11746367Sbostic #define SETBIT(A,N) ((A)[N/BITS_PER_MAP] |= (1<<(N%BITS_PER_MAP))) 11846367Sbostic #define ISSET(A,N) ((A)[N/BITS_PER_MAP] & (1<<(N%BITS_PER_MAP))) 11946367Sbostic 12046367Sbostic /* Overflow management */ 12146367Sbostic /* 12246367Sbostic Overflow page numbers are allocated per split point. 12346367Sbostic At each doubling of the table, we can allocate extra 12446367Sbostic pages. So, an overflow page number has the top 5 bits 12546367Sbostic indicate which split point and the lower 11 bits indicate 12646367Sbostic which page at that split point is indicated (pages within 12746367Sbostic split points are numberered starting with 1). 12846367Sbostic 12946367Sbostic 13046367Sbostic */ 13146367Sbostic 13246367Sbostic #define SPLITSHIFT 11 13346367Sbostic #define SPLITMASK 0x7FF 13446367Sbostic #define SPLITNUM(N) (((unsigned)N) >> SPLITSHIFT) 13546367Sbostic #define OPAGENUM(N) (N & SPLITMASK) 13646367Sbostic #define OADDR_OF(S,O) ((S << SPLITSHIFT) + O) 13746367Sbostic 13846367Sbostic #define BUCKET_TO_PAGE(B) \ 13946367Sbostic B + hashp->HDRPAGES + (B ? hashp->SPARES[__log2(B+1)-1] : 0) 14046367Sbostic #define OADDR_TO_PAGE(B) \ 14146367Sbostic BUCKET_TO_PAGE ( (1 << SPLITNUM(B)) -1 ) + OPAGENUM(B); 14246367Sbostic 14346367Sbostic /* 14446367Sbostic page.h contains a detailed description of the page format. 14546367Sbostic 14646367Sbostic Normally, keys and data are accessed from offset tables in the 14746367Sbostic top of each page which point to the beginning of the key and 14846367Sbostic data. There are four flag values which may be stored in these 14946367Sbostic offset tables which indicate the following: 15046367Sbostic 15146367Sbostic OVFLPAGE Rather than a key data pair, this pair contains 15246367Sbostic the address of an overflow page. The format of 15346367Sbostic the pair is: 15446367Sbostic OVERFLOW_PAGE_NUMBER OVFLPAGE 15546367Sbostic 15646367Sbostic PARTIAL_KEY This must be the first key/data pair on a page 15746367Sbostic and implies that page contains only a partial key. 15846367Sbostic That is, the key is too big to fit on a single page 15946367Sbostic so it starts on this page and continues on the next. 16046367Sbostic The format of the page is: 16146367Sbostic KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE 16246367Sbostic 16346367Sbostic KEY_OFF -- offset of the beginning of the key 16446367Sbostic PARTIAL_KEY -- 1 16546367Sbostic OVFL_PAGENO - page number of the next overflow page 16646367Sbostic OVFLPAGE -- 0 16746367Sbostic FULL_KEY This must be the first key/data pair on the page. It 16846367Sbostic is used in two cases. 16946367Sbostic 17046367Sbostic Case 1: 17146367Sbostic There is a complete key on the page but no data 17246367Sbostic (because it wouldn't fit). The next page contains 17346367Sbostic the data. 17446367Sbostic 17546367Sbostic Page format it: 17646367Sbostic KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 17746367Sbostic 17846367Sbostic KEY_OFF -- offset of the beginning of the key 17946367Sbostic FULL_KEY -- 2 18046367Sbostic OVFL_PAGENO - page number of the next overflow page 18146367Sbostic OVFLPAGE -- 0 18246367Sbostic 18346367Sbostic Case 2: 18446367Sbostic This page contains no key, but part of a large 18546367Sbostic data field, which is continued on the next page. 18646367Sbostic 18746367Sbostic Page format it: 18846367Sbostic DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 18946367Sbostic 19046367Sbostic KEY_OFF -- offset of the beginning of the data on 19146367Sbostic this page 19246367Sbostic FULL_KEY -- 2 19346367Sbostic OVFL_PAGENO - page number of the next overflow page 19446367Sbostic OVFLPAGE -- 0 19546367Sbostic 19646367Sbostic FULL_KEY_DATA This must be the first key/data pair on the page. 19746367Sbostic There are two cases: 19846367Sbostic 19946367Sbostic Case 1: 20046367Sbostic This page contains a key and the beginning of the 20146367Sbostic data field, but the data field is continued on the 20246367Sbostic next page. 20346367Sbostic 20446367Sbostic Page format is: 20546367Sbostic KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF 20646367Sbostic 20746367Sbostic KEY_OFF -- offset of the beginning of the key 20846367Sbostic FULL_KEY_DATA -- 3 20946367Sbostic OVFL_PAGENO - page number of the next overflow page 21046367Sbostic DATA_OFF -- offset of the beginning of the data 21146367Sbostic 21246367Sbostic Case 2: 21346367Sbostic This page contains the last page of a big data pair. 21446367Sbostic There is no key, only the tail end of the data 21546367Sbostic on this page. 21646367Sbostic 21746367Sbostic Page format is: 21846367Sbostic DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE> 21946367Sbostic 22046367Sbostic DATA_OFF -- offset of the beginning of the data on 22146367Sbostic this page 22246367Sbostic FULL_KEY_DATA -- 3 22346367Sbostic OVFL_PAGENO - page number of the next overflow page 22446367Sbostic OVFLPAGE -- 0 22546367Sbostic 22646367Sbostic OVFL_PAGENO and OVFLPAGE are optional (they are 22746367Sbostic not present if there is no next page). 22846367Sbostic */ 229*46458Sbostic 23046367Sbostic #define OVFLPAGE 0 23146367Sbostic #define PARTIAL_KEY 1 23246367Sbostic #define FULL_KEY 2 23346367Sbostic #define FULL_KEY_DATA 3 23446367Sbostic #define REAL_KEY 4 23546367Sbostic /* Short hands for accessing structure */ 23646367Sbostic #define BSIZE hdr.bsize 23746367Sbostic #define BSHIFT hdr.bshift 23846367Sbostic #define DSIZE hdr.dsize 23946367Sbostic #define SGSIZE hdr.ssize 24046367Sbostic #define SSHIFT hdr.sshift 24146367Sbostic #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