1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8#ifndef _DB_AM_H_ 9#define _DB_AM_H_ 10 11#if defined(__cplusplus) 12extern "C" { 13#endif 14 15/* 16 * Temporary for the patch release, define this bit here so it 17 * does not renumber the other bits for DB->open. 18 */ 19#define DB_NOERROR 0x10000000 20 21struct __db_foreign_info; \ 22 typedef struct __db_foreign_info DB_FOREIGN_INFO; 23 24/* 25 * Keep track of information for foreign keys. Used to maintain a linked list 26 * of 'primary' DBs which reference this 'foreign' DB. 27 */ 28struct __db_foreign_info { 29 DB *dbp; 30 u_int32_t flags; 31 int (*callback) __P((DB *, const DBT *, DBT *, const DBT *, int *)); 32 33 /* 34 * List entries for foreign key. 35 * 36 * !!! 37 * Explicit representations of structures from queue.h. 38 * LIST_ENTRY(__db) s_links; 39 */ 40 struct { 41 struct __db_foreign_info *le_next; 42 struct __db_foreign_info **le_prev; 43 } f_links; 44}; 45 46/* 47 * IS_ENV_AUTO_COMMIT -- 48 * Auto-commit test for enviroment operations: DbEnv::{open,remove,rename} 49 */ 50#define IS_ENV_AUTO_COMMIT(env, txn, flags) \ 51 (LF_ISSET(DB_AUTO_COMMIT) || ((txn) == NULL && \ 52 F_ISSET((env)->dbenv, DB_ENV_AUTO_COMMIT) && \ 53 !LF_ISSET(DB_NO_AUTO_COMMIT))) 54 55/* 56 * IS_DB_AUTO_COMMIT -- 57 * Auto-commit test for database operations. 58 */ 59#define IS_DB_AUTO_COMMIT(dbp, txn) \ 60 ((txn) == NULL && F_ISSET((dbp), DB_AM_TXN)) 61 62/* 63 * STRIP_AUTO_COMMIT -- 64 * Releases after 4.3 no longer requires DB operations to specify the 65 * AUTO_COMMIT flag, but the API continues to allow it to be specified. 66 */ 67#define STRIP_AUTO_COMMIT(f) FLD_CLR((f), DB_AUTO_COMMIT) 68 69/* DB recovery operation codes. */ 70#define DB_ADD_DUP 1 71#define DB_REM_DUP 2 72#define DB_ADD_BIG 3 73#define DB_REM_BIG 4 74#define DB_ADD_PAGE_COMPAT 5 /* Compatibility for 4.2 db_relink */ 75#define DB_REM_PAGE_COMPAT 6 /* Compatibility for 4.2 db_relink */ 76#define DB_APPEND_BIG 7 77 78/* 79 * Standard initialization and shutdown macros for all recovery functions. 80 */ 81#define REC_INTRO(func, ip, do_cursor) do { \ 82 argp = NULL; \ 83 dbc = NULL; \ 84 file_dbp = NULL; \ 85 COMPQUIET(mpf, NULL); /* Not all recovery routines use mpf. */\ 86 if ((ret = func(env, &file_dbp, \ 87 (info != NULL) ? ((DB_TXNHEAD *)info)->td : NULL, \ 88 dbtp->data, &argp)) != 0) { \ 89 if (ret == DB_DELETED) { \ 90 ret = 0; \ 91 goto done; \ 92 } \ 93 goto out; \ 94 } \ 95 if (do_cursor) { \ 96 if ((ret = \ 97 __db_cursor(file_dbp, ip, NULL, &dbc, 0)) != 0) \ 98 goto out; \ 99 F_SET(dbc, DBC_RECOVER); \ 100 } \ 101 mpf = file_dbp->mpf; \ 102} while (0) 103 104#define REC_CLOSE { \ 105 int __t_ret; \ 106 if (argp != NULL) \ 107 __os_free(env, argp); \ 108 if (dbc != NULL && \ 109 (__t_ret = __dbc_close(dbc)) != 0 && ret == 0) \ 110 ret = __t_ret; \ 111 } \ 112 return (ret) 113 114/* 115 * No-op versions of the same macros. 116 */ 117#define REC_NOOP_INTRO(func) do { \ 118 argp = NULL; \ 119 if ((ret = func(env, dbtp->data, &argp)) != 0) \ 120 return (ret); \ 121} while (0) 122#define REC_NOOP_CLOSE \ 123 if (argp != NULL) \ 124 __os_free(env, argp); \ 125 return (ret) 126 127/* 128 * Macro for reading pages during recovery. In most cases we 129 * want to avoid an error if the page is not found during rollback. 130 */ 131#define REC_FGET(mpf, ip, pgno, pagep, cont) \ 132 if ((ret = __memp_fget(mpf, \ 133 &(pgno), ip, NULL, 0, pagep)) != 0) { \ 134 if (ret != DB_PAGE_NOTFOUND) { \ 135 ret = __db_pgerr(file_dbp, pgno, ret); \ 136 goto out; \ 137 } else \ 138 goto cont; \ 139 } 140#define REC_DIRTY(mpf, ip, priority, pagep) \ 141 if ((ret = __memp_dirty(mpf, \ 142 pagep, ip, NULL, priority, DB_MPOOL_EDIT)) != 0) { \ 143 ret = __db_pgerr(file_dbp, PGNO(*(pagep)), ret); \ 144 goto out; \ 145 } 146 147/* 148 * Standard debugging macro for all recovery functions. 149 */ 150#ifdef DEBUG_RECOVER 151#define REC_PRINT(func) \ 152 (void)func(env, dbtp, lsnp, op, info); 153#else 154#define REC_PRINT(func) 155#endif 156 157/* 158 * Actions to __db_lget 159 */ 160#define LCK_ALWAYS 1 /* Lock even for off page dup cursors */ 161#define LCK_COUPLE 2 /* Lock Couple */ 162#define LCK_COUPLE_ALWAYS 3 /* Lock Couple even in txn. */ 163#define LCK_DOWNGRADE 4 /* Downgrade the lock. (internal) */ 164#define LCK_ROLLBACK 5 /* Lock even if in rollback */ 165 166/* 167 * If doing transactions we have to hold the locks associated with a data item 168 * from a page for the entire transaction. However, we don't have to hold the 169 * locks associated with walking the tree. Distinguish between the two so that 170 * we don't tie up the internal pages of the tree longer than necessary. 171 */ 172#define __LPUT(dbc, lock) \ 173 __ENV_LPUT((dbc)->env, lock) 174 175#define __ENV_LPUT(env, lock) \ 176 (LOCK_ISSET(lock) ? __lock_put(env, &(lock)) : 0) 177 178/* 179 * __TLPUT -- transactional lock put 180 * If the lock is valid then 181 * If we are not in a transaction put the lock. 182 * Else if the cursor is doing dirty reads and this was a read then 183 * put the lock. 184 * Else if the db is supporting dirty reads and this is a write then 185 * downgrade it. 186 * Else do nothing. 187 */ 188#define __TLPUT(dbc, lock) \ 189 (LOCK_ISSET(lock) ? __db_lput(dbc, &(lock)) : 0) 190 191/* 192 * Check whether a database is a primary (that is, has associated secondaries). 193 */ 194#define DB_IS_PRIMARY(dbp) (LIST_FIRST(&dbp->s_secondaries) != NULL) 195/* 196 * A database should be required to be readonly if it's been explicitly 197 * specified as such or if we're a client in a replicated environment 198 * and the user did not specify DB_TXN_NOT_DURABLE. 199 */ 200#define DB_IS_READONLY(dbp) \ 201 (F_ISSET(dbp, DB_AM_RDONLY) || \ 202 (IS_REP_CLIENT((dbp)->env) && !F_ISSET((dbp), DB_AM_NOT_DURABLE))) 203 204#ifdef HAVE_COMPRESSION 205/* 206 * Check whether a database is compressed (btree only) 207 */ 208#define DB_IS_COMPRESSED(dbp) \ 209 (((BTREE *)(dbp)->bt_internal)->bt_compress != NULL) 210#endif 211 212/* 213 * We copy the key out if there's any chance the key in the database is not 214 * the same as the user-specified key. If there is a custom comparator we 215 * return a key, as the user-specified key might be a partial key, containing 216 * only the unique identifier. [#13572] [#15770] 217 * 218 * The test for (flags != 0) is necessary for Db.{get,pget}, but it's not 219 * legal to pass a non-zero flags value to Dbc.{get,pget}. 220 * 221 * We need to split out the hash component, since it is possible to build 222 * without hash support enabled. Which would result in a null pointer access. 223 */ 224#ifdef HAVE_HASH 225#define DB_RETURNS_A_KEY_HASH(dbp) \ 226 ((HASH *)(dbp)->h_internal)->h_compare != NULL 227#else 228#define DB_RETURNS_A_KEY_HASH(dbp) 0 229#endif 230#define DB_RETURNS_A_KEY(dbp, flags) \ 231 (((flags) != 0 && (flags) != DB_GET_BOTH && \ 232 (flags) != DB_GET_BOTH_RANGE && (flags) != DB_SET) || \ 233 ((BTREE *)(dbp)->bt_internal)->bt_compare != __bam_defcmp ||\ 234 DB_RETURNS_A_KEY_HASH(dbp)) 235 236/* 237 * For portability, primary keys that are record numbers are stored in 238 * secondaries in the same byte order as the secondary database. As a 239 * consequence, we need to swap the byte order of these keys before attempting 240 * to use them for lookups in the primary. We also need to swap user-supplied 241 * primary keys that are used in secondary lookups (for example, with the 242 * DB_GET_BOTH flag on a secondary get). 243 */ 244#include "dbinc/db_swap.h" 245 246#define SWAP_IF_NEEDED(sdbp, pkey) \ 247 do { \ 248 if (((sdbp)->s_primary->type == DB_QUEUE || \ 249 (sdbp)->s_primary->type == DB_RECNO) && \ 250 F_ISSET((sdbp), DB_AM_SWAP)) \ 251 P_32_SWAP((pkey)->data); \ 252 } while (0) 253 254/* 255 * Cursor adjustment: 256 * Return the first DB handle in the sorted ENV list of DB 257 * handles that has a matching file ID. 258 */ 259#define FIND_FIRST_DB_MATCH(env, dbp, tdbp) do { \ 260 for ((tdbp) = (dbp); \ 261 TAILQ_PREV((tdbp), __dblist, dblistlinks) != NULL && \ 262 TAILQ_PREV((tdbp), \ 263 __dblist, dblistlinks)->adj_fileid == (dbp)->adj_fileid;\ 264 (tdbp) = TAILQ_PREV((tdbp), __dblist, dblistlinks)) \ 265 ; \ 266} while (0) 267 268/* 269 * Macros used to implement a binary search algorithm. Shared between the 270 * btree and hash implementations. 271 */ 272#define DB_BINARY_SEARCH_FOR(base, limit, nument, adjust) \ 273 for (base = 0, limit = (nument) / (db_indx_t)(adjust); \ 274 (limit) != 0; (limit) >>= 1) 275 276#define DB_BINARY_SEARCH_INCR(index, base, limit, adjust) \ 277 index = (base) + (((limit) >> 1) * (adjust)) 278 279#define DB_BINARY_SEARCH_SHIFT_BASE(index, base, limit, adjust) do { \ 280 base = (index) + (adjust); \ 281 --(limit); \ 282} while (0) 283 284/* 285 * Sequence macros, shared between sequence.c and seq_stat.c 286 */ 287#define SEQ_IS_OPEN(seq) ((seq)->seq_key.data != NULL) 288 289#define SEQ_ILLEGAL_AFTER_OPEN(seq, name) \ 290 if (SEQ_IS_OPEN(seq)) \ 291 return (__db_mi_open((seq)->seq_dbp->env, name, 1)); 292 293#define SEQ_ILLEGAL_BEFORE_OPEN(seq, name) \ 294 if (!SEQ_IS_OPEN(seq)) \ 295 return (__db_mi_open((seq)->seq_dbp->env, name, 0)); 296 297/* 298 * Flags to __db_chk_meta. 299 */ 300#define DB_CHK_META 0x01 /* Checksum the meta page. */ 301#define DB_CHK_NOLSN 0x02 /* Don't check the LSN. */ 302 303#if defined(__cplusplus) 304} 305#endif 306 307#include "dbinc/db_dispatch.h" 308#include "dbinc_auto/db_auto.h" 309#include "dbinc_auto/crdel_auto.h" 310#include "dbinc_auto/db_ext.h" 311#endif /* !_DB_AM_H_ */ 312