xref: /illumos-gate/usr/src/cmd/sendmail/db/xa/xa_db.c (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1998
5  *	Sleepycat Software.  All rights reserved.
6  */
7 
8 #include "config.h"
9 
10 #ifndef lint
11 static const char sccsid[] = "@(#)xa_db.c	10.6 (Sleepycat) 12/19/98";
12 #endif /* not lint */
13 
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
16 
17 #include <errno.h>
18 #include <stdio.h>
19 #include <string.h>
20 #endif
21 
22 #include "db_int.h"
23 #include "db_page.h"
24 #include "xa.h"
25 #include "xa_ext.h"
26 #include "db_am.h"
27 #include "db_ext.h"
28 #include "common_ext.h"
29 
30 static int __xa_c_close __P((DBC *));
31 static int __xa_c_del __P((DBC *, u_int32_t));
32 static int __xa_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
33 static int __xa_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
34 static int __xa_close __P((DB *, u_int32_t));
35 static int __xa_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
36 static int __xa_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
37 static int __xa_fd __P((DB *, int *));
38 static int __xa_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
39 static int __xa_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
40 static int __xa_stat __P((DB *, void *, void *(*)(size_t), u_int32_t));
41 static int __xa_sync __P((DB *, u_int32_t));
42 
43 int
44 db_xa_open(fname, type, flags, mode, dbinfo, dbpp)
45 	const char *fname;
46 	DBTYPE type;
47 	u_int32_t flags;
48 	int mode;
49 	DB_INFO *dbinfo;
50 	DB **dbpp;
51 {
52 	DB *dbp, *real_dbp;
53 	DB_ENV *dbenv;
54 	struct __rmname *rp;
55 	int ret;
56 
57 	/*
58 	 * First try to open up the underlying DB.
59 	 *
60 	 * !!!
61 	 * The dbenv argument is taken from the global list of environments.
62 	 * When the transaction manager called xa_start() (__db_xa_start()),
63 	 * the "current" DB environment was moved to the start of the list.
64 	 * However, if we were called in a tpsvrinit function (which is
65 	 * entirely plausible), then it's possible that xa_open was called
66 	 * (which simply recorded the name of the environment to open) and
67 	 * this is the next call into DB.  In that case, we still have to
68 	 * open the environment.
69 	 *
70 	 * The way that we know that xa_open and nothing else was called
71 	 * is because the nameq is not NULL.
72 	 */
73 	if ((rp = TAILQ_FIRST(&DB_GLOBAL(db_nameq))) != NULL &&
74 	    (ret = __db_rmid_to_env(rp->rmid, &dbenv, 1)) != 0)
75 		return (ret);
76 
77 	dbenv = TAILQ_FIRST(&DB_GLOBAL(db_envq));
78 	if ((ret = db_open(fname,
79 	    type, flags, mode, dbenv, dbinfo, &real_dbp)) != 0)
80 		return (ret);
81 
82 	/*
83 	 * Allocate our own DB handle, and copy the exported fields and
84 	 * function pointers into it.  The internal pointer references
85 	 * the real underlying DB handle.
86 	 */
87 	if ((ret = __os_calloc(1, sizeof(DB), &dbp)) != 0) {
88 		(void)real_dbp->close(real_dbp, 0);
89 		return (ret);
90 	}
91 	dbp->type = real_dbp->type;
92 	dbp->byteswapped = real_dbp->byteswapped;
93 	dbp->dbenv = dbenv;
94 	dbp->internal = real_dbp;
95 	TAILQ_INIT(&dbp->active_queue);
96 	TAILQ_INIT(&dbp->free_queue);
97 	dbp->close = __xa_close;
98 	dbp->cursor = __xa_cursor;
99 	dbp->del = __xa_del;
100 	dbp->fd = __xa_fd;
101 	dbp->get = __xa_get;
102 	dbp->join = real_dbp->join;
103 	dbp->put = __xa_put;
104 	dbp->stat = __xa_stat;
105 	dbp->sync = __xa_sync;
106 
107 	*dbpp = dbp;
108 	return (0);
109 }
110 
111 static int
112 __xa_close(dbp, flags)
113 	DB *dbp;
114 	u_int32_t flags;
115 {
116 	DB *real_dbp;
117 	DBC *dbc;
118 	int ret;
119 
120 	/* Close any associated cursors. */
121 	while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
122 		(void)dbc->c_close(dbc);
123 
124 	/* Close the DB handle. */
125 	real_dbp = (DB *)dbp->internal;
126 	ret = real_dbp->close(real_dbp, flags);
127 
128 	__os_free(dbp, sizeof(DB));
129 	return (ret);
130 }
131 
132 static int
133 __xa_cursor(dbp, txn, dbcp, flags)
134 	DB *dbp;
135 	DB_TXN *txn;
136 	DBC **dbcp;
137 	u_int32_t flags;
138 {
139 	DB *real_dbp;
140 	DBC *real_dbc, *dbc;
141 	int ret;
142 
143 	real_dbp = (DB *)dbp->internal;
144 	txn = dbp->dbenv->xa_txn;
145 
146 	if ((ret = real_dbp->cursor(real_dbp, txn, &real_dbc, flags)) != 0)
147 		return (ret);
148 
149 	/*
150 	 * Allocate our own DBC handle, and copy the exported fields and
151 	 * function pointers into it.  The internal pointer references
152 	 * the real underlying DBC handle.
153 	 */
154 	if ((ret = __os_calloc(1, sizeof(DBC), &dbc)) != 0) {
155 		(void)real_dbc->c_close(real_dbc);
156 		return (ret);
157 	}
158 	dbc->dbp = dbp;
159 	dbc->c_close = __xa_c_close;
160 	dbc->c_del = __xa_c_del;
161 	dbc->c_get = __xa_c_get;
162 	dbc->c_put = __xa_c_put;
163 	dbc->internal = real_dbc;
164 	TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
165 
166 	*dbcp = dbc;
167 	return (0);
168 }
169 
170 static int
171 __xa_fd(dbp, fdp)
172 	DB *dbp;
173 	int *fdp;
174 {
175 	DB *real_dbp;
176 
177 	COMPQUIET(fdp, NULL);
178 
179 	real_dbp = (DB *)dbp->internal;
180 	return (__db_eopnotsup(real_dbp->dbenv));
181 }
182 
183 static int
184 __xa_del(dbp, txn, key, flags)
185 	DB *dbp;
186 	DB_TXN *txn;
187 	DBT *key;
188 	u_int32_t flags;
189 {
190 	DB *real_dbp;
191 
192 	real_dbp = (DB *)dbp->internal;
193 	txn = dbp->dbenv->xa_txn;
194 
195 	return (real_dbp->del(real_dbp, txn, key, flags));
196 }
197 
198 static int
199 __xa_get(dbp, txn, key, data, flags)
200 	DB *dbp;
201 	DB_TXN *txn;
202 	DBT *key;
203 	DBT *data;
204 	u_int32_t flags;
205 {
206 	DB *real_dbp;
207 
208 	real_dbp = (DB *)dbp->internal;
209 	txn = dbp->dbenv->xa_txn;
210 
211 	return (real_dbp->get(real_dbp, txn, key, data, flags));
212 }
213 
214 static int
215 __xa_put(dbp, txn, key, data, flags)
216 	DB *dbp;
217 	DB_TXN *txn;
218 	DBT *key;
219 	DBT *data;
220 	u_int32_t flags;
221 {
222 	DB *real_dbp;
223 
224 	real_dbp = (DB *)dbp->internal;
225 	txn = dbp->dbenv->xa_txn;
226 
227 	return (real_dbp->put(real_dbp, txn, key, data, flags));
228 }
229 
230 static int
231 __xa_stat(dbp, spp, db_malloc, flags)
232 	DB *dbp;
233 	void *spp;
234 	void *(*db_malloc) __P((size_t));
235 	u_int32_t flags;
236 {
237 	DB *real_dbp;
238 
239 	real_dbp = (DB *)dbp->internal;
240 	return (real_dbp->stat(real_dbp, spp, db_malloc, flags));
241 }
242 
243 static int
244 __xa_sync(dbp, flags)
245 	DB *dbp;
246 	u_int32_t flags;
247 {
248 	DB *real_dbp;
249 
250 	real_dbp = (DB *)dbp->internal;
251 	return (real_dbp->sync(real_dbp, flags));
252 }
253 
254 static int
255 __xa_c_close(dbc)
256 	DBC *dbc;
257 {
258 	DBC *real_dbc;
259 	int ret;
260 
261 	real_dbc = (DBC *)dbc->internal;
262 
263 	ret = real_dbc->c_close(real_dbc);
264 
265 	TAILQ_REMOVE(&dbc->dbp->active_queue, dbc, links);
266 	__os_free(dbc, sizeof(DBC));
267 
268 	return (ret);
269 }
270 
271 static int
272 __xa_c_del(dbc, flags)
273 	DBC *dbc;
274 	u_int32_t flags;
275 {
276 	DBC *real_dbc;
277 
278 	real_dbc = (DBC *)dbc->internal;
279 	return (real_dbc->c_del(real_dbc, flags));
280 }
281 
282 static int
283 __xa_c_get(dbc, key, data, flags)
284 	DBC *dbc;
285 	DBT *key;
286 	DBT *data;
287 	u_int32_t flags;
288 {
289 	DBC *real_dbc;
290 
291 	real_dbc = (DBC *)dbc->internal;
292 	return (real_dbc->c_get(real_dbc, key, data, flags));
293 }
294 
295 static int
296 __xa_c_put(dbc, key, data, flags)
297 	DBC *dbc;
298 	DBT *key;
299 	DBT *data;
300 	u_int32_t flags;
301 {
302 	DBC *real_dbc;
303 
304 	real_dbc = (DBC *)dbc->internal;
305 	return (real_dbc->c_put(real_dbc, key, data, flags));
306 }
307