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