diff options
author | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
---|---|---|
committer | Jesse Morgan <jesse@jesterpm.net> | 2016-12-17 21:28:53 -0800 |
commit | 54df2afaa61c6a03cbb4a33c9b90fa572b6d07b8 (patch) | |
tree | 18147b92b969d25ffbe61935fb63035cac820dd0 /db-4.8.30/dbinc/btree.h |
Berkeley DB 4.8 with rust build script for linux.
Diffstat (limited to 'db-4.8.30/dbinc/btree.h')
-rw-r--r-- | db-4.8.30/dbinc/btree.h | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/db-4.8.30/dbinc/btree.h b/db-4.8.30/dbinc/btree.h new file mode 100644 index 0000000..afb81b3 --- /dev/null +++ b/db-4.8.30/dbinc/btree.h @@ -0,0 +1,480 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996-2009 Oracle. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ +#ifndef _DB_BTREE_H_ +#define _DB_BTREE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Forward structure declarations. */ +struct __btree; typedef struct __btree BTREE; +struct __cursor; typedef struct __cursor BTREE_CURSOR; +struct __epg; typedef struct __epg EPG; + +#define DEFMINKEYPAGE (2) + +/* + * A recno order of 0 indicates that we don't have an order, not that we've + * an order less than 1. + */ +#define INVALID_ORDER 0 + +#define ISINTERNAL(p) (TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) +#define ISLEAF(p) (TYPE(p) == P_LBTREE || \ + TYPE(p) == P_LRECNO || TYPE(p) == P_LDUP) + +/* Flags for __bam_cadjust_log(). */ +#define CAD_UPDATEROOT 0x01 /* Root page count was updated. */ + +/* Flags for __bam_split_log(). */ +#define SPL_NRECS 0x01 /* Split tree has record count. */ +#define SPL_RECNO 0x02 /* This is a Recno cursor. */ + +/* Flags for __bam_iitem(). */ +#define BI_DELETED 0x01 /* Key/data pair only placeholder. */ + +/* Flags for __bam_stkrel(). */ +#define STK_CLRDBC 0x01 /* Clear dbc->page reference. */ +#define STK_NOLOCK 0x02 /* Don't retain locks. */ +#define STK_PGONLY 0x04 + +/* Flags for __ram_ca(). These get logged, so make the values explicit. */ +typedef enum { + CA_DELETE = 0, /* Delete the current record. */ + CA_IAFTER = 1, /* Insert before the current record. */ + CA_IBEFORE = 2, /* Insert after the current record. */ + CA_ICURRENT = 3 /* Overwrite the current record. */ +} ca_recno_arg; + +/* + * Flags for __bam_search() and __bam_rsearch(). + * + * Note, internal page searches must find the largest record less than key in + * the tree so that descents work. Leaf page searches must find the smallest + * record greater than key so that the returned index is the record's correct + * position for insertion. + * + * The flags parameter to the search routines describes three aspects of the + * search: the type of locking required (including if we're locking a pair of + * pages), the item to return in the presence of duplicates and whether or not + * to return deleted entries. To simplify both the mnemonic representation + * and the code that checks for various cases, we construct a set of bitmasks. + */ +#define SR_READ 0x00001 /* Read locks. */ +#define SR_WRITE 0x00002 /* Write locks. */ + +#define SR_APPEND 0x00040 /* Append to the tree. */ +#define SR_DELNO 0x00080 /* Don't return deleted items. */ +#define SR_DUPFIRST 0x00100 /* Return first duplicate. */ +#define SR_DUPLAST 0x00200 /* Return last duplicate. */ +#define SR_EXACT 0x00400 /* Exact items only. */ +#define SR_PARENT 0x00800 /* Lock page pair. */ +#define SR_STACK 0x01000 /* Need a complete stack. */ +#define SR_PAST_EOF 0x02000 /* If doing insert search (or keyfirst + * or keylast operations), or a split + * on behalf of an insert, it's okay to + * return an entry one past end-of-page. + */ +#define SR_STK_ONLY 0x04000 /* Just return info in the stack */ +#define SR_MAX 0x08000 /* Get the right most key */ +#define SR_MIN 0x10000 /* Get the left most key */ +#define SR_NEXT 0x20000 /* Get the page after this key */ +#define SR_DEL 0x40000 /* Get the tree to delete this key. */ +#define SR_START 0x80000 /* Level to start stack. */ +#define SR_BOTH 0x100000 /* Get this and the NEXT page */ + +#define SR_DELETE \ + (SR_WRITE | SR_DUPFIRST | SR_DELNO | SR_EXACT | SR_STACK) +#define SR_FIND (SR_READ | SR_DUPFIRST | SR_DELNO) +#define SR_FIND_WR (SR_WRITE | SR_DUPFIRST | SR_DELNO) +#define SR_INSERT (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_STACK) +#define SR_KEYFIRST (SR_WRITE | SR_DUPFIRST | SR_PAST_EOF | SR_STACK) +#define SR_KEYLAST (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_STACK) +#define SR_WRPAIR (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_PARENT) + +/* + * Various routines pass around page references. A page reference is + * a pointer to the page, and the indx indicates an item on the page. + * Each page reference may include a lock. + */ +struct __epg { + PAGE *page; /* The page. */ + db_indx_t indx; /* The index on the page. */ + db_indx_t entries; /* The number of entries on page */ + DB_LOCK lock; /* The page's lock. */ + db_lockmode_t lock_mode; /* The lock mode. */ +}; + +/* + * We maintain a stack of the pages that we're locking in the tree. Grow + * the stack as necessary. + * + * XXX + * Temporary fix for #3243 -- clear the page and lock from the stack entry. + * The correct fix is to never release a stack that doesn't hold items. + */ +#define BT_STK_CLR(c) do { \ + (c)->csp = (c)->sp; \ + (c)->csp->page = NULL; \ + LOCK_INIT((c)->csp->lock); \ +} while (0) + +#define BT_STK_ENTER(env, c, pagep, page_indx, l, mode, ret) do { \ + if ((ret = ((c)->csp == (c)->esp ? \ + __bam_stkgrow(env, c) : 0)) == 0) { \ + (c)->csp->page = pagep; \ + (c)->csp->indx = (page_indx); \ + (c)->csp->entries = NUM_ENT(pagep); \ + (c)->csp->lock = l; \ + (c)->csp->lock_mode = mode; \ + } \ +} while (0) + +#define BT_STK_PUSH(env, c, pagep, page_indx, lock, mode, ret) do { \ + BT_STK_ENTER(env, c, pagep, page_indx, lock, mode, ret); \ + ++(c)->csp; \ +} while (0) + +#define BT_STK_NUM(env, c, pagep, page_indx, ret) do { \ + if ((ret = ((c)->csp == \ + (c)->esp ? __bam_stkgrow(env, c) : 0)) == 0) { \ + (c)->csp->page = NULL; \ + (c)->csp->indx = (page_indx); \ + (c)->csp->entries = NUM_ENT(pagep); \ + LOCK_INIT((c)->csp->lock); \ + (c)->csp->lock_mode = DB_LOCK_NG; \ + } \ +} while (0) + +#define BT_STK_NUMPUSH(env, c, pagep, page_indx, ret) do { \ + BT_STK_NUM(env, cp, pagep, page_indx, ret); \ + ++(c)->csp; \ +} while (0) + +#define BT_STK_POP(c) \ + ((c)->csp == (c)->sp ? NULL : --(c)->csp) + +/* + * Flags for __bam_dpages. + */ +#define BTD_UPDATE 0x0001 /* Update parents. */ +#define BTD_RELINK 0x0002 /* Relink leaf pages. */ + +/* + * TRY_LOCK + * When holding a stack we have pages latched but not locked so + * we must avoid an undetectable deadlock by not then blocking on a + * lock. + */ +#define TRY_LOCK(dbc, pgno, saved_pgno, saved_lock, lock_mode, label) \ + TRY_LOCK2(dbc, NULL, pgno, saved_pgno, saved_lock, lock_mode, label) +/* + * TRY_LOCK2 + * This is a special call for __bam_compact_int which uses 2 + * overlapping stacks. + */ + +#ifdef BTREE_DEBUG +#define TRY_LOCK2(dbc, ndbc, pgno, \ + saved_pgno, saved_lock, lock_mode, label) do { \ + static int BTcount = 0; \ + if ((pgno) != (saved_pgno) && \ + ((BTcount++ % 5) == 0 || \ + (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, DB_LOCK_NOWAIT, &(saved_lock))) != 0)) { \ + if (ret != 0 && ret != DB_LOCK_NOTGRANTED && \ + ret != DB_LOCK_DEADLOCK) \ + break; \ + if ((ndbc) != NULL) { \ + BTREE_CURSOR *__cp; \ + __cp = (BTREE_CURSOR *) (dbc)->internal; \ + __cp->sp->page = NULL; \ + LOCK_INIT(__cp->sp->lock); \ + if ((ret = __bam_stkrel(ndbc, 0)) != 0) \ + break; \ + } \ + if ((ret = __bam_stkrel(dbc, 0)) != 0) \ + break; \ + if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, 0, &(saved_lock))) != 0) \ + break; \ + saved_pgno = pgno; \ + goto label; \ + } \ + saved_pgno = pgno; \ +} while (0) +#else +#define TRY_LOCK2(dbc, ndbc, pgno, \ + saved_pgno, saved_lock, lock_mode, label) do { \ + if ((pgno) != (saved_pgno) && \ + (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, DB_LOCK_NOWAIT, &(saved_lock))) != 0) { \ + if (ret != DB_LOCK_NOTGRANTED && \ + ret != DB_LOCK_DEADLOCK) \ + break; \ + if ((ndbc) != NULL) { \ + BTREE_CURSOR *__cp; \ + __cp = (BTREE_CURSOR *) (dbc)->internal; \ + __cp->sp->page = NULL; \ + LOCK_INIT(__cp->sp->lock); \ + if ((ret = __bam_stkrel(ndbc, 0)) != 0) \ + break; \ + } \ + if ((ret = __bam_stkrel(dbc, 0)) != 0) \ + break; \ + if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, 0, &(saved_lock))) != 0) \ + break; \ + saved_pgno = pgno; \ + goto label; \ + } \ + saved_pgno = pgno; \ +} while (0) +#endif + +/* Btree/Recno cursor. */ +struct __cursor { + /* struct __dbc_internal */ + __DBC_INTERNAL + + /* btree private part */ + EPG *sp; /* Stack pointer. */ + EPG *csp; /* Current stack entry. */ + EPG *esp; /* End stack pointer. */ + EPG stack[5]; + + db_indx_t ovflsize; /* Maximum key/data on-page size. */ + + db_recno_t recno; /* Current record number. */ + u_int32_t order; /* Relative order among deleted curs. */ + +#ifdef HAVE_COMPRESSION + /* + * Compression: + * + * We need to hold the current compressed chunk, as well as the previous + * key/data, in order to decompress the next key/data. We do that by + * swapping whether prevKey/Data and currentKey/Data point to + * key1/data1, or key2/data2. + * + * We store prevcursor in order to be able to perform one level of + * DB_PREV by returning prevKey/prevData. We need prev2cursor to more + * efficiently do a subsequent DB_PREV with a linear search from the + * begining of the compressed chunk. + * + * When we delete entries, we set the cursor to point to the next entry + * after the last deleted key, and set C_COMPRESS_DELETED. The del_key + * DBT holds the key of the deleted entry supposedly pointed to by a + * compressed cursor, and is used to implement DB_PREV_DUP, + * DB_PREV_NODUP, DB_NEXT_DUP, and DB_NEXT_NODUP on a deleted entry. + */ + DBT compressed; /* Current compressed chunk */ + DBT key1; /* Holds prevKey or currentKey */ + DBT key2; /* Holds prevKey or currentKey */ + DBT data1; /* Holds prevData or currentData */ + DBT data2; /* Holds prevData or currentData */ + DBT del_key; /* Holds key from the deleted entry */ + DBT del_data; /* Holds data from the deleted entry */ + DBT *prevKey; /* Previous key decompressed */ + DBT *prevData; /* Previous data decompressed */ + DBT *currentKey; /* Current key decompressed */ + DBT *currentData; /* Current data decompressed */ + u_int8_t *compcursor; /* Current position in compressed */ + u_int8_t *compend; /* End of compressed */ + u_int8_t *prevcursor; /* Previous current position */ + u_int8_t *prev2cursor; /* Previous previous current position */ +#endif + + /* + * Btree: + * We set a flag in the cursor structure if the underlying object has + * been deleted. It's not strictly necessary, we could get the same + * information by looking at the page itself, but this method doesn't + * require us to retrieve the page on cursor delete. + * + * Recno: + * When renumbering recno databases during deletes, cursors referencing + * "deleted" records end up positioned between two records, and so must + * be specially adjusted on the next operation. + */ +#define C_DELETED 0x0001 /* Record was deleted. */ + /* + * There are three tree types that require maintaining record numbers. + * Recno AM trees, Btree AM trees for which the DB_RECNUM flag was set, + * and Btree off-page duplicate trees. + */ +#define C_RECNUM 0x0002 /* Tree requires record counts. */ + /* + * Recno trees have immutable record numbers by default, but optionally + * support mutable record numbers. Off-page duplicate Recno trees have + * mutable record numbers. All Btrees with record numbers (including + * off-page duplicate trees) are mutable by design, no flag is needed. + */ +#define C_RENUMBER 0x0004 /* Tree records are mutable. */ + /* + * The current compressed key/data could be deleted, as well as the + * key/data that the underlying BTree cursor points to. + */ +#define C_COMPRESS_DELETED 0x0008 /* Compressed record was deleted. */ + /* + * The current compressed chunk has been modified by another DBC. A + * compressed cursor will have to seek it's position again if necessary + * when it is next accessed. + */ +#define C_COMPRESS_MODIFIED 0x0010 /* Compressed record was modified. */ + u_int32_t flags; +}; + +/* + * Threshhold value, as a function of bt_minkey, of the number of + * bytes a key/data pair can use before being placed on an overflow + * page. Assume every item requires the maximum alignment for + * padding, out of sheer paranoia. + */ +#define B_MINKEY_TO_OVFLSIZE(dbp, minkey, pgsize) \ + ((u_int16_t)(((pgsize) - P_OVERHEAD(dbp)) / ((minkey) * P_INDX) -\ + (BKEYDATA_PSIZE(0) + DB_ALIGN(1, sizeof(int32_t))))) + +/* + * The maximum space that a single item can ever take up on one page. + * Used by __bam_split to determine whether a split is still necessary. + */ +#define B_MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define B_MAXSIZEONPAGE(ovflsize) \ + (B_MAX(BOVERFLOW_PSIZE, BKEYDATA_PSIZE(ovflsize))) + +/* + * The in-memory, per-tree btree/recno data structure. + */ +struct __btree { /* Btree access method. */ + /* + * !!! + * These fields are write-once (when the structure is created) and + * so are ignored as far as multi-threading is concerned. + */ + db_pgno_t bt_meta; /* Database meta-data page. */ + db_pgno_t bt_root; /* Database root page. */ + + u_int32_t bt_minkey; /* Minimum keys per page. */ + + /* Btree comparison function. */ + int (*bt_compare) __P((DB *, const DBT *, const DBT *)); + /* Btree prefix function. */ + size_t (*bt_prefix) __P((DB *, const DBT *, const DBT *)); + /* Btree compress function. */ +#ifdef HAVE_COMPRESSION + int (*bt_compress) __P((DB *, const DBT *, const DBT *, const DBT *, + const DBT *, DBT *)); + /* Btree decompress function. */ + int (*bt_decompress) __P((DB *, const DBT *, const DBT *, DBT *, DBT *, + DBT *)); + /* dup_compare for compression */ + int (*compress_dup_compare) __P((DB *, const DBT *, const DBT *)); +#endif + + /* Recno access method. */ + int re_pad; /* Fixed-length padding byte. */ + int re_delim; /* Variable-length delimiting byte. */ + u_int32_t re_len; /* Length for fixed-length records. */ + char *re_source; /* Source file name. */ + + /* + * !!! + * The bt_lpgno field is NOT protected by any mutex, and for this + * reason must be advisory only, so, while it is read/written by + * multiple threads, DB is completely indifferent to the quality + * of its information. + */ + db_pgno_t bt_lpgno; /* Last insert location. */ + DB_LSN bt_llsn; /* Last insert LSN. */ + + /* + * !!! + * The re_modified field is NOT protected by any mutex, and for this + * reason cannot be anything more complicated than a zero/non-zero + * value. The actual writing of the backing source file cannot be + * threaded, so clearing the flag isn't a problem. + */ + int re_modified; /* If the tree was modified. */ + + /* + * !!! + * These fields are ignored as far as multi-threading is concerned. + * There are no transaction semantics associated with backing files, + * nor is there any thread protection. + */ + FILE *re_fp; /* Source file handle. */ + int re_eof; /* Backing source file EOF reached. */ + db_recno_t re_last; /* Last record number read. */ + +}; + +/* + * Modes for the __bam_curadj recovery records (btree_curadj). + * These appear in log records, so we wire the values and + * do not leave it up to the compiler. + */ +typedef enum { + DB_CA_DI = 1, + DB_CA_DUP = 2, + DB_CA_RSPLIT = 3, + DB_CA_SPLIT = 4 +} db_ca_mode; + +/* + * Flags for __bam_pinsert. + */ +#define BPI_SPACEONLY 0x01 /* Only check for space to update. */ +#define BPI_NORECNUM 0x02 /* Not update the recnum on the left. */ +#define BPI_NOLOGGING 0x04 /* Don't log the update. */ +#define BPI_REPLACE 0x08 /* Repleace the record. */ + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/btree_auto.h" +#include "dbinc_auto/btree_ext.h" +#include "dbinc/db_am.h" +#endif /* !_DB_BTREE_H_ */ |