Annotation of parser3/src/lib/sdbm/sdbm_pair.c, revision 1.2
1.1 paf 1: /* ====================================================================
2: * The Apache Software License, Version 1.1
3: *
4: * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
5: * reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: *
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: *
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in
16: * the documentation and/or other materials provided with the
17: * distribution.
18: *
19: * 3. The end-user documentation included with the redistribution,
20: * if any, must include the following acknowledgment:
21: * "This product includes software developed by the
22: * Apache Software Foundation (http://www.apache.org/)."
23: * Alternately, this acknowledgment may appear in the software itself,
24: * if and wherever such third-party acknowledgments normally appear.
25: *
26: * 4. The names "Apache" and "Apache Software Foundation" must
27: * not be used to endorse or promote products derived from this
28: * software without prior written permission. For written
29: * permission, please contact apache@apache.org.
30: *
31: * 5. Products derived from this software may not be called "Apache",
32: * nor may "Apache" appear in their name, without prior written
33: * permission of the Apache Software Foundation.
34: *
35: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46: * SUCH DAMAGE.
47: * ====================================================================
48: *
49: * This software consists of voluntary contributions made by many
50: * individuals on behalf of the Apache Software Foundation. For more
51: * information on the Apache Software Foundation, please see
52: * <http://www.apache.org/>.
53: */
54:
55: /*
56: * sdbm - ndbm work-alike hashed database library
57: * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
58: * author: oz@nexus.yorku.ca
59: * status: ex-public domain.
60: *
61: * page-level routines
62: */
63:
1.2 ! moko 64: #include "pa_sdbm.h"
1.1 paf 65:
66: #include "sdbm_tune.h"
67: #include "sdbm_pair.h"
68: #include "sdbm_private.h"
69:
70: #include <string.h> /* for memset() */
71:
72:
73: #define exhash(item) sdbm_hash((item).dptr, (item).dsize)
74:
75: /*
76: * forward
77: */
78: static int seepair(char *, int, char *, int);
79:
80: /*
81: * page format:
82: * +------------------------------+
83: * ino | n | keyoff | datoff | keyoff |
84: * +------------+--------+--------+
85: * | datoff | - - - ----> |
86: * +--------+---------------------+
87: * | F R E E A R E A |
88: * +--------------+---------------+
89: * | <---- - - - | data |
90: * +--------+-----+----+----------+
91: * | key | data | key |
92: * +--------+----------+----------+
93: *
94: * calculating the offsets for free area: if the number
95: * of entries (ino[0]) is zero, the offset to the END of
96: * the free area is the block size. Otherwise, it is the
97: * nth (ino[ino[0]]) entry's offset.
98: */
99:
100: int
101: fitpair(pag, need)
102: char *pag;
103: int need;
104: {
105: register int n;
106: register int off;
107: register int avail;
108: register short *ino = (short *) pag;
109:
110: off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
111: avail = off - (n + 1) * sizeof(short);
112: need += 2 * sizeof(short);
113:
114: debug(("avail %d need %d\n", avail, need));
115:
116: return need <= avail;
117: }
118:
119: void
120: putpair(pag, key, val)
121: char *pag;
1.2 ! moko 122: pa_sdbm_datum_t key;
! 123: pa_sdbm_datum_t val;
1.1 paf 124: {
125: register int n;
126: register int off;
127: register short *ino = (short *) pag;
128:
129: off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
130: /*
131: * enter the key first
132: */
133: off -= key.dsize;
134: (void) memcpy(pag + off, key.dptr, key.dsize);
135: ino[n + 1] = off;
136: /*
137: * now the data
138: */
139: off -= val.dsize;
140: (void) memcpy(pag + off, val.dptr, val.dsize);
141: ino[n + 2] = off;
142: /*
143: * adjust item count
144: */
145: ino[0] += 2;
146: }
147:
1.2 ! moko 148: pa_sdbm_datum_t
1.1 paf 149: getpair(pag, key)
150: char *pag;
1.2 ! moko 151: pa_sdbm_datum_t key;
1.1 paf 152: {
153: register int i;
154: register int n;
1.2 ! moko 155: pa_sdbm_datum_t val;
1.1 paf 156: register short *ino = (short *) pag;
157:
158: if ((n = ino[0]) == 0)
159: return sdbm_nullitem;
160:
161: if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
162: return sdbm_nullitem;
163:
164: val.dptr = pag + ino[i + 1];
165: val.dsize = ino[i] - ino[i + 1];
166: return val;
167: }
168:
169: int
170: duppair(pag, key)
171: char *pag;
1.2 ! moko 172: pa_sdbm_datum_t key;
1.1 paf 173: {
174: register short *ino = (short *) pag;
175: return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
176: }
177:
1.2 ! moko 178: pa_sdbm_datum_t
1.1 paf 179: getnkey(pag, num)
180: char *pag;
181: int num;
182: {
1.2 ! moko 183: pa_sdbm_datum_t key;
1.1 paf 184: register int off;
185: register short *ino = (short *) pag;
186:
187: num = num * 2 - 1;
188: if (ino[0] == 0 || num > ino[0])
189: return sdbm_nullitem;
190:
191: off = (num > 1) ? ino[num - 1] : PBLKSIZ;
192:
193: key.dptr = pag + ino[num];
194: key.dsize = off - ino[num];
195:
196: return key;
197: }
198:
199: int
200: delpair(pag, key)
201: char *pag;
1.2 ! moko 202: pa_sdbm_datum_t key;
1.1 paf 203: {
204: register int n;
205: register int i;
206: register short *ino = (short *) pag;
207:
208: if ((n = ino[0]) == 0)
209: return 0;
210:
211: if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
212: return 0;
213: /*
214: * found the key. if it is the last entry
215: * [i.e. i == n - 1] we just adjust the entry count.
216: * hard case: move all data down onto the deleted pair,
217: * shift offsets onto deleted offsets, and adjust them.
218: * [note: 0 < i < n]
219: */
220: if (i < n - 1) {
221: register int m;
222: register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
223: register char *src = pag + ino[i + 1];
224: register int zoo = dst - src;
225:
226: debug(("free-up %d ", zoo));
227: /*
228: * shift data/keys down
229: */
230: m = ino[i + 1] - ino[n];
231:
232: #undef DUFF /* just use memmove. it should be plenty fast. */
233: #ifdef DUFF
234: #define MOVB *--dst = *--src
235:
236: if (m > 0) {
237: register int loop = (m + 8 - 1) >> 3;
238:
239: switch (m & (8 - 1)) {
240: case 0: do {
241: MOVB; case 7: MOVB;
242: case 6: MOVB; case 5: MOVB;
243: case 4: MOVB; case 3: MOVB;
244: case 2: MOVB; case 1: MOVB;
245: } while (--loop);
246: }
247: }
248: #else
249: dst -= m;
250: src -= m;
251: memmove(dst, src, m);
252: #endif
253:
254: /*
255: * adjust offset index up
256: */
257: while (i < n - 1) {
258: ino[i] = ino[i + 2] + zoo;
259: i++;
260: }
261: }
262: ino[0] -= 2;
263: return 1;
264: }
265:
266: /*
267: * search for the key in the page.
268: * return offset index in the range 0 < i < n.
269: * return 0 if not found.
270: */
271: static int
272: seepair(pag, n, key, siz)
273: char *pag;
274: register int n;
275: register char *key;
276: register int siz;
277: {
278: register int i;
279: register int off = PBLKSIZ;
280: register short *ino = (short *) pag;
281:
282: for (i = 1; i < n; i += 2) {
283: if (siz == off - ino[i] &&
284: memcmp(key, pag + ino[i], siz) == 0)
285: return i;
286: off = ino[i + 1];
287: }
288: return 0;
289: }
290:
291: void
292: splpage(pag, new, sbit)
293: char *pag;
294: char *new;
295: long sbit;
296: {
1.2 ! moko 297: pa_sdbm_datum_t key;
! 298: pa_sdbm_datum_t val;
1.1 paf 299:
300: register int n;
301: register int off = PBLKSIZ;
302: char cur[PBLKSIZ];
303: register short *ino = (short *) cur;
304:
305: (void) memcpy(cur, pag, PBLKSIZ);
306: (void) memset(pag, 0, PBLKSIZ);
307: (void) memset(new, 0, PBLKSIZ);
308:
309: n = ino[0];
310: for (ino++; n > 0; ino += 2) {
311: key.dptr = cur + ino[0];
312: key.dsize = off - ino[0];
313: val.dptr = cur + ino[1];
314: val.dsize = ino[0] - ino[1];
315: /*
316: * select the page pointer (by looking at sbit) and insert
317: */
318: (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
319:
320: off = ino[1];
321: n -= 2;
322: }
323:
324: debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
325: ((short *) new)[0] / 2,
326: ((short *) pag)[0] / 2));
327: }
328:
329: /*
330: * check page sanity:
331: * number of entries should be something
332: * reasonable, and all offsets in the index should be in order.
333: * this could be made more rigorous.
334: */
335: int
336: chkpage(pag)
337: char *pag;
338: {
339: register int n;
340: register int off;
341: register short *ino = (short *) pag;
342:
343: if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
344: return 0;
345:
346: if (n > 0) {
347: off = PBLKSIZ;
348: for (ino++; n > 0; ino += 2) {
349: if (ino[0] > off || ino[1] > off ||
350: ino[1] > ino[0])
351: return 0;
352: off = ino[1];
353: n -= 2;
354: }
355: }
356: return 1;
357: }
E-mail: