2 * sdbm - ndbm work-alike hashed database library
3 * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
4 * author: oz@nexus.yorku.ca
5 * status: public domain.
11 static char rcsid[] = "$Id: pair.c,v 1.10 90/12/13 13:00:35 oz Exp $";
19 #define exhash(item) sdbm_hash((item).dptr, (item).dsize)
24 static int seepair proto((char *, int, char *, int));
28 * +------------------------------+
29 * ino | n | keyoff | datoff | keyoff |
30 * +------------+--------+--------+
31 * | datoff | - - - ----> |
32 * +--------+---------------------+
34 * +--------------+---------------+
35 * | <---- - - - | data |
36 * +--------+-----+----+----------+
37 * | key | data | key |
38 * +--------+----------+----------+
40 * calculating the offsets for free area: if the number
41 * of entries (ino[0]) is zero, the offset to the END of
42 * the free area is the block size. Otherwise, it is the
43 * nth (ino[ino[0]]) entry's offset.
54 register short *ino = (short *) pag;
56 off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
57 free = off - (n + 1) * sizeof(short);
58 need += 2 * sizeof(short);
60 debug(("free %d need %d\n", free, need));
66 putpair(pag, key, val)
73 register short *ino = (short *) pag;
75 off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
80 (void) memcpy(pag + off, key.dptr, key.dsize);
86 (void) memcpy(pag + off, val.dptr, val.dsize);
102 register short *ino = (short *) pag;
104 if ((n = ino[0]) == 0)
107 if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
110 val.dptr = pag + ino[i + 1];
111 val.dsize = ino[i] - ino[i + 1];
121 register short *ino = (short *) pag;
122 return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
133 register short *ino = (short *) pag;
136 if (ino[0] == 0 || num > ino[0])
139 off = (num > 1) ? ino[num - 1] : PBLKSIZ;
141 key.dptr = pag + ino[num];
142 key.dsize = off - ino[num];
154 register short *ino = (short *) pag;
156 if ((n = ino[0]) == 0)
159 if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
162 * found the key. if it is the last entry
163 * [i.e. i == n - 1] we just adjust the entry count.
164 * hard case: move all data down onto the deleted pair,
165 * shift offsets onto deleted offsets, and adjust them.
170 register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
171 register char *src = pag + ino[i + 1];
172 register int zoo = dst - src;
174 debug(("free-up %d ", zoo));
176 * shift data/keys down
178 m = ino[i + 1] - ino[n];
180 #define MOVB *--dst = *--src
183 register int loop = (m + 8 - 1) >> 3;
185 switch (m & (8 - 1)) {
188 case 6: MOVB; case 5: MOVB;
189 case 4: MOVB; case 3: MOVB;
190 case 2: MOVB; case 1: MOVB;
196 memmove(dst, src, m);
203 * adjust offset index up
206 ino[i] = ino[i + 2] + zoo;
215 * search for the key in the page.
216 * return offset index in the range 0 < i < n.
217 * return 0 if not found.
220 seepair(pag, n, key, siz)
227 register int off = PBLKSIZ;
228 register short *ino = (short *) pag;
230 for (i = 1; i < n; i += 2) {
231 if (siz == off - ino[i] &&
232 memcmp(key, pag + ino[i], siz) == 0)
240 splpage(pag, new, sbit)
249 register int off = PBLKSIZ;
251 register short *ino = (short *) cur;
253 (void) memcpy(cur, pag, PBLKSIZ);
254 (void) memset(pag, 0, PBLKSIZ);
255 (void) memset(new, 0, PBLKSIZ);
258 for (ino++; n > 0; ino += 2) {
259 key.dptr = cur + ino[0];
260 key.dsize = off - ino[0];
261 val.dptr = cur + ino[1];
262 val.dsize = ino[0] - ino[1];
264 * select the page pointer (by looking at sbit) and insert
266 (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
272 debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
273 ((short *) new)[0] / 2,
274 ((short *) pag)[0] / 2));
279 * number of entries should be something
280 * reasonable, and all offsets in the index should be in order.
281 * this could be made more rigorous.
289 register short *ino = (short *) pag;
291 if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
296 for (ino++; n > 0; ino += 2) {
297 if (ino[0] > off || ino[1] > off ||