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