Annotation of parser3/src/lib/sdbm/sdbm_pair.c, revision 1.1
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:
! 64: #include "apr_sdbm.h"
! 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;
! 122: apr_sdbm_datum_t key;
! 123: apr_sdbm_datum_t val;
! 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:
! 148: apr_sdbm_datum_t
! 149: getpair(pag, key)
! 150: char *pag;
! 151: apr_sdbm_datum_t key;
! 152: {
! 153: register int i;
! 154: register int n;
! 155: apr_sdbm_datum_t val;
! 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;
! 172: apr_sdbm_datum_t key;
! 173: {
! 174: register short *ino = (short *) pag;
! 175: return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
! 176: }
! 177:
! 178: apr_sdbm_datum_t
! 179: getnkey(pag, num)
! 180: char *pag;
! 181: int num;
! 182: {
! 183: apr_sdbm_datum_t key;
! 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;
! 202: apr_sdbm_datum_t key;
! 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: {
! 297: apr_sdbm_datum_t key;
! 298: apr_sdbm_datum_t val;
! 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: