#ifndef _DB_INT_H_
#define _DB_INT_H_
#ifdef HAVE_SYSTEM_INCLUDE_FILES
#include <sys/types.h>
#ifdef DIAG_MVCC
#include <sys/mman.h>
#endif
#include <sys/stat.h>
#if defined(__INCLUDE_SELECT_H)
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_VXWORKS
#include <selectLib.h>
#endif
#endif
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#ifdef HAVE_VXWORKS
#include <net/uio.h>
#else
#include <sys/uio.h>
#endif
#if defined(__INCLUDE_NETWORKING)
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
#if defined(STDC_HEADERS) || defined(__cplusplus)
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if defined(__INCLUDE_DIRECTORY)
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#endif
#endif
#ifdef DB_WIN32
#include "dbinc/win_db.h"
#endif
#include "db.h"
#include "clib_port.h"
#include "dbinc/queue.h"
#include "dbinc/shqueue.h"
#if defined(__cplusplus)
extern "C" {
#endif
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE (!FALSE)
#define MEGABYTE 1048576
#define GIGABYTE 1073741824
#define NS_PER_MS 1000000
#define NS_PER_US 1000
#define NS_PER_SEC 1000000000
#define US_PER_MS 1000
#define US_PER_SEC 1000000
#define MS_PER_NS 1000000
#define MS_PER_SEC 1000
#define RECNO_OOB 0
#define POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
#define DB_MIN_PGSIZE 0x000200
#define DB_MAX_PGSIZE 0x010000
#define IS_VALID_PAGESIZE(x) \
(POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE))
#define DB_MINPAGECACHE 16
#define DB_DEF_IOSIZE (8 * 1024)
#undef DB_ALIGN
#define DB_ALIGN(v, bound) \
(((v) + (bound) - 1) & ~(((uintmax_t)(bound)) - 1))
#undef ALIGNP_INC
#define ALIGNP_INC(p, bound) \
(void *)(((uintptr_t)(p) + (bound) - 1) & ~(((uintptr_t)(bound)) - 1))
#define P_TO_ULONG(p) ((u_long)(uintptr_t)(p))
#define P_TO_UINT32(p) ((u_int32_t)(uintptr_t)(p))
#define P_TO_UINT16(p) ((u_int16_t)(uintptr_t)(p))
#undef SSZ
#define SSZ(name, field) P_TO_UINT16(&(((name *)0)->field))
#undef SSZA
#define SSZA(name, field) P_TO_UINT16(&(((name *)0)->field[0]))
typedef struct __fn {
u_int32_t mask;
const char *name;
} FN;
#define FLD_CLR(fld, f) (fld) &= ~(f)
#define FLD_ISSET(fld, f) ((fld) & (f))
#define FLD_SET(fld, f) (fld) |= (f)
#define F_CLR(p, f) (p)->flags &= ~(f)
#define F_ISSET(p, f) ((p)->flags & (f))
#define F_SET(p, f) (p)->flags |= (f)
#define LF_CLR(f) ((flags) &= ~(f))
#define LF_ISSET(f) ((flags) & (f))
#define LF_SET(f) ((flags) |= (f))
#define DB_PCT(v, total) \
((int)((total) == 0 ? 0 : ((double)(v) * 100) / (total)))
#define DB_PCT_PG(v, total, pgsize) \
((int)((total) == 0 ? 0 : \
100 - ((double)(v) * 100) / (((double)total) * (pgsize))))
#undef STAT
#ifdef HAVE_STATISTICS
#define STAT(x) x
#else
#define STAT(x)
#endif
typedef struct __db_msgbuf {
char *buf;
char *cur;
size_t len;
} DB_MSGBUF;
#define DB_MSGBUF_INIT(a) do { \
(a)->buf = (a)->cur = NULL; \
(a)->len = 0; \
} while (0)
#define DB_MSGBUF_FLUSH(dbenv, a) do { \
if ((a)->buf != NULL) { \
if ((a)->cur != (a)->buf) \
__db_msg(dbenv, "%s", (a)->buf); \
__os_free(dbenv, (a)->buf); \
DB_MSGBUF_INIT(a); \
} \
} while (0)
#define STAT_FMT(msg, fmt, type, v) do { \
DB_MSGBUF __mb; \
DB_MSGBUF_INIT(&__mb); \
__db_msgadd(dbenv, &__mb, fmt, (type)(v)); \
__db_msgadd(dbenv, &__mb, "\t%s", msg); \
DB_MSGBUF_FLUSH(dbenv, &__mb); \
} while (0)
#define STAT_HEX(msg, v) \
__db_msg(dbenv, "%#lx\t%s", (u_long)(v), msg)
#define STAT_ISSET(msg, p) \
__db_msg(dbenv, "%sSet\t%s", (p) == NULL ? "!" : " ", msg)
#define STAT_LONG(msg, v) \
__db_msg(dbenv, "%ld\t%s", (long)(v), msg)
#define STAT_LSN(msg, lsnp) \
__db_msg(dbenv, "%lu/%lu\t%s", \
(u_long)(lsnp)->file, (u_long)(lsnp)->offset, msg)
#define STAT_POINTER(msg, v) \
__db_msg(dbenv, "%#lx\t%s", P_TO_ULONG(v), msg)
#define STAT_STRING(msg, p) do { \
const char *__p = p; \
__db_msg(dbenv, "%s\t%s", __p == NULL ? "!Set" : __p, msg); \
} while (0)
#define STAT_ULONG(msg, v) \
__db_msg(dbenv, "%lu\t%s", (u_long)(v), msg)
#define DB_SET_DBT(dbt, d, s) do { \
(dbt).data = (void *)(d); \
(dbt).size = (u_int32_t)(s); \
} while (0)
#define DB_INIT_DBT(dbt, d, s) do { \
memset(&(dbt), 0, sizeof(dbt)); \
DB_SET_DBT(dbt, d, s); \
} while (0)
#define DB_RETOK_STD(ret) ((ret) == 0)
#define DB_RETOK_DBCDEL(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \
(ret) == DB_NOTFOUND)
#define DB_RETOK_DBCGET(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \
(ret) == DB_NOTFOUND)
#define DB_RETOK_DBCPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST || \
(ret) == DB_NOTFOUND)
#define DB_RETOK_DBDEL(ret) DB_RETOK_DBCDEL(ret)
#define DB_RETOK_DBGET(ret) DB_RETOK_DBCGET(ret)
#define DB_RETOK_DBPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST)
#define DB_RETOK_EXISTS(ret) DB_RETOK_DBCGET(ret)
#define DB_RETOK_LGGET(ret) ((ret) == 0 || (ret) == DB_NOTFOUND)
#define DB_RETOK_MPGET(ret) ((ret) == 0 || (ret) == DB_PAGE_NOTFOUND)
#define DB_RETOK_REPPMSG(ret) ((ret) == 0 || \
(ret) == DB_REP_IGNORE || \
(ret) == DB_REP_ISPERM || \
(ret) == DB_REP_NEWMASTER || \
(ret) == DB_REP_NEWSITE || \
(ret) == DB_REP_NOTPERM)
#ifdef EOPNOTSUPP
#define DB_OPNOTSUP EOPNOTSUPP
#else
#ifdef ENOTSUP
#define DB_OPNOTSUP ENOTSUP
#else
#define DB_OPNOTSUP EINVAL
#endif
#endif
#define DB_MAXPATHLEN 1024
#define PATH_DOT "."
#define PATH_SEPARATOR "\\/:"
typedef enum {
DB_APP_NONE=0,
DB_APP_DATA,
DB_APP_LOG,
DB_APP_TMP
} APPNAME;
#define ALIVE_ON(dbenv) ((dbenv)->is_alive != NULL)
#define CDB_LOCKING(dbenv) F_ISSET(dbenv, DB_ENV_CDB)
#define CRYPTO_ON(dbenv) ((dbenv)->crypto_handle != NULL)
#define LOCKING_ON(dbenv) ((dbenv)->lk_handle != NULL)
#define LOGGING_ON(dbenv) ((dbenv)->lg_handle != NULL)
#define MPOOL_ON(dbenv) ((dbenv)->mp_handle != NULL)
#define MUTEX_ON(dbenv) ((dbenv)->mutex_handle != NULL)
#define REP_ON(dbenv) \
((dbenv)->rep_handle != NULL && (dbenv)->rep_handle->region != NULL)
#define RPC_ON(dbenv) ((dbenv)->cl_handle != NULL)
#define TXN_ON(dbenv) ((dbenv)->tx_handle != NULL)
#define STD_LOCKING(dbc) \
(!F_ISSET(dbc, DBC_OPD) && \
!CDB_LOCKING((dbc)->dbp->dbenv) && LOCKING_ON((dbc)->dbp->dbenv))
#define IS_RECOVERING(dbenv) \
(LOGGING_ON(dbenv) && F_ISSET((dbenv)->lg_handle, DBLOG_RECOVER))
#define ENV_ILLEGAL_AFTER_OPEN(dbenv, name) \
if (F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
return (__db_mi_open(dbenv, name, 1));
#define ENV_ILLEGAL_BEFORE_OPEN(dbenv, name) \
if (!F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
return (__db_mi_open(dbenv, name, 0));
#define ENV_REQUIRES_CONFIG(dbenv, handle, i, flags) \
if (handle == NULL) \
return (__db_env_config(dbenv, i, flags));
#define ENV_REQUIRES_CONFIG_XX(dbenv, handle, i, flags) \
if ((dbenv)->handle->region == NULL) \
return (__db_env_config(dbenv, i, flags));
#define ENV_NOT_CONFIGURED(dbenv, handle, i, flags) \
if (F_ISSET((dbenv), DB_ENV_OPEN_CALLED)) \
ENV_REQUIRES_CONFIG(dbenv, handle, i, flags)
#define ENV_ENTER(dbenv, ip) do { \
int __ret; \
if ((dbenv)->thr_hashtab == NULL) \
ip = NULL; \
else { \
if ((__ret = \
__env_set_state(dbenv, &(ip), THREAD_ACTIVE)) != 0) \
return (__ret); \
} \
} while (0)
#ifdef DIAGNOSTIC
#define ENV_LEAVE(dbenv, ip) do { \
if ((ip) != NULL) { \
DB_ASSERT(dbenv, (ip)->dbth_state == THREAD_ACTIVE); \
(ip)->dbth_state = THREAD_OUT; \
} \
} while (0)
#else
#define ENV_LEAVE(dbenv, ip) do { \
if ((ip) != NULL) \
(ip)->dbth_state = THREAD_OUT; \
} while (0)
#endif
#ifdef DIAGNOSTIC
#define CHECK_THREAD(dbenv) do { \
DB_THREAD_INFO *__ip; \
if ((dbenv)->thr_hashtab != NULL) { \
(void)__env_set_state(dbenv, &__ip, THREAD_DIAGNOSTIC); \
DB_ASSERT(dbenv, \
__ip != NULL && __ip->dbth_state != THREAD_OUT); \
} \
} while (0)
#ifdef HAVE_STATISTICS
#define CHECK_MTX_THREAD(dbenv, mtx) do { \
if (mtx->alloc_id != MTX_MUTEX_REGION && \
mtx->alloc_id != MTX_ENV_REGION && \
mtx->alloc_id != MTX_APPLICATION) \
CHECK_THREAD(dbenv); \
} while (0)
#else
#define CHECK_MTX_THREAD(dbenv, mtx)
#endif
#else
#define CHECK_THREAD(dbenv)
#define CHECK_MTX_THREAD(dbenv, mtx)
#endif
typedef enum {
THREAD_SLOT_NOT_IN_USE=0,
THREAD_OUT,
THREAD_ACTIVE,
THREAD_BLOCKED
#ifdef DIAGNOSTIC
, THREAD_DIAGNOSTIC
#endif
} DB_THREAD_STATE;
typedef struct __db_thread_info {
pid_t dbth_pid;
db_threadid_t dbth_tid;
DB_THREAD_STATE dbth_state;
SH_TAILQ_ENTRY dbth_links;
} DB_THREAD_INFO;
typedef struct __env_thread_info {
u_int32_t thr_count;
u_int32_t thr_max;
u_int32_t thr_nbucket;
roff_t thr_hashoff;
} THREAD_INFO;
#define DB_EVENT(dbenv, e, einfo) do { \
if ((dbenv)->db_event_func != NULL) \
(dbenv)->db_event_func(dbenv, e, einfo); \
} while (0)
#define DB_IS_THREADED(dbp) \
((dbp)->mutex != MUTEX_INVALID)
#define DB_ILLEGAL_AFTER_OPEN(dbp, name) \
if (F_ISSET((dbp), DB_AM_OPEN_CALLED)) \
return (__db_mi_open((dbp)->dbenv, name, 1));
#define DB_ILLEGAL_BEFORE_OPEN(dbp, name) \
if (!F_ISSET((dbp), DB_AM_OPEN_CALLED)) \
return (__db_mi_open((dbp)->dbenv, name, 0));
#define DB_ILLEGAL_IN_ENV(dbp, name) \
if (!F_ISSET((dbp)->dbenv, DB_ENV_DBLOCAL)) \
return (__db_mi_env((dbp)->dbenv, name));
#define DB_ILLEGAL_METHOD(dbp, flags) { \
int __ret; \
if ((__ret = __dbh_am_chk(dbp, flags)) != 0) \
return (__ret); \
}
#define __DBC_INTERNAL \
DBC *opd; \
\
void *page; \
db_pgno_t root; \
db_pgno_t pgno; \
db_indx_t indx; \
\
DB_LOCK lock; \
db_lockmode_t lock_mode;
struct __dbc_internal {
__DBC_INTERNAL
};
typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN } mu_action;
#define IS_INITIALIZED(dbc) ((dbc)->internal->pgno != PGNO_INVALID)
#define FREE_IF_NEEDED(dbenv, dbt) \
if (F_ISSET((dbt), DB_DBT_APPMALLOC)) { \
__os_ufree((dbenv), (dbt)->data); \
F_CLR((dbt), DB_DBT_APPMALLOC); \
}
#define SET_RET_MEM(dbc, owner) \
do { \
(dbc)->rskey = &(owner)->my_rskey; \
(dbc)->rkey = &(owner)->my_rkey; \
(dbc)->rdata = &(owner)->my_rdata; \
} while (0)
#define COPY_RET_MEM(src, dest) \
do { \
(dest)->rskey = (src)->rskey; \
(dest)->rkey = (src)->rkey; \
(dest)->rdata = (src)->rdata; \
} while (0)
#define RESET_RET_MEM(dbc) \
do { \
(dbc)->rskey = &(dbc)->my_rskey; \
(dbc)->rkey = &(dbc)->my_rkey; \
(dbc)->rdata = &(dbc)->my_rdata; \
} while (0)
#define DB_FTYPE_SET -1
#define DB_FTYPE_NOTSET 0
#define DB_LSN_OFF_NOTSET -1
#define DB_CLEARLEN_NOTSET UINT32_MAX
typedef struct __dbpginfo {
size_t db_pagesize;
u_int32_t flags;
DBTYPE type;
} DB_PGINFO;
#define ZERO_LSN(LSN) do { \
(LSN).file = 0; \
(LSN).offset = 0; \
} while (0)
#define IS_ZERO_LSN(LSN) ((LSN).file == 0 && (LSN).offset == 0)
#define IS_INIT_LSN(LSN) ((LSN).file == 1 && (LSN).offset == 0)
#define INIT_LSN(LSN) do { \
(LSN).file = 1; \
(LSN).offset = 0; \
} while (0)
#define MAX_LSN(LSN) do { \
(LSN).file = UINT32_MAX; \
(LSN).offset = UINT32_MAX; \
} while (0)
#define IS_MAX_LSN(LSN) \
((LSN).file == UINT32_MAX && (LSN).offset == UINT32_MAX)
#define LSN_NOT_LOGGED(LSN) do { \
(LSN).file = 0; \
(LSN).offset = 1; \
} while (0)
#define IS_NOT_LOGGED_LSN(LSN) \
((LSN).file == 0 && (LSN).offset == 1)
#define LOG_COMPARE(lsn0, lsn1) \
((lsn0)->file != (lsn1)->file ? \
((lsn0)->file < (lsn1)->file ? -1 : 1) : \
((lsn0)->offset != (lsn1)->offset ? \
((lsn0)->offset < (lsn1)->offset ? -1 : 1) : 0))
#define DB_NONBLOCK(C) ((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT))
#define NOWAIT_FLAG(txn) \
((txn) != NULL && F_ISSET((txn), TXN_NOWAIT) ? DB_LOCK_NOWAIT : 0)
#define IS_REAL_TXN(txn) \
((txn) != NULL && !F_ISSET(txn, TXN_CDSGROUP))
#define IS_SUBTRANSACTION(txn) \
((txn) != NULL && (txn)->parent != NULL)
#define DB_IV_BYTES 16
#define DB_MAC_KEY 20
#ifdef CONFIG_TEST
#define DB_RPC2ND_MASK 0x00f00000
#define DB_RPC2ND_REVERSEDATA 0x00100000
#define DB_RPC2ND_NOOP 0x00200000
#define DB_RPC2ND_CONCATKEYDATA 0x00300000
#define DB_RPC2ND_CONCATDATAKEY 0x00400000
#define DB_RPC2ND_REVERSECONCAT 0x00500000
#define DB_RPC2ND_TRUNCDATA 0x00600000
#define DB_RPC2ND_CONSTANT 0x00700000
#define DB_RPC2ND_GETZIP 0x00800000
#define DB_RPC2ND_GETNAME 0x00900000
#endif
struct __db_reginfo_t; typedef struct __db_reginfo_t REGINFO;
struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD;
struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST;
struct __vrfy_childinfo;typedef struct __vrfy_childinfo VRFY_CHILDINFO;
struct __vrfy_dbinfo; typedef struct __vrfy_dbinfo VRFY_DBINFO;
struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO;
typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB;
#if defined(__cplusplus)
}
#endif
#include "dbinc/globals.h"
#include "dbinc/clock.h"
#include "dbinc/debug.h"
#include "dbinc/region.h"
#include "dbinc_auto/env_ext.h"
#include "dbinc/mutex.h"
#include "dbinc/os.h"
#ifdef HAVE_REPLICATION_THREADS
#include "dbinc/repmgr.h"
#endif
#include "dbinc/rep.h"
#include "dbinc_auto/clib_ext.h"
#include "dbinc_auto/common_ext.h"
#define DBENV_LOGGING(dbenv) \
(LOGGING_ON(dbenv) && !IS_REP_CLIENT(dbenv) && \
(!IS_RECOVERING(dbenv)))
#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP)
#define DBC_LOGGING(dbc) __dbc_logging(dbc)
#else
#define DBC_LOGGING(dbc) \
((dbc)->txn != NULL && LOGGING_ON((dbc)->dbp->dbenv) && \
!F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->dbp->dbenv))
#endif
#endif