xref: /dragonfly/lib/libc/db/hash/hash.h (revision 08acb08c0a6e4dcab346cdf0c24c7567d8a66858)
1 /*-
2  * Copyright (c) 1990, 1993, 1994
3  *        The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Margo Seltzer.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *        @(#)hash.h          8.3 (Berkeley) 5/31/94
33  * $FreeBSD: head/lib/libc/db/hash/hash.h 206178 2010-04-05 10:12:21Z avg $
34  */
35 
36 /* Operations */
37 typedef enum {
38           HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
39 } ACTION;
40 
41 /* Buffer Management structures */
42 typedef struct _bufhead BUFHEAD;
43 
44 struct _bufhead {
45           BUFHEAD             *prev;              /* LRU links */
46           BUFHEAD             *next;              /* LRU links */
47           BUFHEAD             *ovfl;              /* Overflow page buffer header */
48           uint32_t   addr;              /* Address of this page */
49           char                *page;              /* Actual page data */
50           char                flags;
51 #define   BUF_MOD             0x0001
52 #define BUF_DISK    0x0002
53 #define   BUF_BUCKET          0x0004
54 #define   BUF_PIN             0x0008
55 };
56 
57 #define IS_BUCKET(X)          ((X) & BUF_BUCKET)
58 
59 typedef BUFHEAD **SEGMENT;
60 
61 /* Hash Table Information */
62 typedef struct hashhdr {                /* Disk resident portion */
63           int32_t             magic;              /* Magic NO for hash tables */
64           int32_t             version;  /* Version ID */
65           uint32_t  lorder;             /* Byte Order */
66           int32_t             bsize;              /* Bucket/Page Size */
67           int32_t             bshift;             /* Bucket shift */
68           int32_t             dsize;              /* Directory Size */
69           int32_t             ssize;              /* Segment Size */
70           int32_t             sshift;             /* Segment shift */
71           int32_t             ovfl_point;         /* Where overflow pages are being
72                                                    * allocated */
73           int32_t             last_freed;         /* Last overflow page freed */
74           uint32_t  max_bucket;         /* ID of Maximum bucket in use */
75           uint32_t  high_mask;          /* Mask to modulo into entire table */
76           uint32_t  low_mask; /* Mask to modulo into lower half of
77                                                    * table */
78           uint32_t  ffactor;  /* Fill factor */
79           int32_t             nkeys;              /* Number of keys in hash table */
80           int32_t             hdrpages; /* Size of table header */
81           int32_t             h_charkey;          /* value of hash(CHARKEY) */
82 #define NCACHED     32                            /* number of bit maps and spare
83                                                    * points */
84           int32_t             spares[NCACHED];/* spare pages for overflow */
85           uint16_t  bitmaps[NCACHED];   /* address of overflow page
86                                                              * bitmaps */
87 } HASHHDR;
88 
89 typedef struct htab  {                  /* Memory resident data structure */
90           HASHHDR   hdr;                /* Header */
91           int                 nsegs;              /* Number of allocated segments */
92           int                 exsegs;             /* Number of extra allocated
93                                                    * segments */
94           uint32_t                      /* Hash function */
95               (*hash)(const void *, size_t);
96           int                 flags;              /* Flag values */
97           int                 fp;                 /* File pointer */
98           char                *tmp_buf; /* Temporary Buffer for BIG data */
99           char                *tmp_key; /* Temporary Buffer for BIG keys */
100           BUFHEAD   *cpage;             /* Current page */
101           int                 cbucket;  /* Current bucket */
102           int                 cndx;               /* Index of next item on cpage */
103           int                 error;              /* Error Number -- for DBM
104                                                    * compatibility */
105           int                 new_file; /* Indicates if fd is backing store
106                                                    * or no */
107           int                 save_file;          /* Indicates whether we need to flush
108                                                    * file at
109                                                    * exit */
110           uint32_t  *mapp[NCACHED];     /* Pointers to page maps */
111           int                 nmaps;              /* Initial number of bitmaps */
112           int                 nbufs;              /* Number of buffers left to
113                                                    * allocate */
114           BUFHEAD   bufhead;  /* Header of buffer lru list */
115           SEGMENT   *dir;               /* Hash Bucket directory */
116 } HTAB;
117 
118 /*
119  * Constants
120  */
121 #define   NOM_BSIZE           16384               /* a reasonable blksize */
122 #define   MAX_BSIZE           32768               /* 2^15 but should be 65536 */
123 #define MIN_BUFFERS           6
124 #define MINHDRSIZE            512
125 #define DEF_BUFSIZE           65536               /* 64 K */
126 #define DEF_BUCKET_SIZE                 4096
127 #define DEF_BUCKET_SHIFT      12                  /* log2(BUCKET) */
128 #define DEF_SEGSIZE           256
129 #define DEF_SEGSIZE_SHIFT     8                   /* log2(SEGSIZE)     */
130 #define DEF_DIRSIZE           256
131 #define DEF_FFACTOR           65536
132 #define MIN_FFACTOR           4
133 #define SPLTMAX                         8
134 #define CHARKEY                         "%$sniglet^&"
135 #define NUMKEY                          1038583
136 #define BYTE_SHIFT            3
137 #define INT_TO_BYTE           2
138 #define INT_BYTE_SHIFT                  5
139 #define ALL_SET                         ((uint32_t)0xFFFFFFFF)
140 #define ALL_CLEAR             0
141 
142 #define PTROF(X)    ((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
143 #define ISMOD(X)    ((uint32_t)(ptrdiff_t)(X)&0x1)
144 #define DOMOD(X)    ((X) = (char *)((ptrdiff_t)(X)|0x1))
145 #define ISDISK(X)   ((uint32_t)(ptrdiff_t)(X)&0x2)
146 #define DODISK(X)   ((X) = (char *)((ptrdiff_t)(X)|0x2))
147 
148 #define BITS_PER_MAP          32
149 
150 /* Given the address of the beginning of a big map, clear/set the nth bit */
151 #define CLRBIT(A, N)          ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
152 #define SETBIT(A, N)          ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
153 #define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
154 
155 /* Overflow management */
156 /*
157  * Overflow page numbers are allocated per split point.  At each doubling of
158  * the table, we can allocate extra pages.  So, an overflow page number has
159  * the top 5 bits indicate which split point and the lower 11 bits indicate
160  * which page at that split point is indicated (pages within split points are
161  * numberered starting with 1).
162  */
163 
164 #define SPLITSHIFT  11
165 #define SPLITMASK   0x7FF
166 #define SPLITNUM(N) (((uint32_t)(N)) >> SPLITSHIFT)
167 #define OPAGENUM(N) ((N) & SPLITMASK)
168 #define   OADDR_OF(S,O)       ((uint32_t)((uint32_t)(S) << SPLITSHIFT) + (O))
169 
170 #define BUCKET_TO_PAGE(B) \
171           (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
172 #define OADDR_TO_PAGE(B)      \
173           BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
174 
175 /*
176  * page.h contains a detailed description of the page format.
177  *
178  * Normally, keys and data are accessed from offset tables in the top of
179  * each page which point to the beginning of the key and data.  There are
180  * four flag values which may be stored in these offset tables which indicate
181  * the following:
182  *
183  *
184  * OVFLPAGE         Rather than a key data pair, this pair contains
185  *                  the address of an overflow page.  The format of
186  *                  the pair is:
187  *                      OVERFLOW_PAGE_NUMBER OVFLPAGE
188  *
189  * PARTIAL_KEY      This must be the first key/data pair on a page
190  *                  and implies that page contains only a partial key.
191  *                  That is, the key is too big to fit on a single page
192  *                  so it starts on this page and continues on the next.
193  *                  The format of the page is:
194  *                      KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
195  *
196  *                      KEY_OFF -- offset of the beginning of the key
197  *                      PARTIAL_KEY -- 1
198  *                      OVFL_PAGENO - page number of the next overflow page
199  *                      OVFLPAGE -- 0
200  *
201  * FULL_KEY         This must be the first key/data pair on the page.  It
202  *                  is used in two cases.
203  *
204  *                  Case 1:
205  *                      There is a complete key on the page but no data
206  *                      (because it wouldn't fit).  The next page contains
207  *                      the data.
208  *
209  *                      Page format it:
210  *                      KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
211  *
212  *                      KEY_OFF -- offset of the beginning of the key
213  *                      FULL_KEY -- 2
214  *                      OVFL_PAGENO - page number of the next overflow page
215  *                      OVFLPAGE -- 0
216  *
217  *                  Case 2:
218  *                      This page contains no key, but part of a large
219  *                      data field, which is continued on the next page.
220  *
221  *                      Page format it:
222  *                      DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
223  *
224  *                      KEY_OFF -- offset of the beginning of the data on
225  *                                      this page
226  *                      FULL_KEY -- 2
227  *                      OVFL_PAGENO - page number of the next overflow page
228  *                      OVFLPAGE -- 0
229  *
230  * FULL_KEY_DATA
231  *                  This must be the first key/data pair on the page.
232  *                  There are two cases:
233  *
234  *                  Case 1:
235  *                      This page contains a key and the beginning of the
236  *                      data field, but the data field is continued on the
237  *                      next page.
238  *
239  *                      Page format is:
240  *                      KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
241  *
242  *                      KEY_OFF -- offset of the beginning of the key
243  *                      FULL_KEY_DATA -- 3
244  *                      OVFL_PAGENO - page number of the next overflow page
245  *                      DATA_OFF -- offset of the beginning of the data
246  *
247  *                  Case 2:
248  *                      This page contains the last page of a big data pair.
249  *                      There is no key, only the  tail end of the data
250  *                      on this page.
251  *
252  *                      Page format is:
253  *                      DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
254  *
255  *                      DATA_OFF -- offset of the beginning of the data on
256  *                                      this page
257  *                      FULL_KEY_DATA -- 3
258  *                      OVFL_PAGENO - page number of the next overflow page
259  *                      OVFLPAGE -- 0
260  *
261  *                      OVFL_PAGENO and OVFLPAGE are optional (they are
262  *                      not present if there is no next page).
263  */
264 
265 #define OVFLPAGE    0
266 #define PARTIAL_KEY 1
267 #define FULL_KEY    2
268 #define FULL_KEY_DATA         3
269 #define   REAL_KEY  4
270 
271 /* Short hands for accessing structure */
272 #define BSIZE                 hdr.bsize
273 #define BSHIFT                hdr.bshift
274 #define DSIZE                 hdr.dsize
275 #define SGSIZE                hdr.ssize
276 #define SSHIFT                hdr.sshift
277 #define LORDER                hdr.lorder
278 #define OVFL_POINT  hdr.ovfl_point
279 #define   LAST_FREED          hdr.last_freed
280 #define MAX_BUCKET  hdr.max_bucket
281 #define FFACTOR               hdr.ffactor
282 #define HIGH_MASK   hdr.high_mask
283 #define LOW_MASK    hdr.low_mask
284 #define NKEYS                 hdr.nkeys
285 #define HDRPAGES    hdr.hdrpages
286 #define SPARES                hdr.spares
287 #define BITMAPS               hdr.bitmaps
288 #define VERSION               hdr.version
289 #define MAGIC                 hdr.magic
290 #define NEXT_FREE   hdr.next_free
291 #define H_CHARKEY   hdr.h_charkey
292