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
db_xa_open(fname,type,flags,mode,dbinfo,dbpp)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
__xa_close(dbp,flags)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
__xa_cursor(dbp,txn,dbcp,flags)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
__xa_fd(dbp,fdp)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
__xa_del(dbp,txn,key,flags)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
__xa_get(dbp,txn,key,data,flags)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
__xa_put(dbp,txn,key,data,flags)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
__xa_stat(dbp,spp,db_malloc,flags)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
__xa_sync(dbp,flags)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
__xa_c_close(dbc)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
__xa_c_del(dbc,flags)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
__xa_c_get(dbc,key,data,flags)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
__xa_c_put(dbc,key,data,flags)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