예제 #1
0
/*
 * Add the given pair to the page
 *
 * Returns:
 *	0 ==> OK
 *	1 ==> failure
 */
extern int
__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
	u_int16_t *bp, *sop;
	int do_expand;

	bp = (u_int16_t *)bufp->page;
	do_expand = 0;
	while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
		/* Exception case */
		if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
			/* This is the last page of a big key/data pair
			   and we need to add another page */
			break;
		else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
			bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
			if (!bufp)
				return (-1);
			bp = (u_int16_t *)bufp->page;
		} else
			/* Try to squeeze key on this page */
			if (FREESPACE(bp) > PAIRSIZE(key, val)) {
				squeeze_key(bp, key, val);
				return (0);
			} else {
				bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
				if (!bufp)
					return (-1);
				bp = (u_int16_t *)bufp->page;
			}

	if (PAIRFITS(bp, key, val))
		putpair(bufp->page, key, val);
	else {
		do_expand = 1;
		bufp = __add_ovflpage(hashp, bufp);
		if (!bufp)
			return (-1);
		sop = (u_int16_t *)bufp->page;

		if (PAIRFITS(sop, key, val))
			putpair((char *)sop, key, val);
		else
			if (__big_insert(hashp, bufp, key, val))
				return (-1);
	}
	bufp->flags |= BUF_MOD;
	/*
	 * If the average number of keys per bucket exceeds the fill factor,
	 * expand the table.
	 */
	hashp->NKEYS++;
	if (do_expand ||
	    (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
		return (__expand_table(hashp));
	return (0);
}
예제 #2
0
파일: pair.c 프로젝트: 1310701102/sl4a
void
splpage(char *pag, char *New, long int sbit)
{
	datum key;
	datum val;

	register int n;
	register int off = PBLKSIZ;
	char cur[PBLKSIZ];
	register short *ino = (short *) cur;

	(void) memcpy(cur, pag, PBLKSIZ);
	(void) memset(pag, 0, PBLKSIZ);
	(void) memset(New, 0, PBLKSIZ);

	n = ino[0];
	for (ino++; n > 0; ino += 2) {
		key.dptr = cur + ino[0]; 
		key.dsize = off - ino[0];
		val.dptr = cur + ino[1];
		val.dsize = ino[0] - ino[1];
/*
 * select the page pointer (by looking at sbit) and insert
 */
		(void) putpair((exhash(key) & sbit) ? New : pag, key, val);

		off = ino[1];
		n -= 2;
	}

	debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
	       ((short *) New)[0] / 2,
	       ((short *) pag)[0] / 2));
}
예제 #3
0
void
cmdlinePairExtract(char *buf, int (*putpair)(char *str), int removeFound)
{
char *beg,*end;

	if ( !buf || !putpair )
		return;

	/* find 'name=' tags */

	/* this algorithm is copied from the svgm BSP (startup/bspstart.c) */
	for (beg=buf; beg && (beg=fnam(beg)); beg=end) {
		/* simple algorithm to find the end of quoted 'name=quoted'
		 * substring. As a side effect, quotes are removed from
		 * the value.
		 */
		if ( (end = strchr(beg,'=')) ) {
			char *dst;

			/* now unquote the value */
			if ('\'' == *++end) {
				/* end points to the 1st char after '=' which is a '\'' */

				dst = end++;

				/* end points to 1st char after '\'' */

				while ('\'' != *end || '\'' == *++end) {
					if ( 0 == (*dst++=*end++) ) {
						/* NO TERMINATING QUOTE FOUND
						 * (for a properly quoted string we
						 * should never get here)
						 */
						end = 0;
						dst--;
						break;
					}
				}
				*dst = 0;
			} else {
				/* first space terminates non-quoted strings */
				if ( (dst = end = strchr(end,' ')) )
					*(end++)=0;
			}
			if ( 0 == putpair(beg) && removeFound ) {
				if ( end ) {
					memmove(beg, end, strlen(end)+1);
					end = beg;
				} else {
					*beg = 0;
				}
			} else {
				if ( dst )
					*dst = ' ';
			}
		}
	}
	return;
}
예제 #4
0
파일: sdbm.c 프로젝트: JoeFord/rig-build
int
sdbm_store(register DBM *db, datum key, datum val, int flags)
{
	int need;
	register long hash;

	if (db == NULL || bad(key))
		return errno = EINVAL, -1;
	if (sdbm_rdonly(db))
		return errno = EPERM, -1;

	need = key.dsize + val.dsize;
/*
 * is the pair too big (or too small) for this database ??
 */
	if (need < 0 || need > PAIRMAX)
		return errno = EINVAL, -1;

	if (getpage(db, (hash = exhash(key)))) {
/*
 * if we need to replace, delete the key/data pair
 * first. If it is not there, ignore.
 */
		if (flags == DBM_REPLACE)
			(void) delpair(db->pagbuf, key);
#ifdef SEEDUPS
		else if (duppair(db->pagbuf, key))
			return 1;
#endif
/*
 * if we do not have enough room, we have to split.
 */
		if (!fitpair(db->pagbuf, need))
			if (!makroom(db, hash, need))
				return ioerr(db), -1;
/*
 * we have enough room or split is successful. insert the key,
 * and update the page file.
 */
		(void) putpair(db->pagbuf, key, val);

		if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
		    || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
			return ioerr(db), -1;
	/*
	 * success
	 */
		return 0;
	}

	return ioerr(db), -1;
}
예제 #5
0
/*
 * 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
 * the key/data pairs fit on their respective pages and because we may need
 * overflow pages for both the old and new pages.
 *
 * 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
 * page or it might be a big key/data pair in which case we need to fix the
 * big key/data pair.
 *
 * Returns:
 *	 0 ==> success
 *	-1 ==> failure
 */
static int
ugly_split(
	HTAB *hashp,
	uint32_t obucket,	/* Same as __split_page. */
	BUFHEAD *old_bufp,
	BUFHEAD *new_bufp,
	int copyto,	/* First byte on page which contains key/data values. */
	int moved	/* Number of pairs moved to new page. */
)
{
	BUFHEAD *bufp;	/* Buffer header for ino */
	uint16_t *ino;	/* Page keys come off of */
	uint16_t *np;	/* New page */
	uint16_t *op;	/* Page keys go on to if they aren't moving */
	size_t temp;

	BUFHEAD *last_bfp;	/* Last buf header OVFL needing to be freed */
	DBT key, val;
	SPLIT_RETURN ret;
	uint16_t n, off, ov_addr, scopyto;
	char *cino;		/* Character value of ino */

	bufp = old_bufp;
	ino = (uint16_t *)(void *)old_bufp->page;
	np = (uint16_t *)(void *)new_bufp->page;
	op = (uint16_t *)(void *)old_bufp->page;
	last_bfp = NULL;
	scopyto = (uint16_t)copyto;	/* ANSI */

	n = ino[0] - 1;
	while (n < ino[0]) {
		if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
			if (__big_split(hashp, old_bufp,
			    new_bufp, bufp, (int)bufp->addr, obucket, &ret))
				return (-1);
			old_bufp = ret.oldp;
			if (!old_bufp)
				return (-1);
			op = (uint16_t *)(void *)old_bufp->page;
			new_bufp = ret.newp;
			if (!new_bufp)
				return (-1);
			np = (uint16_t *)(void *)new_bufp->page;
			bufp = ret.nextp;
			if (!bufp)
				return (0);
			cino = (char *)bufp->page;
			ino = (uint16_t *)(void *)cino;
			last_bfp = ret.nextp;
		} else if (ino[n + 1] == OVFLPAGE) {
			ov_addr = ino[n];
			/*
			 * Fix up the old page -- the extra 2 are the fields
			 * which contained the overflow information.
			 */
			ino[0] -= (moved + 2);
			temp = sizeof(uint16_t) * (ino[0] + 3);
			_DIAGASSERT(scopyto >= temp);
			FREESPACE(ino) = (uint16_t)(scopyto - temp);
			OFFSET(ino) = scopyto;

			bufp = __get_buf(hashp, (uint32_t)ov_addr, bufp, 0);
			if (!bufp)
				return (-1);

			ino = (uint16_t *)(void *)bufp->page;
			n = 1;
			scopyto = hashp->BSIZE;
			moved = 0;

			if (last_bfp)
				__free_ovflpage(hashp, last_bfp);
			last_bfp = bufp;
		}
		/* Move regular sized pairs of there are any */
		off = hashp->BSIZE;
		for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
			cino = (char *)(void *)ino;
			key.data = (uint8_t *)cino + ino[n];
			key.size = off - ino[n];
			val.data = (uint8_t *)cino + ino[n + 1];
			val.size = ino[n] - ino[n + 1];
			off = ino[n + 1];

			if (__call_hash(hashp, key.data, (int)key.size) == obucket) {
				/* Keep on old page */
				if (PAIRFITS(op, (&key), (&val)))
					putpair((char *)(void *)op, &key, &val);
				else {
					old_bufp =
					    __add_ovflpage(hashp, old_bufp);
					if (!old_bufp)
						return (-1);
					op = (uint16_t *)(void *)old_bufp->page;
					putpair((char *)(void *)op, &key, &val);
				}
				old_bufp->flags |= BUF_MOD;
			} else {
				/* Move to new page */
				if (PAIRFITS(np, (&key), (&val)))
					putpair((char *)(void *)np, &key, &val);
				else {
					new_bufp =
					    __add_ovflpage(hashp, new_bufp);
					if (!new_bufp)
						return (-1);
					np = (uint16_t *)(void *)new_bufp->page;
					putpair((char *)(void *)np, &key, &val);
				}
				new_bufp->flags |= BUF_MOD;
			}
		}
	}
	if (last_bfp)
		__free_ovflpage(hashp, last_bfp);
	return (0);
}
예제 #6
0
/*
 * Returns:
 *	 0 ==> OK
 *	-1 ==> Error
 */
int
__split_page(HTAB *hashp, uint32_t obucket, uint32_t nbucket)
{
	BUFHEAD *new_bufp, *old_bufp;
	uint16_t *ino;
	char *np;
	DBT key, val;
	int n, ndx, retval;
	uint16_t copyto, diff, off, moved;
	char *op;
	size_t temp;

	copyto = (uint16_t)hashp->BSIZE;
	off = (uint16_t)hashp->BSIZE;
	old_bufp = __get_buf(hashp, obucket, NULL, 0);
	if (old_bufp == NULL)
		return (-1);
	new_bufp = __get_buf(hashp, nbucket, NULL, 0);
	if (new_bufp == NULL)
		return (-1);

	old_bufp->flags |= (BUF_MOD | BUF_PIN);
	new_bufp->flags |= (BUF_MOD | BUF_PIN);

	ino = (uint16_t *)(void *)(op = old_bufp->page);
	np = new_bufp->page;

	moved = 0;

	for (n = 1, ndx = 1; n < ino[0]; n += 2) {
		if (ino[n + 1] < REAL_KEY) {
			retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
			    (int)copyto, (int)moved);
			old_bufp->flags &= ~BUF_PIN;
			new_bufp->flags &= ~BUF_PIN;
			return (retval);

		}
		key.data = (uint8_t *)op + ino[n];
		key.size = off - ino[n];

		if (__call_hash(hashp, key.data, (int)key.size) == obucket) {
			/* Don't switch page */
			diff = copyto - off;
			if (diff) {
				copyto = ino[n + 1] + diff;
				memmove(op + copyto, op + ino[n + 1],
				    (size_t)(off - ino[n + 1]));
				ino[ndx] = copyto + ino[n] - ino[n + 1];
				ino[ndx + 1] = copyto;
			} else
				copyto = ino[n + 1];
			ndx += 2;
		} else {
			/* Switch page */
			val.data = (uint8_t *)op + ino[n + 1];
			val.size = ino[n] - ino[n + 1];
			putpair(np, &key, &val);
			moved += 2;
		}

		off = ino[n + 1];
	}

	/* Now clean up the page */
	ino[0] -= moved;
	temp = sizeof(uint16_t) * (ino[0] + 3);
	_DIAGASSERT(copyto >= temp);
	FREESPACE(ino) = (uint16_t)(copyto - temp);
	OFFSET(ino) = copyto;

#ifdef DEBUG3
	(void)fprintf(stderr, "split %d/%d\n",
	    ((uint16_t *)np)[0] / 2,
	    ((uint16_t *)op)[0] / 2);
#endif
	/* unpin both pages */
	old_bufp->flags &= ~BUF_PIN;
	new_bufp->flags &= ~BUF_PIN;
	return (0);
}
예제 #7
0
파일: h_page.c 프로젝트: MekliCZ/positron
/*
 * Add the given pair to the page
 *
 * Returns:
 *  0 ==> OK
 *  1 ==> failure
 */
extern int
__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
    register uint16 *bp, *sop;
    int do_expand;

    bp = (uint16 *)bufp->page;
    do_expand = 0;
    while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
        /* Exception case */
        if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
            /* This is the last page of a big key/data pair
               and we need to add another page */
            break;
        else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
            bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
            if (!bufp) {
#ifdef DEBUG
                assert(0);
#endif
                return (-1);
            }
            bp = (uint16 *)bufp->page;
        } else
            /* Try to squeeze key on this page */
            if (FREESPACE(bp) > PAIRSIZE(key, val)) {
            {
                squeeze_key(bp, key, val);

                /* LJM: I added this because I think it was
                 * left out on accident.
                 * if this isn't incremented nkeys will not
                 * be the actual number of keys in the db.
                 */
                hashp->NKEYS++;
                return (0);
            }
        } else {
            bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
            if (!bufp) {
#ifdef DEBUG
                assert(0);
#endif
                return (-1);
            }
            bp = (uint16 *)bufp->page;
        }

    if (PAIRFITS(bp, key, val))
        putpair(bufp->page, key, (DBT *)val);
    else {
        do_expand = 1;
        bufp = __add_ovflpage(hashp, bufp);
        if (!bufp) {
#ifdef DEBUG
            assert(0);
#endif
            return (-1);
        }
        sop = (uint16 *)bufp->page;

        if (PAIRFITS(sop, key, val))
            putpair((char *)sop, key, (DBT *)val);
        else if (__big_insert(hashp, bufp, key, val)) {
#ifdef DEBUG
            assert(0);
#endif
            return (-1);
        }
    }
    bufp->flags |= BUF_MOD;
    /*
     * If the average number of keys per bucket exceeds the fill factor,
     * expand the table.
     */
    hashp->NKEYS++;
    if (do_expand ||
        (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
        return (__expand_table(hashp));
    return (0);
}
예제 #8
0
파일: h_page.c 프로젝트: MekliCZ/positron
static int
ugly_split(HTAB *hashp, uint32 obucket, BUFHEAD *old_bufp,
           BUFHEAD *new_bufp, /* Same as __split_page. */ int copyto, int moved)
/* int copyto;   First byte on page which contains key/data values. */
/* int moved;    Number of pairs moved to new page. */
{
    register BUFHEAD *bufp; /* Buffer header for ino */
    register uint16 *ino;   /* Page keys come off of */
    register uint16 *np;    /* New page */
    register uint16 *op;    /* Page keys go on to if they aren't moving */
    uint32 loop_detection = 0;

    BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */
    DBT key, val;
    SPLIT_RETURN ret;
    uint16 n, off, ov_addr, scopyto;
    char *cino; /* Character value of ino */
    int status;

    bufp = old_bufp;
    ino = (uint16 *)old_bufp->page;
    np = (uint16 *)new_bufp->page;
    op = (uint16 *)old_bufp->page;
    last_bfp = NULL;
    scopyto = (uint16)copyto; /* ANSI */

    n = ino[0] - 1;
    while (n < ino[0]) {

        /* this function goes nuts sometimes and never returns.
         * I havent found the problem yet but I need a solution
         * so if we loop too often we assume a database curruption error
         * :LJM
         */
        loop_detection++;

        if (loop_detection > MAX_UGLY_SPLIT_LOOPS)
            return DATABASE_CORRUPTED_ERROR;

        if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
            if ((status = __big_split(hashp, old_bufp,
                                      new_bufp, bufp, bufp->addr, obucket, &ret)))
                return (status);
            old_bufp = ret.oldp;
            if (!old_bufp)
                return (-1);
            op = (uint16 *)old_bufp->page;
            new_bufp = ret.newp;
            if (!new_bufp)
                return (-1);
            np = (uint16 *)new_bufp->page;
            bufp = ret.nextp;
            if (!bufp)
                return (0);
            cino = (char *)bufp->page;
            ino = (uint16 *)cino;
            last_bfp = ret.nextp;
        } else if (ino[n + 1] == OVFLPAGE) {
            ov_addr = ino[n];
            /*
             * Fix up the old page -- the extra 2 are the fields
             * which contained the overflow information.
             */
            ino[0] -= (moved + 2);
            FREESPACE(ino) =
                scopyto - sizeof(uint16) * (ino[0] + 3);
            OFFSET(ino) = scopyto;

            bufp = __get_buf(hashp, ov_addr, bufp, 0);
            if (!bufp)
                return (-1);

            ino = (uint16 *)bufp->page;
            n = 1;
            scopyto = hashp->BSIZE;
            moved = 0;

            if (last_bfp)
                __free_ovflpage(hashp, last_bfp);
            last_bfp = bufp;
        }
        /* Move regular sized pairs of there are any */
        off = hashp->BSIZE;
        for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
            cino = (char *)ino;
            key.data = (uint8 *)cino + ino[n];
            key.size = off - ino[n];
            val.data = (uint8 *)cino + ino[n + 1];
            val.size = ino[n] - ino[n + 1];
            off = ino[n + 1];

            if (__call_hash(hashp, (char *)key.data, key.size) == obucket) {
                /* Keep on old page */
                if (PAIRFITS(op, (&key), (&val)))
                    putpair((char *)op, &key, &val);
                else {
                    old_bufp =
                        __add_ovflpage(hashp, old_bufp);
                    if (!old_bufp)
                        return (-1);
                    op = (uint16 *)old_bufp->page;
                    putpair((char *)op, &key, &val);
                }
                old_bufp->flags |= BUF_MOD;
            } else {
                /* Move to new page */
                if (PAIRFITS(np, (&key), (&val)))
                    putpair((char *)np, &key, &val);
                else {
                    new_bufp =
                        __add_ovflpage(hashp, new_bufp);
                    if (!new_bufp)
                        return (-1);
                    np = (uint16 *)new_bufp->page;
                    putpair((char *)np, &key, &val);
                }
                new_bufp->flags |= BUF_MOD;
            }
        }
    }
    if (last_bfp)
        __free_ovflpage(hashp, last_bfp);
    return (0);
}
예제 #9
0
파일: h_page.c 프로젝트: MekliCZ/positron
/*
 * Returns:
 *   0 ==> OK
 *  -1 ==> Error
 */
extern int
__split_page(HTAB *hashp, uint32 obucket, uint32 nbucket)
{
    register BUFHEAD *new_bufp, *old_bufp;
    register uint16 *ino;
    register uint16 *tmp_uint16_array;
    register char *np;
    DBT key, val;
    uint16 n, ndx;
    int retval;
    uint16 copyto, diff, moved;
    size_t off;
    char *op;

    copyto = (uint16)hashp->BSIZE;
    off = (uint16)hashp->BSIZE;
    old_bufp = __get_buf(hashp, obucket, NULL, 0);
    if (old_bufp == NULL)
        return (-1);
    new_bufp = __get_buf(hashp, nbucket, NULL, 0);
    if (new_bufp == NULL)
        return (-1);

    old_bufp->flags |= (BUF_MOD | BUF_PIN);
    new_bufp->flags |= (BUF_MOD | BUF_PIN);

    ino = (uint16 *)(op = old_bufp->page);
    np = new_bufp->page;

    moved = 0;

    for (n = 1, ndx = 1; n < ino[0]; n += 2) {
        if (ino[n + 1] < REAL_KEY) {
            retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
                                (int)copyto, (int)moved);
            old_bufp->flags &= ~BUF_PIN;
            new_bufp->flags &= ~BUF_PIN;
            return (retval);
        }
        key.data = (uint8 *)op + ino[n];

        /* check here for ino[n] being greater than
         * off.  If it is then the database has
         * been corrupted.
         */
        if (ino[n] > off)
            return (DATABASE_CORRUPTED_ERROR);

        key.size = off - ino[n];

#ifdef DEBUG
        /* make sure the size is positive */
        assert(((int)key.size) > -1);
#endif

        if (__call_hash(hashp, (char *)key.data, key.size) == obucket) {
            /* Don't switch page */
            diff = copyto - off;
            if (diff) {
                copyto = ino[n + 1] + diff;
                memmove(op + copyto, op + ino[n + 1],
                        off - ino[n + 1]);
                ino[ndx] = copyto + ino[n] - ino[n + 1];
                ino[ndx + 1] = copyto;
            } else
                copyto = ino[n + 1];
            ndx += 2;
        } else {
            /* Switch page */
            val.data = (uint8 *)op + ino[n + 1];
            val.size = ino[n] - ino[n + 1];

            /* if the pair doesn't fit something is horribly
             * wrong.  LJM
             */
            tmp_uint16_array = (uint16 *)np;
            if (!PAIRFITS(tmp_uint16_array, &key, &val))
                return (DATABASE_CORRUPTED_ERROR);

            putpair(np, &key, &val);
            moved += 2;
        }

        off = ino[n + 1];
    }

    /* Now clean up the page */
    ino[0] -= moved;
    FREESPACE(ino) = copyto - sizeof(uint16) * (ino[0] + 3);
    OFFSET(ino) = copyto;

#ifdef DEBUG3
    (void)fprintf(stderr, "split %d/%d\n",
                  ((uint16 *)np)[0] / 2,
                  ((uint16 *)op)[0] / 2);
#endif
    /* unpin both pages */
    old_bufp->flags &= ~BUF_PIN;
    new_bufp->flags &= ~BUF_PIN;
    return (0);
}