Exemple #1
0
/*
 * Returns:
 *  0 => OK
 * -1 => error
 */
int
__big_split(
	HTAB *hashp,
	BUFHEAD *op,	/* Pointer to where to put keys that go in old bucket */
	BUFHEAD *np,	/* Pointer to new bucket page */
			/* Pointer to first page containing the big key/data */
	BUFHEAD *big_keyp,
	int addr,	/* Address of big_keyp */
	uint32_t   obucket,/* Old Bucket */
	SPLIT_RETURN *ret
)
{
	BUFHEAD *tmpp;
	uint16_t *tp;
	BUFHEAD *bp;
	DBT key, val;
	uint32_t change;
	uint16_t free_space, n, off;
	size_t temp;

	bp = big_keyp;

	/* Now figure out where the big key/data goes */
	if (__big_keydata(hashp, big_keyp, &key, &val, 0))
		return (-1);
	change = (__call_hash(hashp, key.data, (int)key.size) != obucket);

	if ((ret->next_addr = __find_last_page(hashp, &big_keyp)) != 0) {
		if (!(ret->nextp =
		    __get_buf(hashp, (uint32_t)ret->next_addr, big_keyp, 0)))
			return (-1);
	} else
		ret->nextp = NULL;

	/* Now make one of np/op point to the big key/data pair */
	_DIAGASSERT(np->ovfl == NULL);
	if (change)
		tmpp = np;
	else
		tmpp = op;

	tmpp->flags |= BUF_MOD;
#ifdef DEBUG1
	(void)fprintf(stderr,
	    "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
	    (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
#endif
	tmpp->ovfl = bp;	/* one of op/np point to big_keyp */
	tp = (uint16_t *)(void *)tmpp->page;
	_DIAGASSERT(FREESPACE(tp) >= OVFLSIZE);
	n = tp[0];
	off = OFFSET(tp);
	free_space = FREESPACE(tp);
	tp[++n] = (uint16_t)addr;
	tp[++n] = OVFLPAGE;
	tp[0] = n;
	OFFSET(tp) = off;
	temp = free_space - OVFLSIZE;
	_DBFIT(temp, uint16_t);
	FREESPACE(tp) = (uint16_t)temp;

	/*
	 * Finally, set the new and old return values. BIG_KEYP contains a
	 * pointer to the last page of the big key_data pair. Make sure that
	 * big_keyp has no following page (2 elements) or create an empty
	 * following page.
	 */

	ret->newp = np;
	ret->oldp = op;

	tp = (uint16_t *)(void *)big_keyp->page;
	big_keyp->flags |= BUF_MOD;
	if (tp[0] > 2) {
		/*
		 * There may be either one or two offsets on this page.  If
		 * there is one, then the overflow page is linked on normally
		 * and tp[4] is OVFLPAGE.  If there are two, tp[4] contains
		 * the second offset and needs to get stuffed in after the
		 * next overflow page is added.
		 */
		n = tp[4];
		free_space = FREESPACE(tp);
		off = OFFSET(tp);
		tp[0] -= 2;
		temp = free_space + OVFLSIZE;
		_DBFIT(temp, uint16_t);
		FREESPACE(tp) = (uint16_t)temp;
		OFFSET(tp) = off;
		tmpp = __add_ovflpage(hashp, big_keyp);
		if (!tmpp)
			return (-1);
		tp[4] = n;
	} else
		tmpp = big_keyp;

	if (change)
		ret->newp = tmpp;
	else
		ret->oldp = tmpp;
	return (0);
}
Exemple #2
0
static int
hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
{
	u_int32_t bucket;
	BUFHEAD *bufp;
	HTAB *hashp;
	u_int16_t *bp, ndx;

	hashp = (HTAB *)dbp->internal;
	if (flag && flag != R_FIRST && flag != R_NEXT) {
		hashp->error = errno = EINVAL;
		return (ERROR);
	}
#ifdef HASH_STATISTICS
	hash_accesses++;
#endif
	if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
		hashp->cbucket = 0;
		hashp->cndx = 1;
		hashp->cpage = NULL;
	}
next_bucket:
	for (bp = NULL; !bp || !bp[0]; ) {
		if (!(bufp = hashp->cpage)) {
			for (bucket = hashp->cbucket;
			    bucket <= hashp->MAX_BUCKET;
			    bucket++, hashp->cndx = 1) {
				bufp = __get_buf(hashp, bucket, NULL, 0);
				if (!bufp)
					return (ERROR);
				hashp->cpage = bufp;
				bp = (u_int16_t *)bufp->page;
				if (bp[0])
					break;
			}
			hashp->cbucket = bucket;
			if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) {
				hashp->cbucket = -1;
				return (ABNORMAL);
			}
		} else {
			bp = (u_int16_t *)hashp->cpage->page;
			if (flag == R_NEXT || flag == 0) {
				hashp->cndx += 2;
				if (hashp->cndx > bp[0]) {
					hashp->cpage = NULL;
					hashp->cbucket++;
					hashp->cndx = 1;
					goto next_bucket;
				}
			}
		}

#ifdef DEBUG
		assert(bp);
		assert(bufp);
#endif
		while (bp[hashp->cndx + 1] == OVFLPAGE) {
			bufp = hashp->cpage =
			    __get_buf(hashp, bp[hashp->cndx], bufp, 0);
			if (!bufp)
				return (ERROR);
			bp = (u_int16_t *)(bufp->page);
			hashp->cndx = 1;
		}
		if (!bp[0]) {
			hashp->cpage = NULL;
			++hashp->cbucket;
		}
	}
	ndx = hashp->cndx;
	if (bp[ndx + 1] < REAL_KEY) {
		if (__big_keydata(hashp, bufp, key, data, 1))
			return (ERROR);
	} else {
		if (hashp->cpage == 0)
			return (ERROR);
		key->data = (u_char *)hashp->cpage->page + bp[ndx];
		key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
		data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
		data->size = bp[ndx] - bp[ndx + 1];
	}
	return (SUCCESS);
}
Exemple #3
0
static int
hash_seq(const DB *dbp, DBT *key, DBT *data, uint32_t flag)
{
	uint32_t bucket;
	BUFHEAD *bufp = NULL; /* XXX: gcc */
	HTAB *hashp;
	uint16_t *bp, ndx;

	hashp = dbp->internal;
	if (flag && flag != R_FIRST && flag != R_NEXT) {
		hashp->err = errno = EINVAL;
		return (ERROR);
	}
#ifdef HASH_STATISTICS
	hash_accesses++;
#endif
	if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
		hashp->cbucket = 0;
		hashp->cndx = 1;
		hashp->cpage = NULL;
	}

	for (bp = NULL; !bp || !bp[0]; ) {
		if (!(bufp = hashp->cpage)) {
			for (bucket = hashp->cbucket;
			    bucket <= hashp->MAX_BUCKET;
			    bucket++, hashp->cndx = 1) {
				bufp = __get_buf(hashp, bucket, NULL, 0);
				if (!bufp)
					return (ERROR);
				hashp->cpage = bufp;
				bp = (uint16_t *)(void *)bufp->page;
				if (bp[0])
					break;
			}
			hashp->cbucket = bucket;
			if (hashp->cbucket > hashp->MAX_BUCKET) {
				hashp->cbucket = -1;
				return (ABNORMAL);
			}
		} else
			bp = (uint16_t *)(void *)hashp->cpage->page;

		_DIAGASSERT(bp != NULL);
		_DIAGASSERT(bufp != NULL);
		while (bp[hashp->cndx + 1] == OVFLPAGE) {
			bufp = hashp->cpage =
			    __get_buf(hashp, (uint32_t)bp[hashp->cndx], bufp,
				0);
			if (!bufp)
				return (ERROR);
			bp = (uint16_t *)(void *)(bufp->page);
			hashp->cndx = 1;
		}
		if (!bp[0]) {
			hashp->cpage = NULL;
			++hashp->cbucket;
		}
	}
	ndx = hashp->cndx;
	if (bp[ndx + 1] < REAL_KEY) {
		if (__big_keydata(hashp, bufp, key, data, 1))
			return (ERROR);
	} else {
		if (hashp->cpage == NULL)
			return (ERROR);
		key->data = (uint8_t *)hashp->cpage->page + bp[ndx];
		key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
		data->data = (uint8_t *)hashp->cpage->page + bp[ndx + 1];
		data->size = bp[ndx] - bp[ndx + 1];
		ndx += 2;
		if (ndx > bp[0]) {
			hashp->cpage = NULL;
			hashp->cbucket++;
			hashp->cndx = 1;
		} else
			hashp->cndx = ndx;
	}
	return (SUCCESS);
}