]> git.saurik.com Git - apple/libc.git/blobdiff - db/hash/hash_bigkey-fbsd.c
Libc-763.13.tar.gz
[apple/libc.git] / db / hash / hash_bigkey-fbsd.c
index e4d75a5be78f7deb79bbe93864355bf978976fad..d325105edcb900aaf3ee8de41ccfb08e0f60ab68 100644 (file)
  * 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.
@@ -38,7 +34,7 @@
 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
@@ -86,14 +82,12 @@ static int collect_data(HTAB *, BUFHEAD *, int, int);
  * 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;
 
@@ -124,18 +118,30 @@ __big_insert(hashp, bufp, key, val)
                        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;
@@ -186,10 +192,8 @@ __big_insert(hashp, bufp, key, val)
  * 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;
@@ -247,12 +251,12 @@ __big_delete(hashp, bufp)
        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--;
@@ -265,13 +269,8 @@ __big_delete(hashp, bufp)
  * -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;
@@ -317,10 +316,8 @@ __find_bigpair(hashp, bufp, ndx, key, size)
  * 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;
@@ -358,13 +355,8 @@ __find_last_page(hashp, bpp)
  * 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;
@@ -433,8 +425,8 @@ __big_return(hashp, bufp, ndx, val, set_current)
                        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. */
@@ -450,10 +442,7 @@ __big_return(hashp, bufp, ndx, val, set_current)
  * 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;
@@ -505,15 +494,11 @@ collect_data(hashp, bufp, len, set)
 /*
  * 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);
@@ -524,12 +509,7 @@ __big_keydata(hashp, bufp, key, val, set)
  * 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;
@@ -568,23 +548,19 @@ collect_key(hashp, bufp, len, val, set)
  *  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;
 
@@ -596,7 +572,7 @@ __big_split(hashp, op, np, big_keyp, addr, obucket, ret)
        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;