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