2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1999-2009 Oracle. All rights reserved.
12 #include "dbinc/db_page.h"
13 #include "dbinc/btree.h"
14 #include "dbinc/qam.h"
16 static int __bam_set_bt_minkey __P((DB *, u_int32_t));
17 static int __bam_get_bt_compare
18 __P((DB *, int (**)(DB *, const DBT *, const DBT *)));
19 static int __bam_get_bt_prefix
20 __P((DB *, size_t(**)(DB *, const DBT *, const DBT *)));
21 static int __bam_set_bt_prefix
22 __P((DB *, size_t(*)(DB *, const DBT *, const DBT *)));
23 static int __bam_get_bt_compress __P((DB *,
24 int (**)(DB *, const DBT *, const DBT *, const DBT *, const DBT *, DBT *),
25 int (**)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *)));
26 static int __ram_get_re_delim __P((DB *, int *));
27 static int __ram_set_re_delim __P((DB *, int));
28 static int __ram_set_re_len __P((DB *, u_int32_t));
29 static int __ram_set_re_pad __P((DB *, int));
30 static int __ram_get_re_source __P((DB *, const char **));
31 static int __ram_set_re_source __P((DB *, const char *));
35 * Btree specific initialization of the DB structure.
37 * PUBLIC: int __bam_db_create __P((DB *));
46 /* Allocate and initialize the private btree structure. */
47 if ((ret = __os_calloc(dbp->env, 1, sizeof(BTREE), &t)) != 0)
51 t->bt_minkey = DEFMINKEYPAGE; /* Btree */
52 t->bt_compare = __bam_defcmp;
53 t->bt_prefix = __bam_defpfx;
54 #ifdef HAVE_COMPRESSION
55 t->bt_compress = NULL;
56 t->bt_decompress = NULL;
57 t->compress_dup_compare = NULL;
60 * DB_AM_COMPRESS may have been set in __bam_metachk before the
61 * bt_internal structure existed.
63 if (F_ISSET(dbp, DB_AM_COMPRESS) &&
64 (ret = __bam_set_bt_compress(dbp, NULL, NULL)) != 0)
68 dbp->get_bt_compare = __bam_get_bt_compare;
69 dbp->set_bt_compare = __bam_set_bt_compare;
70 dbp->get_bt_minkey = __bam_get_bt_minkey;
71 dbp->set_bt_minkey = __bam_set_bt_minkey;
72 dbp->get_bt_prefix = __bam_get_bt_prefix;
73 dbp->set_bt_prefix = __bam_set_bt_prefix;
74 dbp->get_bt_compress = __bam_get_bt_compress;
75 dbp->set_bt_compress = __bam_set_bt_compress;
77 t->re_pad = ' '; /* Recno */
81 dbp->get_re_delim = __ram_get_re_delim;
82 dbp->set_re_delim = __ram_set_re_delim;
83 dbp->get_re_len = __ram_get_re_len;
84 dbp->set_re_len = __ram_set_re_len;
85 dbp->get_re_pad = __ram_get_re_pad;
86 dbp->set_re_pad = __ram_set_re_pad;
87 dbp->get_re_source = __ram_get_re_source;
88 dbp->set_re_source = __ram_set_re_source;
95 * Btree specific discard of the DB structure.
97 * PUBLIC: int __bam_db_close __P((DB *));
105 if ((t = dbp->bt_internal) == NULL)
108 /* Close any backing source file descriptor. */
109 if (t->re_fp != NULL)
110 (void)fclose(t->re_fp);
112 /* Free any backing source file name. */
113 if (t->re_source != NULL)
114 __os_free(dbp->env, t->re_source);
116 __os_free(dbp->env, t);
117 dbp->bt_internal = NULL;
124 * Map Btree specific flags from public to the internal values.
126 * PUBLIC: void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *));
129 __bam_map_flags(dbp, inflagsp, outflagsp)
131 u_int32_t *inflagsp, *outflagsp;
133 COMPQUIET(dbp, NULL);
135 if (FLD_ISSET(*inflagsp, DB_DUP)) {
136 FLD_SET(*outflagsp, DB_AM_DUP);
137 FLD_CLR(*inflagsp, DB_DUP);
139 if (FLD_ISSET(*inflagsp, DB_DUPSORT)) {
140 FLD_SET(*outflagsp, DB_AM_DUP | DB_AM_DUPSORT);
141 FLD_CLR(*inflagsp, DB_DUPSORT);
143 if (FLD_ISSET(*inflagsp, DB_RECNUM)) {
144 FLD_SET(*outflagsp, DB_AM_RECNUM);
145 FLD_CLR(*inflagsp, DB_RECNUM);
147 if (FLD_ISSET(*inflagsp, DB_REVSPLITOFF)) {
148 FLD_SET(*outflagsp, DB_AM_REVSPLITOFF);
149 FLD_CLR(*inflagsp, DB_REVSPLITOFF);
155 * Set Btree specific flags.
157 * PUBLIC: int __bam_set_flags __P((DB *, u_int32_t *flagsp));
160 __bam_set_flags(dbp, flagsp)
167 t = dbp->bt_internal;
170 if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF))
171 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
174 * The DB_DUP and DB_DUPSORT flags are shared by the Hash
175 * and Btree access methods.
177 if (LF_ISSET(DB_DUP | DB_DUPSORT))
178 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH);
180 if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF))
181 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
183 /* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */
184 if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM))
187 /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
188 if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP))
191 /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */
192 if (LF_ISSET(DB_RECNUM) && LF_ISSET(DB_DUP | DB_DUPSORT))
195 #ifdef HAVE_COMPRESSION
196 /* DB_RECNUM is incompatible with compression */
197 if (LF_ISSET(DB_RECNUM) && DB_IS_COMPRESSED(dbp)) {
199 "DB_RECNUM cannot be used with compression");
203 /* DB_DUP without DB_DUPSORT is incompatible with compression */
204 if (LF_ISSET(DB_DUP) && !LF_ISSET(DB_DUPSORT) &&
205 !F_ISSET(dbp, DB_AM_DUPSORT) && DB_IS_COMPRESSED(dbp)) {
207 "DB_DUP cannot be used with compression without DB_DUPSORT");
212 if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL) {
213 #ifdef HAVE_COMPRESSION
214 if (DB_IS_COMPRESSED(dbp)) {
215 dbp->dup_compare = __bam_compress_dupcmp;
216 t->compress_dup_compare = __bam_defcmp;
219 dbp->dup_compare = __bam_defcmp;
222 __bam_map_flags(dbp, flagsp, &dbp->flags);
226 return (__db_ferr(dbp->env, "DB->set_flags", 1));
230 * __bam_get_bt_compare --
231 * Get the comparison function.
234 __bam_get_bt_compare(dbp, funcp)
236 int (**funcp) __P((DB *, const DBT *, const DBT *));
240 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
242 t = dbp->bt_internal;
245 *funcp = t->bt_compare;
251 * __bam_set_bt_compare --
252 * Set the comparison function.
254 * PUBLIC: int __bam_set_bt_compare
255 * PUBLIC: __P((DB *, int (*)(DB *, const DBT *, const DBT *)));
258 __bam_set_bt_compare(dbp, func)
260 int (*func) __P((DB *, const DBT *, const DBT *));
264 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare");
265 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
267 t = dbp->bt_internal;
270 * Can't default the prefix routine if the user supplies a comparison
271 * routine; shortening the keys can break their comparison algorithm.
273 t->bt_compare = func;
274 if (t->bt_prefix == __bam_defpfx)
281 * __bam_get_bt_compress --
282 * Get the compression functions.
285 __bam_get_bt_compress(dbp, compressp, decompressp)
287 int (**compressp) __P((DB *, const DBT *, const DBT *, const DBT *,
288 const DBT *, DBT *));
289 int (**decompressp) __P((DB *, const DBT *, const DBT *, DBT *, DBT *,
292 #ifdef HAVE_COMPRESSION
295 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
297 t = dbp->bt_internal;
299 if (compressp != NULL)
300 *compressp = t->bt_compress;
301 if (decompressp != NULL)
302 *decompressp = t->bt_decompress;
306 COMPQUIET(compressp, NULL);
307 COMPQUIET(decompressp, NULL);
309 __db_errx(dbp->env, "compression support has not been compiled in");
315 * __bam_set_bt_compress --
316 * Set the compression functions.
318 * PUBLIC: int __bam_set_bt_compress __P((DB *,
319 * PUBLIC: int (*)(DB *, const DBT *, const DBT *,
320 * PUBLIC: const DBT *, const DBT *, DBT *),
321 * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *)));
324 __bam_set_bt_compress(dbp, compress, decompress)
326 int (*compress) __P((DB *, const DBT *, const DBT *, const DBT *,
327 const DBT *, DBT *));
328 int (*decompress) __P((DB *, const DBT *, const DBT *, DBT *, DBT *,
331 #ifdef HAVE_COMPRESSION
334 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compress");
335 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
337 t = dbp->bt_internal;
339 /* compression is incompatible with DB_RECNUM */
340 if (F_ISSET(dbp, DB_AM_RECNUM)) {
342 "compression cannot be used with DB_RECNUM");
346 /* compression is incompatible with DB_DUP without DB_DUPSORT */
347 if (F_ISSET(dbp, DB_AM_DUP) && !F_ISSET(dbp, DB_AM_DUPSORT)) {
349 "compression cannot be used with DB_DUP without DB_DUPSORT");
353 if (compress != 0 && decompress != 0) {
354 t->bt_compress = compress;
355 t->bt_decompress = decompress;
356 } else if (compress == 0 && decompress == 0) {
357 t->bt_compress = __bam_defcompress;
358 t->bt_decompress = __bam_defdecompress;
361 "to enable compression you need to supply both function arguments");
364 F_SET(dbp, DB_AM_COMPRESS);
366 /* Copy dup_compare to compress_dup_compare, and use the compression
368 if (F_ISSET(dbp, DB_AM_DUPSORT)) {
369 t->compress_dup_compare = dbp->dup_compare;
370 dbp->dup_compare = __bam_compress_dupcmp;
375 COMPQUIET(compress, NULL);
376 COMPQUIET(decompress, NULL);
378 __db_errx(dbp->env, "compression support has not been compiled in");
384 * __db_get_bt_minkey --
385 * Get the minimum keys per page.
387 * PUBLIC: int __bam_get_bt_minkey __P((DB *, u_int32_t *));
390 __bam_get_bt_minkey(dbp, bt_minkeyp)
392 u_int32_t *bt_minkeyp;
396 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
398 t = dbp->bt_internal;
399 *bt_minkeyp = t->bt_minkey;
404 * __bam_set_bt_minkey --
405 * Set the minimum keys per page.
408 __bam_set_bt_minkey(dbp, bt_minkey)
414 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey");
415 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
417 t = dbp->bt_internal;
420 __db_errx(dbp->env, "minimum bt_minkey value is 2");
424 t->bt_minkey = bt_minkey;
429 * __bam_get_bt_prefix --
430 * Get the prefix function.
433 __bam_get_bt_prefix(dbp, funcp)
435 size_t (**funcp) __P((DB *, const DBT *, const DBT *));
439 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
441 t = dbp->bt_internal;
443 *funcp = t->bt_prefix;
448 * __bam_set_bt_prefix --
449 * Set the prefix function.
452 __bam_set_bt_prefix(dbp, func)
454 size_t (*func) __P((DB *, const DBT *, const DBT *));
458 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix");
459 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
461 t = dbp->bt_internal;
469 * Copy the configuration of one DB handle to another.
470 * PUBLIC: void __bam_copy_config __P((DB *, DB*, u_int32_t));
473 __bam_copy_config(src, dst, nparts)
479 COMPQUIET(nparts, 0);
481 s = src->bt_internal;
482 d = dst->bt_internal;
483 d->bt_compare = s->bt_compare;
484 d->bt_minkey = s->bt_minkey;
485 d->bt_minkey = s->bt_minkey;
486 d->bt_prefix = s->bt_prefix;
487 #ifdef HAVE_COMPRESSION
488 d->bt_compress = s->bt_compress;
489 d->bt_decompress = s->bt_decompress;
490 d->compress_dup_compare = s->compress_dup_compare;
496 * Map Recno specific flags from public to the internal values.
498 * PUBLIC: void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *));
501 __ram_map_flags(dbp, inflagsp, outflagsp)
503 u_int32_t *inflagsp, *outflagsp;
505 COMPQUIET(dbp, NULL);
507 if (FLD_ISSET(*inflagsp, DB_RENUMBER)) {
508 FLD_SET(*outflagsp, DB_AM_RENUMBER);
509 FLD_CLR(*inflagsp, DB_RENUMBER);
511 if (FLD_ISSET(*inflagsp, DB_SNAPSHOT)) {
512 FLD_SET(*outflagsp, DB_AM_SNAPSHOT);
513 FLD_CLR(*inflagsp, DB_SNAPSHOT);
519 * Set Recno specific flags.
521 * PUBLIC: int __ram_set_flags __P((DB *, u_int32_t *flagsp));
524 __ram_set_flags(dbp, flagsp)
531 if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) {
532 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags");
533 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
536 __ram_map_flags(dbp, flagsp, &dbp->flags);
541 * __db_get_re_delim --
542 * Get the variable-length input record delimiter.
545 __ram_get_re_delim(dbp, re_delimp)
551 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
552 t = dbp->bt_internal;
553 *re_delimp = t->re_delim;
558 * __ram_set_re_delim --
559 * Set the variable-length input record delimiter.
562 __ram_set_re_delim(dbp, re_delim)
568 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim");
569 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
571 t = dbp->bt_internal;
573 t->re_delim = re_delim;
574 F_SET(dbp, DB_AM_DELIMITER);
581 * Get the variable-length input record length.
583 * PUBLIC: int __ram_get_re_len __P((DB *, u_int32_t *));
586 __ram_get_re_len(dbp, re_lenp)
593 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
596 * This has to work for all access methods, before or after opening the
597 * database. When the record length is set with __ram_set_re_len, the
598 * value in both the BTREE and QUEUE structs will be correct.
599 * Otherwise, this only makes sense after the database in opened, in
600 * which case we know the type.
602 if (dbp->type == DB_QUEUE) {
604 *re_lenp = q->re_len;
606 t = dbp->bt_internal;
607 *re_lenp = t->re_len;
614 * __ram_set_re_len --
615 * Set the variable-length input record length.
618 __ram_set_re_len(dbp, re_len)
625 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len");
626 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
628 t = dbp->bt_internal;
634 F_SET(dbp, DB_AM_FIXEDLEN);
641 * Get the fixed-length record pad character.
643 * PUBLIC: int __ram_get_re_pad __P((DB *, int *));
646 __ram_get_re_pad(dbp, re_padp)
653 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
656 * This has to work for all access methods, before or after opening the
657 * database. When the record length is set with __ram_set_re_pad, the
658 * value in both the BTREE and QUEUE structs will be correct.
659 * Otherwise, this only makes sense after the database in opened, in
660 * which case we know the type.
662 if (dbp->type == DB_QUEUE) {
664 *re_padp = q->re_pad;
666 t = dbp->bt_internal;
667 *re_padp = t->re_pad;
674 * __ram_set_re_pad --
675 * Set the fixed-length record pad character.
678 __ram_set_re_pad(dbp, re_pad)
685 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad");
686 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO);
688 t = dbp->bt_internal;
694 F_SET(dbp, DB_AM_PAD);
700 * __db_get_re_source --
701 * Get the backing source file name.
704 __ram_get_re_source(dbp, re_sourcep)
706 const char **re_sourcep;
710 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
712 t = dbp->bt_internal;
713 *re_sourcep = t->re_source;
718 * __ram_set_re_source --
719 * Set the backing source file name.
722 __ram_set_re_source(dbp, re_source)
724 const char *re_source;
728 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source");
729 DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO);
731 t = dbp->bt_internal;
733 return (__os_strdup(dbp->env, re_source, &t->re_source));