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