diff options
Diffstat (limited to 'storage/bdb/xa')
-rw-r--r-- | storage/bdb/xa/xa.c | 539 | ||||
-rw-r--r-- | storage/bdb/xa/xa_db.c | 182 | ||||
-rw-r--r-- | storage/bdb/xa/xa_map.c | 167 |
3 files changed, 888 insertions, 0 deletions
diff --git a/storage/bdb/xa/xa.c b/storage/bdb/xa/xa.c new file mode 100644 index 00000000000..6667d14c2bf --- /dev/null +++ b/storage/bdb/xa/xa.c @@ -0,0 +1,539 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: xa.c,v 11.23 2002/08/29 14:22:25 margo Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <stdlib.h> +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/txn.h" + +static int __db_xa_close __P((char *, int, long)); +static int __db_xa_commit __P((XID *, int, long)); +static int __db_xa_complete __P((int *, int *, int, long)); +static int __db_xa_end __P((XID *, int, long)); +static int __db_xa_forget __P((XID *, int, long)); +static int __db_xa_open __P((char *, int, long)); +static int __db_xa_prepare __P((XID *, int, long)); +static int __db_xa_recover __P((XID *, long, int, long)); +static int __db_xa_rollback __P((XID *, int, long)); +static int __db_xa_start __P((XID *, int, long)); +static void __xa_txn_end __P((DB_TXN *)); + +/* + * Possible flag values: + * Dynamic registration 0 => no dynamic registration + * TMREGISTER => dynamic registration + * Asynchronous operation 0 => no support for asynchrony + * TMUSEASYNC => async support + * Migration support 0 => migration of transactions across + * threads is possible + * TMNOMIGRATE => no migration across threads + */ +const struct xa_switch_t db_xa_switch = { + "Berkeley DB", /* name[RMNAMESZ] */ + TMNOMIGRATE, /* flags */ + 0, /* version */ + __db_xa_open, /* xa_open_entry */ + __db_xa_close, /* xa_close_entry */ + __db_xa_start, /* xa_start_entry */ + __db_xa_end, /* xa_end_entry */ + __db_xa_rollback, /* xa_rollback_entry */ + __db_xa_prepare, /* xa_prepare_entry */ + __db_xa_commit, /* xa_commit_entry */ + __db_xa_recover, /* xa_recover_entry */ + __db_xa_forget, /* xa_forget_entry */ + __db_xa_complete /* xa_complete_entry */ +}; + +/* + * __db_xa_open -- + * The open call in the XA protocol. The rmid field is an id number + * that the TM assigned us and will pass us on every xa call. We need to + * map that rmid number into a dbenv structure that we create during + * initialization. Since this id number is thread specific, we do not + * need to store it in shared memory. The file xa_map.c implements all + * such xa->db mappings. + * The xa_info field is instance specific information. We require + * that the value of DB_HOME be passed in xa_info. Since xa_info is the + * only thing that we get to pass to db_env_create, any config information + * will have to be done via a config file instead of via the db_env_create + * call. + */ +static int +__db_xa_open(xa_info, rmid, flags) + char *xa_info; + int rmid; + long flags; +{ + DB_ENV *env; + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + if (flags != TMNOFLAGS) + return (XAER_INVAL); + + /* Verify if we already have this environment open. */ + if (__db_rmid_to_env(rmid, &env) == 0) + return (XA_OK); + if (__os_calloc(env, 1, sizeof(DB_ENV), &env) != 0) + return (XAER_RMERR); + + /* Open a new environment. */ +#define XA_FLAGS \ + DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN + if (db_env_create(&env, 0) != 0) + return (XAER_RMERR); + if (env->open(env, xa_info, XA_FLAGS, 0) != 0) + goto err; + + /* Create the mapping. */ + if (__db_map_rmid(rmid, env) != 0) + goto err; + + /* Allocate space for the current transaction. */ + if (__os_calloc(env, 1, sizeof(DB_TXN), &env->xa_txn) != 0) + goto err; + env->xa_txn->txnid = TXN_INVALID; + + return (XA_OK); + +err: (void)env->close(env, 0); + + return (XAER_RMERR); +} + +/* + * __db_xa_close -- + * The close call of the XA protocol. The only trickiness here + * is that if there are any active transactions, we must fail. It is + * *not* an error to call close on an environment that has already been + * closed (I am interpreting that to mean it's OK to call close on an + * environment that has never been opened). + */ +static int +__db_xa_close(xa_info, rmid, flags) + char *xa_info; + int rmid; + long flags; +{ + DB_ENV *env; + int ret, t_ret; + + COMPQUIET(xa_info, NULL); + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + if (flags != TMNOFLAGS) + return (XAER_INVAL); + + /* If the environment is closed, then we're done. */ + if (__db_rmid_to_env(rmid, &env) != 0) + return (XA_OK); + + /* Check if there are any pending transactions. */ + if (env->xa_txn != NULL && env->xa_txn->txnid != TXN_INVALID) + return (XAER_PROTO); + + /* Destroy the mapping. */ + ret = __db_unmap_rmid(rmid); + + /* Discard space held for the current transaction. */ + if (env->xa_txn != NULL) + __os_free(env, env->xa_txn); + + /* Close the environment. */ + if ((t_ret = env->close(env, 0)) != 0 && ret == 0) + ret = t_ret; + + return (ret == 0 ? XA_OK : XAER_RMERR); +} + +/* + * __db_xa_start -- + * Begin a transaction for the current resource manager. + */ +static int +__db_xa_start(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + TXN_DETAIL *td; + size_t off; + int is_known; + +#define OK_FLAGS (TMJOIN | TMRESUME | TMNOWAIT | TMASYNC | TMNOFLAGS) + if (LF_ISSET(~OK_FLAGS)) + return (XAER_INVAL); + + if (LF_ISSET(TMJOIN) && LF_ISSET(TMRESUME)) + return (XAER_INVAL); + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + is_known = __db_xid_to_txn(env, xid, &off) == 0; + + if (is_known && !LF_ISSET(TMRESUME) && !LF_ISSET(TMJOIN)) + return (XAER_DUPID); + + if (!is_known && LF_ISSET(TMRESUME | TMJOIN)) + return (XAER_NOTA); + + /* + * This can't block, so we can ignore TMNOWAIT. + * + * Other error conditions: RMERR, RMFAIL, OUTSIDE, PROTO, RB* + */ + if (is_known) { + td = (TXN_DETAIL *) + R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + if (td->xa_status == TXN_XA_SUSPENDED && + !LF_ISSET(TMRESUME | TMJOIN)) + return (XAER_PROTO); + if (td->xa_status == TXN_XA_DEADLOCKED) + return (XA_RBDEADLOCK); + if (td->xa_status == TXN_XA_ABORTED) + return (XA_RBOTHER); + + /* Now, fill in the global transaction structure. */ + __txn_continue(env, env->xa_txn, td, off); + td->xa_status = TXN_XA_STARTED; + } else { + if (__txn_xa_begin(env, env->xa_txn) != 0) + return (XAER_RMERR); + (void)__db_map_xid(env, xid, env->xa_txn->off); + td = (TXN_DETAIL *) + R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, + env->xa_txn->off); + td->xa_status = TXN_XA_STARTED; + } + return (XA_OK); +} + +/* + * __db_xa_end -- + * Disassociate the current transaction from the current process. + */ +static int +__db_xa_end(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + DB_TXN *txn; + TXN_DETAIL *td; + size_t off; + + if (flags != TMNOFLAGS && !LF_ISSET(TMSUSPEND | TMSUCCESS | TMFAIL)) + return (XAER_INVAL); + + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + if (__db_xid_to_txn(env, xid, &off) != 0) + return (XAER_NOTA); + + txn = env->xa_txn; + if (off != txn->off) + return (XAER_PROTO); + + td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + if (td->xa_status == TXN_XA_DEADLOCKED) + return (XA_RBDEADLOCK); + + if (td->status == TXN_ABORTED) + return (XA_RBOTHER); + + if (td->xa_status != TXN_XA_STARTED) + return (XAER_PROTO); + + /* Update the shared memory last_lsn field */ + td->last_lsn = txn->last_lsn; + + /* + * If we ever support XA migration, we cannot keep SUSPEND/END + * status in the shared region; it would have to be process local. + */ + if (LF_ISSET(TMSUSPEND)) + td->xa_status = TXN_XA_SUSPENDED; + else + td->xa_status = TXN_XA_ENDED; + + txn->txnid = TXN_INVALID; + return (XA_OK); +} + +/* + * __db_xa_prepare -- + * Sync the log to disk so we can guarantee recoverability. + */ +static int +__db_xa_prepare(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + TXN_DETAIL *td; + size_t off; + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + if (flags != TMNOFLAGS) + return (XAER_INVAL); + + /* + * We need to know if we've ever called prepare on this. + * As part of the prepare, we set the xa_status field to + * reflect that fact that prepare has been called, and if + * it's ever called again, it's an error. + */ + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + if (__db_xid_to_txn(env, xid, &off) != 0) + return (XAER_NOTA); + + td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + if (td->xa_status == TXN_XA_DEADLOCKED) + return (XA_RBDEADLOCK); + + if (td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED) + return (XAER_PROTO); + + /* Now, fill in the global transaction structure. */ + __txn_continue(env, env->xa_txn, td, off); + + if (env->xa_txn->prepare(env->xa_txn, (u_int8_t *)xid->data) != 0) + return (XAER_RMERR); + + td->xa_status = TXN_XA_PREPARED; + + /* No fatal value that would require an XAER_RMFAIL. */ + __xa_txn_end(env->xa_txn); + return (XA_OK); +} + +/* + * __db_xa_commit -- + * Commit the transaction + */ +static int +__db_xa_commit(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + TXN_DETAIL *td; + size_t off; + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); +#undef OK_FLAGS +#define OK_FLAGS (TMNOFLAGS | TMNOWAIT | TMONEPHASE) + if (LF_ISSET(~OK_FLAGS)) + return (XAER_INVAL); + + /* + * We need to know if we've ever called prepare on this. + * We can verify this by examining the xa_status field. + */ + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + if (__db_xid_to_txn(env, xid, &off) != 0) + return (XAER_NOTA); + + td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + if (td->xa_status == TXN_XA_DEADLOCKED) + return (XA_RBDEADLOCK); + + if (td->xa_status == TXN_XA_ABORTED) + return (XA_RBOTHER); + + if (LF_ISSET(TMONEPHASE) && + td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED) + return (XAER_PROTO); + + if (!LF_ISSET(TMONEPHASE) && td->xa_status != TXN_XA_PREPARED) + return (XAER_PROTO); + + /* Now, fill in the global transaction structure. */ + __txn_continue(env, env->xa_txn, td, off); + + if (env->xa_txn->commit(env->xa_txn, 0) != 0) + return (XAER_RMERR); + + /* No fatal value that would require an XAER_RMFAIL. */ + __xa_txn_end(env->xa_txn); + return (XA_OK); +} + +/* + * __db_xa_recover -- + * Returns a list of prepared and heuristically completed transactions. + * + * The return value is the number of xids placed into the xid array (less + * than or equal to the count parameter). The flags are going to indicate + * whether we are starting a scan or continuing one. + */ +static int +__db_xa_recover(xids, count, rmid, flags) + XID *xids; + long count, flags; + int rmid; +{ + DB_ENV *env; + u_int32_t newflags; + long rval; + + /* If the environment is closed, then we're done. */ + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + if (LF_ISSET(TMSTARTRSCAN)) + newflags = DB_FIRST; + else if (LF_ISSET(TMENDRSCAN)) + newflags = DB_LAST; + else + newflags = DB_NEXT; + + rval = 0; + if (__txn_get_prepared(env, xids, NULL, count, &rval, newflags) != 0) + return (XAER_RMERR); + else + return (rval); +} + +/* + * __db_xa_rollback + * Abort an XA transaction. + */ +static int +__db_xa_rollback(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + TXN_DETAIL *td; + size_t off; + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + if (flags != TMNOFLAGS) + return (XAER_INVAL); + + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + if (__db_xid_to_txn(env, xid, &off) != 0) + return (XAER_NOTA); + + td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + if (td->xa_status == TXN_XA_DEADLOCKED) + return (XA_RBDEADLOCK); + + if (td->xa_status == TXN_XA_ABORTED) + return (XA_RBOTHER); + + if (td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED + && td->xa_status != TXN_XA_PREPARED) + return (XAER_PROTO); + + /* Now, fill in the global transaction structure. */ + __txn_continue(env, env->xa_txn, td, off); + if (env->xa_txn->abort(env->xa_txn) != 0) + return (XAER_RMERR); + + /* No fatal value that would require an XAER_RMFAIL. */ + __xa_txn_end(env->xa_txn); + return (XA_OK); +} + +/* + * __db_xa_forget -- + * Forget about an XID for a transaction that was heuristically + * completed. Since we do not heuristically complete anything, I + * don't think we have to do anything here, but we should make sure + * that we reclaim the slots in the txnid table. + */ +static int +__db_xa_forget(xid, rmid, flags) + XID *xid; + int rmid; + long flags; +{ + DB_ENV *env; + size_t off; + + if (LF_ISSET(TMASYNC)) + return (XAER_ASYNC); + if (flags != TMNOFLAGS) + return (XAER_INVAL); + + if (__db_rmid_to_env(rmid, &env) != 0) + return (XAER_PROTO); + + /* + * If mapping is gone, then we're done. + */ + if (__db_xid_to_txn(env, xid, &off) != 0) + return (XA_OK); + + __db_unmap_xid(env, xid, off); + + /* No fatal value that would require an XAER_RMFAIL. */ + return (XA_OK); +} + +/* + * __db_xa_complete -- + * Used to wait for asynchronous operations to complete. Since we're + * not doing asynch, this is an invalid operation. + */ +static int +__db_xa_complete(handle, retval, rmid, flags) + int *handle, *retval, rmid; + long flags; +{ + COMPQUIET(handle, NULL); + COMPQUIET(retval, NULL); + COMPQUIET(rmid, 0); + COMPQUIET(flags, 0); + + return (XAER_INVAL); +} + +/* + * __xa_txn_end -- + * Invalidate a transaction structure that was generated by __txn_continue. + */ +static void +__xa_txn_end(txn) + DB_TXN *txn; +{ + if (txn != NULL) + txn->txnid = TXN_INVALID; +} diff --git a/storage/bdb/xa/xa_db.c b/storage/bdb/xa/xa_db.c new file mode 100644 index 00000000000..b84bb1c9fa9 --- /dev/null +++ b/storage/bdb/xa/xa_db.c @@ -0,0 +1,182 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: xa_db.c,v 11.21 2002/08/29 14:22:25 margo Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> +#endif + +#include "db_int.h" +#include "dbinc/xa.h" +#include "dbinc/txn.h" + +static int __xa_close __P((DB *, u_int32_t)); +static int __xa_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t)); +static int __xa_del __P((DB *, DB_TXN *, DBT *, u_int32_t)); +static int __xa_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); +static int __xa_open __P((DB *, DB_TXN *, + const char *, const char *, DBTYPE, u_int32_t, int)); +static int __xa_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + +typedef struct __xa_methods { + int (*close) __P((DB *, u_int32_t)); + int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t)); + int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t)); + int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*open) __P((DB *, DB_TXN *, + const char *, const char *, DBTYPE, u_int32_t, int)); + int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); +} XA_METHODS; + +/* + * __db_xa_create -- + * DB XA constructor. + * + * PUBLIC: int __db_xa_create __P((DB *)); + */ +int +__db_xa_create(dbp) + DB *dbp; +{ + XA_METHODS *xam; + int ret; + + /* + * Interpose XA routines in front of any method that takes a TXN + * ID as an argument. + */ + if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(XA_METHODS), &xam)) != 0) + return (ret); + + dbp->xa_internal = xam; + xam->open = dbp->open; + dbp->open = __xa_open; + xam->close = dbp->close; + dbp->close = __xa_close; + + return (0); +} + +/* + * __xa_open -- + * XA open wrapper. + */ + +static int +__xa_open(dbp, txn, name, subdb, type, flags, mode) + DB *dbp; + DB_TXN *txn; + const char *name, *subdb; + DBTYPE type; + u_int32_t flags; + int mode; +{ + XA_METHODS *xam; + int ret; + + xam = (XA_METHODS *)dbp->xa_internal; + + if ((ret = xam->open(dbp, txn, name, subdb, type, flags, mode)) != 0) + return (ret); + + xam->cursor = dbp->cursor; + xam->del = dbp->del; + xam->get = dbp->get; + xam->put = dbp->put; + dbp->cursor = __xa_cursor; + dbp->del = __xa_del; + dbp->get = __xa_get; + dbp->put = __xa_put; + + return (0); +} + +static int +__xa_cursor(dbp, txn, dbcp, flags) + DB *dbp; + DB_TXN *txn; + DBC **dbcp; + u_int32_t flags; +{ + DB_TXN *t; + + t = txn != NULL ? txn : dbp->dbenv->xa_txn; + if (t->txnid == TXN_INVALID) + t = NULL; + + return (((XA_METHODS *)dbp->xa_internal)->cursor (dbp, t, dbcp, flags)); +} + +static int +__xa_del(dbp, txn, key, flags) + DB *dbp; + DB_TXN *txn; + DBT *key; + u_int32_t flags; +{ + DB_TXN *t; + + t = txn != NULL ? txn : dbp->dbenv->xa_txn; + if (t->txnid == TXN_INVALID) + t = NULL; + + return (((XA_METHODS *)dbp->xa_internal)->del(dbp, t, key, flags)); +} + +static int +__xa_close(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + int (*real_close) __P((DB *, u_int32_t)); + + real_close = ((XA_METHODS *)dbp->xa_internal)->close; + + __os_free(dbp->dbenv, dbp->xa_internal); + dbp->xa_internal = NULL; + + return (real_close(dbp, flags)); +} + +static int +__xa_get(dbp, txn, key, data, flags) + DB *dbp; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DB_TXN *t; + + t = txn != NULL ? txn : dbp->dbenv->xa_txn; + if (t->txnid == TXN_INVALID) + t = NULL; + + return (((XA_METHODS *)dbp->xa_internal)->get + (dbp, t, key, data, flags)); +} + +static int +__xa_put(dbp, txn, key, data, flags) + DB *dbp; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DB_TXN *t; + + t = txn != NULL ? txn : dbp->dbenv->xa_txn; + if (t->txnid == TXN_INVALID) + t = NULL; + + return (((XA_METHODS *)dbp->xa_internal)->put + (dbp, t, key, data, flags)); +} diff --git a/storage/bdb/xa/xa_map.c b/storage/bdb/xa/xa_map.c new file mode 100644 index 00000000000..42fa4b20ed2 --- /dev/null +++ b/storage/bdb/xa/xa_map.c @@ -0,0 +1,167 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996-2002 + * Sleepycat Software. All rights reserved. + */ + +#include "db_config.h" + +#ifndef lint +static const char revid[] = "$Id: xa_map.c,v 11.19 2002/09/03 14:58:27 sue Exp $"; +#endif /* not lint */ + +#ifndef NO_SYSTEM_INCLUDES +#include <sys/types.h> + +#include <string.h> +#endif + +#include "db_int.h" +#include "dbinc/txn.h" + +/* + * This file contains all the mapping information that we need to support + * the DB/XA interface. + */ + +/* + * __db_rmid_to_env + * Return the environment associated with a given XA rmid. + * + * PUBLIC: int __db_rmid_to_env __P((int rmid, DB_ENV **envp)); + */ +int +__db_rmid_to_env(rmid, envp) + int rmid; + DB_ENV **envp; +{ + DB_ENV *env; + + env = TAILQ_FIRST(&DB_GLOBAL(db_envq)); + if (env != NULL && env->xa_rmid == rmid) { + *envp = env; + return (0); + } + + /* + * When we map an rmid, move that environment to be the first one in + * the list of environments, so we acquire the correct environment + * in DB->open. + */ + for (; env != NULL; env = TAILQ_NEXT(env, links)) + if (env->xa_rmid == rmid) { + TAILQ_REMOVE(&DB_GLOBAL(db_envq), env, links); + TAILQ_INSERT_HEAD(&DB_GLOBAL(db_envq), env, links); + *envp = env; + return (0); + } + + return (1); +} + +/* + * __db_xid_to_txn + * Return the txn that corresponds to this XID. + * + * PUBLIC: int __db_xid_to_txn __P((DB_ENV *, XID *, size_t *)); + */ +int +__db_xid_to_txn(dbenv, xid, offp) + DB_ENV *dbenv; + XID *xid; + size_t *offp; +{ + struct __txn_detail *td; + + return (__txn_map_gid(dbenv, (u_int8_t *)xid->data, &td, offp)); +} + +/* + * __db_map_rmid + * Create a mapping between the specified rmid and environment. + * + * PUBLIC: int __db_map_rmid __P((int, DB_ENV *)); + */ +int +__db_map_rmid(rmid, env) + int rmid; + DB_ENV *env; +{ + env->xa_rmid = rmid; + TAILQ_INSERT_TAIL(&DB_GLOBAL(db_envq), env, links); + return (0); +} + +/* + * __db_unmap_rmid + * Destroy the mapping for the given rmid. + * + * PUBLIC: int __db_unmap_rmid __P((int)); + */ +int +__db_unmap_rmid(rmid) + int rmid; +{ + DB_ENV *e; + + for (e = TAILQ_FIRST(&DB_GLOBAL(db_envq)); + e->xa_rmid != rmid; + e = TAILQ_NEXT(e, links)); + + if (e == NULL) + return (EINVAL); + + TAILQ_REMOVE(&DB_GLOBAL(db_envq), e, links); + return (0); +} + +/* + * __db_map_xid + * Create a mapping between this XID and the transaction at + * "off" in the shared region. + * + * PUBLIC: int __db_map_xid __P((DB_ENV *, XID *, size_t)); + */ +int +__db_map_xid(env, xid, off) + DB_ENV *env; + XID *xid; + size_t off; +{ + REGINFO *infop; + TXN_DETAIL *td; + + infop = &((DB_TXNMGR *)env->tx_handle)->reginfo; + td = (TXN_DETAIL *)R_ADDR(infop, off); + + R_LOCK(env, infop); + memcpy(td->xid, xid->data, XIDDATASIZE); + td->bqual = (u_int32_t)xid->bqual_length; + td->gtrid = (u_int32_t)xid->gtrid_length; + td->format = (int32_t)xid->formatID; + R_UNLOCK(env, infop); + + return (0); +} + +/* + * __db_unmap_xid + * Destroy the mapping for the specified XID. + * + * PUBLIC: void __db_unmap_xid __P((DB_ENV *, XID *, size_t)); + */ + +void +__db_unmap_xid(env, xid, off) + DB_ENV *env; + XID *xid; + size_t off; +{ + TXN_DETAIL *td; + + COMPQUIET(xid, NULL); + + td = (TXN_DETAIL *)R_ADDR(&((DB_TXNMGR *)env->tx_handle)->reginfo, off); + memset(td->xid, 0, sizeof(td->xid)); +} |