1/*****************************************************************************
2
3Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2016, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file include/trx0trx.ic
22The transaction
23
24Created 3/26/1996 Heikki Tuuri
25*******************************************************/
26
27/**********************************************************************//**
28Determines if a transaction is in the given state.
29The caller must hold trx_sys.mutex, or it must be the thread
30that is serving a running transaction.
31A running RW transaction must be in trx_sys.rw_trx_hash.
32@return TRUE if trx->state == state */
33UNIV_INLINE
34bool
35trx_state_eq(
36/*=========*/
37 const trx_t* trx, /*!< in: transaction */
38 trx_state_t state, /*!< in: state;
39 if state != TRX_STATE_NOT_STARTED
40 asserts that
41 trx->state != TRX_STATE_NOT_STARTED */
42 bool relaxed)
43 /*!< in: whether to allow
44 trx->state == TRX_STATE_NOT_STARTED
45 after an error has been reported */
46{
47#ifdef UNIV_DEBUG
48 switch (trx->state) {
49 case TRX_STATE_PREPARED:
50
51 ut_ad(!trx_is_autocommit_non_locking(trx));
52 return(trx->state == state);
53
54 case TRX_STATE_ACTIVE:
55
56 assert_trx_nonlocking_or_in_list(trx);
57 return(state == trx->state);
58
59 case TRX_STATE_COMMITTED_IN_MEMORY:
60
61 check_trx_state(trx);
62 return(state == trx->state);
63
64 case TRX_STATE_NOT_STARTED:
65 /* These states are not allowed for running transactions. */
66 ut_a(state == TRX_STATE_NOT_STARTED
67 || (relaxed
68 && thd_get_error_number(trx->mysql_thd)));
69
70 return(true);
71 }
72 ut_error;
73#endif /* UNIV_DEBUG */
74 return(trx->state == state);
75}
76
77/****************************************************************//**
78Retrieves the error_info field from a trx.
79@return the error info */
80UNIV_INLINE
81const dict_index_t*
82trx_get_error_info(
83/*===============*/
84 const trx_t* trx) /*!< in: trx object */
85{
86 return(trx->error_info);
87}
88
89/*******************************************************************//**
90Retrieves transaction's que state in a human readable string. The string
91should not be free()'d or modified.
92@return string in the data segment */
93UNIV_INLINE
94const char*
95trx_get_que_state_str(
96/*==================*/
97 const trx_t* trx) /*!< in: transaction */
98{
99 /* be sure to adjust TRX_QUE_STATE_STR_MAX_LEN if you change this */
100 switch (trx->lock.que_state) {
101 case TRX_QUE_RUNNING:
102 return("RUNNING");
103 case TRX_QUE_LOCK_WAIT:
104 return("LOCK WAIT");
105 case TRX_QUE_ROLLING_BACK:
106 return("ROLLING BACK");
107 case TRX_QUE_COMMITTING:
108 return("COMMITTING");
109 default:
110 return("UNKNOWN");
111 }
112}
113
114/** Retreieves the transaction ID.
115In a given point in time it is guaranteed that IDs of the running
116transactions are unique. The values returned by this function for readonly
117transactions may be reused, so a subsequent RO transaction may get the same ID
118as a RO transaction that existed in the past. The values returned by this
119function should be used for printing purposes only.
120@param[in] trx transaction whose id to retrieve
121@return transaction id */
122UNIV_INLINE
123trx_id_t
124trx_get_id_for_print(
125 const trx_t* trx)
126{
127 /* Readonly and transactions whose intentions are unknown (whether
128 they will eventually do a WRITE) don't have trx_t::id assigned (it is
129 0 for those transactions). Transaction IDs in
130 innodb_trx.trx_id,
131 innodb_locks.lock_id,
132 innodb_locks.lock_trx_id,
133 innodb_lock_waits.requesting_trx_id,
134 innodb_lock_waits.blocking_trx_id should match because those tables
135 could be used in an SQL JOIN on those columns. Also trx_t::id is
136 printed by SHOW ENGINE INNODB STATUS, and in logs, so we must have the
137 same value printed everywhere consistently. */
138
139 /* DATA_TRX_ID_LEN is the storage size in bytes. */
140 static const trx_id_t max_trx_id
141 = (1ULL << (DATA_TRX_ID_LEN * CHAR_BIT)) - 1;
142
143 ut_ad(trx->id <= max_trx_id);
144
145 return(trx->id != 0
146 ? trx->id
147 : reinterpret_cast<trx_id_t>(trx) | (max_trx_id + 1));
148}
149
150/**********************************************************************//**
151Determine if a transaction is a dictionary operation.
152@return dictionary operation mode */
153UNIV_INLINE
154enum trx_dict_op_t
155trx_get_dict_operation(
156/*===================*/
157 const trx_t* trx) /*!< in: transaction */
158{
159 trx_dict_op_t op = static_cast<trx_dict_op_t>(trx->dict_operation);
160
161#ifdef UNIV_DEBUG
162 switch (op) {
163 case TRX_DICT_OP_NONE:
164 case TRX_DICT_OP_TABLE:
165 case TRX_DICT_OP_INDEX:
166 return(op);
167 }
168 ut_error;
169#endif /* UNIV_DEBUG */
170 return(op);
171}
172/**********************************************************************//**
173Flag a transaction a dictionary operation. */
174UNIV_INLINE
175void
176trx_set_dict_operation(
177/*===================*/
178 trx_t* trx, /*!< in/out: transaction */
179 enum trx_dict_op_t op) /*!< in: operation, not
180 TRX_DICT_OP_NONE */
181{
182#ifdef UNIV_DEBUG
183 enum trx_dict_op_t old_op = trx_get_dict_operation(trx);
184
185 switch (op) {
186 case TRX_DICT_OP_NONE:
187 ut_error;
188 break;
189 case TRX_DICT_OP_TABLE:
190 switch (old_op) {
191 case TRX_DICT_OP_NONE:
192 case TRX_DICT_OP_INDEX:
193 case TRX_DICT_OP_TABLE:
194 goto ok;
195 }
196 ut_error;
197 break;
198 case TRX_DICT_OP_INDEX:
199 ut_ad(old_op == TRX_DICT_OP_NONE);
200 break;
201 }
202ok:
203#endif /* UNIV_DEBUG */
204
205 trx->ddl = true;
206 trx->dict_operation = op;
207}
208