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