* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and 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
* without specific prior written permission.
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.5 2003/02/16 17:29:09 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/db/hash/hash_bigkey.c,v 1.10 2009/03/28 06:47:05 delphij Exp $");
/*
* PACKAGE: hash
* 0 ==> OK
*-1 ==> ERROR
*/
-extern int
-__big_insert(hashp, bufp, key, val)
- HTAB *hashp;
- BUFHEAD *bufp;
- const DBT *key, *val;
+int
+__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *p;
- int key_size, n, val_size;
+ int key_size, n;
+ unsigned int val_size;
u_int16_t space, move_bytes, off;
char *cp, *key_data, *val_data;
return (-1);
n = p[0];
if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
off = OFFSET(p) - move_bytes;
- p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
+ p[n] = off;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
- } else
+ } else {
+ toolarge:
p[n - 2] = FULL_KEY;
+ }
}
p = (u_int16_t *)bufp->page;
cp = bufp->page;
* 0 => OK
*-1 => ERROR
*/
-extern int
-__big_delete(hashp, bufp)
- HTAB *hashp;
- BUFHEAD *bufp;
+int
+__big_delete(HTAB *hashp, BUFHEAD *bufp)
{
BUFHEAD *last_bfp, *rbufp;
u_int16_t *bp, pageno;
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
+ OFFSET(bp) = hashp->BSIZE;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
- if (last_bfp != rbufp)
+ if (last_bfp && last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
* -2 means key not found and this is big key/data
* -3 error
*/
-extern int
-__find_bigpair(hashp, bufp, ndx, key, size)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- char *key;
- int size;
+int
+__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
{
u_int16_t *bp;
char *p;
* of the pair; 0 if there isn't any (i.e. big pair is the last key in the
* bucket)
*/
-extern u_int16_t
-__find_last_page(hashp, bpp)
- HTAB *hashp;
- BUFHEAD **bpp;
+u_int16_t
+__find_last_page(HTAB *hashp, BUFHEAD **bpp)
{
BUFHEAD *bufp;
u_int16_t *bp, pageno;
* Return the data for the key/data pair that begins on this page at this
* index (index should always be 1).
*/
-extern int
-__big_return(hashp, bufp, ndx, val, set_current)
- HTAB *hashp;
- BUFHEAD *bufp;
- int ndx;
- DBT *val;
- int set_current;
+int
+__big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current)
{
BUFHEAD *save_p;
u_int16_t *bp, len, off, save_addr;
return (0);
}
- val->size = collect_data(hashp, bufp, (int)len, set_current);
- if (val->size == -1)
+ val->size = (size_t)collect_data(hashp, bufp, (int)len, set_current);
+ if (val->size == (size_t)-1)
return (-1);
if (save_p->addr != save_addr) {
/* We are pretty short on buffers. */
* allocate a buffer and copy the data as you recurse up.
*/
static int
-collect_data(hashp, bufp, len, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len, set;
+collect_data(HTAB *hashp, BUFHEAD *bufp, int len, int set)
{
u_int16_t *bp;
char *p;
/*
* Fill in the key and data for this big pair.
*/
-extern int
-__big_keydata(hashp, bufp, key, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- DBT *key, *val;
- int set;
+int
+__big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set)
{
- key->size = collect_key(hashp, bufp, 0, val, set);
- if (key->size == -1)
+ key->size = (size_t)collect_key(hashp, bufp, 0, val, set);
+ if (key->size == (size_t)-1)
return (-1);
key->data = (u_char *)hashp->tmp_key;
return (0);
* collect the data, allocate a buffer and copy the key as you recurse up.
*/
static int
-collect_key(hashp, bufp, len, val, set)
- HTAB *hashp;
- BUFHEAD *bufp;
- int len;
- DBT *val;
- int set;
+collect_key(HTAB *hashp, BUFHEAD *bufp, int len, DBT *val, int set)
{
BUFHEAD *xbp;
char *p;
* 0 => OK
* -1 => error
*/
-extern int
-__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
- 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 */
- u_int32_t obucket;/* Old Bucket */
- SPLIT_RETURN *ret;
+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 */
+ BUFHEAD *big_keyp, /* Pointer to first page containing the big key/data */
+ int addr, /* Address of big_keyp */
+ u_int32_t obucket, /* Old Bucket */
+ SPLIT_RETURN *ret)
{
- BUFHEAD *tmpp;
- u_int16_t *tp;
- BUFHEAD *bp;
+ BUFHEAD *bp, *tmpp;
DBT key, val;
u_int32_t change;
- u_int16_t free_space, n, off;
+ u_int16_t free_space, n, off, *tp;
bp = big_keyp;
if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
if (!(ret->nextp =
__get_buf(hashp, ret->next_addr, big_keyp, 0)))
- return (-1);;
+ return (-1);
} else
ret->nextp = NULL;