1*495ee684SToomas Soome /*
254925bf6Swillf * Copyright (c) 1990, 1993, 1994
354925bf6Swillf * The Regents of the University of California. All rights reserved.
454925bf6Swillf *
554925bf6Swillf * This code is derived from software contributed to Berkeley by
654925bf6Swillf * Margo Seltzer.
754925bf6Swillf *
854925bf6Swillf * Redistribution and use in source and binary forms, with or without
954925bf6Swillf * modification, are permitted provided that the following conditions
1054925bf6Swillf * are met:
1154925bf6Swillf * 1. Redistributions of source code must retain the above copyright
1254925bf6Swillf * notice, this list of conditions and the following disclaimer.
1354925bf6Swillf * 2. Redistributions in binary form must reproduce the above copyright
1454925bf6Swillf * notice, this list of conditions and the following disclaimer in the
1554925bf6Swillf * documentation and/or other materials provided with the distribution.
1654925bf6Swillf * 3. All advertising materials mentioning features or use of this software
1754925bf6Swillf * must display the following acknowledgement:
1854925bf6Swillf * This product includes software developed by the University of
1954925bf6Swillf * California, Berkeley and its contributors.
2054925bf6Swillf * 4. Neither the name of the University nor the names of its contributors
2154925bf6Swillf * may be used to endorse or promote products derived from this software
2254925bf6Swillf * without specific prior written permission.
2354925bf6Swillf *
2454925bf6Swillf * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2554925bf6Swillf * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2654925bf6Swillf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2754925bf6Swillf * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2854925bf6Swillf * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2954925bf6Swillf * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3054925bf6Swillf * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3154925bf6Swillf * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3254925bf6Swillf * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3354925bf6Swillf * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3454925bf6Swillf * SUCH DAMAGE.
3554925bf6Swillf */
3654925bf6Swillf
3754925bf6Swillf /*
3854925bf6Swillf * PACKAGE: hash
3954925bf6Swillf * DESCRIPTION:
4054925bf6Swillf * Big key/data handling for the hashing package.
4154925bf6Swillf *
4254925bf6Swillf * ROUTINES:
4354925bf6Swillf * External
4454925bf6Swillf * __big_keydata
4554925bf6Swillf * __big_split
4654925bf6Swillf * __big_insert
4754925bf6Swillf * __big_return
4854925bf6Swillf * __big_delete
4954925bf6Swillf * __find_last_page
5054925bf6Swillf * Internal
5154925bf6Swillf * collect_key
5254925bf6Swillf * collect_data
5354925bf6Swillf */
5454925bf6Swillf #include <sys/types.h>
5554925bf6Swillf
5654925bf6Swillf #include <stdlib.h>
5754925bf6Swillf #include <string.h>
5854925bf6Swillf
5954925bf6Swillf #ifdef DEBUG
6054925bf6Swillf #include <assert.h>
6154925bf6Swillf #endif
6254925bf6Swillf
6354925bf6Swillf #include "db-int.h"
6454925bf6Swillf #include "hash.h"
6554925bf6Swillf #include "page.h"
6654925bf6Swillf #include "extern.h"
6754925bf6Swillf
6854925bf6Swillf static int32_t collect_key __P((HTAB *, PAGE16 *, int32_t, db_pgno_t *));
6954925bf6Swillf static int32_t collect_data __P((HTAB *, PAGE16 *, int32_t));
7054925bf6Swillf
7154925bf6Swillf /*
7254925bf6Swillf * Big_insert
7354925bf6Swillf *
7454925bf6Swillf * You need to do an insert and the key/data pair is greater than
7554925bf6Swillf * MINFILL * the bucket size
7654925bf6Swillf *
7754925bf6Swillf * Returns:
7854925bf6Swillf * 0 ==> OK
7954925bf6Swillf * -1 ==> ERROR
8054925bf6Swillf */
8154925bf6Swillf int32_t
__big_insert(hashp,pagep,key,val)8254925bf6Swillf __big_insert(hashp, pagep, key, val)
8354925bf6Swillf HTAB *hashp;
8454925bf6Swillf PAGE16 *pagep;
8554925bf6Swillf const DBT *key, *val;
8654925bf6Swillf {
8754925bf6Swillf size_t key_size, val_size;
8854925bf6Swillf indx_t key_move_bytes, val_move_bytes;
8954925bf6Swillf int8_t *key_data, *val_data, base_page;
9054925bf6Swillf
9154925bf6Swillf key_data = (int8_t *)key->data;
9254925bf6Swillf key_size = key->size;
9354925bf6Swillf val_data = (int8_t *)val->data;
9454925bf6Swillf val_size = val->size;
9554925bf6Swillf
9654925bf6Swillf NUM_ENT(pagep) = NUM_ENT(pagep) + 1;
9754925bf6Swillf
9854925bf6Swillf for (base_page = 1; key_size + val_size;) {
9954925bf6Swillf /* Add a page! */
10054925bf6Swillf pagep =
10154925bf6Swillf __add_bigpage(hashp, pagep, NUM_ENT(pagep) - 1, base_page);
10254925bf6Swillf if (!pagep)
10354925bf6Swillf return (-1);
10454925bf6Swillf
10554925bf6Swillf /* There's just going to be one entry on this page. */
10654925bf6Swillf NUM_ENT(pagep) = 1;
10754925bf6Swillf
10854925bf6Swillf /* Move the key's data. */
10954925bf6Swillf key_move_bytes = MIN(FREESPACE(pagep), key_size);
11054925bf6Swillf /* Mark the page as to how much key & data is on this page. */
11154925bf6Swillf BIGKEYLEN(pagep) = key_move_bytes;
11254925bf6Swillf val_move_bytes =
11354925bf6Swillf MIN(FREESPACE(pagep) - key_move_bytes, val_size);
11454925bf6Swillf BIGDATALEN(pagep) = val_move_bytes;
11554925bf6Swillf
11654925bf6Swillf /* Note big pages build beginning --> end, not vice versa. */
11754925bf6Swillf if (key_move_bytes)
11854925bf6Swillf memmove(BIGKEY(pagep), key_data, key_move_bytes);
11954925bf6Swillf if (val_move_bytes)
12054925bf6Swillf memmove(BIGDATA(pagep), val_data, val_move_bytes);
12154925bf6Swillf
12254925bf6Swillf key_size -= key_move_bytes;
12354925bf6Swillf key_data += key_move_bytes;
12454925bf6Swillf val_size -= val_move_bytes;
12554925bf6Swillf val_data += val_move_bytes;
12654925bf6Swillf
12754925bf6Swillf base_page = 0;
12854925bf6Swillf }
12954925bf6Swillf __put_page(hashp, pagep, A_RAW, 1);
13054925bf6Swillf return (0);
13154925bf6Swillf }
13254925bf6Swillf
13354925bf6Swillf /*
13454925bf6Swillf * Called when we need to delete a big pair.
13554925bf6Swillf *
13654925bf6Swillf * Returns:
13754925bf6Swillf * 0 => OK
13854925bf6Swillf * -1 => ERROR
13954925bf6Swillf */
14054925bf6Swillf int32_t
14154925bf6Swillf #ifdef __STDC__
__big_delete(HTAB * hashp,PAGE16 * pagep,indx_t ndx)14254925bf6Swillf __big_delete(HTAB *hashp, PAGE16 *pagep, indx_t ndx)
14354925bf6Swillf #else
14454925bf6Swillf __big_delete(hashp, pagep, ndx)
14554925bf6Swillf HTAB *hashp;
14654925bf6Swillf PAGE16 *pagep;
14754925bf6Swillf u_int32_t ndx; /* Index of big pair on base page. */
14854925bf6Swillf #endif
14954925bf6Swillf {
15054925bf6Swillf PAGE16 *last_pagep;
15154925bf6Swillf
15254925bf6Swillf /* Get first page with big key/data. */
15354925bf6Swillf pagep = __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
15454925bf6Swillf if (!pagep)
15554925bf6Swillf return (-1);
15654925bf6Swillf
15754925bf6Swillf /*
15854925bf6Swillf * Traverse through the pages, freeing the previous one (except
15954925bf6Swillf * the first) at each new page.
16054925bf6Swillf */
16154925bf6Swillf while (NEXT_PGNO(pagep) != INVALID_PGNO) {
16254925bf6Swillf last_pagep = pagep;
16354925bf6Swillf pagep = __get_page(hashp, NEXT_PGNO(pagep), A_RAW);
16454925bf6Swillf if (!pagep)
16554925bf6Swillf return (-1);
16654925bf6Swillf __delete_page(hashp, last_pagep, A_OVFL);
16754925bf6Swillf }
16854925bf6Swillf
16954925bf6Swillf /* Free the last page in the chain. */
17054925bf6Swillf __delete_page(hashp, pagep, A_OVFL);
17154925bf6Swillf return (0);
17254925bf6Swillf }
17354925bf6Swillf
17454925bf6Swillf /*
17554925bf6Swillf * Given a key, indicates whether the big key at cursorp matches the
17654925bf6Swillf * given key.
17754925bf6Swillf *
17854925bf6Swillf * Returns:
17954925bf6Swillf * 1 = Found!
18054925bf6Swillf * 0 = Key not found
18154925bf6Swillf * -1 error
18254925bf6Swillf */
18354925bf6Swillf int32_t
__find_bigpair(hashp,cursorp,key,size)18454925bf6Swillf __find_bigpair(hashp, cursorp, key, size)
18554925bf6Swillf HTAB *hashp;
18654925bf6Swillf CURSOR *cursorp;
18754925bf6Swillf int8_t *key;
18854925bf6Swillf int32_t size;
18954925bf6Swillf {
19054925bf6Swillf PAGE16 *pagep, *hold_pagep;
19154925bf6Swillf db_pgno_t next_pgno;
19254925bf6Swillf int32_t ksize;
19354925bf6Swillf int8_t *kkey;
19454925bf6Swillf
19554925bf6Swillf ksize = size;
19654925bf6Swillf kkey = key;
19754925bf6Swillf
19854925bf6Swillf hold_pagep = NULL;
19954925bf6Swillf /* Chances are, hashp->cpage is the base page. */
20054925bf6Swillf if (cursorp->pagep)
20154925bf6Swillf pagep = hold_pagep = cursorp->pagep;
20254925bf6Swillf else {
20354925bf6Swillf pagep = __get_page(hashp, cursorp->pgno, A_RAW);
20454925bf6Swillf if (!pagep)
20554925bf6Swillf return (-1);
20654925bf6Swillf }
20754925bf6Swillf
20854925bf6Swillf /*
20954925bf6Swillf * Now, get the first page with the big stuff on it.
21054925bf6Swillf *
21154925bf6Swillf * XXX
21254925bf6Swillf * KLUDGE: we know that cursor is looking at the _next_ item, so
21354925bf6Swillf * we have to look at pgndx - 1.
21454925bf6Swillf */
21554925bf6Swillf next_pgno = OADDR_TO_PAGE(DATA_OFF(pagep, (cursorp->pgndx - 1)));
21654925bf6Swillf if (!hold_pagep)
21754925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
21854925bf6Swillf pagep = __get_page(hashp, next_pgno, A_RAW);
21954925bf6Swillf if (!pagep)
22054925bf6Swillf return (-1);
22154925bf6Swillf
22254925bf6Swillf /* While there are both keys to compare. */
22354925bf6Swillf while ((ksize > 0) && (BIGKEYLEN(pagep))) {
22454925bf6Swillf if (ksize < KEY_OFF(pagep, 0) ||
22554925bf6Swillf memcmp(BIGKEY(pagep), kkey, BIGKEYLEN(pagep))) {
22654925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
22754925bf6Swillf return (0);
22854925bf6Swillf }
22954925bf6Swillf kkey += BIGKEYLEN(pagep);
23054925bf6Swillf ksize -= BIGKEYLEN(pagep);
23154925bf6Swillf if (NEXT_PGNO(pagep) != INVALID_PGNO) {
23254925bf6Swillf next_pgno = NEXT_PGNO(pagep);
23354925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
23454925bf6Swillf pagep = __get_page(hashp, next_pgno, A_RAW);
23554925bf6Swillf if (!pagep)
23654925bf6Swillf return (-1);
23754925bf6Swillf }
23854925bf6Swillf }
23954925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
24054925bf6Swillf #ifdef DEBUG
24154925bf6Swillf assert(ksize >= 0);
24254925bf6Swillf #endif
24354925bf6Swillf if (ksize != 0) {
24454925bf6Swillf #ifdef HASH_STATISTICS
24554925bf6Swillf ++hash_collisions;
24654925bf6Swillf #endif
24754925bf6Swillf return (0);
24854925bf6Swillf } else
24954925bf6Swillf return (1);
25054925bf6Swillf }
25154925bf6Swillf
25254925bf6Swillf /*
25354925bf6Swillf * Fill in the key and data for this big pair.
25454925bf6Swillf */
25554925bf6Swillf int32_t
__big_keydata(hashp,pagep,key,val,ndx)25654925bf6Swillf __big_keydata(hashp, pagep, key, val, ndx)
25754925bf6Swillf HTAB *hashp;
25854925bf6Swillf PAGE16 *pagep;
25954925bf6Swillf DBT *key, *val;
26054925bf6Swillf int32_t ndx;
26154925bf6Swillf {
26254925bf6Swillf ITEM_INFO ii;
26354925bf6Swillf PAGE16 *key_pagep;
26454925bf6Swillf db_pgno_t last_page;
26554925bf6Swillf
26654925bf6Swillf key_pagep =
26754925bf6Swillf __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
26854925bf6Swillf if (!key_pagep)
26954925bf6Swillf return (-1);
27054925bf6Swillf key->size = collect_key(hashp, key_pagep, 0, &last_page);
27154925bf6Swillf key->data = hashp->bigkey_buf;
27254925bf6Swillf __put_page(hashp, key_pagep, A_RAW, 0);
27354925bf6Swillf
27454925bf6Swillf if (key->size == -1)
27554925bf6Swillf return (-1);
27654925bf6Swillf
27754925bf6Swillf /* Create an item_info to direct __big_return to the beginning pgno. */
27854925bf6Swillf ii.pgno = last_page;
27954925bf6Swillf return (__big_return(hashp, &ii, val, 1));
28054925bf6Swillf }
28154925bf6Swillf
28254925bf6Swillf /*
28354925bf6Swillf * Return the big key on page, ndx.
28454925bf6Swillf */
28554925bf6Swillf int32_t
28654925bf6Swillf #ifdef __STDC__
__get_bigkey(HTAB * hashp,PAGE16 * pagep,indx_t ndx,DBT * key)28754925bf6Swillf __get_bigkey(HTAB *hashp, PAGE16 *pagep, indx_t ndx, DBT *key)
28854925bf6Swillf #else
28954925bf6Swillf __get_bigkey(hashp, pagep, ndx, key)
29054925bf6Swillf HTAB *hashp;
29154925bf6Swillf PAGE16 *pagep;
29254925bf6Swillf u_int32_t ndx;
29354925bf6Swillf DBT *key;
29454925bf6Swillf #endif
29554925bf6Swillf {
29654925bf6Swillf PAGE16 *key_pagep;
29754925bf6Swillf
29854925bf6Swillf key_pagep =
29954925bf6Swillf __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW);
30054925bf6Swillf if (!pagep)
30154925bf6Swillf return (-1);
30254925bf6Swillf key->size = collect_key(hashp, key_pagep, 0, NULL);
30354925bf6Swillf key->data = hashp->bigkey_buf;
30454925bf6Swillf
30554925bf6Swillf __put_page(hashp, key_pagep, A_RAW, 0);
30654925bf6Swillf
30754925bf6Swillf return (0);
30854925bf6Swillf }
30954925bf6Swillf
31054925bf6Swillf /*
31154925bf6Swillf * Return the big key and data indicated in item_info.
31254925bf6Swillf */
31354925bf6Swillf int32_t
__big_return(hashp,item_info,val,on_bigkey_page)31454925bf6Swillf __big_return(hashp, item_info, val, on_bigkey_page)
31554925bf6Swillf HTAB *hashp;
31654925bf6Swillf ITEM_INFO *item_info;
31754925bf6Swillf DBT *val;
31854925bf6Swillf int32_t on_bigkey_page;
31954925bf6Swillf {
32054925bf6Swillf PAGE16 *pagep;
32154925bf6Swillf db_pgno_t next_pgno;
32254925bf6Swillf
32354925bf6Swillf if (!on_bigkey_page) {
32454925bf6Swillf /* Get first page with big pair on it. */
32554925bf6Swillf pagep = __get_page(hashp,
32654925bf6Swillf OADDR_TO_PAGE(item_info->data_off), A_RAW);
32754925bf6Swillf if (!pagep)
32854925bf6Swillf return (-1);
32954925bf6Swillf } else {
33054925bf6Swillf pagep = __get_page(hashp, item_info->pgno, A_RAW);
33154925bf6Swillf if (!pagep)
33254925bf6Swillf return (-1);
33354925bf6Swillf }
33454925bf6Swillf
33554925bf6Swillf /* Traverse through the bigkey pages until a page with data is found. */
33654925bf6Swillf while (!BIGDATALEN(pagep)) {
33754925bf6Swillf next_pgno = NEXT_PGNO(pagep);
33854925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
33954925bf6Swillf pagep = __get_page(hashp, next_pgno, A_RAW);
34054925bf6Swillf if (!pagep)
34154925bf6Swillf return (-1);
34254925bf6Swillf }
34354925bf6Swillf
34454925bf6Swillf val->size = collect_data(hashp, pagep, 0);
34554925bf6Swillf if (val->size < 1)
34654925bf6Swillf return (-1);
34754925bf6Swillf val->data = (void *)hashp->bigdata_buf;
34854925bf6Swillf
34954925bf6Swillf __put_page(hashp, pagep, A_RAW, 0);
35054925bf6Swillf return (0);
35154925bf6Swillf }
35254925bf6Swillf
35354925bf6Swillf /*
35454925bf6Swillf * Given a page with a big key on it, traverse through the pages counting data
35554925bf6Swillf * length, and collect all of the data on the way up. Store the key in
35654925bf6Swillf * hashp->bigkey_buf. last_page indicates to the calling function what the
35754925bf6Swillf * last page with key on it is; this will help if you later want to retrieve
35854925bf6Swillf * the data portion.
35954925bf6Swillf *
36054925bf6Swillf * Does the work for __get_bigkey.
36154925bf6Swillf *
36254925bf6Swillf * Return total length of data; -1 if error.
36354925bf6Swillf */
36454925bf6Swillf static int32_t
collect_key(hashp,pagep,len,last_page)36554925bf6Swillf collect_key(hashp, pagep, len, last_page)
36654925bf6Swillf HTAB *hashp;
36754925bf6Swillf PAGE16 *pagep;
36854925bf6Swillf int32_t len;
36954925bf6Swillf db_pgno_t *last_page;
37054925bf6Swillf {
37154925bf6Swillf PAGE16 *next_pagep;
37254925bf6Swillf int32_t totlen, retval;
37354925bf6Swillf db_pgno_t next_pgno;
37454925bf6Swillf #ifdef DEBUG
37554925bf6Swillf db_pgno_t save_addr;
37654925bf6Swillf #endif
37754925bf6Swillf
37854925bf6Swillf /* If this is the last page with key. */
37954925bf6Swillf if (BIGDATALEN(pagep)) {
38054925bf6Swillf totlen = len + BIGKEYLEN(pagep);
38154925bf6Swillf if (hashp->bigkey_buf)
38254925bf6Swillf free(hashp->bigkey_buf);
38354925bf6Swillf hashp->bigkey_buf = (u_int8_t *)malloc(totlen);
38454925bf6Swillf if (!hashp->bigkey_buf)
38554925bf6Swillf return (-1);
38654925bf6Swillf memcpy(hashp->bigkey_buf + len,
38754925bf6Swillf BIGKEY(pagep), BIGKEYLEN(pagep));
38854925bf6Swillf if (last_page)
38954925bf6Swillf *last_page = ADDR(pagep);
39054925bf6Swillf return (totlen);
39154925bf6Swillf }
39254925bf6Swillf
39354925bf6Swillf /* Key filled up all of last key page, so we've gone 1 too far. */
39454925bf6Swillf if (BIGKEYLEN(pagep) == 0) {
39554925bf6Swillf if (hashp->bigkey_buf)
39654925bf6Swillf free(hashp->bigkey_buf);
39754925bf6Swillf hashp->bigkey_buf = (u_int8_t *)malloc(len);
39854925bf6Swillf return (hashp->bigkey_buf ? len : -1);
39954925bf6Swillf }
40054925bf6Swillf totlen = len + BIGKEYLEN(pagep);
40154925bf6Swillf
40254925bf6Swillf /* Set pagep to the next page in the chain. */
40354925bf6Swillf if (last_page)
40454925bf6Swillf *last_page = ADDR(pagep);
40554925bf6Swillf next_pgno = NEXT_PGNO(pagep);
40654925bf6Swillf next_pagep = __get_page(hashp, next_pgno, A_RAW);
40754925bf6Swillf if (!next_pagep)
40854925bf6Swillf return (-1);
40954925bf6Swillf #ifdef DEBUG
41054925bf6Swillf save_addr = ADDR(pagep);
41154925bf6Swillf #endif
41254925bf6Swillf retval = collect_key(hashp, next_pagep, totlen, last_page);
41354925bf6Swillf
41454925bf6Swillf #ifdef DEBUG
41554925bf6Swillf assert(save_addr == ADDR(pagep));
41654925bf6Swillf #endif
41754925bf6Swillf memcpy(hashp->bigkey_buf + len, BIGKEY(pagep), BIGKEYLEN(pagep));
41854925bf6Swillf __put_page(hashp, next_pagep, A_RAW, 0);
41954925bf6Swillf
42054925bf6Swillf return (retval);
42154925bf6Swillf }
42254925bf6Swillf
42354925bf6Swillf /*
42454925bf6Swillf * Given a page with big data on it, recur through the pages counting data
42554925bf6Swillf * length, and collect all of the data on the way up. Store the data in
42654925bf6Swillf * hashp->bigdata_buf.
42754925bf6Swillf *
42854925bf6Swillf * Does the work for __big_return.
42954925bf6Swillf *
43054925bf6Swillf * Return total length of data; -1 if error.
43154925bf6Swillf */
43254925bf6Swillf static int32_t
collect_data(hashp,pagep,len)43354925bf6Swillf collect_data(hashp, pagep, len)
43454925bf6Swillf HTAB *hashp;
43554925bf6Swillf PAGE16 *pagep;
43654925bf6Swillf int32_t len;
43754925bf6Swillf {
43854925bf6Swillf PAGE16 *next_pagep;
43954925bf6Swillf int32_t totlen, retval;
44054925bf6Swillf db_pgno_t next_pgno;
44154925bf6Swillf #ifdef DEBUG
44254925bf6Swillf db_pgno_t save_addr;
44354925bf6Swillf #endif
44454925bf6Swillf
44554925bf6Swillf /* If there is no next page. */
44654925bf6Swillf if (NEXT_PGNO(pagep) == INVALID_PGNO) {
44754925bf6Swillf if (hashp->bigdata_buf)
44854925bf6Swillf free(hashp->bigdata_buf);
44954925bf6Swillf totlen = len + BIGDATALEN(pagep);
45054925bf6Swillf hashp->bigdata_buf = (u_int8_t *)malloc(totlen);
45154925bf6Swillf if (!hashp->bigdata_buf)
45254925bf6Swillf return (-1);
45354925bf6Swillf memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep),
45454925bf6Swillf BIGDATA(pagep), BIGDATALEN(pagep));
45554925bf6Swillf return (totlen);
45654925bf6Swillf }
45754925bf6Swillf totlen = len + BIGDATALEN(pagep);
45854925bf6Swillf
45954925bf6Swillf /* Set pagep to the next page in the chain. */
46054925bf6Swillf next_pgno = NEXT_PGNO(pagep);
46154925bf6Swillf next_pagep = __get_page(hashp, next_pgno, A_RAW);
46254925bf6Swillf if (!next_pagep)
46354925bf6Swillf return (-1);
46454925bf6Swillf
46554925bf6Swillf #ifdef DEBUG
46654925bf6Swillf save_addr = ADDR(pagep);
46754925bf6Swillf #endif
46854925bf6Swillf retval = collect_data(hashp, next_pagep, totlen);
46954925bf6Swillf #ifdef DEBUG
47054925bf6Swillf assert(save_addr == ADDR(pagep));
47154925bf6Swillf #endif
47254925bf6Swillf memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep),
47354925bf6Swillf BIGDATA(pagep), BIGDATALEN(pagep));
47454925bf6Swillf __put_page(hashp, next_pagep, A_RAW, 0);
47554925bf6Swillf
47654925bf6Swillf return (retval);
47754925bf6Swillf }
478