1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999,2008 Oracle. All rights reserved. 5 * 6 * $Id: bt_method.c,v 12.10 2008/01/08 20:57:59 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/btree.h" 14#include "dbinc/qam.h" 15 16static int __bam_set_bt_minkey __P((DB *, u_int32_t)); 17static int __bam_set_bt_prefix 18 __P((DB *, size_t(*)(DB *, const DBT *, const DBT *))); 19static int __ram_get_re_delim __P((DB *, int *)); 20static int __ram_set_re_delim __P((DB *, int)); 21static int __ram_set_re_len __P((DB *, u_int32_t)); 22static int __ram_set_re_pad __P((DB *, int)); 23static int __ram_get_re_source __P((DB *, const char **)); 24static int __ram_set_re_source __P((DB *, const char *)); 25 26/* 27 * __bam_db_create -- 28 * Btree specific initialization of the DB structure. 29 * 30 * PUBLIC: int __bam_db_create __P((DB *)); 31 */ 32int 33__bam_db_create(dbp) 34 DB *dbp; 35{ 36 BTREE *t; 37 int ret; 38 39 /* Allocate and initialize the private btree structure. */ 40 if ((ret = __os_calloc(dbp->env, 1, sizeof(BTREE), &t)) != 0) 41 return (ret); 42 dbp->bt_internal = t; 43 44 t->bt_minkey = DEFMINKEYPAGE; /* Btree */ 45 t->bt_compare = __bam_defcmp; 46 t->bt_prefix = __bam_defpfx; 47 48 dbp->set_bt_compare = __bam_set_bt_compare; 49 dbp->get_bt_minkey = __bam_get_bt_minkey; 50 dbp->set_bt_minkey = __bam_set_bt_minkey; 51 dbp->set_bt_prefix = __bam_set_bt_prefix; 52 53 t->re_pad = ' '; /* Recno */ 54 t->re_delim = '\n'; 55 t->re_eof = 1; 56 57 dbp->get_re_delim = __ram_get_re_delim; 58 dbp->set_re_delim = __ram_set_re_delim; 59 dbp->get_re_len = __ram_get_re_len; 60 dbp->set_re_len = __ram_set_re_len; 61 dbp->get_re_pad = __ram_get_re_pad; 62 dbp->set_re_pad = __ram_set_re_pad; 63 dbp->get_re_source = __ram_get_re_source; 64 dbp->set_re_source = __ram_set_re_source; 65 66 return (0); 67} 68 69/* 70 * __bam_db_close -- 71 * Btree specific discard of the DB structure. 72 * 73 * PUBLIC: int __bam_db_close __P((DB *)); 74 */ 75int 76__bam_db_close(dbp) 77 DB *dbp; 78{ 79 BTREE *t; 80 81 if ((t = dbp->bt_internal) == NULL) 82 return (0); 83 /* Recno */ 84 /* Close any backing source file descriptor. */ 85 if (t->re_fp != NULL) 86 (void)fclose(t->re_fp); 87 88 /* Free any backing source file name. */ 89 if (t->re_source != NULL) 90 __os_free(dbp->env, t->re_source); 91 92 __os_free(dbp->env, t); 93 dbp->bt_internal = NULL; 94 95 return (0); 96} 97 98/* 99 * __bam_map_flags -- 100 * Map Btree specific flags from public to the internal values. 101 * 102 * PUBLIC: void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *)); 103 */ 104void 105__bam_map_flags(dbp, inflagsp, outflagsp) 106 DB *dbp; 107 u_int32_t *inflagsp, *outflagsp; 108{ 109 COMPQUIET(dbp, NULL); 110 111 if (FLD_ISSET(*inflagsp, DB_DUP)) { 112 FLD_SET(*outflagsp, DB_AM_DUP); 113 FLD_CLR(*inflagsp, DB_DUP); 114 } 115 if (FLD_ISSET(*inflagsp, DB_DUPSORT)) { 116 FLD_SET(*outflagsp, DB_AM_DUP | DB_AM_DUPSORT); 117 FLD_CLR(*inflagsp, DB_DUPSORT); 118 } 119 if (FLD_ISSET(*inflagsp, DB_RECNUM)) { 120 FLD_SET(*outflagsp, DB_AM_RECNUM); 121 FLD_CLR(*inflagsp, DB_RECNUM); 122 } 123 if (FLD_ISSET(*inflagsp, DB_REVSPLITOFF)) { 124 FLD_SET(*outflagsp, DB_AM_REVSPLITOFF); 125 FLD_CLR(*inflagsp, DB_REVSPLITOFF); 126 } 127} 128 129/* 130 * __bam_set_flags -- 131 * Set Btree specific flags. 132 * 133 * PUBLIC: int __bam_set_flags __P((DB *, u_int32_t *flagsp)); 134 */ 135int 136__bam_set_flags(dbp, flagsp) 137 DB *dbp; 138 u_int32_t *flagsp; 139{ 140 u_int32_t flags; 141 142 flags = *flagsp; 143 if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF)) 144 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); 145 146 /* 147 * The DB_DUP and DB_DUPSORT flags are shared by the Hash 148 * and Btree access methods. 149 */ 150 if (LF_ISSET(DB_DUP | DB_DUPSORT)) 151 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); 152 153 if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF)) 154 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); 155 156 /* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */ 157 if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM)) 158 goto incompat; 159 160 /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */ 161 if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP)) 162 goto incompat; 163 164 if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL) 165 dbp->dup_compare = __bam_defcmp; 166 167 __bam_map_flags(dbp, flagsp, &dbp->flags); 168 return (0); 169 170incompat: 171 return (__db_ferr(dbp->env, "DB->set_flags", 1)); 172} 173 174/* 175 * __bam_set_bt_compare -- 176 * Set the comparison function. 177 * 178 * PUBLIC: int __bam_set_bt_compare 179 * PUBLIC: __P((DB *, int (*)(DB *, const DBT *, const DBT *))); 180 */ 181int 182__bam_set_bt_compare(dbp, func) 183 DB *dbp; 184 int (*func) __P((DB *, const DBT *, const DBT *)); 185{ 186 BTREE *t; 187 188 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare"); 189 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); 190 191 t = dbp->bt_internal; 192 193 /* 194 * Can't default the prefix routine if the user supplies a comparison 195 * routine; shortening the keys can break their comparison algorithm. 196 */ 197 t->bt_compare = func; 198 if (t->bt_prefix == __bam_defpfx) 199 t->bt_prefix = NULL; 200 201 return (0); 202} 203 204/* 205 * __db_get_bt_minkey -- 206 * Get the minimum keys per page. 207 * 208 * PUBLIC: int __bam_get_bt_minkey __P((DB *, u_int32_t *)); 209 */ 210int 211__bam_get_bt_minkey(dbp, bt_minkeyp) 212 DB *dbp; 213 u_int32_t *bt_minkeyp; 214{ 215 BTREE *t; 216 217 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); 218 219 t = dbp->bt_internal; 220 *bt_minkeyp = t->bt_minkey; 221 return (0); 222} 223 224/* 225 * __bam_set_bt_minkey -- 226 * Set the minimum keys per page. 227 */ 228static int 229__bam_set_bt_minkey(dbp, bt_minkey) 230 DB *dbp; 231 u_int32_t bt_minkey; 232{ 233 BTREE *t; 234 235 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey"); 236 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); 237 238 t = dbp->bt_internal; 239 240 if (bt_minkey < 2) { 241 __db_errx(dbp->env, "minimum bt_minkey value is 2"); 242 return (EINVAL); 243 } 244 245 t->bt_minkey = bt_minkey; 246 return (0); 247} 248 249/* 250 * __bam_set_bt_prefix -- 251 * Set the prefix function. 252 */ 253static int 254__bam_set_bt_prefix(dbp, func) 255 DB *dbp; 256 size_t (*func) __P((DB *, const DBT *, const DBT *)); 257{ 258 BTREE *t; 259 260 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix"); 261 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); 262 263 t = dbp->bt_internal; 264 265 t->bt_prefix = func; 266 return (0); 267} 268 269/* 270 * __ram_map_flags -- 271 * Map Recno specific flags from public to the internal values. 272 * 273 * PUBLIC: void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *)); 274 */ 275void 276__ram_map_flags(dbp, inflagsp, outflagsp) 277 DB *dbp; 278 u_int32_t *inflagsp, *outflagsp; 279{ 280 COMPQUIET(dbp, NULL); 281 282 if (FLD_ISSET(*inflagsp, DB_RENUMBER)) { 283 FLD_SET(*outflagsp, DB_AM_RENUMBER); 284 FLD_CLR(*inflagsp, DB_RENUMBER); 285 } 286 if (FLD_ISSET(*inflagsp, DB_SNAPSHOT)) { 287 FLD_SET(*outflagsp, DB_AM_SNAPSHOT); 288 FLD_CLR(*inflagsp, DB_SNAPSHOT); 289 } 290} 291 292/* 293 * __ram_set_flags -- 294 * Set Recno specific flags. 295 * 296 * PUBLIC: int __ram_set_flags __P((DB *, u_int32_t *flagsp)); 297 */ 298int 299__ram_set_flags(dbp, flagsp) 300 DB *dbp; 301 u_int32_t *flagsp; 302{ 303 u_int32_t flags; 304 305 flags = *flagsp; 306 if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) { 307 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); 308 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); 309 } 310 311 __ram_map_flags(dbp, flagsp, &dbp->flags); 312 return (0); 313} 314 315/* 316 * __db_get_re_delim -- 317 * Get the variable-length input record delimiter. 318 */ 319static int 320__ram_get_re_delim(dbp, re_delimp) 321 DB *dbp; 322 int *re_delimp; 323{ 324 BTREE *t; 325 326 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); 327 t = dbp->bt_internal; 328 *re_delimp = t->re_delim; 329 return (0); 330} 331 332/* 333 * __ram_set_re_delim -- 334 * Set the variable-length input record delimiter. 335 */ 336static int 337__ram_set_re_delim(dbp, re_delim) 338 DB *dbp; 339 int re_delim; 340{ 341 BTREE *t; 342 343 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim"); 344 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); 345 346 t = dbp->bt_internal; 347 348 t->re_delim = re_delim; 349 F_SET(dbp, DB_AM_DELIMITER); 350 351 return (0); 352} 353 354/* 355 * __db_get_re_len -- 356 * Get the variable-length input record length. 357 * 358 * PUBLIC: int __ram_get_re_len __P((DB *, u_int32_t *)); 359 */ 360int 361__ram_get_re_len(dbp, re_lenp) 362 DB *dbp; 363 u_int32_t *re_lenp; 364{ 365 BTREE *t; 366 QUEUE *q; 367 368 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); 369 370 /* 371 * This has to work for all access methods, before or after opening the 372 * database. When the record length is set with __ram_set_re_len, the 373 * value in both the BTREE and QUEUE structs will be correct. 374 * Otherwise, this only makes sense after the database in opened, in 375 * which case we know the type. 376 */ 377 if (dbp->type == DB_QUEUE) { 378 q = dbp->q_internal; 379 *re_lenp = q->re_len; 380 } else { 381 t = dbp->bt_internal; 382 *re_lenp = t->re_len; 383 } 384 385 return (0); 386} 387 388/* 389 * __ram_set_re_len -- 390 * Set the variable-length input record length. 391 */ 392static int 393__ram_set_re_len(dbp, re_len) 394 DB *dbp; 395 u_int32_t re_len; 396{ 397 BTREE *t; 398 QUEUE *q; 399 400 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len"); 401 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); 402 403 t = dbp->bt_internal; 404 t->re_len = re_len; 405 406 q = dbp->q_internal; 407 q->re_len = re_len; 408 409 F_SET(dbp, DB_AM_FIXEDLEN); 410 411 return (0); 412} 413 414/* 415 * __db_get_re_pad -- 416 * Get the fixed-length record pad character. 417 * 418 * PUBLIC: int __ram_get_re_pad __P((DB *, int *)); 419 */ 420int 421__ram_get_re_pad(dbp, re_padp) 422 DB *dbp; 423 int *re_padp; 424{ 425 BTREE *t; 426 QUEUE *q; 427 428 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); 429 430 /* 431 * This has to work for all access methods, before or after opening the 432 * database. When the record length is set with __ram_set_re_pad, the 433 * value in both the BTREE and QUEUE structs will be correct. 434 * Otherwise, this only makes sense after the database in opened, in 435 * which case we know the type. 436 */ 437 if (dbp->type == DB_QUEUE) { 438 q = dbp->q_internal; 439 *re_padp = q->re_pad; 440 } else { 441 t = dbp->bt_internal; 442 *re_padp = t->re_pad; 443 } 444 445 return (0); 446} 447 448/* 449 * __ram_set_re_pad -- 450 * Set the fixed-length record pad character. 451 */ 452static int 453__ram_set_re_pad(dbp, re_pad) 454 DB *dbp; 455 int re_pad; 456{ 457 BTREE *t; 458 QUEUE *q; 459 460 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad"); 461 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); 462 463 t = dbp->bt_internal; 464 t->re_pad = re_pad; 465 466 q = dbp->q_internal; 467 q->re_pad = re_pad; 468 469 F_SET(dbp, DB_AM_PAD); 470 471 return (0); 472} 473 474/* 475 * __db_get_re_source -- 476 * Get the backing source file name. 477 */ 478static int 479__ram_get_re_source(dbp, re_sourcep) 480 DB *dbp; 481 const char **re_sourcep; 482{ 483 BTREE *t; 484 485 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); 486 487 t = dbp->bt_internal; 488 *re_sourcep = t->re_source; 489 return (0); 490} 491 492/* 493 * __ram_set_re_source -- 494 * Set the backing source file name. 495 */ 496static int 497__ram_set_re_source(dbp, re_source) 498 DB *dbp; 499 const char *re_source; 500{ 501 BTREE *t; 502 503 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source"); 504 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); 505 506 t = dbp->bt_internal; 507 508 return (__os_strdup(dbp->env, re_source, &t->re_source)); 509} 510