diff options
Diffstat (limited to 'db/txn/txn_failchk.c')
-rw-r--r-- | db/txn/txn_failchk.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/db/txn/txn_failchk.c b/db/txn/txn_failchk.c new file mode 100644 index 000000000..4301fdab8 --- /dev/null +++ b/db/txn/txn_failchk.c @@ -0,0 +1,96 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005-2006 + * Oracle Corporation. All rights reserved. + * + * $Id: txn_failchk.c,v 12.6 2006/08/24 14:46:53 bostic Exp $ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/txn.h" + +/* + * __txn_failchk -- + * Check for transactions started by dead threads of control. + * + * PUBLIC: int __txn_failchk __P((DB_ENV *)); + */ +int +__txn_failchk(dbenv) + DB_ENV *dbenv; +{ + DB_TXN *ktxn, *txn; + DB_TXNMGR *mgr; + DB_TXNREGION *region; + TXN_DETAIL *ktd, *td; + db_threadid_t tid; + int ret; + char buf[DB_THREADID_STRLEN]; + pid_t pid; + + mgr = dbenv->tx_handle; + region = mgr->reginfo.primary; + +retry: TXN_SYSTEM_LOCK(dbenv); + + SH_TAILQ_FOREACH(td, ®ion->active_txn, links, __txn_detail) { + /* + * If this is a child transaction, skip it. + * The parent will take care of it. + */ + if (td->parent != INVALID_ROFF) + continue; + /* + * If the txn is prepared, then it does not matter + * what the state of the thread is. + */ + if (td->status == TXN_PREPARED) + continue; + + /* If the thread is still alive, it's not a problem. */ + if (dbenv->is_alive(dbenv, td->pid, td->tid, 0)) + continue; + + if (F_ISSET(td, TXN_DTL_INMEMORY)) + return (__db_failed(dbenv, + "Transaction has in memory logs", + td->pid, td->tid)); + + /* Abort the transaction. */ + TXN_SYSTEM_UNLOCK(dbenv); + if ((ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), &txn)) != 0) + return (ret); + __txn_continue(dbenv, txn, td); + F_SET(txn, TXN_MALLOC); + SH_TAILQ_FOREACH(ktd, &td->kids, klinks, __txn_detail) { + if (F_ISSET(ktd, TXN_DTL_INMEMORY)) + return (__db_failed(dbenv, + "Transaction has in memory logs", + td->pid, td->tid)); + if ((ret = + __os_calloc(dbenv, 1, sizeof(DB_TXN), &ktxn)) != 0) + return (ret); + __txn_continue(dbenv, ktxn, ktd); + F_SET(ktxn, TXN_MALLOC); + ktxn->parent = txn; + TAILQ_INSERT_HEAD(&txn->kids, txn, klinks); + } + TAILQ_INSERT_TAIL(&mgr->txn_chain, txn, links); + pid = td->pid; + tid = td->tid; + (void)dbenv->thread_id_string(dbenv, pid, tid, buf); + __db_msg(dbenv, + "Aborting txn %#lx: %s", (u_long)txn->txnid, buf); + if ((ret = __txn_abort(txn)) != 0) + return (__db_failed(dbenv, + "Transaction abort failed", pid, tid)); + goto retry; + } + + TXN_SYSTEM_UNLOCK(dbenv); + + return (0); +} |