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