1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2005-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/txn.h" 13 14/* 15 * __txn_failchk -- 16 * Check for transactions started by dead threads of control. 17 * 18 * PUBLIC: int __txn_failchk __P((ENV *)); 19 */ 20int 21__txn_failchk(env) 22 ENV *env; 23{ 24 DB_ENV *dbenv; 25 DB_TXN *ktxn, *txn; 26 DB_TXNMGR *mgr; 27 DB_TXNREGION *region; 28 TXN_DETAIL *ktd, *td; 29 db_threadid_t tid; 30 int ret; 31 char buf[DB_THREADID_STRLEN]; 32 pid_t pid; 33 34 mgr = env->tx_handle; 35 dbenv = env->dbenv; 36 region = mgr->reginfo.primary; 37 38retry: TXN_SYSTEM_LOCK(env); 39 40 SH_TAILQ_FOREACH(td, ®ion->active_txn, links, __txn_detail) { 41 /* 42 * If this is a child transaction, skip it. 43 * The parent will take care of it. 44 */ 45 if (td->parent != INVALID_ROFF) 46 continue; 47 /* 48 * If the txn is prepared, then it does not matter 49 * what the state of the thread is. 50 */ 51 if (td->status == TXN_PREPARED) 52 continue; 53 54 /* If the thread is still alive, it's not a problem. */ 55 if (dbenv->is_alive(dbenv, td->pid, td->tid, 0)) 56 continue; 57 58 if (F_ISSET(td, TXN_DTL_INMEMORY)) { 59 TXN_SYSTEM_UNLOCK(env); 60 return (__db_failed(env, 61 "Transaction has in memory logs", 62 td->pid, td->tid)); 63 } 64 65 /* Abort the transaction. */ 66 TXN_SYSTEM_UNLOCK(env); 67 if ((ret = __os_calloc(env, 1, sizeof(DB_TXN), &txn)) != 0) 68 return (ret); 69 if ((ret = __txn_continue(env, txn, td)) != 0) 70 return (ret); 71 F_SET(txn, TXN_MALLOC); 72 SH_TAILQ_FOREACH(ktd, &td->kids, klinks, __txn_detail) { 73 if (F_ISSET(ktd, TXN_DTL_INMEMORY)) 74 return (__db_failed(env, 75 "Transaction has in memory logs", 76 td->pid, td->tid)); 77 if ((ret = 78 __os_calloc(env, 1, sizeof(DB_TXN), &ktxn)) != 0) 79 return (ret); 80 if ((ret = __txn_continue(env, ktxn, ktd)) != 0) 81 return (ret); 82 F_SET(ktxn, TXN_MALLOC); 83 ktxn->parent = txn; 84 TAILQ_INSERT_HEAD(&txn->kids, txn, klinks); 85 } 86 TAILQ_INSERT_TAIL(&mgr->txn_chain, txn, links); 87 pid = td->pid; 88 tid = td->tid; 89 (void)dbenv->thread_id_string(dbenv, pid, tid, buf); 90 __db_msg(env, 91 "Aborting txn %#lx: %s", (u_long)txn->txnid, buf); 92 if ((ret = __txn_abort(txn)) != 0) 93 return (__db_failed(env, 94 "Transaction abort failed", pid, tid)); 95 goto retry; 96 } 97 98 TXN_SYSTEM_UNLOCK(env); 99 100 return (0); 101} 102