146137Smao /*- 261196Sbostic * Copyright (c) 1990, 1993 361196Sbostic * The Regents of the University of California. All rights reserved. 446137Smao * 546137Smao * This code is derived from software contributed to Berkeley by 646137Smao * Mike Olson. 746137Smao * 846137Smao * %sccs.include.redist.c% 946137Smao */ 1046137Smao 1146137Smao #if defined(LIBC_SCCS) && !defined(lint) 12*66192Sbostic static char sccsid[] = "@(#)bt_utils.c 8.3 (Berkeley) 02/21/94"; 1346137Smao #endif /* LIBC_SCCS and not lint */ 1446137Smao 1550989Sbostic #include <sys/param.h> 1656740Sbostic 1750989Sbostic #include <stdio.h> 1846561Sbostic #include <stdlib.h> 1946561Sbostic #include <string.h> 2056740Sbostic 2157932Sbostic #include <db.h> 2246137Smao #include "btree.h" 2346137Smao 2446137Smao /* 2550989Sbostic * __BT_RET -- Build return key/data pair as a result of search or scan. 2646137Smao * 2750989Sbostic * Parameters: 2850989Sbostic * t: tree 2950989Sbostic * d: LEAF to be returned to the user. 3051109Sbostic * key: user's key structure (NULL if not to be filled in) 3150989Sbostic * data: user's data structure 3246137Smao * 3350989Sbostic * Returns: 3450989Sbostic * RET_SUCCESS, RET_ERROR. 3546137Smao */ 3646137Smao int 3750989Sbostic __bt_ret(t, e, key, data) 3850989Sbostic BTREE *t; 3950989Sbostic EPG *e; 4050989Sbostic DBT *key, *data; 4146137Smao { 4250989Sbostic register BLEAF *bl; 4351109Sbostic register void *p; 4446137Smao 4550989Sbostic bl = GETBLEAF(e->page, e->index); 4650989Sbostic 4764460Sbostic /* 4864460Sbostic * We always copy big keys/data to make them contigous. Otherwise, 4964460Sbostic * we leave the page pinned and don't copy unless the user specified 5064460Sbostic * concurrent access. 5164460Sbostic */ 5250989Sbostic if (bl->flags & P_BIGDATA) { 5350989Sbostic if (__ovfl_get(t, bl->bytes + bl->ksize, 5450989Sbostic &data->size, &t->bt_dbuf, &t->bt_dbufsz)) 5546137Smao return (RET_ERROR); 5664460Sbostic data->data = t->bt_dbuf; 5764460Sbostic } else if (ISSET(t, B_DB_LOCK)) { 5856707Sbostic /* Use +1 in case the first record retrieved is 0 length. */ 5956707Sbostic if (bl->dsize + 1 > t->bt_dbufsz) { 6056707Sbostic if ((p = realloc(t->bt_dbuf, bl->dsize + 1)) == NULL) 6146137Smao return (RET_ERROR); 6251109Sbostic t->bt_dbuf = p; 6356707Sbostic t->bt_dbufsz = bl->dsize + 1; 6446137Smao } 6558017Sbostic memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize); 6650989Sbostic data->size = bl->dsize; 6764460Sbostic data->data = t->bt_dbuf; 6864460Sbostic } else { 6964460Sbostic data->size = bl->dsize; 7064460Sbostic data->data = bl->bytes + bl->ksize; 7146137Smao } 7246137Smao 7351109Sbostic if (key == NULL) 7451109Sbostic return (RET_SUCCESS); 7551109Sbostic 7651109Sbostic if (bl->flags & P_BIGKEY) { 7751109Sbostic if (__ovfl_get(t, bl->bytes, 7851109Sbostic &key->size, &t->bt_kbuf, &t->bt_kbufsz)) 7951109Sbostic return (RET_ERROR); 8064460Sbostic key->data = t->bt_kbuf; 8164460Sbostic } else if (ISSET(t, B_DB_LOCK)) { 8251109Sbostic if (bl->ksize > t->bt_kbufsz) { 8351109Sbostic if ((p = realloc(t->bt_kbuf, bl->ksize)) == NULL) 8451109Sbostic return (RET_ERROR); 8551109Sbostic t->bt_kbuf = p; 8651109Sbostic t->bt_kbufsz = bl->ksize; 8751109Sbostic } 8858017Sbostic memmove(t->bt_kbuf, bl->bytes, bl->ksize); 8951109Sbostic key->size = bl->ksize; 9064460Sbostic key->data = t->bt_kbuf; 9164460Sbostic } else { 9264460Sbostic key->size = bl->ksize; 9364460Sbostic key->data = bl->bytes; 9451109Sbostic } 9546137Smao return (RET_SUCCESS); 9646137Smao } 9746137Smao 9846137Smao /* 9950989Sbostic * __BT_CMP -- Compare a key to a given record. 10046137Smao * 10150989Sbostic * Parameters: 10250989Sbostic * t: tree 10350989Sbostic * k1: DBT pointer of first arg to comparison 10450989Sbostic * e: pointer to EPG for comparison 10546137Smao * 10650989Sbostic * Returns: 10750989Sbostic * < 0 if k1 is < record 10850989Sbostic * = 0 if k1 is = record 10950989Sbostic * > 0 if k1 is > record 11046137Smao */ 11146137Smao int 11250989Sbostic __bt_cmp(t, k1, e) 11350989Sbostic BTREE *t; 11450989Sbostic const DBT *k1; 11550989Sbostic EPG *e; 11646137Smao { 11750989Sbostic BINTERNAL *bi; 11850989Sbostic BLEAF *bl; 11950989Sbostic DBT k2; 12050989Sbostic PAGE *h; 12150989Sbostic void *bigkey; 12246137Smao 12346137Smao /* 12450989Sbostic * The left-most key on internal pages, at any level of the tree, is 12550989Sbostic * guaranteed by the following code to be less than any user key. 12650989Sbostic * This saves us from having to update the leftmost key on an internal 12750989Sbostic * page when the user inserts a new key in the tree smaller than 12850989Sbostic * anything we've yet seen. 12946137Smao */ 13050989Sbostic h = e->page; 13150989Sbostic if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF)) 13246137Smao return (1); 13346137Smao 13450989Sbostic bigkey = NULL; 13550989Sbostic if (h->flags & P_BLEAF) { 13650989Sbostic bl = GETBLEAF(h, e->index); 13750989Sbostic if (bl->flags & P_BIGKEY) 13850989Sbostic bigkey = bl->bytes; 13950989Sbostic else { 14050989Sbostic k2.data = bl->bytes; 14150989Sbostic k2.size = bl->ksize; 14246137Smao } 14346137Smao } else { 14450989Sbostic bi = GETBINTERNAL(h, e->index); 14550989Sbostic if (bi->flags & P_BIGKEY) 14650989Sbostic bigkey = bi->bytes; 14750989Sbostic else { 14850989Sbostic k2.data = bi->bytes; 14950989Sbostic k2.size = bi->ksize; 15046137Smao } 15146137Smao } 15246137Smao 15350989Sbostic if (bigkey) { 15450989Sbostic if (__ovfl_get(t, bigkey, 15550989Sbostic &k2.size, &t->bt_dbuf, &t->bt_dbufsz)) 15650989Sbostic return (RET_ERROR); 15750989Sbostic k2.data = t->bt_dbuf; 15850989Sbostic } 15959627Sbostic return ((*t->bt_cmp)(k1, &k2)); 16046137Smao } 16146137Smao 16246137Smao /* 16350989Sbostic * __BT_DEFCMP -- Default comparison routine. 16446137Smao * 16550989Sbostic * Parameters: 16650989Sbostic * a: DBT #1 16750989Sbostic * b: DBT #2 16846137Smao * 16950989Sbostic * Returns: 17050989Sbostic * < 0 if a is < b 17150989Sbostic * = 0 if a is = b 17250989Sbostic * > 0 if a is > b 17346137Smao */ 17446137Smao int 17550989Sbostic __bt_defcmp(a, b) 17650989Sbostic const DBT *a, *b; 17746137Smao { 178*66192Sbostic register size_t len; 17950989Sbostic register u_char *p1, *p2; 18046137Smao 181*66192Sbostic /* 182*66192Sbostic * XXX 183*66192Sbostic * If a size_t doesn't fit in an int, this routine can lose. 184*66192Sbostic * What we need is a integral type which is guaranteed to be 185*66192Sbostic * larger than a size_t, and there is no such thing. 186*66192Sbostic */ 18750989Sbostic len = MIN(a->size, b->size); 18850989Sbostic for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) 189*66192Sbostic if (*p1 != *p2) 190*66192Sbostic return ((int)*p1 - (int)*p2); 191*66192Sbostic return ((int)a->size - (int)b->size); 19246137Smao } 19346137Smao 19450989Sbostic /* 19550989Sbostic * __BT_DEFPFX -- Default prefix routine. 19650989Sbostic * 19750989Sbostic * Parameters: 19850989Sbostic * a: DBT #1 19950989Sbostic * b: DBT #2 20050989Sbostic * 20150989Sbostic * Returns: 20250989Sbostic * Number of bytes needed to distinguish b from a. 20350989Sbostic */ 204*66192Sbostic size_t 20550989Sbostic __bt_defpfx(a, b) 20650989Sbostic const DBT *a, *b; 20746137Smao { 20850989Sbostic register u_char *p1, *p2; 209*66192Sbostic register size_t cnt, len; 21046137Smao 21150989Sbostic cnt = 1; 21250989Sbostic len = MIN(a->size, b->size); 21350989Sbostic for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) 21450989Sbostic if (*p1 != *p2) 21559627Sbostic return (cnt); 21651109Sbostic 21751109Sbostic /* a->size must be <= b->size, or they wouldn't be in this order. */ 21851109Sbostic return (a->size < b->size ? a->size + 1 : a->size); 21946137Smao } 220