Annotation of parser3/src/lib/sdbm/sdbm_pair.c, revision 1.3

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: #define exhash(item)   sdbm_hash((item).dptr, (item).dsize)
                     71: 
                     72: /* 
                     73:  * forward 
                     74:  */
                     75: static int seepair(char *, int, char *, int);
                     76: 
                     77: /*
                     78:  * page format:
                     79:  *     +------------------------------+
                     80:  * ino | n | keyoff | datoff | keyoff |
                     81:  *     +------------+--------+--------+
                     82:  *     | datoff | - - - ---->         |
                     83:  *     +--------+---------------------+
                     84:  *     |        F R E E A R E A       |
                     85:  *     +--------------+---------------+
                     86:  *     |  <---- - - - | data          |
                     87:  *     +--------+-----+----+----------+
                     88:  *     |  key   | data     | key      |
                     89:  *     +--------+----------+----------+
                     90:  *
                     91:  * calculating the offsets for free area:  if the number
                     92:  * of entries (ino[0]) is zero, the offset to the END of
                     93:  * the free area is the block size. Otherwise, it is the
                     94:  * nth (ino[ino[0]]) entry's offset.
                     95:  */
                     96: 
                     97: int
                     98: fitpair(pag, need)
                     99: char *pag;
                    100: int need;
                    101: {
                    102:        register int n;
                    103:        register int off;
                    104:        register int avail;
                    105:        register short *ino = (short *) pag;
                    106: 
                    107:        off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
                    108:        avail = off - (n + 1) * sizeof(short);
                    109:        need += 2 * sizeof(short);
                    110: 
                    111:        debug(("avail %d need %d\n", avail, need));
                    112: 
                    113:        return need <= avail;
                    114: }
                    115: 
                    116: void
                    117: putpair(pag, key, val)
                    118: char *pag;
1.2       moko      119: pa_sdbm_datum_t key;
                    120: pa_sdbm_datum_t val;
1.1       paf       121: {
                    122:        register int n;
                    123:        register int off;
                    124:        register short *ino = (short *) pag;
                    125: 
                    126:        off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
                    127: /*
                    128:  * enter the key first
                    129:  */
                    130:        off -= key.dsize;
                    131:        (void) memcpy(pag + off, key.dptr, key.dsize);
                    132:        ino[n + 1] = off;
                    133: /*
                    134:  * now the data
                    135:  */
                    136:        off -= val.dsize;
                    137:        (void) memcpy(pag + off, val.dptr, val.dsize);
                    138:        ino[n + 2] = off;
                    139: /*
                    140:  * adjust item count
                    141:  */
                    142:        ino[0] += 2;
                    143: }
                    144: 
1.2       moko      145: pa_sdbm_datum_t
1.1       paf       146: getpair(pag, key)
                    147: char *pag;
1.2       moko      148: pa_sdbm_datum_t key;
1.1       paf       149: {
                    150:        register int i;
                    151:        register int n;
1.2       moko      152:        pa_sdbm_datum_t val;
1.1       paf       153:        register short *ino = (short *) pag;
                    154: 
                    155:        if ((n = ino[0]) == 0)
                    156:                return sdbm_nullitem;
                    157: 
                    158:        if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
                    159:                return sdbm_nullitem;
                    160: 
                    161:        val.dptr = pag + ino[i + 1];
                    162:        val.dsize = ino[i] - ino[i + 1];
                    163:        return val;
                    164: }
                    165: 
                    166: int
                    167: duppair(pag, key)
                    168: char *pag;
1.2       moko      169: pa_sdbm_datum_t key;
1.1       paf       170: {
                    171:        register short *ino = (short *) pag;
                    172:        return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
                    173: }
                    174: 
1.2       moko      175: pa_sdbm_datum_t
1.1       paf       176: getnkey(pag, num)
                    177: char *pag;
                    178: int num;
                    179: {
1.2       moko      180:        pa_sdbm_datum_t key;
1.1       paf       181:        register int off;
                    182:        register short *ino = (short *) pag;
                    183: 
                    184:        num = num * 2 - 1;
                    185:        if (ino[0] == 0 || num > ino[0])
                    186:                return sdbm_nullitem;
                    187: 
                    188:        off = (num > 1) ? ino[num - 1] : PBLKSIZ;
                    189: 
                    190:        key.dptr = pag + ino[num];
                    191:        key.dsize = off - ino[num];
                    192: 
                    193:        return key;
                    194: }
                    195: 
                    196: int
                    197: delpair(pag, key)
                    198: char *pag;
1.2       moko      199: pa_sdbm_datum_t key;
1.1       paf       200: {
                    201:        register int n;
                    202:        register int i;
                    203:        register short *ino = (short *) pag;
                    204: 
                    205:        if ((n = ino[0]) == 0)
                    206:                return 0;
                    207: 
                    208:        if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
                    209:                return 0;
                    210: /*
                    211:  * found the key. if it is the last entry
                    212:  * [i.e. i == n - 1] we just adjust the entry count.
                    213:  * hard case: move all data down onto the deleted pair,
                    214:  * shift offsets onto deleted offsets, and adjust them.
                    215:  * [note: 0 < i < n]
                    216:  */
                    217:        if (i < n - 1) {
                    218:                register int m;
                    219:                register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
                    220:                register char *src = pag + ino[i + 1];
                    221:                register int   zoo = dst - src;
                    222: 
                    223:                debug(("free-up %d ", zoo));
                    224: /*
                    225:  * shift data/keys down
                    226:  */
                    227:                m = ino[i + 1] - ino[n];
                    228: 
                    229: #undef DUFF    /* just use memmove. it should be plenty fast. */
                    230: #ifdef DUFF
                    231: #define MOVB   *--dst = *--src
                    232: 
                    233:                if (m > 0) {
                    234:                        register int loop = (m + 8 - 1) >> 3;
                    235: 
                    236:                        switch (m & (8 - 1)) {
                    237:                        case 0: do {
                    238:                                MOVB;   case 7: MOVB;
                    239:                        case 6: MOVB;   case 5: MOVB;
                    240:                        case 4: MOVB;   case 3: MOVB;
                    241:                        case 2: MOVB;   case 1: MOVB;
                    242:                                } while (--loop);
                    243:                        }
                    244:                }
                    245: #else
                    246:                dst -= m;
                    247:                src -= m;
                    248:                memmove(dst, src, m);
                    249: #endif
                    250: 
                    251: /*
                    252:  * adjust offset index up
                    253:  */
                    254:                while (i < n - 1) {
                    255:                        ino[i] = ino[i + 2] + zoo;
                    256:                        i++;
                    257:                }
                    258:        }
                    259:        ino[0] -= 2;
                    260:        return 1;
                    261: }
                    262: 
                    263: /*
                    264:  * search for the key in the page.
                    265:  * return offset index in the range 0 < i < n.
                    266:  * return 0 if not found.
                    267:  */
                    268: static int
                    269: seepair(pag, n, key, siz)
                    270: char *pag;
                    271: register int n;
                    272: register char *key;
                    273: register int siz;
                    274: {
                    275:        register int i;
                    276:        register int off = PBLKSIZ;
                    277:        register short *ino = (short *) pag;
                    278: 
                    279:        for (i = 1; i < n; i += 2) {
                    280:                if (siz == off - ino[i] &&
                    281:                    memcmp(key, pag + ino[i], siz) == 0)
                    282:                        return i;
                    283:                off = ino[i + 1];
                    284:        }
                    285:        return 0;
                    286: }
                    287: 
                    288: void
                    289: splpage(pag, new, sbit)
                    290: char *pag;
                    291: char *new;
                    292: long sbit;
                    293: {
1.2       moko      294:        pa_sdbm_datum_t key;
                    295:        pa_sdbm_datum_t val;
1.1       paf       296: 
                    297:        register int n;
                    298:        register int off = PBLKSIZ;
                    299:        char cur[PBLKSIZ];
                    300:        register short *ino = (short *) cur;
                    301: 
                    302:        (void) memcpy(cur, pag, PBLKSIZ);
                    303:        (void) memset(pag, 0, PBLKSIZ);
                    304:        (void) memset(new, 0, PBLKSIZ);
                    305: 
                    306:        n = ino[0];
                    307:        for (ino++; n > 0; ino += 2) {
                    308:                key.dptr = cur + ino[0]; 
                    309:                key.dsize = off - ino[0];
                    310:                val.dptr = cur + ino[1];
                    311:                val.dsize = ino[0] - ino[1];
                    312: /*
                    313:  * select the page pointer (by looking at sbit) and insert
                    314:  */
                    315:                (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
                    316: 
                    317:                off = ino[1];
                    318:                n -= 2;
                    319:        }
                    320: 
                    321:        debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
                    322:               ((short *) new)[0] / 2,
                    323:               ((short *) pag)[0] / 2));
                    324: }
                    325: 
                    326: /*
                    327:  * check page sanity: 
                    328:  * number of entries should be something
                    329:  * reasonable, and all offsets in the index should be in order.
                    330:  * this could be made more rigorous.
                    331:  */
                    332: int
                    333: chkpage(pag)
                    334: char *pag;
                    335: {
                    336:        register int n;
                    337:        register int off;
                    338:        register short *ino = (short *) pag;
                    339: 
                    340:        if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
                    341:                return 0;
                    342: 
                    343:        if (n > 0) {
                    344:                off = PBLKSIZ;
                    345:                for (ino++; n > 0; ino += 2) {
                    346:                        if (ino[0] > off || ino[1] > off ||
                    347:                            ino[1] > ino[0])
                    348:                                return 0;
                    349:                        off = ino[1];
                    350:                        n -= 2;
                    351:                }
                    352:        }
                    353:        return 1;
                    354: }

E-mail: