xref: /illumos-gate/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash_bigkey.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
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