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*64460Sbostic static char sccsid[] = "@(#)bt_utils.c 8.2 (Berkeley) 09/07/93"; 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 47*64460Sbostic /* 48*64460Sbostic * We always copy big keys/data to make them contigous. Otherwise, 49*64460Sbostic * we leave the page pinned and don't copy unless the user specified 50*64460Sbostic * concurrent access. 51*64460Sbostic */ 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); 56*64460Sbostic data->data = t->bt_dbuf; 57*64460Sbostic } 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; 67*64460Sbostic data->data = t->bt_dbuf; 68*64460Sbostic } else { 69*64460Sbostic data->size = bl->dsize; 70*64460Sbostic 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); 80*64460Sbostic key->data = t->bt_kbuf; 81*64460Sbostic } 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; 90*64460Sbostic key->data = t->bt_kbuf; 91*64460Sbostic } else { 92*64460Sbostic key->size = bl->ksize; 93*64460Sbostic 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 { 17850989Sbostic register u_char *p1, *p2; 17950989Sbostic register int diff, len; 18046137Smao 18150989Sbostic len = MIN(a->size, b->size); 18250989Sbostic for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) 18350989Sbostic if (diff = *p1 - *p2) 18459627Sbostic return (diff); 18559627Sbostic return (a->size - b->size); 18646137Smao } 18746137Smao 18850989Sbostic /* 18950989Sbostic * __BT_DEFPFX -- Default prefix routine. 19050989Sbostic * 19150989Sbostic * Parameters: 19250989Sbostic * a: DBT #1 19350989Sbostic * b: DBT #2 19450989Sbostic * 19550989Sbostic * Returns: 19650989Sbostic * Number of bytes needed to distinguish b from a. 19750989Sbostic */ 19850989Sbostic int 19950989Sbostic __bt_defpfx(a, b) 20050989Sbostic const DBT *a, *b; 20146137Smao { 20250989Sbostic register u_char *p1, *p2; 20350989Sbostic register int len; 20450989Sbostic int cnt; 20546137Smao 20650989Sbostic cnt = 1; 20750989Sbostic len = MIN(a->size, b->size); 20850989Sbostic for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) 20950989Sbostic if (*p1 != *p2) 21059627Sbostic return (cnt); 21151109Sbostic 21251109Sbostic /* a->size must be <= b->size, or they wouldn't be in this order. */ 21351109Sbostic return (a->size < b->size ? a->size + 1 : a->size); 21446137Smao } 215