summaryrefslogtreecommitdiff
path: root/src/include/api.h
blob: 54baf37351cd4c7975dd5976dae61b2683ae8ecc (plain)
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
/*-
 * Copyright (c) 2008-2012 WiredTiger, Inc.
 *	All rights reserved.
 *
 * See the file LICENSE for redistribution information.
 */

/* Standard entry points to the API: declares/initializes local variables. */
#define	API_CONF_DEFAULTS(h, n, cfg)					\
	{ __wt_confdfl_##h##_##n, (cfg), NULL }

#define	API_SESSION_INIT(s, h, n, cur, bt)				\
	WT_BTREE *__oldbtree = (s)->btree;				\
	const char *__oldname = (s)->name;				\
	(s)->cursor = (cur);						\
	(s)->btree = (bt);						\
	(s)->name = #h "." #n;

#define	API_CALL_NOCONF(s, h, n, cur, bt) do {				\
	API_SESSION_INIT(s, h, n, cur, bt);				\
	WT_ERR(F_ISSET(S2C(s), WT_CONN_PANIC) ? __wt_panic(s) : 0)

#define	API_CALL(s, h, n, cur, bt, cfg, cfgvar) do {			\
	const char *cfgvar[] = API_CONF_DEFAULTS(h, n, cfg);		\
	API_SESSION_INIT(s, h, n, cur, bt);				\
	WT_ERR(F_ISSET(S2C(s), WT_CONN_PANIC) ? __wt_panic(s) : 0);	\
	WT_ERR(((cfg) != NULL) ?					\
	    __wt_config_check((s), __wt_confchk_##h##_##n, (cfg), 0) : 0)

#define	API_END(s)							\
	if ((s) != NULL) {						\
		(s)->btree = __oldbtree;				\
		(s)->name = __oldname;					\
	}								\
} while (0)

/* An API call wrapped in a transaction if necessary. */
#define	TXN_API_CALL(s, h, n, cur, bt, cfg, cfgvar) do {		\
	int __autotxn = 0;						\
	API_CALL(s, h, n, bt, cur, cfg, cfgvar);			\
	__autotxn = F_ISSET(S2C(s), WT_CONN_TRANSACTIONAL) &&		\
	    !F_ISSET(&(s)->txn, TXN_RUNNING);				\
	if (__autotxn)							\
		F_SET(&(s)->txn, TXN_AUTOCOMMIT)

/* An API call wrapped in a transaction if necessary. */
#define	TXN_API_CALL_NOCONF(s, h, n, cur, bt) do {			\
	int __autotxn = 0;						\
	API_CALL_NOCONF(s, h, n, cur, bt);				\
	__autotxn = F_ISSET(S2C(s), WT_CONN_TRANSACTIONAL) &&		\
	    !F_ISSET(&(s)->txn, TXN_AUTOCOMMIT | TXN_RUNNING);		\
	if (__autotxn)							\
		F_SET(&(s)->txn, TXN_AUTOCOMMIT)

/*
 * End a transactional API call.
 */
#define	TXN_API_END(s, ret)						\
	API_END(s);							\
	if (__autotxn) {						\
		if (F_ISSET(&(s)->txn, TXN_AUTOCOMMIT))			\
			F_CLR(&(s)->txn, TXN_AUTOCOMMIT);		\
		else if (ret == 0 && !F_ISSET(&(s)->txn, TXN_ERROR))	\
			ret = __wt_txn_commit((s), NULL);		\
		else {							\
			WT_TRET(__wt_txn_rollback((s), NULL));		\
			if (ret == 0 || ret == WT_DEADLOCK) {		\
				ret = 0;				\
				continue;				\
			}						\
		}							\
	} else if (F_ISSET(&(s)->txn, TXN_RUNNING) && (ret) != 0 &&	\
	    (ret) != WT_NOTFOUND &&					\
	    (ret) != WT_DUPLICATE_KEY)					\
		F_SET(&(s)->txn, TXN_ERROR);				\
	break;								\
} while (1)

/*
 * If a session or connection method is about to return WT_NOTFOUND (some
 * underlying object was not found), map it to ENOENT, only cursor methods
 * return WT_NOTFOUND.
 */
#define	API_END_NOTFOUND_MAP(s, ret)					\
	API_END(s);							\
	return ((ret) == WT_NOTFOUND ? ENOENT : (ret))

#define	TXN_API_END_NOTFOUND_MAP(s, ret)				\
	TXN_API_END(s, ret);						\
	return ((ret) == WT_NOTFOUND ? ENOENT : (ret))

#define	CONNECTION_API_CALL(conn, s, n, cfg, cfgvar)			\
	s = (conn)->default_session;					\
	API_CALL(s, connection, n, NULL, NULL, cfg, cfgvar)

#define	SESSION_API_CALL(s, n, cfg, cfgvar)				\
	API_CALL(s, session, n, NULL, NULL, cfg, cfgvar)

#define	SESSION_TXN_API_CALL(s, n, cfg, cfgvar)				\
	TXN_API_CALL(s, session, n, NULL, NULL, cfg, cfgvar)

#define	CURSOR_API_CALL(cur, s, n, bt)					\
	(s) = (WT_SESSION_IMPL *)(cur)->session;			\
	API_CALL_NOCONF(s, cursor, n, cur, bt)

#define	CURSOR_UPDATE_API_CALL(cur, s, n, bt)				\
	(s) = (WT_SESSION_IMPL *)(cur)->session;			\
	TXN_API_CALL_NOCONF(s, cursor, n, cur, bt)

#define	CURSOR_UPDATE_API_END(s, ret)					\
	TXN_API_END(s, ret)