158f0484fSRodney W. Grimes /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 4f1e396bcSPaul Traina * Copyright (c) 1990, 1993, 1994 558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 658f0484fSRodney W. Grimes * 758f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 858f0484fSRodney W. Grimes * Margo Seltzer. 958f0484fSRodney W. Grimes * 1058f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1158f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1258f0484fSRodney W. Grimes * are met: 1358f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1558f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1658f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1758f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1958f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2058f0484fSRodney W. Grimes * without specific prior written permission. 2158f0484fSRodney W. Grimes * 2258f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2358f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2458f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2558f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2658f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2758f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2858f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2958f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3058f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3158f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3258f0484fSRodney W. Grimes * SUCH DAMAGE. 3358f0484fSRodney W. Grimes */ 3458f0484fSRodney W. Grimes 3558f0484fSRodney W. Grimes /* Operations */ 3658f0484fSRodney W. Grimes typedef enum { 3758f0484fSRodney W. Grimes HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT 3858f0484fSRodney W. Grimes } ACTION; 3958f0484fSRodney W. Grimes 4058f0484fSRodney W. Grimes /* Buffer Management structures */ 4158f0484fSRodney W. Grimes typedef struct _bufhead BUFHEAD; 4258f0484fSRodney W. Grimes 4358f0484fSRodney W. Grimes struct _bufhead { 4458f0484fSRodney W. Grimes BUFHEAD *prev; /* LRU links */ 4558f0484fSRodney W. Grimes BUFHEAD *next; /* LRU links */ 4658f0484fSRodney W. Grimes BUFHEAD *ovfl; /* Overflow page buffer header */ 47f1e396bcSPaul Traina u_int32_t addr; /* Address of this page */ 4858f0484fSRodney W. Grimes char *page; /* Actual page data */ 4958f0484fSRodney W. Grimes char flags; 5058f0484fSRodney W. Grimes #define BUF_MOD 0x0001 5158f0484fSRodney W. Grimes #define BUF_DISK 0x0002 5258f0484fSRodney W. Grimes #define BUF_BUCKET 0x0004 5358f0484fSRodney W. Grimes #define BUF_PIN 0x0008 5458f0484fSRodney W. Grimes }; 5558f0484fSRodney W. Grimes 5658f0484fSRodney W. Grimes #define IS_BUCKET(X) ((X) & BUF_BUCKET) 5758f0484fSRodney W. Grimes 5858f0484fSRodney W. Grimes typedef BUFHEAD **SEGMENT; 5958f0484fSRodney W. Grimes 6058f0484fSRodney W. Grimes /* Hash Table Information */ 6158f0484fSRodney W. Grimes typedef struct hashhdr { /* Disk resident portion */ 62eb3144b2SXin LI int32_t magic; /* Magic NO for hash tables */ 63eb3144b2SXin LI int32_t version; /* Version ID */ 64f1e396bcSPaul Traina u_int32_t lorder; /* Byte Order */ 65eb3144b2SXin LI int32_t bsize; /* Bucket/Page Size */ 66eb3144b2SXin LI int32_t bshift; /* Bucket shift */ 67eb3144b2SXin LI int32_t dsize; /* Directory Size */ 68eb3144b2SXin LI int32_t ssize; /* Segment Size */ 69eb3144b2SXin LI int32_t sshift; /* Segment shift */ 70eb3144b2SXin LI int32_t ovfl_point; /* Where overflow pages are being 71f1e396bcSPaul Traina * allocated */ 72eb3144b2SXin LI int32_t last_freed; /* Last overflow page freed */ 73f60486b3SXin LI u_int32_t max_bucket; /* ID of Maximum bucket in use */ 74f60486b3SXin LI u_int32_t high_mask; /* Mask to modulo into entire table */ 75f60486b3SXin LI u_int32_t low_mask; /* Mask to modulo into lower half of 76f1e396bcSPaul Traina * table */ 77f60486b3SXin LI u_int32_t ffactor; /* Fill factor */ 78eb3144b2SXin LI int32_t nkeys; /* Number of keys in hash table */ 79eb3144b2SXin LI int32_t hdrpages; /* Size of table header */ 80eb3144b2SXin LI int32_t h_charkey; /* value of hash(CHARKEY) */ 81f1e396bcSPaul Traina #define NCACHED 32 /* number of bit maps and spare 82f1e396bcSPaul Traina * points */ 83eb3144b2SXin LI int32_t spares[NCACHED];/* spare pages for overflow */ 84f1e396bcSPaul Traina u_int16_t bitmaps[NCACHED]; /* address of overflow page 85f1e396bcSPaul Traina * bitmaps */ 8658f0484fSRodney W. Grimes } HASHHDR; 8758f0484fSRodney W. Grimes 8858f0484fSRodney W. Grimes typedef struct htab { /* Memory resident data structure */ 8958f0484fSRodney W. Grimes HASHHDR hdr; /* Header */ 9058f0484fSRodney W. Grimes int nsegs; /* Number of allocated segments */ 91f1e396bcSPaul Traina int exsegs; /* Number of extra allocated 92f1e396bcSPaul Traina * segments */ 9358f0484fSRodney W. Grimes u_int32_t /* Hash function */ 94c05ac53bSDavid E. O'Brien (*hash)(const void *, size_t); 9558f0484fSRodney W. Grimes int flags; /* Flag values */ 9658f0484fSRodney W. Grimes int fp; /* File pointer */ 9758f0484fSRodney W. Grimes char *tmp_buf; /* Temporary Buffer for BIG data */ 9858f0484fSRodney W. Grimes char *tmp_key; /* Temporary Buffer for BIG keys */ 9958f0484fSRodney W. Grimes BUFHEAD *cpage; /* Current page */ 10058f0484fSRodney W. Grimes int cbucket; /* Current bucket */ 10158f0484fSRodney W. Grimes int cndx; /* Index of next item on cpage */ 102f1e396bcSPaul Traina int error; /* Error Number -- for DBM 103a3573c66SJeroen Ruigrok van der Werven * compatibility */ 104f1e396bcSPaul Traina int new_file; /* Indicates if fd is backing store 105f1e396bcSPaul Traina * or no */ 106f1e396bcSPaul Traina int save_file; /* Indicates whether we need to flush 107f1e396bcSPaul Traina * file at 10858f0484fSRodney W. Grimes * exit */ 109f1e396bcSPaul Traina u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ 11058f0484fSRodney W. Grimes int nmaps; /* Initial number of bitmaps */ 111f1e396bcSPaul Traina int nbufs; /* Number of buffers left to 112f1e396bcSPaul Traina * allocate */ 11358f0484fSRodney W. Grimes BUFHEAD bufhead; /* Header of buffer lru list */ 11458f0484fSRodney W. Grimes SEGMENT *dir; /* Hash Bucket directory */ 11558f0484fSRodney W. Grimes } HTAB; 11658f0484fSRodney W. Grimes 11758f0484fSRodney W. Grimes /* 11858f0484fSRodney W. Grimes * Constants 11958f0484fSRodney W. Grimes */ 120f3c733e8SAndriy Gapon #define MAX_BSIZE 32768 /* 2^15 but should be 65536 */ 12158f0484fSRodney W. Grimes #define MIN_BUFFERS 6 12258f0484fSRodney W. Grimes #define MINHDRSIZE 512 12358f0484fSRodney W. Grimes #define DEF_BUFSIZE 65536 /* 64 K */ 12458f0484fSRodney W. Grimes #define DEF_BUCKET_SIZE 4096 12558f0484fSRodney W. Grimes #define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ 12658f0484fSRodney W. Grimes #define DEF_SEGSIZE 256 12758f0484fSRodney W. Grimes #define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ 12858f0484fSRodney W. Grimes #define DEF_DIRSIZE 256 12958f0484fSRodney W. Grimes #define DEF_FFACTOR 65536 13058f0484fSRodney W. Grimes #define MIN_FFACTOR 4 13158f0484fSRodney W. Grimes #define SPLTMAX 8 13258f0484fSRodney W. Grimes #define CHARKEY "%$sniglet^&" 13358f0484fSRodney W. Grimes #define NUMKEY 1038583 13458f0484fSRodney W. Grimes #define BYTE_SHIFT 3 13558f0484fSRodney W. Grimes #define INT_TO_BYTE 2 13658f0484fSRodney W. Grimes #define INT_BYTE_SHIFT 5 137f1e396bcSPaul Traina #define ALL_SET ((u_int32_t)0xFFFFFFFF) 13858f0484fSRodney W. Grimes #define ALL_CLEAR 0 13958f0484fSRodney W. Grimes 14045308eecSBrooks Davis #define PTROF(X) ((BUFHEAD *)((intptr_t)(X)&~0x3)) 14145308eecSBrooks Davis #define ISMOD(X) ((u_int32_t)(intptr_t)(X)&0x1) 14245308eecSBrooks Davis #define DOMOD(X) ((X) = (char *)((intptr_t)(X)|0x1)) 14345308eecSBrooks Davis #define ISDISK(X) ((u_int32_t)(intptr_t)(X)&0x2) 14445308eecSBrooks Davis #define DODISK(X) ((X) = (char *)((intptr_t)(X)|0x2)) 14558f0484fSRodney W. Grimes 14658f0484fSRodney W. Grimes #define BITS_PER_MAP 32 14758f0484fSRodney W. Grimes 14858f0484fSRodney W. Grimes /* Given the address of the beginning of a big map, clear/set the nth bit */ 14958f0484fSRodney W. Grimes #define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) 15058f0484fSRodney W. Grimes #define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) 15158f0484fSRodney W. Grimes #define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) 15258f0484fSRodney W. Grimes 15358f0484fSRodney W. Grimes /* Overflow management */ 15458f0484fSRodney W. Grimes /* 15558f0484fSRodney W. Grimes * Overflow page numbers are allocated per split point. At each doubling of 15658f0484fSRodney W. Grimes * the table, we can allocate extra pages. So, an overflow page number has 15758f0484fSRodney W. Grimes * the top 5 bits indicate which split point and the lower 11 bits indicate 15858f0484fSRodney W. Grimes * which page at that split point is indicated (pages within split points are 15958f0484fSRodney W. Grimes * numberered starting with 1). 16058f0484fSRodney W. Grimes */ 16158f0484fSRodney W. Grimes 16258f0484fSRodney W. Grimes #define SPLITSHIFT 11 16358f0484fSRodney W. Grimes #define SPLITMASK 0x7FF 164f1e396bcSPaul Traina #define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT) 16558f0484fSRodney W. Grimes #define OPAGENUM(N) ((N) & SPLITMASK) 166f1e396bcSPaul Traina #define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) 16758f0484fSRodney W. Grimes 16858f0484fSRodney W. Grimes #define BUCKET_TO_PAGE(B) \ 16958f0484fSRodney W. Grimes (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0) 17058f0484fSRodney W. Grimes #define OADDR_TO_PAGE(B) \ 17158f0484fSRodney W. Grimes BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); 17258f0484fSRodney W. Grimes 17358f0484fSRodney W. Grimes /* 17458f0484fSRodney W. Grimes * page.h contains a detailed description of the page format. 17558f0484fSRodney W. Grimes * 17658f0484fSRodney W. Grimes * Normally, keys and data are accessed from offset tables in the top of 17758f0484fSRodney W. Grimes * each page which point to the beginning of the key and data. There are 17858f0484fSRodney W. Grimes * four flag values which may be stored in these offset tables which indicate 17958f0484fSRodney W. Grimes * the following: 18058f0484fSRodney W. Grimes * 18158f0484fSRodney W. Grimes * 18258f0484fSRodney W. Grimes * OVFLPAGE Rather than a key data pair, this pair contains 18358f0484fSRodney W. Grimes * the address of an overflow page. The format of 18458f0484fSRodney W. Grimes * the pair is: 18558f0484fSRodney W. Grimes * OVERFLOW_PAGE_NUMBER OVFLPAGE 18658f0484fSRodney W. Grimes * 18758f0484fSRodney W. Grimes * PARTIAL_KEY This must be the first key/data pair on a page 18858f0484fSRodney W. Grimes * and implies that page contains only a partial key. 18958f0484fSRodney W. Grimes * That is, the key is too big to fit on a single page 19058f0484fSRodney W. Grimes * so it starts on this page and continues on the next. 19158f0484fSRodney W. Grimes * The format of the page is: 19258f0484fSRodney W. Grimes * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE 19358f0484fSRodney W. Grimes * 19458f0484fSRodney W. Grimes * KEY_OFF -- offset of the beginning of the key 19558f0484fSRodney W. Grimes * PARTIAL_KEY -- 1 19658f0484fSRodney W. Grimes * OVFL_PAGENO - page number of the next overflow page 19758f0484fSRodney W. Grimes * OVFLPAGE -- 0 19858f0484fSRodney W. Grimes * 19958f0484fSRodney W. Grimes * FULL_KEY This must be the first key/data pair on the page. It 20058f0484fSRodney W. Grimes * is used in two cases. 20158f0484fSRodney W. Grimes * 20258f0484fSRodney W. Grimes * Case 1: 20358f0484fSRodney W. Grimes * There is a complete key on the page but no data 20458f0484fSRodney W. Grimes * (because it wouldn't fit). The next page contains 20558f0484fSRodney W. Grimes * the data. 20658f0484fSRodney W. Grimes * 20758f0484fSRodney W. Grimes * Page format it: 20858f0484fSRodney W. Grimes * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 20958f0484fSRodney W. Grimes * 21058f0484fSRodney W. Grimes * KEY_OFF -- offset of the beginning of the key 21158f0484fSRodney W. Grimes * FULL_KEY -- 2 21258f0484fSRodney W. Grimes * OVFL_PAGENO - page number of the next overflow page 21358f0484fSRodney W. Grimes * OVFLPAGE -- 0 21458f0484fSRodney W. Grimes * 21558f0484fSRodney W. Grimes * Case 2: 21658f0484fSRodney W. Grimes * This page contains no key, but part of a large 21758f0484fSRodney W. Grimes * data field, which is continued on the next page. 21858f0484fSRodney W. Grimes * 21958f0484fSRodney W. Grimes * Page format it: 22058f0484fSRodney W. Grimes * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE 22158f0484fSRodney W. Grimes * 22258f0484fSRodney W. Grimes * KEY_OFF -- offset of the beginning of the data on 22358f0484fSRodney W. Grimes * this page 22458f0484fSRodney W. Grimes * FULL_KEY -- 2 22558f0484fSRodney W. Grimes * OVFL_PAGENO - page number of the next overflow page 22658f0484fSRodney W. Grimes * OVFLPAGE -- 0 22758f0484fSRodney W. Grimes * 22858f0484fSRodney W. Grimes * FULL_KEY_DATA 22958f0484fSRodney W. Grimes * This must be the first key/data pair on the page. 23058f0484fSRodney W. Grimes * There are two cases: 23158f0484fSRodney W. Grimes * 23258f0484fSRodney W. Grimes * Case 1: 23358f0484fSRodney W. Grimes * This page contains a key and the beginning of the 23458f0484fSRodney W. Grimes * data field, but the data field is continued on the 23558f0484fSRodney W. Grimes * next page. 23658f0484fSRodney W. Grimes * 23758f0484fSRodney W. Grimes * Page format is: 23858f0484fSRodney W. Grimes * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF 23958f0484fSRodney W. Grimes * 24058f0484fSRodney W. Grimes * KEY_OFF -- offset of the beginning of the key 24158f0484fSRodney W. Grimes * FULL_KEY_DATA -- 3 24258f0484fSRodney W. Grimes * OVFL_PAGENO - page number of the next overflow page 24358f0484fSRodney W. Grimes * DATA_OFF -- offset of the beginning of the data 24458f0484fSRodney W. Grimes * 24558f0484fSRodney W. Grimes * Case 2: 24658f0484fSRodney W. Grimes * This page contains the last page of a big data pair. 24758f0484fSRodney W. Grimes * There is no key, only the tail end of the data 24858f0484fSRodney W. Grimes * on this page. 24958f0484fSRodney W. Grimes * 25058f0484fSRodney W. Grimes * Page format is: 25158f0484fSRodney W. Grimes * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE> 25258f0484fSRodney W. Grimes * 25358f0484fSRodney W. Grimes * DATA_OFF -- offset of the beginning of the data on 25458f0484fSRodney W. Grimes * this page 25558f0484fSRodney W. Grimes * FULL_KEY_DATA -- 3 25658f0484fSRodney W. Grimes * OVFL_PAGENO - page number of the next overflow page 25758f0484fSRodney W. Grimes * OVFLPAGE -- 0 25858f0484fSRodney W. Grimes * 25958f0484fSRodney W. Grimes * OVFL_PAGENO and OVFLPAGE are optional (they are 26058f0484fSRodney W. Grimes * not present if there is no next page). 26158f0484fSRodney W. Grimes */ 26258f0484fSRodney W. Grimes 26358f0484fSRodney W. Grimes #define OVFLPAGE 0 26458f0484fSRodney W. Grimes #define PARTIAL_KEY 1 26558f0484fSRodney W. Grimes #define FULL_KEY 2 26658f0484fSRodney W. Grimes #define FULL_KEY_DATA 3 26758f0484fSRodney W. Grimes #define REAL_KEY 4 26858f0484fSRodney W. Grimes 26958f0484fSRodney W. Grimes /* Short hands for accessing structure */ 27058f0484fSRodney W. Grimes #define BSIZE hdr.bsize 27158f0484fSRodney W. Grimes #define BSHIFT hdr.bshift 27258f0484fSRodney W. Grimes #define DSIZE hdr.dsize 27358f0484fSRodney W. Grimes #define SGSIZE hdr.ssize 27458f0484fSRodney W. Grimes #define SSHIFT hdr.sshift 27558f0484fSRodney W. Grimes #define LORDER hdr.lorder 27658f0484fSRodney W. Grimes #define OVFL_POINT hdr.ovfl_point 27758f0484fSRodney W. Grimes #define LAST_FREED hdr.last_freed 27858f0484fSRodney W. Grimes #define MAX_BUCKET hdr.max_bucket 27958f0484fSRodney W. Grimes #define FFACTOR hdr.ffactor 28058f0484fSRodney W. Grimes #define HIGH_MASK hdr.high_mask 28158f0484fSRodney W. Grimes #define LOW_MASK hdr.low_mask 28258f0484fSRodney W. Grimes #define NKEYS hdr.nkeys 28358f0484fSRodney W. Grimes #define HDRPAGES hdr.hdrpages 28458f0484fSRodney W. Grimes #define SPARES hdr.spares 28558f0484fSRodney W. Grimes #define BITMAPS hdr.bitmaps 28658f0484fSRodney W. Grimes #define VERSION hdr.version 28758f0484fSRodney W. Grimes #define MAGIC hdr.magic 28858f0484fSRodney W. Grimes #define NEXT_FREE hdr.next_free 28958f0484fSRodney W. Grimes #define H_CHARKEY hdr.h_charkey 290