Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

xa.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1998-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: xa.c,v 12.5 2005/11/01 00:44:39 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #endif
00018 
00019 #include "db_int.h"
00020 #include "dbinc/txn.h"
00021 
00022 static int __db_xa_close __P((char *, int, long));
00023 static int __db_xa_commit __P((XID *, int, long));
00024 static int __db_xa_complete __P((int *, int *, int, long));
00025 static int __db_xa_end __P((XID *, int, long));
00026 static int __db_xa_forget __P((XID *, int, long));
00027 static int __db_xa_open __P((char *, int, long));
00028 static int __db_xa_prepare __P((XID *, int, long));
00029 static int __db_xa_recover __P((XID *, long, int, long));
00030 static int __db_xa_rollback __P((XID *, int, long));
00031 static int __db_xa_start __P((XID *, int, long));
00032 static int __xa_put_txn __P((DB_ENV *, DB_TXN *));
00033 
00034 /*
00035  * Possible flag values:
00036  *      Dynamic registration    0 => no dynamic registration
00037  *                              TMREGISTER => dynamic registration
00038  *      Asynchronous operation  0 => no support for asynchrony
00039  *                              TMUSEASYNC => async support
00040  *      Migration support       0 => migration of transactions across
00041  *                                   threads is possible
00042  *                              TMNOMIGRATE => no migration across threads
00043  */
00044 const struct xa_switch_t db_xa_switch = {
00045          "Berkeley DB",         /* name[RMNAMESZ] */
00046          TMNOMIGRATE,           /* flags */
00047          0,                     /* version */
00048          __db_xa_open,          /* xa_open_entry */
00049          __db_xa_close,         /* xa_close_entry */
00050          __db_xa_start,         /* xa_start_entry */
00051          __db_xa_end,           /* xa_end_entry */
00052          __db_xa_rollback,      /* xa_rollback_entry */
00053          __db_xa_prepare,       /* xa_prepare_entry */
00054          __db_xa_commit,        /* xa_commit_entry */
00055          __db_xa_recover,       /* xa_recover_entry */
00056          __db_xa_forget,        /* xa_forget_entry */
00057          __db_xa_complete       /* xa_complete_entry */
00058 };
00059 
00060 /*
00061  * If you want your XA server to be multi-threaded, then you must (at least)
00062  * edit this file and change:
00063  *      #undef  XA_MULTI_THREAD
00064  * to:
00065  *      #define XA_MULTI_THREAD 1
00066  */
00067 #undef XA_MULTI_THREAD
00068 
00069 /*
00070  * __xa_get_txn --
00071  *      Return a pointer to the current transaction structure for the
00072  * designated environment.  If do_init is non-zero and we don't find a
00073  * structure for the current thread, then create a new structure for it.
00074  *
00075  * PUBLIC: int __xa_get_txn __P((DB_ENV *, DB_TXN **, int));
00076  */
00077 int
00078 __xa_get_txn(dbenv, txnp, do_init)
00079         DB_ENV *dbenv;
00080         DB_TXN **txnp;
00081         int do_init;
00082 {
00083 #ifdef XA_MULTI_THREAD
00084         DB_TXN *t;
00085         DB_TXNMGR *mgr;
00086         TXN_DETAIL *td;
00087         db_threadid_t tid;
00088         pid_t pid;
00089 #endif
00090         int ret;
00091 
00092         ret = 0;
00093 
00094 #ifdef XA_MULTI_THREAD
00095         dbenv->thread_id(dbenv, &pid, &tid);
00096         *txnp = NULL;
00097 
00098         DB_ASSERT(dbenv->tx_handle != NULL);
00099         mgr = (DB_TXNMGR *)dbenv->tx_handle;
00100 
00101         /*
00102          * We need to protect the xa_txn linked list, but the environment does
00103          * not have a mutex.  Since we are in an XA transaction environment,
00104          * we know there is a transaction structure, we can use its mutex.
00105          */
00106         MUTEX_LOCK(dbenv, mgr->mutex);
00107         for (t = TAILQ_FIRST(&dbenv->xa_txn);
00108             t != NULL;
00109             t = TAILQ_NEXT(t, xalinks)) {
00110                 td = t->td;
00111                 if (td->pid != pid)
00112                         continue;
00113 #ifdef HAVE_INTEGRAL_THREAD_TYPE
00114                 if (t->tid == tid) {
00115                         *txnp = t;
00116                         break;
00117                 }
00118 #else
00119                 if (memcmp(&t->tid, &tid, sizeof(tid)) == 0) {
00120                         *txnp = t;
00121                         break;
00122                 }
00123 #endif
00124         }
00125         MUTEX_UNLOCK(dbenv, mgr->mutex);
00126 
00127         if (*txnp == NULL) {
00128                 if (!do_init)
00129                         ret = EINVAL;
00130                 else if ((ret =
00131                     __os_malloc(dbenv, sizeof(DB_TXN), txnp)) == 0) {
00132                         (*txnp)->tid = tid;
00133                         MUTEX_LOCK(dbenv, mgr->mutex);
00134                         TAILQ_INSERT_HEAD(&dbenv->xa_txn, *txnp, xalinks);
00135                         MUTEX_UNLOCK(dbenv, mgr->mutex);
00136                 }
00137         }
00138 #else
00139         COMPQUIET(do_init, 0);
00140 
00141         *txnp = TAILQ_FIRST(&dbenv->xa_txn);
00142         if (*txnp == NULL &&
00143             (ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), txnp)) == 0) {
00144                 (*txnp)->txnid = TXN_INVALID;
00145                 TAILQ_INSERT_HEAD(&dbenv->xa_txn, *txnp, xalinks);
00146         }
00147 #endif
00148 
00149         return (ret);
00150 }
00151 
00152 static int
00153 __xa_put_txn(dbenv, txnp)
00154         DB_ENV *dbenv;
00155         DB_TXN *txnp;
00156 {
00157 #ifdef XA_MULTI_THREAD
00158         DB_TXNMGR *mgr;
00159         mgr = (DB_TXNMGR *)dbenv->tx_handle;
00160 
00161         MUTEX_LOCK(dbenv, mgr->mutex);
00162         TAILQ_REMOVE(&dbenv->xa_txn, txnp, xalinks);
00163         MUTEX_UNLOCK(dbenv, mgr->mutex);
00164         __os_free(dbenv, txnp);
00165 #else
00166         COMPQUIET(dbenv, NULL);
00167         txnp->txnid = TXN_INVALID;
00168 #endif
00169         return (0);
00170 }
00171 
00172 #ifdef XA_MULTI_THREAD
00173 #define XA_FLAGS \
00174         (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | \
00175         DB_INIT_TXN | DB_THREAD)
00176 #else
00177 #define XA_FLAGS \
00178         (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | \
00179         DB_INIT_TXN)
00180 #endif
00181 
00182 /*
00183  * __db_xa_open --
00184  *      The open call in the XA protocol.  The rmid field is an id number
00185  * that the TM assigned us and will pass us on every xa call.  We need to
00186  * map that rmid number into a dbenv structure that we create during
00187  * initialization.  Since this id number is thread specific, we do not
00188  * need to store it in shared memory.  The file xa_map.c implements all
00189  * such xa->db mappings.
00190  *      The xa_info field is instance specific information.  We require
00191  * that the value of DB_HOME be passed in xa_info.  Since xa_info is the
00192  * only thing that we get to pass to db_env_create, any config information
00193  * will have to be done via a config file instead of via the db_env_create
00194  * call.
00195  */
00196 static int
00197 __db_xa_open(xa_info, rmid, arg_flags)
00198         char *xa_info;
00199         int rmid;
00200         long arg_flags;
00201 {
00202         DB_ENV *dbenv;
00203         u_long flags;
00204 
00205         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00206 
00207         if (LF_ISSET(TMASYNC))
00208                 return (XAER_ASYNC);
00209         if (flags != TMNOFLAGS)
00210                 return (XAER_INVAL);
00211 
00212         /* Verify if we already have this environment open. */
00213         if (__db_rmid_to_env(rmid, &dbenv) == 0)
00214                 return (XA_OK);
00215 
00216         /* Open a new environment. */
00217         if (db_env_create(&dbenv, 0) != 0)
00218                 return (XAER_RMERR);
00219         if (dbenv->open(dbenv, xa_info, XA_FLAGS, 0) != 0)
00220                 goto err;
00221 
00222         /* Create the mapping. */
00223         if (__db_map_rmid(rmid, dbenv) != 0)
00224                 goto err;
00225 
00226         /* Allocate space for the current transaction. */
00227         TAILQ_INIT(&dbenv->xa_txn);
00228 
00229         return (XA_OK);
00230 
00231 err:    (void)dbenv->close(dbenv, 0);
00232 
00233         return (XAER_RMERR);
00234 }
00235 
00236 /*
00237  * __db_xa_close --
00238  *      The close call of the XA protocol.  The only trickiness here
00239  * is that if there are any active transactions, we must fail.  It is
00240  * *not* an error to call close on an environment that has already been
00241  * closed (I am interpreting that to mean it's OK to call close on an
00242  * environment that has never been opened).
00243  */
00244 static int
00245 __db_xa_close(xa_info, rmid, arg_flags)
00246         char *xa_info;
00247         int rmid;
00248         long arg_flags;
00249 {
00250         DB_ENV *dbenv;
00251         DB_TXN *t;
00252         int ret, t_ret;
00253         u_long flags;
00254 
00255         COMPQUIET(xa_info, NULL);
00256 
00257         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00258 
00259         if (LF_ISSET(TMASYNC))
00260                 return (XAER_ASYNC);
00261         if (flags != TMNOFLAGS)
00262                 return (XAER_INVAL);
00263 
00264         /* If the environment is closed, then we're done. */
00265         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00266                 return (XA_OK);
00267 
00268         /* Check if there are any pending transactions. */
00269         if ((t = TAILQ_FIRST(&dbenv->xa_txn)) != NULL &&
00270             t->txnid != TXN_INVALID)
00271                 return (XAER_PROTO);
00272 
00273         /* Destroy the mapping. */
00274         ret = __db_unmap_rmid(rmid);
00275 
00276         /* Discard space held for the current transaction. */
00277         while ((t = TAILQ_FIRST(&dbenv->xa_txn)) != NULL) {
00278                 TAILQ_REMOVE(&dbenv->xa_txn, t, xalinks);
00279                 __os_free(dbenv, t);
00280         }
00281 
00282         /* Close the environment. */
00283         if ((t_ret = dbenv->close(dbenv, 0)) != 0 && ret == 0)
00284                 ret = t_ret;
00285 
00286         return (ret == 0 ? XA_OK : XAER_RMERR);
00287 }
00288 
00289 /*
00290  * __db_xa_start --
00291  *      Begin a transaction for the current resource manager.
00292  */
00293 static int
00294 __db_xa_start(xid, rmid, arg_flags)
00295         XID *xid;
00296         int rmid;
00297         long arg_flags;
00298 {
00299         DB_ENV *dbenv;
00300         DB_TXN *txnp;
00301         TXN_DETAIL *td;
00302         roff_t off;
00303         u_long flags;
00304         int is_known;
00305 
00306         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00307 
00308 #define OK_FLAGS        (TMJOIN | TMRESUME | TMNOWAIT | TMASYNC | TMNOFLAGS)
00309         if (LF_ISSET(~OK_FLAGS))
00310                 return (XAER_INVAL);
00311 
00312         if (LF_ISSET(TMJOIN) && LF_ISSET(TMRESUME))
00313                 return (XAER_INVAL);
00314 
00315         if (LF_ISSET(TMASYNC))
00316                 return (XAER_ASYNC);
00317 
00318         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00319                 return (XAER_PROTO);
00320 
00321         is_known = __db_xid_to_txn(dbenv, xid, &off) == 0;
00322 
00323         if (is_known && !LF_ISSET(TMRESUME) && !LF_ISSET(TMJOIN))
00324                 return (XAER_DUPID);
00325 
00326         if (!is_known && LF_ISSET(TMRESUME | TMJOIN))
00327                 return (XAER_NOTA);
00328 
00329         /*
00330          * This can't block, so we can ignore TMNOWAIT.
00331          *
00332          * Other error conditions: RMERR, RMFAIL, OUTSIDE, PROTO, RB*
00333          */
00334         if (is_known) {
00335                 td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
00336                 if (td->xa_status == TXN_XA_SUSPENDED &&
00337                     !LF_ISSET(TMRESUME | TMJOIN))
00338                         return (XAER_PROTO);
00339                 if (td->xa_status == TXN_XA_DEADLOCKED)
00340                         return (XA_RBDEADLOCK);
00341                 if (td->xa_status == TXN_XA_ABORTED)
00342                         return (XA_RBOTHER);
00343 
00344                 /* Now, fill in the global transaction structure. */
00345                 if (__xa_get_txn(dbenv, &txnp, 1) != 0)
00346                         return (XAER_RMERR);
00347                 __txn_continue(dbenv, txnp, td);
00348                 td->xa_status = TXN_XA_STARTED;
00349         } else {
00350                 if (__xa_get_txn(dbenv, &txnp, 1) != 0)
00351                         return (XAER_RMERR);
00352                 if (__txn_xa_begin(dbenv, txnp))
00353                         return (XAER_RMERR);
00354                 (void)__db_map_xid(dbenv, xid, txnp->td);
00355                 td = txnp->td;
00356                 td->xa_status = TXN_XA_STARTED;
00357         }
00358         return (XA_OK);
00359 }
00360 
00361 /*
00362  * __db_xa_end --
00363  *      Disassociate the current transaction from the current process.
00364  */
00365 static int
00366 __db_xa_end(xid, rmid, flags)
00367         XID *xid;
00368         int rmid;
00369         long flags;
00370 {
00371         DB_ENV *dbenv;
00372         DB_TXN *txn;
00373         TXN_DETAIL *td;
00374         roff_t off;
00375 
00376         if (flags != TMNOFLAGS && !LF_ISSET(TMSUSPEND | TMSUCCESS | TMFAIL))
00377                 return (XAER_INVAL);
00378 
00379         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00380                 return (XAER_PROTO);
00381 
00382         if (__db_xid_to_txn(dbenv, xid, &off) != 0)
00383                 return (XAER_NOTA);
00384 
00385         if (__xa_get_txn(dbenv, &txn, 0) != 0)
00386                 return (XAER_RMERR);
00387 
00388         td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
00389         if (td != txn->td)
00390                 return (XAER_PROTO);
00391 
00392         if (td->xa_status == TXN_XA_DEADLOCKED)
00393                 return (XA_RBDEADLOCK);
00394 
00395         if (td->status == TXN_ABORTED)
00396                 return (XA_RBOTHER);
00397 
00398         if (td->xa_status != TXN_XA_STARTED)
00399                 return (XAER_PROTO);
00400 
00401         /*
00402          * If we ever support XA migration, we cannot keep SUSPEND/END
00403          * status in the shared region; it would have to be process local.
00404          */
00405         if (LF_ISSET(TMSUSPEND))
00406                 td->xa_status = TXN_XA_SUSPENDED;
00407         else
00408                 td->xa_status = TXN_XA_ENDED;
00409 
00410         /*
00411          * XXX
00412          * This can fail in XA_MULTI_THREAD mode.
00413          */
00414         (void)__xa_put_txn(dbenv, txn);
00415         return (XA_OK);
00416 }
00417 
00418 /*
00419  * __db_xa_prepare --
00420  *      Sync the log to disk so we can guarantee recoverability.
00421  */
00422 static int
00423 __db_xa_prepare(xid, rmid, arg_flags)
00424         XID *xid;
00425         int rmid;
00426         long arg_flags;
00427 {
00428         DB_ENV *dbenv;
00429         DB_TXN *txnp;
00430         TXN_DETAIL *td;
00431         roff_t off;
00432         u_long flags;
00433 
00434         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00435 
00436         if (LF_ISSET(TMASYNC))
00437                 return (XAER_ASYNC);
00438         if (flags != TMNOFLAGS)
00439                 return (XAER_INVAL);
00440 
00441         /*
00442          * We need to know if we've ever called prepare on this.
00443          * As part of the prepare, we set the xa_status field to
00444          * reflect that fact that prepare has been called, and if
00445          * it's ever called again, it's an error.
00446          */
00447         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00448                 return (XAER_PROTO);
00449 
00450         if (__db_xid_to_txn(dbenv, xid, &off) != 0)
00451                 return (XAER_NOTA);
00452         td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
00453         if (td->xa_status == TXN_XA_DEADLOCKED)
00454                 return (XA_RBDEADLOCK);
00455 
00456         if (td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED)
00457                 return (XAER_PROTO);
00458 
00459         /* Now, fill in the global transaction structure. */
00460         if (__xa_get_txn(dbenv, &txnp, 0) != 0)
00461                 return (XAER_PROTO);
00462         __txn_continue(dbenv, txnp, td);
00463 
00464         if (txnp->prepare(txnp, (u_int8_t *)xid->data) != 0)
00465                 return (XAER_RMERR);
00466 
00467         td->xa_status = TXN_XA_PREPARED;
00468 
00469         /*
00470          * XXX
00471          * This can fail in XA_MULTI_THREAD mode.
00472          */
00473         (void)__xa_put_txn(dbenv, txnp);
00474         return (XA_OK);
00475 }
00476 
00477 /*
00478  * __db_xa_commit --
00479  *      Commit the transaction
00480  */
00481 static int
00482 __db_xa_commit(xid, rmid, arg_flags)
00483         XID *xid;
00484         int rmid;
00485         long arg_flags;
00486 {
00487         DB_ENV *dbenv;
00488         DB_TXN *txnp;
00489         TXN_DETAIL *td;
00490         roff_t off;
00491         u_long flags;
00492 
00493         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00494 
00495         if (LF_ISSET(TMASYNC))
00496                 return (XAER_ASYNC);
00497 #undef  OK_FLAGS
00498 #define OK_FLAGS        (TMNOFLAGS | TMNOWAIT | TMONEPHASE)
00499         if (LF_ISSET(~OK_FLAGS))
00500                 return (XAER_INVAL);
00501 
00502         /*
00503          * We need to know if we've ever called prepare on this.
00504          * We can verify this by examining the xa_status field.
00505          */
00506         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00507                 return (XAER_PROTO);
00508 
00509         if (__db_xid_to_txn(dbenv, xid, &off) != 0)
00510                 return (XAER_NOTA);
00511 
00512         td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
00513         if (td->xa_status == TXN_XA_DEADLOCKED)
00514                 return (XA_RBDEADLOCK);
00515 
00516         if (td->xa_status == TXN_XA_ABORTED)
00517                 return (XA_RBOTHER);
00518 
00519         if (LF_ISSET(TMONEPHASE) &&
00520             td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED)
00521                 return (XAER_PROTO);
00522 
00523         if (!LF_ISSET(TMONEPHASE) && td->xa_status != TXN_XA_PREPARED)
00524                 return (XAER_PROTO);
00525 
00526         /* Now, fill in the global transaction structure. */
00527         if (__xa_get_txn(dbenv, &txnp, 0) != 0)
00528                 return (XAER_RMERR);
00529         __txn_continue(dbenv, txnp, td);
00530 
00531         if (txnp->commit(txnp, 0) != 0)
00532                 return (XAER_RMERR);
00533 
00534         /*
00535          * XXX
00536          * This can fail in XA_MULTI_THREAD mode.
00537          */
00538         (void)__xa_put_txn(dbenv, txnp);
00539         return (XA_OK);
00540 }
00541 
00542 /*
00543  * __db_xa_recover --
00544  *      Returns a list of prepared and heuristically completed transactions.
00545  *
00546  * The return value is the number of xids placed into the xid array (less
00547  * than or equal to the count parameter).  The flags are going to indicate
00548  * whether we are starting a scan or continuing one.
00549  */
00550 static int
00551 __db_xa_recover(xids, count, rmid, flags)
00552         XID *xids;
00553         long count, flags;
00554         int rmid;
00555 {
00556         DB_ENV *dbenv;
00557         u_int32_t newflags;
00558         long rval;
00559 
00560         /* If the environment is closed, then we're done. */
00561         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00562                 return (XAER_PROTO);
00563 
00564         if (LF_ISSET(TMSTARTRSCAN))
00565                 newflags = DB_FIRST;
00566         else if (LF_ISSET(TMENDRSCAN))
00567                 newflags = DB_LAST;
00568         else
00569                 newflags = DB_NEXT;
00570 
00571         rval = 0;
00572         if (__txn_get_prepared(dbenv, xids, NULL, count, &rval, newflags) != 0)
00573                 return (XAER_RMERR);
00574         else
00575                 return (rval);
00576 }
00577 
00578 /*
00579  * __db_xa_rollback
00580  *      Abort an XA transaction.
00581  */
00582 static int
00583 __db_xa_rollback(xid, rmid, arg_flags)
00584         XID *xid;
00585         int rmid;
00586         long arg_flags;
00587 {
00588         DB_ENV *dbenv;
00589         DB_TXN *txnp;
00590         TXN_DETAIL *td;
00591         roff_t off;
00592         u_long flags;
00593 
00594         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00595 
00596         if (LF_ISSET(TMASYNC))
00597                 return (XAER_ASYNC);
00598         if (flags != TMNOFLAGS)
00599                 return (XAER_INVAL);
00600 
00601         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00602                 return (XAER_PROTO);
00603 
00604         if (__db_xid_to_txn(dbenv, xid, &off) != 0)
00605                 return (XAER_NOTA);
00606 
00607         td = R_ADDR(&((DB_TXNMGR *)dbenv->tx_handle)->reginfo, off);
00608         if (td->xa_status == TXN_XA_DEADLOCKED)
00609                 return (XA_RBDEADLOCK);
00610 
00611         if (td->xa_status == TXN_XA_ABORTED)
00612                 return (XA_RBOTHER);
00613 
00614         if (td->xa_status != TXN_XA_ENDED &&
00615             td->xa_status != TXN_XA_SUSPENDED &&
00616             td->xa_status != TXN_XA_PREPARED)
00617                 return (XAER_PROTO);
00618 
00619         /* Now, fill in the global transaction structure. */
00620         if (__xa_get_txn(dbenv, &txnp, 0) != 0)
00621                 return (XAER_RMERR);
00622         __txn_continue(dbenv, txnp, td);
00623         if (txnp->abort(txnp) != 0)
00624                 return (XAER_RMERR);
00625 
00626         /*
00627          * XXX
00628          * This can fail in XA_MULTI_THREAD mode.
00629          */
00630         (void)__xa_put_txn(dbenv, txnp);
00631         return (XA_OK);
00632 }
00633 
00634 /*
00635  * __db_xa_forget --
00636  *      Forget about an XID for a transaction that was heuristically
00637  * completed.  Since we do not heuristically complete anything, I
00638  * don't think we have to do anything here, but we should make sure
00639  * that we reclaim the slots in the txnid table.
00640  */
00641 static int
00642 __db_xa_forget(xid, rmid, arg_flags)
00643         XID *xid;
00644         int rmid;
00645         long arg_flags;
00646 {
00647         DB_ENV *dbenv;
00648         roff_t off;
00649         u_long flags;
00650 
00651         flags = (u_long)arg_flags;      /* Conversion for bit operations. */
00652 
00653         if (LF_ISSET(TMASYNC))
00654                 return (XAER_ASYNC);
00655         if (flags != TMNOFLAGS)
00656                 return (XAER_INVAL);
00657 
00658         if (__db_rmid_to_env(rmid, &dbenv) != 0)
00659                 return (XAER_PROTO);
00660 
00661         /*
00662          * If mapping is gone, then we're done.
00663          */
00664         if (__db_xid_to_txn(dbenv, xid, &off) != 0)
00665                 return (XA_OK);
00666 
00667         __db_unmap_xid(dbenv, xid, off);
00668 
00669         /* No fatal value that would require an XAER_RMFAIL. */
00670         return (XA_OK);
00671 }
00672 
00673 /*
00674  * __db_xa_complete --
00675  *      Used to wait for asynchronous operations to complete.  Since we're
00676  *      not doing asynch, this is an invalid operation.
00677  */
00678 static int
00679 __db_xa_complete(handle, retval, rmid, flags)
00680         int *handle, *retval, rmid;
00681         long flags;
00682 {
00683         COMPQUIET(handle, NULL);
00684         COMPQUIET(retval, NULL);
00685         COMPQUIET(rmid, 0);
00686         COMPQUIET(flags, 0);
00687 
00688         return (XAER_INVAL);
00689 }

Generated on Sun Dec 25 12:14:57 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2