1 /*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Olson. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)bt_utils.c 8.8 (Berkeley) 7/20/94 33 * $DragonFly: src/lib/libc/db/btree/bt_utils.c,v 1.4 2005/09/19 09:20:37 asmodai Exp $ 34 */ 35 36 #include <sys/param.h> 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 42 #include <db.h> 43 #include "btree.h" 44 45 /* 46 * __bt_ret -- 47 * Build return key/data pair. 48 * 49 * Parameters: 50 * t: tree 51 * e: key/data pair to be returned 52 * key: user's key structure (NULL if not to be filled in) 53 * rkey: memory area to hold key 54 * data: user's data structure (NULL if not to be filled in) 55 * rdata: memory area to hold data 56 * copy: always copy the key/data item 57 * 58 * Returns: 59 * RET_SUCCESS, RET_ERROR. 60 */ 61 int 62 __bt_ret(t, e, key, rkey, data, rdata, copy) 63 BTREE *t; 64 EPG *e; 65 DBT *key, *rkey, *data, *rdata; 66 int copy; 67 { 68 BLEAF *bl; 69 void *p; 70 71 bl = GETBLEAF(e->page, e->index); 72 73 /* 74 * We must copy big keys/data to make them contigous. Otherwise, 75 * leave the page pinned and don't copy unless the user specified 76 * concurrent access. 77 */ 78 if (key == NULL) 79 goto dataonly; 80 81 if (bl->flags & P_BIGKEY) { 82 if (__ovfl_get(t, bl->bytes, 83 &key->size, &rkey->data, &rkey->size)) 84 return (RET_ERROR); 85 key->data = rkey->data; 86 } else if (copy || F_ISSET(t, B_DB_LOCK)) { 87 if (bl->ksize > rkey->size) { 88 p = (void *)(rkey->data == NULL ? 89 malloc(bl->ksize) : realloc(rkey->data, bl->ksize)); 90 if (p == NULL) 91 return (RET_ERROR); 92 rkey->data = p; 93 rkey->size = bl->ksize; 94 } 95 memmove(rkey->data, bl->bytes, bl->ksize); 96 key->size = bl->ksize; 97 key->data = rkey->data; 98 } else { 99 key->size = bl->ksize; 100 key->data = bl->bytes; 101 } 102 103 dataonly: 104 if (data == NULL) 105 return (RET_SUCCESS); 106 107 if (bl->flags & P_BIGDATA) { 108 if (__ovfl_get(t, bl->bytes + bl->ksize, 109 &data->size, &rdata->data, &rdata->size)) 110 return (RET_ERROR); 111 data->data = rdata->data; 112 } else if (copy || F_ISSET(t, B_DB_LOCK)) { 113 /* Use +1 in case the first record retrieved is 0 length. */ 114 if (bl->dsize + 1 > rdata->size) { 115 p = (void *)(rdata->data == NULL ? 116 malloc(bl->dsize + 1) : 117 realloc(rdata->data, bl->dsize + 1)); 118 if (p == NULL) 119 return (RET_ERROR); 120 rdata->data = p; 121 rdata->size = bl->dsize + 1; 122 } 123 memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize); 124 data->size = bl->dsize; 125 data->data = rdata->data; 126 } else { 127 data->size = bl->dsize; 128 data->data = bl->bytes + bl->ksize; 129 } 130 131 return (RET_SUCCESS); 132 } 133 134 /* 135 * __BT_CMP -- Compare a key to a given record. 136 * 137 * Parameters: 138 * t: tree 139 * k1: DBT pointer of first arg to comparison 140 * e: pointer to EPG for comparison 141 * 142 * Returns: 143 * < 0 if k1 is < record 144 * = 0 if k1 is = record 145 * > 0 if k1 is > record 146 */ 147 int 148 __bt_cmp(t, k1, e) 149 BTREE *t; 150 const DBT *k1; 151 EPG *e; 152 { 153 BINTERNAL *bi; 154 BLEAF *bl; 155 DBT k2; 156 PAGE *h; 157 void *bigkey; 158 159 /* 160 * The left-most key on internal pages, at any level of the tree, is 161 * guaranteed by the following code to be less than any user key. 162 * This saves us from having to update the leftmost key on an internal 163 * page when the user inserts a new key in the tree smaller than 164 * anything we've yet seen. 165 */ 166 h = e->page; 167 if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF)) 168 return (1); 169 170 bigkey = NULL; 171 if (h->flags & P_BLEAF) { 172 bl = GETBLEAF(h, e->index); 173 if (bl->flags & P_BIGKEY) 174 bigkey = bl->bytes; 175 else { 176 k2.data = bl->bytes; 177 k2.size = bl->ksize; 178 } 179 } else { 180 bi = GETBINTERNAL(h, e->index); 181 if (bi->flags & P_BIGKEY) 182 bigkey = bi->bytes; 183 else { 184 k2.data = bi->bytes; 185 k2.size = bi->ksize; 186 } 187 } 188 189 if (bigkey) { 190 if (__ovfl_get(t, bigkey, 191 &k2.size, &t->bt_rdata.data, &t->bt_rdata.size)) 192 return (RET_ERROR); 193 k2.data = t->bt_rdata.data; 194 } 195 return ((*t->bt_cmp)(k1, &k2)); 196 } 197 198 /* 199 * __BT_DEFCMP -- Default comparison routine. 200 * 201 * Parameters: 202 * a: DBT #1 203 * b: DBT #2 204 * 205 * Returns: 206 * < 0 if a is < b 207 * = 0 if a is = b 208 * > 0 if a is > b 209 */ 210 int 211 __bt_defcmp(a, b) 212 const DBT *a, *b; 213 { 214 size_t len; 215 u_char *p1, *p2; 216 217 /* 218 * XXX 219 * If a size_t doesn't fit in an int, this routine can lose. 220 * What we need is a integral type which is guaranteed to be 221 * larger than a size_t, and there is no such thing. 222 */ 223 len = MIN(a->size, b->size); 224 for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) 225 if (*p1 != *p2) 226 return ((int)*p1 - (int)*p2); 227 return ((int)a->size - (int)b->size); 228 } 229 230 /* 231 * __BT_DEFPFX -- Default prefix routine. 232 * 233 * Parameters: 234 * a: DBT #1 235 * b: DBT #2 236 * 237 * Returns: 238 * Number of bytes needed to distinguish b from a. 239 */ 240 size_t 241 __bt_defpfx(a, b) 242 const DBT *a, *b; 243 { 244 u_char *p1, *p2; 245 size_t cnt, len; 246 247 cnt = 1; 248 len = MIN(a->size, b->size); 249 for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) 250 if (*p1 != *p2) 251 return (cnt); 252 253 /* a->size must be <= b->size, or they wouldn't be in this order. */ 254 return (a->size < b->size ? a->size + 1 : a->size); 255 } 256