1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#include "ft/logger/log-internal.h"
40#include "ft/txn/txn_child_manager.h"
41
42toku_instr_key *txn_child_manager_mutex_key;
43
44//
45// initialized a txn_child_manager,
46// when called, root->txnid.parent_id64 may not yet be set
47//
48void txn_child_manager::init(TOKUTXN root) {
49 invariant(root->txnid.child_id64 == TXNID_NONE);
50 invariant(root->parent == NULL);
51 m_root = root;
52 m_last_xid = TXNID_NONE;
53 ZERO_STRUCT(m_mutex);
54
55 toku_pthread_mutexattr_t attr;
56 toku_mutexattr_init(&attr);
57 toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE);
58 toku_mutex_init(*txn_child_manager_mutex_key, &m_mutex, &attr);
59 toku_mutexattr_destroy(&attr);
60}
61
62void txn_child_manager::destroy() {
63 toku_mutex_destroy(&m_mutex);
64}
65
66void txn_child_manager::start_child_txn_for_recovery(TOKUTXN child, TOKUTXN parent, TXNID_PAIR txnid) {
67 invariant(parent->txnid.parent_id64 == m_root->txnid.parent_id64);
68 invariant(txnid.parent_id64 == m_root->txnid.parent_id64);
69
70 child->txnid = txnid;
71 toku_mutex_lock(&m_mutex);
72 if (txnid.child_id64 > m_last_xid) {
73 m_last_xid = txnid.child_id64;
74 }
75 parent->child = child;
76 toku_mutex_unlock(&m_mutex);
77}
78
79void txn_child_manager::start_child_txn(TOKUTXN child, TOKUTXN parent) {
80 invariant(parent->txnid.parent_id64 == m_root->txnid.parent_id64);
81 child->txnid.parent_id64 = m_root->txnid.parent_id64;
82 toku_mutex_lock(&m_mutex);
83
84 ++m_last_xid;
85 // Here we ensure that the child_id64 is never equal to the parent_id64
86 // We do this to make this feature work more easily with the XIDs
87 // struct and message application. The XIDs struct stores the parent id
88 // as the first TXNID, and subsequent TXNIDs store child ids. So, if we
89 // have a case where the parent id is the same as the child id, we will
90 // have to do some tricky maneuvering in the message application code
91 // in ule.cc. So, to lessen the probability of bugs, we ensure that the
92 // parent id is not the same as the child id.
93 if (m_last_xid == m_root->txnid.parent_id64) {
94 ++m_last_xid;
95 }
96 child->txnid.child_id64 = m_last_xid;
97
98 parent->child = child;
99 toku_mutex_unlock(&m_mutex);
100}
101
102void txn_child_manager::finish_child_txn(TOKUTXN child) {
103 invariant(child->txnid.parent_id64 == m_root->txnid.parent_id64);
104 toku_mutex_lock(&m_mutex);
105 child->parent->child = NULL;
106 toku_mutex_unlock(&m_mutex);
107}
108
109void txn_child_manager::suspend() {
110 toku_mutex_lock(&m_mutex);
111}
112
113void txn_child_manager::resume() {
114 toku_mutex_unlock(&m_mutex);
115}
116
117void txn_child_manager::find_tokutxn_by_xid_unlocked(TXNID_PAIR xid, TOKUTXN* result) {
118 invariant(xid.parent_id64 == m_root->txnid.parent_id64);
119 TOKUTXN curr_txn = m_root;
120 while (curr_txn != NULL) {
121 if (xid.child_id64 == curr_txn->txnid.child_id64) {
122 *result = curr_txn;
123 break;
124 }
125 curr_txn = curr_txn->child;
126 }
127}
128
129int txn_child_manager::iterate(txn_mgr_iter_callback cb, void* extra) {
130 TOKUTXN curr_txn = m_root;
131 int ret = 0;
132 toku_mutex_lock(&m_mutex);
133 while (curr_txn != NULL) {
134 ret = cb(curr_txn, extra);
135 if (ret != 0) {
136 break;
137 }
138 curr_txn = curr_txn->child;
139 }
140 toku_mutex_unlock(&m_mutex);
141 return ret;
142}
143
144