OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [search/] [hash_page.c] - Diff between revs 207 and 345

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
/*-
/*-
 * Copyright (c) 1990, 1993, 1994
 * Copyright (c) 1990, 1993, 1994
 *      The Regents of the University of California.  All rights reserved.
 *      The Regents of the University of California.  All rights reserved.
 *
 *
 * This code is derived from software contributed to Berkeley by
 * This code is derived from software contributed to Berkeley by
 * Margo Seltzer.
 * Margo Seltzer.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
 * are met:
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *    without specific prior written permission.
 *
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * SUCH DAMAGE.
 */
 */
 
 
#include <sys/param.h>
#include <sys/param.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#endif /* LIBC_SCCS and not lint */
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
#include <sys/cdefs.h>
 
 
/*
/*
 * PACKAGE:  hashing
 * PACKAGE:  hashing
 *
 *
 * DESCRIPTION:
 * DESCRIPTION:
 *      Page manipulation for hashing package.
 *      Page manipulation for hashing package.
 *
 *
 * ROUTINES:
 * ROUTINES:
 *
 *
 * External
 * External
 *      __get_page
 *      __get_page
 *      __add_ovflpage
 *      __add_ovflpage
 * Internal
 * Internal
 *      overflow_page
 *      overflow_page
 *      open_temp
 *      open_temp
 */
 */
 
 
#include <sys/types.h>
#include <sys/types.h>
 
 
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
#include <signal.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
#ifdef DEBUG
#ifdef DEBUG
#include <assert.h>
#include <assert.h>
#endif
#endif
 
 
#include "db_local.h"
#include "db_local.h"
#include "hash.h"
#include "hash.h"
#include "page.h"
#include "page.h"
#include "extern.h"
#include "extern.h"
 
 
static __uint32_t       *fetch_bitmap(HTAB *, int);
static __uint32_t       *fetch_bitmap(HTAB *, int);
static __uint32_t        first_free(__uint32_t);
static __uint32_t        first_free(__uint32_t);
static int       open_temp(HTAB *);
static int       open_temp(HTAB *);
static __uint16_t        overflow_page(HTAB *);
static __uint16_t        overflow_page(HTAB *);
static void      putpair(char *, const DBT *, const DBT *);
static void      putpair(char *, const DBT *, const DBT *);
static void      squeeze_key(__uint16_t *, const DBT *, const DBT *);
static void      squeeze_key(__uint16_t *, const DBT *, const DBT *);
static int       ugly_split
static int       ugly_split
(HTAB *, __uint32_t, BUFHEAD *, BUFHEAD *, int, int);
(HTAB *, __uint32_t, BUFHEAD *, BUFHEAD *, int, int);
 
 
#define PAGE_INIT(P) { \
#define PAGE_INIT(P) { \
        ((__uint16_t *)(P))[0] = 0; \
        ((__uint16_t *)(P))[0] = 0; \
        ((__uint16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(__uint16_t); \
        ((__uint16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(__uint16_t); \
        ((__uint16_t *)(P))[2] = hashp->BSIZE; \
        ((__uint16_t *)(P))[2] = hashp->BSIZE; \
}
}
 
 
/*
/*
 * This is called AFTER we have verified that there is room on the page for
 * This is called AFTER we have verified that there is room on the page for
 * the pair (PAIRFITS has returned true) so we go right ahead and start moving
 * the pair (PAIRFITS has returned true) so we go right ahead and start moving
 * stuff on.
 * stuff on.
 */
 */
static void
static void
putpair(p, key, val)
putpair(p, key, val)
        char *p;
        char *p;
        const DBT *key, *val;
        const DBT *key, *val;
{
{
        __uint16_t *bp, n, off;
        __uint16_t *bp, n, off;
 
 
        bp = (__uint16_t *)p;
        bp = (__uint16_t *)p;
 
 
        /* Enter the key first. */
        /* Enter the key first. */
        n = bp[0];
        n = bp[0];
 
 
        off = OFFSET(bp) - key->size;
        off = OFFSET(bp) - key->size;
        memmove(p + off, key->data, key->size);
        memmove(p + off, key->data, key->size);
        bp[++n] = off;
        bp[++n] = off;
 
 
        /* Now the data. */
        /* Now the data. */
        off -= val->size;
        off -= val->size;
        memmove(p + off, val->data, val->size);
        memmove(p + off, val->data, val->size);
        bp[++n] = off;
        bp[++n] = off;
 
 
        /* Adjust page info. */
        /* Adjust page info. */
        bp[0] = n;
        bp[0] = n;
        bp[n + 1] = off - ((n + 3) * sizeof(__uint16_t));
        bp[n + 1] = off - ((n + 3) * sizeof(__uint16_t));
        bp[n + 2] = off;
        bp[n + 2] = off;
}
}
 
 
/*
/*
 * Returns:
 * Returns:
 *       0 OK
 *       0 OK
 *      -1 error
 *      -1 error
 */
 */
extern int
extern int
__delpair(hashp, bufp, ndx)
__delpair(hashp, bufp, ndx)
        HTAB *hashp;
        HTAB *hashp;
        BUFHEAD *bufp;
        BUFHEAD *bufp;
        int ndx;
        int ndx;
{
{
        __uint16_t *bp, newoff;
        __uint16_t *bp, newoff;
        int n;
        int n;
        __uint16_t pairlen;
        __uint16_t pairlen;
 
 
        bp = (__uint16_t *)bufp->page;
        bp = (__uint16_t *)bufp->page;
        n = bp[0];
        n = bp[0];
 
 
        if (bp[ndx + 1] < REAL_KEY)
        if (bp[ndx + 1] < REAL_KEY)
                return (__big_delete(hashp, bufp));
                return (__big_delete(hashp, bufp));
        if (ndx != 1)
        if (ndx != 1)
                newoff = bp[ndx - 1];
                newoff = bp[ndx - 1];
        else
        else
                newoff = hashp->BSIZE;
                newoff = hashp->BSIZE;
        pairlen = newoff - bp[ndx + 1];
        pairlen = newoff - bp[ndx + 1];
 
 
        if (ndx != (n - 1)) {
        if (ndx != (n - 1)) {
                /* Hard Case -- need to shuffle keys */
                /* Hard Case -- need to shuffle keys */
                int i;
                int i;
                char *src = bufp->page + (int)OFFSET(bp);
                char *src = bufp->page + (int)OFFSET(bp);
                char *dst = src + (int)pairlen;
                char *dst = src + (int)pairlen;
                memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
                memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
 
 
                /* Now adjust the pointers */
                /* Now adjust the pointers */
                for (i = ndx + 2; i <= n; i += 2) {
                for (i = ndx + 2; i <= n; i += 2) {
                        if (bp[i + 1] == OVFLPAGE) {
                        if (bp[i + 1] == OVFLPAGE) {
                                bp[i - 2] = bp[i];
                                bp[i - 2] = bp[i];
                                bp[i - 1] = bp[i + 1];
                                bp[i - 1] = bp[i + 1];
                        } else {
                        } else {
                                bp[i - 2] = bp[i] + pairlen;
                                bp[i - 2] = bp[i] + pairlen;
                                bp[i - 1] = bp[i + 1] + pairlen;
                                bp[i - 1] = bp[i + 1] + pairlen;
                        }
                        }
                }
                }
        }
        }
        /* Finally adjust the page data */
        /* Finally adjust the page data */
        bp[n] = OFFSET(bp) + pairlen;
        bp[n] = OFFSET(bp) + pairlen;
        bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(__uint16_t);
        bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(__uint16_t);
        bp[0] = n - 2;
        bp[0] = n - 2;
        hashp->NKEYS--;
        hashp->NKEYS--;
 
 
        bufp->flags |= BUF_MOD;
        bufp->flags |= BUF_MOD;
        return (0);
        return (0);
}
}
/*
/*
 * Returns:
 * Returns:
 *       0 ==> OK
 *       0 ==> OK
 *      -1 ==> Error
 *      -1 ==> Error
 */
 */
extern int
extern int
__split_page(hashp, obucket, nbucket)
__split_page(hashp, obucket, nbucket)
        HTAB *hashp;
        HTAB *hashp;
        __uint32_t obucket, nbucket;
        __uint32_t obucket, nbucket;
{
{
        BUFHEAD *new_bufp, *old_bufp;
        BUFHEAD *new_bufp, *old_bufp;
        __uint16_t *ino;
        __uint16_t *ino;
        char *np;
        char *np;
        DBT key, val;
        DBT key, val;
        int n, ndx, retval;
        int n, ndx, retval;
        __uint16_t copyto, diff, off, moved;
        __uint16_t copyto, diff, off, moved;
        char *op;
        char *op;
 
 
        copyto = (__uint16_t)hashp->BSIZE;
        copyto = (__uint16_t)hashp->BSIZE;
        off = (__uint16_t)hashp->BSIZE;
        off = (__uint16_t)hashp->BSIZE;
        old_bufp = __get_buf(hashp, obucket, NULL, 0);
        old_bufp = __get_buf(hashp, obucket, NULL, 0);
        if (old_bufp == NULL)
        if (old_bufp == NULL)
                return (-1);
                return (-1);
        new_bufp = __get_buf(hashp, nbucket, NULL, 0);
        new_bufp = __get_buf(hashp, nbucket, NULL, 0);
        if (new_bufp == NULL)
        if (new_bufp == NULL)
                return (-1);
                return (-1);
 
 
        old_bufp->flags |= (BUF_MOD | BUF_PIN);
        old_bufp->flags |= (BUF_MOD | BUF_PIN);
        new_bufp->flags |= (BUF_MOD | BUF_PIN);
        new_bufp->flags |= (BUF_MOD | BUF_PIN);
 
 
        ino = (__uint16_t *)(op = old_bufp->page);
        ino = (__uint16_t *)(op = old_bufp->page);
        np = new_bufp->page;
        np = new_bufp->page;
 
 
        moved = 0;
        moved = 0;
 
 
        for (n = 1, ndx = 1; n < ino[0]; n += 2) {
        for (n = 1, ndx = 1; n < ino[0]; n += 2) {
                if (ino[n + 1] < REAL_KEY) {
                if (ino[n + 1] < REAL_KEY) {
                        retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
                        retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
                            (int)copyto, (int)moved);
                            (int)copyto, (int)moved);
                        old_bufp->flags &= ~BUF_PIN;
                        old_bufp->flags &= ~BUF_PIN;
                        new_bufp->flags &= ~BUF_PIN;
                        new_bufp->flags &= ~BUF_PIN;
                        return (retval);
                        return (retval);
 
 
                }
                }
                key.data = (u_char *)op + ino[n];
                key.data = (u_char *)op + ino[n];
                key.size = off - ino[n];
                key.size = off - ino[n];
 
 
                if (__call_hash(hashp, key.data, key.size) == obucket) {
                if (__call_hash(hashp, key.data, key.size) == obucket) {
                        /* Don't switch page */
                        /* Don't switch page */
                        diff = copyto - off;
                        diff = copyto - off;
                        if (diff) {
                        if (diff) {
                                copyto = ino[n + 1] + diff;
                                copyto = ino[n + 1] + diff;
                                memmove(op + copyto, op + ino[n + 1],
                                memmove(op + copyto, op + ino[n + 1],
                                    off - ino[n + 1]);
                                    off - ino[n + 1]);
                                ino[ndx] = copyto + ino[n] - ino[n + 1];
                                ino[ndx] = copyto + ino[n] - ino[n + 1];
                                ino[ndx + 1] = copyto;
                                ino[ndx + 1] = copyto;
                        } else
                        } else
                                copyto = ino[n + 1];
                                copyto = ino[n + 1];
                        ndx += 2;
                        ndx += 2;
                } else {
                } else {
                        /* Switch page */
                        /* Switch page */
                        val.data = (u_char *)op + ino[n + 1];
                        val.data = (u_char *)op + ino[n + 1];
                        val.size = ino[n] - ino[n + 1];
                        val.size = ino[n] - ino[n + 1];
                        putpair(np, &key, &val);
                        putpair(np, &key, &val);
                        moved += 2;
                        moved += 2;
                }
                }
 
 
                off = ino[n + 1];
                off = ino[n + 1];
        }
        }
 
 
        /* Now clean up the page */
        /* Now clean up the page */
        ino[0] -= moved;
        ino[0] -= moved;
        FREESPACE(ino) = copyto - sizeof(__uint16_t) * (ino[0] + 3);
        FREESPACE(ino) = copyto - sizeof(__uint16_t) * (ino[0] + 3);
        OFFSET(ino) = copyto;
        OFFSET(ino) = copyto;
 
 
#ifdef DEBUG3
#ifdef DEBUG3
        (void)fprintf(stderr, "split %d/%d\n",
        (void)fprintf(stderr, "split %d/%d\n",
            ((__uint16_t *)np)[0] / 2,
            ((__uint16_t *)np)[0] / 2,
            ((__uint16_t *)op)[0] / 2);
            ((__uint16_t *)op)[0] / 2);
#endif
#endif
        /* unpin both pages */
        /* unpin both pages */
        old_bufp->flags &= ~BUF_PIN;
        old_bufp->flags &= ~BUF_PIN;
        new_bufp->flags &= ~BUF_PIN;
        new_bufp->flags &= ~BUF_PIN;
        return (0);
        return (0);
}
}
 
 
/*
/*
 * Called when we encounter an overflow or big key/data page during split
 * Called when we encounter an overflow or big key/data page during split
 * handling.  This is special cased since we have to begin checking whether
 * handling.  This is special cased since we have to begin checking whether
 * the key/data pairs fit on their respective pages and because we may need
 * the key/data pairs fit on their respective pages and because we may need
 * overflow pages for both the old and new pages.
 * overflow pages for both the old and new pages.
 *
 *
 * The first page might be a page with regular key/data pairs in which case
 * The first page might be a page with regular key/data pairs in which case
 * we have a regular overflow condition and just need to go on to the next
 * we have a regular overflow condition and just need to go on to the next
 * page or it might be a big key/data pair in which case we need to fix the
 * page or it might be a big key/data pair in which case we need to fix the
 * big key/data pair.
 * big key/data pair.
 *
 *
 * Returns:
 * Returns:
 *       0 ==> success
 *       0 ==> success
 *      -1 ==> failure
 *      -1 ==> failure
 */
 */
static int
static int
ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
        HTAB *hashp;
        HTAB *hashp;
        __uint32_t obucket;     /* Same as __split_page. */
        __uint32_t obucket;     /* Same as __split_page. */
        BUFHEAD *old_bufp, *new_bufp;
        BUFHEAD *old_bufp, *new_bufp;
        int copyto;     /* First byte on page which contains key/data values. */
        int copyto;     /* First byte on page which contains key/data values. */
        int moved;              /* Number of pairs moved to new page. */
        int moved;              /* Number of pairs moved to new page. */
{
{
        BUFHEAD *bufp;          /* Buffer header for ino */
        BUFHEAD *bufp;          /* Buffer header for ino */
        __uint16_t *ino;                /* Page keys come off of */
        __uint16_t *ino;                /* Page keys come off of */
        __uint16_t *np;         /* New page */
        __uint16_t *np;         /* New page */
        __uint16_t *op;         /* Page keys go on to if they aren't moving */
        __uint16_t *op;         /* Page keys go on to if they aren't moving */
 
 
        BUFHEAD *last_bfp;      /* Last buf header OVFL needing to be freed */
        BUFHEAD *last_bfp;      /* Last buf header OVFL needing to be freed */
        DBT key, val;
        DBT key, val;
        SPLIT_RETURN ret;
        SPLIT_RETURN ret;
        __uint16_t n, off, ov_addr, scopyto;
        __uint16_t n, off, ov_addr, scopyto;
        char *cino;             /* Character value of ino */
        char *cino;             /* Character value of ino */
 
 
        bufp = old_bufp;
        bufp = old_bufp;
        ino = (__uint16_t *)old_bufp->page;
        ino = (__uint16_t *)old_bufp->page;
        np = (__uint16_t *)new_bufp->page;
        np = (__uint16_t *)new_bufp->page;
        op = (__uint16_t *)old_bufp->page;
        op = (__uint16_t *)old_bufp->page;
        last_bfp = NULL;
        last_bfp = NULL;
        scopyto = (__uint16_t)copyto;   /* ANSI */
        scopyto = (__uint16_t)copyto;   /* ANSI */
 
 
        n = ino[0] - 1;
        n = ino[0] - 1;
        while (n < ino[0]) {
        while (n < ino[0]) {
                if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
                if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
                        if (__big_split(hashp, old_bufp,
                        if (__big_split(hashp, old_bufp,
                            new_bufp, bufp, bufp->addr, obucket, &ret))
                            new_bufp, bufp, bufp->addr, obucket, &ret))
                                return (-1);
                                return (-1);
                        old_bufp = ret.oldp;
                        old_bufp = ret.oldp;
                        if (!old_bufp)
                        if (!old_bufp)
                                return (-1);
                                return (-1);
                        op = (__uint16_t *)old_bufp->page;
                        op = (__uint16_t *)old_bufp->page;
                        new_bufp = ret.newp;
                        new_bufp = ret.newp;
                        if (!new_bufp)
                        if (!new_bufp)
                                return (-1);
                                return (-1);
                        np = (__uint16_t *)new_bufp->page;
                        np = (__uint16_t *)new_bufp->page;
                        bufp = ret.nextp;
                        bufp = ret.nextp;
                        if (!bufp)
                        if (!bufp)
                                return (0);
                                return (0);
                        cino = (char *)bufp->page;
                        cino = (char *)bufp->page;
                        ino = (__uint16_t *)cino;
                        ino = (__uint16_t *)cino;
                        last_bfp = ret.nextp;
                        last_bfp = ret.nextp;
                } else if (ino[n + 1] == OVFLPAGE) {
                } else if (ino[n + 1] == OVFLPAGE) {
                        ov_addr = ino[n];
                        ov_addr = ino[n];
                        /*
                        /*
                         * Fix up the old page -- the extra 2 are the fields
                         * Fix up the old page -- the extra 2 are the fields
                         * which contained the overflow information.
                         * which contained the overflow information.
                         */
                         */
                        ino[0] -= (moved + 2);
                        ino[0] -= (moved + 2);
                        FREESPACE(ino) =
                        FREESPACE(ino) =
                            scopyto - sizeof(__uint16_t) * (ino[0] + 3);
                            scopyto - sizeof(__uint16_t) * (ino[0] + 3);
                        OFFSET(ino) = scopyto;
                        OFFSET(ino) = scopyto;
 
 
                        bufp = __get_buf(hashp, ov_addr, bufp, 0);
                        bufp = __get_buf(hashp, ov_addr, bufp, 0);
                        if (!bufp)
                        if (!bufp)
                                return (-1);
                                return (-1);
 
 
                        ino = (__uint16_t *)bufp->page;
                        ino = (__uint16_t *)bufp->page;
                        n = 1;
                        n = 1;
                        scopyto = hashp->BSIZE;
                        scopyto = hashp->BSIZE;
                        moved = 0;
                        moved = 0;
 
 
                        if (last_bfp)
                        if (last_bfp)
                                __free_ovflpage(hashp, last_bfp);
                                __free_ovflpage(hashp, last_bfp);
                        last_bfp = bufp;
                        last_bfp = bufp;
                }
                }
                /* Move regular sized pairs of there are any */
                /* Move regular sized pairs of there are any */
                off = hashp->BSIZE;
                off = hashp->BSIZE;
                for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
                for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
                        cino = (char *)ino;
                        cino = (char *)ino;
                        key.data = (u_char *)cino + ino[n];
                        key.data = (u_char *)cino + ino[n];
                        key.size = off - ino[n];
                        key.size = off - ino[n];
                        val.data = (u_char *)cino + ino[n + 1];
                        val.data = (u_char *)cino + ino[n + 1];
                        val.size = ino[n] - ino[n + 1];
                        val.size = ino[n] - ino[n + 1];
                        off = ino[n + 1];
                        off = ino[n + 1];
 
 
                        if (__call_hash(hashp, key.data, key.size) == obucket) {
                        if (__call_hash(hashp, key.data, key.size) == obucket) {
                                /* Keep on old page */
                                /* Keep on old page */
                                if (PAIRFITS(op, (&key), (&val)))
                                if (PAIRFITS(op, (&key), (&val)))
                                        putpair((char *)op, &key, &val);
                                        putpair((char *)op, &key, &val);
                                else {
                                else {
                                        old_bufp =
                                        old_bufp =
                                            __add_ovflpage(hashp, old_bufp);
                                            __add_ovflpage(hashp, old_bufp);
                                        if (!old_bufp)
                                        if (!old_bufp)
                                                return (-1);
                                                return (-1);
                                        op = (__uint16_t *)old_bufp->page;
                                        op = (__uint16_t *)old_bufp->page;
                                        putpair((char *)op, &key, &val);
                                        putpair((char *)op, &key, &val);
                                }
                                }
                                old_bufp->flags |= BUF_MOD;
                                old_bufp->flags |= BUF_MOD;
                        } else {
                        } else {
                                /* Move to new page */
                                /* Move to new page */
                                if (PAIRFITS(np, (&key), (&val)))
                                if (PAIRFITS(np, (&key), (&val)))
                                        putpair((char *)np, &key, &val);
                                        putpair((char *)np, &key, &val);
                                else {
                                else {
                                        new_bufp =
                                        new_bufp =
                                            __add_ovflpage(hashp, new_bufp);
                                            __add_ovflpage(hashp, new_bufp);
                                        if (!new_bufp)
                                        if (!new_bufp)
                                                return (-1);
                                                return (-1);
                                        np = (__uint16_t *)new_bufp->page;
                                        np = (__uint16_t *)new_bufp->page;
                                        putpair((char *)np, &key, &val);
                                        putpair((char *)np, &key, &val);
                                }
                                }
                                new_bufp->flags |= BUF_MOD;
                                new_bufp->flags |= BUF_MOD;
                        }
                        }
                }
                }
        }
        }
        if (last_bfp)
        if (last_bfp)
                __free_ovflpage(hashp, last_bfp);
                __free_ovflpage(hashp, last_bfp);
        return (0);
        return (0);
}
}
 
 
/*
/*
 * Add the given pair to the page
 * Add the given pair to the page
 *
 *
 * Returns:
 * Returns:
 *      0 ==> OK
 *      0 ==> OK
 *      1 ==> failure
 *      1 ==> failure
 */
 */
extern int
extern int
__addel(hashp, bufp, key, val)
__addel(hashp, bufp, key, val)
        HTAB *hashp;
        HTAB *hashp;
        BUFHEAD *bufp;
        BUFHEAD *bufp;
        const DBT *key, *val;
        const DBT *key, *val;
{
{
        __uint16_t *bp, *sop;
        __uint16_t *bp, *sop;
        int do_expand;
        int do_expand;
 
 
        bp = (__uint16_t *)bufp->page;
        bp = (__uint16_t *)bufp->page;
        do_expand = 0;
        do_expand = 0;
        while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
        while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
                /* Exception case */
                /* Exception case */
                if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
                if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
                        /* This is the last page of a big key/data pair
                        /* This is the last page of a big key/data pair
                           and we need to add another page */
                           and we need to add another page */
                        break;
                        break;
                else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
                else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
                        bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
                        bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
                        if (!bufp)
                        if (!bufp)
                                return (-1);
                                return (-1);
                        bp = (__uint16_t *)bufp->page;
                        bp = (__uint16_t *)bufp->page;
                } else
                } else
                        /* Try to squeeze key on this page */
                        /* Try to squeeze key on this page */
                        if (FREESPACE(bp) > PAIRSIZE(key, val)) {
                        if (FREESPACE(bp) > PAIRSIZE(key, val)) {
                                squeeze_key(bp, key, val);
                                squeeze_key(bp, key, val);
                                return (0);
                                return (0);
                        } else {
                        } else {
                                bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
                                bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
                                if (!bufp)
                                if (!bufp)
                                        return (-1);
                                        return (-1);
                                bp = (__uint16_t *)bufp->page;
                                bp = (__uint16_t *)bufp->page;
                        }
                        }
 
 
        if (PAIRFITS(bp, key, val))
        if (PAIRFITS(bp, key, val))
                putpair(bufp->page, key, val);
                putpair(bufp->page, key, val);
        else {
        else {
                do_expand = 1;
                do_expand = 1;
                bufp = __add_ovflpage(hashp, bufp);
                bufp = __add_ovflpage(hashp, bufp);
                if (!bufp)
                if (!bufp)
                        return (-1);
                        return (-1);
                sop = (__uint16_t *)bufp->page;
                sop = (__uint16_t *)bufp->page;
 
 
                if (PAIRFITS(sop, key, val))
                if (PAIRFITS(sop, key, val))
                        putpair((char *)sop, key, val);
                        putpair((char *)sop, key, val);
                else
                else
                        if (__big_insert(hashp, bufp, key, val))
                        if (__big_insert(hashp, bufp, key, val))
                                return (-1);
                                return (-1);
        }
        }
        bufp->flags |= BUF_MOD;
        bufp->flags |= BUF_MOD;
        /*
        /*
         * If the average number of keys per bucket exceeds the fill factor,
         * If the average number of keys per bucket exceeds the fill factor,
         * expand the table.
         * expand the table.
         */
         */
        hashp->NKEYS++;
        hashp->NKEYS++;
        if (do_expand ||
        if (do_expand ||
            (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
            (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
                return (__expand_table(hashp));
                return (__expand_table(hashp));
        return (0);
        return (0);
}
}
 
 
/*
/*
 *
 *
 * Returns:
 * Returns:
 *      pointer on success
 *      pointer on success
 *      NULL on error
 *      NULL on error
 */
 */
extern BUFHEAD *
extern BUFHEAD *
__add_ovflpage(hashp, bufp)
__add_ovflpage(hashp, bufp)
        HTAB *hashp;
        HTAB *hashp;
        BUFHEAD *bufp;
        BUFHEAD *bufp;
{
{
        __uint16_t *sp;
        __uint16_t *sp;
        __uint16_t ndx, ovfl_num;
        __uint16_t ndx, ovfl_num;
#ifdef DEBUG1
#ifdef DEBUG1
        int tmp1, tmp2;
        int tmp1, tmp2;
#endif
#endif
        sp = (__uint16_t *)bufp->page;
        sp = (__uint16_t *)bufp->page;
 
 
        /* Check if we are dynamically determining the fill factor */
        /* Check if we are dynamically determining the fill factor */
        if (hashp->FFACTOR == DEF_FFACTOR) {
        if (hashp->FFACTOR == DEF_FFACTOR) {
                hashp->FFACTOR = sp[0] >> 1;
                hashp->FFACTOR = sp[0] >> 1;
                if (hashp->FFACTOR < MIN_FFACTOR)
                if (hashp->FFACTOR < MIN_FFACTOR)
                        hashp->FFACTOR = MIN_FFACTOR;
                        hashp->FFACTOR = MIN_FFACTOR;
        }
        }
        bufp->flags |= BUF_MOD;
        bufp->flags |= BUF_MOD;
        ovfl_num = overflow_page(hashp);
        ovfl_num = overflow_page(hashp);
#ifdef DEBUG1
#ifdef DEBUG1
        tmp1 = bufp->addr;
        tmp1 = bufp->addr;
        tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
        tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
#endif
#endif
        if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
        if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
                return (NULL);
                return (NULL);
        bufp->ovfl->flags |= BUF_MOD;
        bufp->ovfl->flags |= BUF_MOD;
#ifdef DEBUG1
#ifdef DEBUG1
        (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
        (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
            tmp1, tmp2, bufp->ovfl->addr);
            tmp1, tmp2, bufp->ovfl->addr);
#endif
#endif
        ndx = sp[0];
        ndx = sp[0];
        /*
        /*
         * Since a pair is allocated on a page only if there's room to add
         * Since a pair is allocated on a page only if there's room to add
         * an overflow page, we know that the OVFL information will fit on
         * an overflow page, we know that the OVFL information will fit on
         * the page.
         * the page.
         */
         */
        sp[ndx + 4] = OFFSET(sp);
        sp[ndx + 4] = OFFSET(sp);
        sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
        sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
        sp[ndx + 1] = ovfl_num;
        sp[ndx + 1] = ovfl_num;
        sp[ndx + 2] = OVFLPAGE;
        sp[ndx + 2] = OVFLPAGE;
        sp[0] = ndx + 2;
        sp[0] = ndx + 2;
#ifdef HASH_STATISTICS
#ifdef HASH_STATISTICS
        hash_overflows++;
        hash_overflows++;
#endif
#endif
        return (bufp->ovfl);
        return (bufp->ovfl);
}
}
 
 
/*
/*
 * Returns:
 * Returns:
 *       0 indicates SUCCESS
 *       0 indicates SUCCESS
 *      -1 indicates FAILURE
 *      -1 indicates FAILURE
 */
 */
extern int
extern int
__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
        HTAB *hashp;
        HTAB *hashp;
        char *p;
        char *p;
        __uint32_t bucket;
        __uint32_t bucket;
        int is_bucket, is_disk, is_bitmap;
        int is_bucket, is_disk, is_bitmap;
{
{
        int fd, page, size;
        int fd, page, size;
        int rsize;
        int rsize;
        __uint16_t *bp;
        __uint16_t *bp;
 
 
        fd = hashp->fp;
        fd = hashp->fp;
        size = hashp->BSIZE;
        size = hashp->BSIZE;
 
 
        if ((fd == -1) || !is_disk) {
        if ((fd == -1) || !is_disk) {
                PAGE_INIT(p);
                PAGE_INIT(p);
                return (0);
                return (0);
        }
        }
        if (is_bucket)
        if (is_bucket)
                page = BUCKET_TO_PAGE(bucket);
                page = BUCKET_TO_PAGE(bucket);
        else
        else
                page = OADDR_TO_PAGE(bucket);
                page = OADDR_TO_PAGE(bucket);
        if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
        if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
            ((rsize = read(fd, p, size)) == -1))
            ((rsize = read(fd, p, size)) == -1))
                return (-1);
                return (-1);
        bp = (__uint16_t *)p;
        bp = (__uint16_t *)p;
        if (!rsize)
        if (!rsize)
                bp[0] = 0;        /* We hit the EOF, so initialize a new page */
                bp[0] = 0;        /* We hit the EOF, so initialize a new page */
        else
        else
                if (rsize != size) {
                if (rsize != size) {
                        errno = EFTYPE;
                        errno = EFTYPE;
                        return (-1);
                        return (-1);
                }
                }
        if (!is_bitmap && !bp[0]) {
        if (!is_bitmap && !bp[0]) {
                PAGE_INIT(p);
                PAGE_INIT(p);
        } else
        } else
               if (hashp->LORDER != DB_BYTE_ORDER) {
               if (hashp->LORDER != DB_BYTE_ORDER) {
                        int i, max;
                        int i, max;
 
 
                        if (is_bitmap) {
                        if (is_bitmap) {
                                max = hashp->BSIZE >> 2; /* divide by 4 */
                                max = hashp->BSIZE >> 2; /* divide by 4 */
                                for (i = 0; i < max; i++)
                                for (i = 0; i < max; i++)
                                        M_32_SWAP(((int *)p)[i]);
                                        M_32_SWAP(((int *)p)[i]);
                        } else {
                        } else {
                                M_16_SWAP(bp[0]);
                                M_16_SWAP(bp[0]);
                                max = bp[0] + 2;
                                max = bp[0] + 2;
                                for (i = 1; i <= max; i++)
                                for (i = 1; i <= max; i++)
                                        M_16_SWAP(bp[i]);
                                        M_16_SWAP(bp[i]);
                        }
                        }
                }
                }
        return (0);
        return (0);
}
}
 
 
/*
/*
 * Write page p to disk
 * Write page p to disk
 *
 *
 * Returns:
 * Returns:
 *       0 ==> OK
 *       0 ==> OK
 *      -1 ==>failure
 *      -1 ==>failure
 */
 */
extern int
extern int
__put_page(hashp, p, bucket, is_bucket, is_bitmap)
__put_page(hashp, p, bucket, is_bucket, is_bitmap)
        HTAB *hashp;
        HTAB *hashp;
        char *p;
        char *p;
        __uint32_t bucket;
        __uint32_t bucket;
        int is_bucket, is_bitmap;
        int is_bucket, is_bitmap;
{
{
        int fd, page, size;
        int fd, page, size;
        int wsize;
        int wsize;
 
 
        size = hashp->BSIZE;
        size = hashp->BSIZE;
        if ((hashp->fp == -1) && open_temp(hashp))
        if ((hashp->fp == -1) && open_temp(hashp))
                return (-1);
                return (-1);
        fd = hashp->fp;
        fd = hashp->fp;
 
 
       if (hashp->LORDER != DB_BYTE_ORDER) {
       if (hashp->LORDER != DB_BYTE_ORDER) {
                int i;
                int i;
                int max;
                int max;
 
 
                if (is_bitmap) {
                if (is_bitmap) {
                        max = hashp->BSIZE >> 2;        /* divide by 4 */
                        max = hashp->BSIZE >> 2;        /* divide by 4 */
                        for (i = 0; i < max; i++)
                        for (i = 0; i < max; i++)
                                M_32_SWAP(((int *)p)[i]);
                                M_32_SWAP(((int *)p)[i]);
                } else {
                } else {
                        max = ((__uint16_t *)p)[0] + 2;
                        max = ((__uint16_t *)p)[0] + 2;
                        for (i = 0; i <= max; i++)
                        for (i = 0; i <= max; i++)
                                M_16_SWAP(((__uint16_t *)p)[i]);
                                M_16_SWAP(((__uint16_t *)p)[i]);
                }
                }
        }
        }
        if (is_bucket)
        if (is_bucket)
                page = BUCKET_TO_PAGE(bucket);
                page = BUCKET_TO_PAGE(bucket);
        else
        else
                page = OADDR_TO_PAGE(bucket);
                page = OADDR_TO_PAGE(bucket);
        if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
        if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
            ((wsize = write(fd, p, size)) == -1))
            ((wsize = write(fd, p, size)) == -1))
                /* Errno is set */
                /* Errno is set */
                return (-1);
                return (-1);
        if (wsize != size) {
        if (wsize != size) {
                errno = EFTYPE;
                errno = EFTYPE;
                return (-1);
                return (-1);
        }
        }
        return (0);
        return (0);
}
}
 
 
#define BYTE_MASK       ((1 << INT_BYTE_SHIFT) -1)
#define BYTE_MASK       ((1 << INT_BYTE_SHIFT) -1)
/*
/*
 * Initialize a new bitmap page.  Bitmap pages are left in memory
 * Initialize a new bitmap page.  Bitmap pages are left in memory
 * once they are read in.
 * once they are read in.
 */
 */
extern int
extern int
__ibitmap(hashp, pnum, nbits, ndx)
__ibitmap(hashp, pnum, nbits, ndx)
        HTAB *hashp;
        HTAB *hashp;
        int pnum, nbits, ndx;
        int pnum, nbits, ndx;
{
{
        __uint32_t *ip;
        __uint32_t *ip;
        int clearbytes, clearints;
        int clearbytes, clearints;
 
 
        if ((ip = (__uint32_t *)malloc(hashp->BSIZE)) == NULL)
        if ((ip = (__uint32_t *)malloc(hashp->BSIZE)) == NULL)
                return (1);
                return (1);
        hashp->nmaps++;
        hashp->nmaps++;
        clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
        clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
        clearbytes = clearints << INT_TO_BYTE;
        clearbytes = clearints << INT_TO_BYTE;
        (void)memset((char *)ip, 0, clearbytes);
        (void)memset((char *)ip, 0, clearbytes);
        (void)memset(((char *)ip) + clearbytes, 0xFF,
        (void)memset(((char *)ip) + clearbytes, 0xFF,
            hashp->BSIZE - clearbytes);
            hashp->BSIZE - clearbytes);
        ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
        ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
        SETBIT(ip, 0);
        SETBIT(ip, 0);
        hashp->BITMAPS[ndx] = (__uint16_t)pnum;
        hashp->BITMAPS[ndx] = (__uint16_t)pnum;
        hashp->mapp[ndx] = ip;
        hashp->mapp[ndx] = ip;
        return (0);
        return (0);
}
}
 
 
static __uint32_t
static __uint32_t
first_free(map)
first_free(map)
        __uint32_t map;
        __uint32_t map;
{
{
        __uint32_t i, mask;
        __uint32_t i, mask;
 
 
        mask = 0x1;
        mask = 0x1;
        for (i = 0; i < BITS_PER_MAP; i++) {
        for (i = 0; i < BITS_PER_MAP; i++) {
                if (!(mask & map))
                if (!(mask & map))
                        return (i);
                        return (i);
                mask = mask << 1;
                mask = mask << 1;
        }
        }
        return (i);
        return (i);
}
}
 
 
static __uint16_t
static __uint16_t
overflow_page(hashp)
overflow_page(hashp)
        HTAB *hashp;
        HTAB *hashp;
{
{
        __uint32_t *freep;
        __uint32_t *freep;
        int max_free, offset, splitnum;
        int max_free, offset, splitnum;
        __uint16_t addr;
        __uint16_t addr;
        int bit, first_page, free_bit, free_page, i, in_use_bits, j;
        int bit, first_page, free_bit, free_page, i, in_use_bits, j;
#ifdef DEBUG2
#ifdef DEBUG2
        int tmp1, tmp2;
        int tmp1, tmp2;
#endif
#endif
        splitnum = hashp->OVFL_POINT;
        splitnum = hashp->OVFL_POINT;
        max_free = hashp->SPARES[splitnum];
        max_free = hashp->SPARES[splitnum];
 
 
        free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
        free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
        free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
        free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
 
 
        /* Look through all the free maps to find the first free block */
        /* Look through all the free maps to find the first free block */
        first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
        first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
        for ( i = first_page; i <= free_page; i++ ) {
        for ( i = first_page; i <= free_page; i++ ) {
                if (!(freep = (__uint32_t *)hashp->mapp[i]) &&
                if (!(freep = (__uint32_t *)hashp->mapp[i]) &&
                    !(freep = fetch_bitmap(hashp, i)))
                    !(freep = fetch_bitmap(hashp, i)))
                        return (0);
                        return (0);
                if (i == free_page)
                if (i == free_page)
                        in_use_bits = free_bit;
                        in_use_bits = free_bit;
                else
                else
                        in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
                        in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
 
 
                if (i == first_page) {
                if (i == first_page) {
                        bit = hashp->LAST_FREED &
                        bit = hashp->LAST_FREED &
                            ((hashp->BSIZE << BYTE_SHIFT) - 1);
                            ((hashp->BSIZE << BYTE_SHIFT) - 1);
                        j = bit / BITS_PER_MAP;
                        j = bit / BITS_PER_MAP;
                        bit = bit & ~(BITS_PER_MAP - 1);
                        bit = bit & ~(BITS_PER_MAP - 1);
                } else {
                } else {
                        bit = 0;
                        bit = 0;
                        j = 0;
                        j = 0;
                }
                }
                for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
                for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
                        if (freep[j] != ALL_SET)
                        if (freep[j] != ALL_SET)
                                goto found;
                                goto found;
        }
        }
 
 
        /* No Free Page Found */
        /* No Free Page Found */
        hashp->LAST_FREED = hashp->SPARES[splitnum];
        hashp->LAST_FREED = hashp->SPARES[splitnum];
        hashp->SPARES[splitnum]++;
        hashp->SPARES[splitnum]++;
        offset = hashp->SPARES[splitnum] -
        offset = hashp->SPARES[splitnum] -
            (splitnum ? hashp->SPARES[splitnum - 1] : 0);
            (splitnum ? hashp->SPARES[splitnum - 1] : 0);
 
 
#define OVMSG   "HASH: Out of overflow pages.  Increase page size\n"
#define OVMSG   "HASH: Out of overflow pages.  Increase page size\n"
        if (offset > SPLITMASK) {
        if (offset > SPLITMASK) {
                if (++splitnum >= NCACHED) {
                if (++splitnum >= NCACHED) {
                        (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
                        (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
                        return (0);
                        return (0);
                }
                }
                hashp->OVFL_POINT = splitnum;
                hashp->OVFL_POINT = splitnum;
                hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
                hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
                hashp->SPARES[splitnum-1]--;
                hashp->SPARES[splitnum-1]--;
                offset = 1;
                offset = 1;
        }
        }
 
 
        /* Check if we need to allocate a new bitmap page */
        /* Check if we need to allocate a new bitmap page */
        if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
        if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
                free_page++;
                free_page++;
                if (free_page >= NCACHED) {
                if (free_page >= NCACHED) {
                        (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
                        (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
                        return (0);
                        return (0);
                }
                }
                /*
                /*
                 * This is tricky.  The 1 indicates that you want the new page
                 * This is tricky.  The 1 indicates that you want the new page
                 * allocated with 1 clear bit.  Actually, you are going to
                 * allocated with 1 clear bit.  Actually, you are going to
                 * allocate 2 pages from this map.  The first is going to be
                 * allocate 2 pages from this map.  The first is going to be
                 * the map page, the second is the overflow page we were
                 * the map page, the second is the overflow page we were
                 * looking for.  The init_bitmap routine automatically, sets
                 * looking for.  The init_bitmap routine automatically, sets
                 * the first bit of itself to indicate that the bitmap itself
                 * the first bit of itself to indicate that the bitmap itself
                 * is in use.  We would explicitly set the second bit, but
                 * is in use.  We would explicitly set the second bit, but
                 * don't have to if we tell init_bitmap not to leave it clear
                 * don't have to if we tell init_bitmap not to leave it clear
                 * in the first place.
                 * in the first place.
                 */
                 */
                if (__ibitmap(hashp,
                if (__ibitmap(hashp,
                    (int)OADDR_OF(splitnum, offset), 1, free_page))
                    (int)OADDR_OF(splitnum, offset), 1, free_page))
                        return (0);
                        return (0);
                hashp->SPARES[splitnum]++;
                hashp->SPARES[splitnum]++;
#ifdef DEBUG2
#ifdef DEBUG2
                free_bit = 2;
                free_bit = 2;
#endif
#endif
                offset++;
                offset++;
                if (offset > SPLITMASK) {
                if (offset > SPLITMASK) {
                        if (++splitnum >= NCACHED) {
                        if (++splitnum >= NCACHED) {
                                (void)write(STDERR_FILENO, OVMSG,
                                (void)write(STDERR_FILENO, OVMSG,
                                    sizeof(OVMSG) - 1);
                                    sizeof(OVMSG) - 1);
                                return (0);
                                return (0);
                        }
                        }
                        hashp->OVFL_POINT = splitnum;
                        hashp->OVFL_POINT = splitnum;
                        hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
                        hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
                        hashp->SPARES[splitnum-1]--;
                        hashp->SPARES[splitnum-1]--;
                        offset = 0;
                        offset = 0;
                }
                }
        } else {
        } else {
                /*
                /*
                 * Free_bit addresses the last used bit.  Bump it to address
                 * Free_bit addresses the last used bit.  Bump it to address
                 * the first available bit.
                 * the first available bit.
                 */
                 */
                free_bit++;
                free_bit++;
                SETBIT(freep, free_bit);
                SETBIT(freep, free_bit);
        }
        }
 
 
        /* Calculate address of the new overflow page */
        /* Calculate address of the new overflow page */
        addr = OADDR_OF(splitnum, offset);
        addr = OADDR_OF(splitnum, offset);
#ifdef DEBUG2
#ifdef DEBUG2
        (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
        (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
            addr, free_bit, free_page);
            addr, free_bit, free_page);
#endif
#endif
        return (addr);
        return (addr);
 
 
found:
found:
        bit = bit + first_free(freep[j]);
        bit = bit + first_free(freep[j]);
        SETBIT(freep, bit);
        SETBIT(freep, bit);
#ifdef DEBUG2
#ifdef DEBUG2
        tmp1 = bit;
        tmp1 = bit;
        tmp2 = i;
        tmp2 = i;
#endif
#endif
        /*
        /*
         * Bits are addressed starting with 0, but overflow pages are addressed
         * Bits are addressed starting with 0, but overflow pages are addressed
         * beginning at 1. Bit is a bit addressnumber, so we need to increment
         * beginning at 1. Bit is a bit addressnumber, so we need to increment
         * it to convert it to a page number.
         * it to convert it to a page number.
         */
         */
        bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
        bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
        if (bit >= hashp->LAST_FREED)
        if (bit >= hashp->LAST_FREED)
                hashp->LAST_FREED = bit - 1;
                hashp->LAST_FREED = bit - 1;
 
 
        /* Calculate the split number for this page */
        /* Calculate the split number for this page */
        for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
        for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
        offset = (i ? bit - hashp->SPARES[i - 1] : bit);
        offset = (i ? bit - hashp->SPARES[i - 1] : bit);
        if (offset >= SPLITMASK)
        if (offset >= SPLITMASK)
                return (0);      /* Out of overflow pages */
                return (0);      /* Out of overflow pages */
        addr = OADDR_OF(i, offset);
        addr = OADDR_OF(i, offset);
#ifdef DEBUG2
#ifdef DEBUG2
        (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
        (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
            addr, tmp1, tmp2);
            addr, tmp1, tmp2);
#endif
#endif
 
 
        /* Allocate and return the overflow page */
        /* Allocate and return the overflow page */
        return (addr);
        return (addr);
}
}
 
 
/*
/*
 * Mark this overflow page as free.
 * Mark this overflow page as free.
 */
 */
extern void
extern void
__free_ovflpage(hashp, obufp)
__free_ovflpage(hashp, obufp)
        HTAB *hashp;
        HTAB *hashp;
        BUFHEAD *obufp;
        BUFHEAD *obufp;
{
{
        __uint16_t addr;
        __uint16_t addr;
        __uint32_t *freep;
        __uint32_t *freep;
        int bit_address, free_page, free_bit;
        int bit_address, free_page, free_bit;
        __uint16_t ndx;
        __uint16_t ndx;
 
 
        addr = obufp->addr;
        addr = obufp->addr;
#ifdef DEBUG1
#ifdef DEBUG1
        (void)fprintf(stderr, "Freeing %d\n", addr);
        (void)fprintf(stderr, "Freeing %d\n", addr);
#endif
#endif
        ndx = (((__uint16_t)addr) >> SPLITSHIFT);
        ndx = (((__uint16_t)addr) >> SPLITSHIFT);
        bit_address =
        bit_address =
            (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
            (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
         if (bit_address < hashp->LAST_FREED)
         if (bit_address < hashp->LAST_FREED)
                hashp->LAST_FREED = bit_address;
                hashp->LAST_FREED = bit_address;
        free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
        free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
        free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
        free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
 
 
        if (!(freep = hashp->mapp[free_page]))
        if (!(freep = hashp->mapp[free_page]))
                freep = fetch_bitmap(hashp, free_page);
                freep = fetch_bitmap(hashp, free_page);
#ifdef DEBUG
#ifdef DEBUG
        /*
        /*
         * This had better never happen.  It means we tried to read a bitmap
         * This had better never happen.  It means we tried to read a bitmap
         * that has already had overflow pages allocated off it, and we
         * that has already had overflow pages allocated off it, and we
         * failed to read it from the file.
         * failed to read it from the file.
         */
         */
        if (!freep)
        if (!freep)
                assert(0);
                assert(0);
#endif
#endif
        CLRBIT(freep, free_bit);
        CLRBIT(freep, free_bit);
#ifdef DEBUG2
#ifdef DEBUG2
        (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
        (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
            obufp->addr, free_bit, free_page);
            obufp->addr, free_bit, free_page);
#endif
#endif
        __reclaim_buf(hashp, obufp);
        __reclaim_buf(hashp, obufp);
}
}
 
 
/*
/*
 * Returns:
 * Returns:
 *       0 success
 *       0 success
 *      -1 failure
 *      -1 failure
 */
 */
static int
static int
open_temp(hashp)
open_temp(hashp)
        HTAB *hashp;
        HTAB *hashp;
{
{
        sigset_t set, oset;
        sigset_t set, oset;
        static char namestr[] = "_hashXXXXXX";
        static char namestr[] = "_hashXXXXXX";
 
 
        /* Block signals; make sure file goes away at process exit. */
        /* Block signals; make sure file goes away at process exit. */
        (void)sigfillset(&set);
        (void)sigfillset(&set);
        (void)sigprocmask(SIG_BLOCK, &set, &oset);
        (void)sigprocmask(SIG_BLOCK, &set, &oset);
        if ((hashp->fp = mkstemp(namestr)) != -1) {
        if ((hashp->fp = mkstemp(namestr)) != -1) {
                (void)unlink(namestr);
                (void)unlink(namestr);
#ifdef HAVE_FCNTL
#ifdef HAVE_FCNTL
                (void)fcntl(hashp->fp, F_SETFD, 1);
                (void)fcntl(hashp->fp, F_SETFD, 1);
#endif
#endif
        }
        }
        (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
        (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
        return (hashp->fp != -1 ? 0 : -1);
        return (hashp->fp != -1 ? 0 : -1);
}
}
 
 
/*
/*
 * We have to know that the key will fit, but the last entry on the page is
 * We have to know that the key will fit, but the last entry on the page is
 * an overflow pair, so we need to shift things.
 * an overflow pair, so we need to shift things.
 */
 */
static void
static void
squeeze_key(sp, key, val)
squeeze_key(sp, key, val)
        __uint16_t *sp;
        __uint16_t *sp;
        const DBT *key, *val;
        const DBT *key, *val;
{
{
        char *p;
        char *p;
        __uint16_t free_space, n, off, pageno;
        __uint16_t free_space, n, off, pageno;
 
 
        p = (char *)sp;
        p = (char *)sp;
        n = sp[0];
        n = sp[0];
        free_space = FREESPACE(sp);
        free_space = FREESPACE(sp);
        off = OFFSET(sp);
        off = OFFSET(sp);
 
 
        pageno = sp[n - 1];
        pageno = sp[n - 1];
        off -= key->size;
        off -= key->size;
        sp[n - 1] = off;
        sp[n - 1] = off;
        memmove(p + off, key->data, key->size);
        memmove(p + off, key->data, key->size);
        off -= val->size;
        off -= val->size;
        sp[n] = off;
        sp[n] = off;
        memmove(p + off, val->data, val->size);
        memmove(p + off, val->data, val->size);
        sp[0] = n + 2;
        sp[0] = n + 2;
        sp[n + 1] = pageno;
        sp[n + 1] = pageno;
        sp[n + 2] = OVFLPAGE;
        sp[n + 2] = OVFLPAGE;
        FREESPACE(sp) = free_space - PAIRSIZE(key, val);
        FREESPACE(sp) = free_space - PAIRSIZE(key, val);
        OFFSET(sp) = off;
        OFFSET(sp) = off;
}
}
 
 
static __uint32_t *
static __uint32_t *
fetch_bitmap(hashp, ndx)
fetch_bitmap(hashp, ndx)
        HTAB *hashp;
        HTAB *hashp;
        int ndx;
        int ndx;
{
{
        if (ndx >= hashp->nmaps)
        if (ndx >= hashp->nmaps)
                return (NULL);
                return (NULL);
        if ((hashp->mapp[ndx] = (__uint32_t *)malloc(hashp->BSIZE)) == NULL)
        if ((hashp->mapp[ndx] = (__uint32_t *)malloc(hashp->BSIZE)) == NULL)
                return (NULL);
                return (NULL);
        if (__get_page(hashp,
        if (__get_page(hashp,
            (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
            (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
                free(hashp->mapp[ndx]);
                free(hashp->mapp[ndx]);
                return (NULL);
                return (NULL);
        }
        }
        return (hashp->mapp[ndx]);
        return (hashp->mapp[ndx]);
}
}
 
 
#ifdef DEBUG4
#ifdef DEBUG4
int
int
print_chain(addr)
print_chain(addr)
        int addr;
        int addr;
{
{
        BUFHEAD *bufp;
        BUFHEAD *bufp;
        short *bp, oaddr;
        short *bp, oaddr;
 
 
        (void)fprintf(stderr, "%d ", addr);
        (void)fprintf(stderr, "%d ", addr);
        bufp = __get_buf(hashp, addr, NULL, 0);
        bufp = __get_buf(hashp, addr, NULL, 0);
        bp = (short *)bufp->page;
        bp = (short *)bufp->page;
        while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
        while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
                ((bp[0] > 2) && bp[2] < REAL_KEY))) {
                ((bp[0] > 2) && bp[2] < REAL_KEY))) {
                oaddr = bp[bp[0] - 1];
                oaddr = bp[bp[0] - 1];
                (void)fprintf(stderr, "%d ", (int)oaddr);
                (void)fprintf(stderr, "%d ", (int)oaddr);
                bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
                bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
                bp = (short *)bufp->page;
                bp = (short *)bufp->page;
        }
        }
        (void)fprintf(stderr, "\n");
        (void)fprintf(stderr, "\n");
}
}
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.