1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
* sdbm - ndbm work-alike hashed database library
19
* based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
20
* author: oz@nexus.yorku.ca
21
* status: ex-public domain.
28
#include "sdbm_tune.h"
29
#include "sdbm_pair.h"
30
#include "sdbm_private.h"
32
#include <string.h> /* for memset() */
35
#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
40
static int seepair(char *, int, char *, int);
44
* +------------------------------+
45
* ino | n | keyoff | datoff | keyoff |
46
* +------------+--------+--------+
47
* | datoff | - - - ----> |
48
* +--------+---------------------+
50
* +--------------+---------------+
51
* | <---- - - - | data |
52
* +--------+-----+----+----------+
53
* | key | data | key |
54
* +--------+----------+----------+
56
* calculating the offsets for free area: if the number
57
* of entries (ino[0]) is zero, the offset to the END of
58
* the free area is the block size. Otherwise, it is the
59
* nth (ino[ino[0]]) entry's offset.
70
register short *ino = (short *) pag;
72
off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
73
avail = off - (n + 1) * sizeof(short);
74
need += 2 * sizeof(short);
76
debug(("avail %d need %d\n", avail, need));
82
putpair(pag, key, val)
89
register short *ino = (short *) pag;
91
off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
96
(void) memcpy(pag + off, key.dptr, key.dsize);
102
(void) memcpy(pag + off, val.dptr, val.dsize);
113
apr_sdbm_datum_t key;
117
apr_sdbm_datum_t val;
118
register short *ino = (short *) pag;
120
if ((n = ino[0]) == 0)
121
return sdbm_nullitem;
123
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
124
return sdbm_nullitem;
126
val.dptr = pag + ino[i + 1];
127
val.dsize = ino[i] - ino[i + 1];
134
apr_sdbm_datum_t key;
136
register short *ino = (short *) pag;
137
return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
145
apr_sdbm_datum_t key;
147
register short *ino = (short *) pag;
150
if (ino[0] == 0 || num > ino[0])
151
return sdbm_nullitem;
153
off = (num > 1) ? ino[num - 1] : PBLKSIZ;
155
key.dptr = pag + ino[num];
156
key.dsize = off - ino[num];
164
apr_sdbm_datum_t key;
168
register short *ino = (short *) pag;
170
if ((n = ino[0]) == 0)
173
if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
176
* found the key. if it is the last entry
177
* [i.e. i == n - 1] we just adjust the entry count.
178
* hard case: move all data down onto the deleted pair,
179
* shift offsets onto deleted offsets, and adjust them.
184
register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
185
register char *src = pag + ino[i + 1];
186
register int zoo = dst - src;
188
debug(("free-up %d ", zoo));
190
* shift data/keys down
192
m = ino[i + 1] - ino[n];
194
#undef DUFF /* just use memmove. it should be plenty fast. */
196
#define MOVB *--dst = *--src
199
register int loop = (m + 8 - 1) >> 3;
201
switch (m & (8 - 1)) {
204
case 6: MOVB; case 5: MOVB;
205
case 4: MOVB; case 3: MOVB;
206
case 2: MOVB; case 1: MOVB;
213
memmove(dst, src, m);
217
* adjust offset index up
220
ino[i] = ino[i + 2] + zoo;
229
* search for the key in the page.
230
* return offset index in the range 0 < i < n.
231
* return 0 if not found.
234
seepair(pag, n, key, siz)
241
register int off = PBLKSIZ;
242
register short *ino = (short *) pag;
244
for (i = 1; i < n; i += 2) {
245
if (siz == off - ino[i] &&
246
memcmp(key, pag + ino[i], siz) == 0)
254
splpage(pag, new, sbit)
259
apr_sdbm_datum_t key;
260
apr_sdbm_datum_t val;
263
register int off = PBLKSIZ;
265
register short *ino = (short *) cur;
267
(void) memcpy(cur, pag, PBLKSIZ);
268
(void) memset(pag, 0, PBLKSIZ);
269
(void) memset(new, 0, PBLKSIZ);
272
for (ino++; n > 0; ino += 2) {
273
key.dptr = cur + ino[0];
274
key.dsize = off - ino[0];
275
val.dptr = cur + ino[1];
276
val.dsize = ino[0] - ino[1];
278
* select the page pointer (by looking at sbit) and insert
280
(void) putpair((exhash(key) & sbit) ? new : pag, key, val);
286
debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
287
((short *) new)[0] / 2,
288
((short *) pag)[0] / 2));
293
* number of entries should be something
294
* reasonable, and all offsets in the index should be in order.
295
* this could be made more rigorous.
303
register short *ino = (short *) pag;
305
if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
310
for (ino++; n > 0; ino += 2) {
311
if (ino[0] > off || ino[1] > off ||