#ifndef _DB_BTREE_H_
#define _DB_BTREE_H_
#if defined(__cplusplus)
extern "C" {
#endif
struct __btree; typedef struct __btree BTREE;
struct __cursor; typedef struct __cursor BTREE_CURSOR;
struct __epg; typedef struct __epg EPG;
#define DEFMINKEYPAGE (2)
#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)
#define CAD_UPDATEROOT 0x01
#define SPL_NRECS 0x01
#define SPL_RECNO 0x02
#define BI_DELETED 0x01
#define STK_CLRDBC 0x01
#define STK_NOLOCK 0x02
#define STK_PGONLY 0x04
typedef enum {
CA_DELETE = 0,
CA_IAFTER = 1,
CA_IBEFORE = 2,
CA_ICURRENT = 3
} ca_recno_arg;
#define SR_READ 0x00001
#define SR_WRITE 0x00002
#define SR_APPEND 0x00040
#define SR_DELNO 0x00080
#define SR_DUPFIRST 0x00100
#define SR_DUPLAST 0x00200
#define SR_EXACT 0x00400
#define SR_PARENT 0x00800
#define SR_STACK 0x01000
#define SR_PAST_EOF 0x02000
#define SR_STK_ONLY 0x04000
#define SR_MAX 0x08000
#define SR_MIN 0x10000
#define SR_NEXT 0x20000
#define SR_DEL 0x40000
#define SR_START 0x80000
#define SR_BOTH 0x100000
#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)
struct __epg {
PAGE *page;
db_indx_t indx;
db_indx_t entries;
DB_LOCK lock;
db_lockmode_t lock_mode;
};
#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)
#define BTD_UPDATE 0x0001
#define BTD_RELINK 0x0002
#define TRY_LOCK(dbc, pgno, saved_pgno, saved_lock, lock_mode, label) \
TRY_LOCK2(dbc, NULL, pgno, saved_pgno, saved_lock, lock_mode, label)
#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
struct __cursor {
__DBC_INTERNAL
EPG *sp;
EPG *csp;
EPG *esp;
EPG stack[5];
db_indx_t ovflsize;
db_recno_t recno;
u_int32_t order;
#ifdef HAVE_COMPRESSION
DBT compressed;
DBT key1;
DBT key2;
DBT data1;
DBT data2;
DBT del_key;
DBT del_data;
DBT *prevKey;
DBT *prevData;
DBT *currentKey;
DBT *currentData;
u_int8_t *compcursor;
u_int8_t *compend;
u_int8_t *prevcursor;
u_int8_t *prev2cursor;
#endif
#define C_DELETED 0x0001
#define C_RECNUM 0x0002
#define C_RENUMBER 0x0004
#define C_COMPRESS_DELETED 0x0008
#define C_COMPRESS_MODIFIED 0x0010
u_int32_t flags;
};
#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)))))
#define B_MAX(a,b) (((a) > (b)) ? (a) : (b))
#define B_MAXSIZEONPAGE(ovflsize) \
(B_MAX(BOVERFLOW_PSIZE, BKEYDATA_PSIZE(ovflsize)))
#define BAM_GET_ROOT(dbc, root_pgno, \
page, get_mode, lock_mode, lock, ret) do { \
BTREE *__t = (dbc)->dbp->bt_internal; \
BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \
db_pgno_t __root; \
u_int32_t __rev = 0; \
if ((root_pgno) == PGNO_INVALID) { \
if (__cp->root == PGNO_INVALID) { \
__root = __t->bt_root; \
__rev = __t->revision; \
} else \
__root = root_pgno = __cp->root; \
} else \
__root = root_pgno; \
if (STD_LOCKING(dbc) && \
((lock_mode) == DB_LOCK_WRITE || F_ISSET(dbc, DBC_DOWNREV) \
|| dbc->dbtype == DB_RECNO || F_ISSET(__cp, C_RECNUM)) && \
(ret = \
__db_lget(dbc, 0, __root, lock_mode, 0, &(lock))) != 0) \
break; \
if ((ret = __memp_fget((dbc)->dbp->mpf, &__root, \
(dbc)->thread_info, dbc->txn, get_mode, &page)) == 0) { \
if (__root == root_pgno) \
break; \
if (F_ISSET(dbc, DBC_OPD) || \
!F_ISSET((dbc)->dbp, DB_AM_SUBDB) || \
(__t->bt_root == __root && \
(LEVEL(page) == LEAFLEVEL || TYPE(page) == \
(dbc->dbtype == DB_BTREE ? P_IBTREE : P_IRECNO)) &&\
__rev == (dbc)->dbp->mpf->mfp->revision)) { \
root_pgno = __root; \
break; \
} \
if ((ret = __memp_fput((dbc)->dbp->mpf, \
(dbc)->thread_info, page, (dbc)->priority)) != 0) \
break; \
} else if (ret != DB_PAGE_NOTFOUND) \
break; \
if ((ret = __LPUT(dbc, lock)) != 0) \
break; \
if ((ret = __db_reopen(dbc)) != 0) \
break; \
} while (1)
#define BAM_ROOT_PGNO(dbc) \
(((BTREE_CURSOR *)(dbc)->internal)->root == PGNO_INVALID ? \
((BTREE*)(dbc)->dbp->bt_internal)->bt_root : \
((BTREE_CURSOR *)(dbc)->internal)->root)
struct __btree {
db_pgno_t bt_meta;
db_pgno_t bt_root;
u_int32_t revision;
u_int32_t bt_minkey;
int (*bt_compare) __P((DB *, const DBT *, const DBT *));
size_t (*bt_prefix) __P((DB *, const DBT *, const DBT *));
#ifdef HAVE_COMPRESSION
int (*bt_compress) __P((DB *, const DBT *, const DBT *, const DBT *,
const DBT *, DBT *));
int (*bt_decompress) __P((DB *, const DBT *, const DBT *, DBT *, DBT *,
DBT *));
int (*compress_dup_compare) __P((DB *, const DBT *, const DBT *));
#endif
int re_pad;
int re_delim;
u_int32_t re_len;
char *re_source;
db_pgno_t bt_lpgno;
DB_LSN bt_llsn;
int re_modified;
FILE *re_fp;
int re_eof;
db_recno_t re_last;
};
typedef enum {
DB_CA_DI = 1,
DB_CA_DUP = 2,
DB_CA_RSPLIT = 3,
DB_CA_SPLIT = 4
} db_ca_mode;
#define BPI_SPACEONLY 0x01
#define BPI_NORECNUM 0x02
#define BPI_NOLOGGING 0x04
#define BPI_REPLACE 0x08
#if defined(__cplusplus)
}
#endif
#include "dbinc_auto/btree_auto.h"
#include "dbinc_auto/btree_ext.h"
#include "dbinc/db_am.h"
#endif