add packaging
[platform/upstream/db4.git] / txn / txn_failchk.c
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  */
20 int
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
38 retry:  TXN_SYSTEM_LOCK(env);
39
40         SH_TAILQ_FOREACH(td, &region->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 }