1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2016, 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/trx0trx.ic |
22 | The transaction |
23 | |
24 | Created 3/26/1996 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | /**********************************************************************//** |
28 | Determines if a transaction is in the given state. |
29 | The caller must hold trx_sys.mutex, or it must be the thread |
30 | that is serving a running transaction. |
31 | A running RW transaction must be in trx_sys.rw_trx_hash. |
32 | @return TRUE if trx->state == state */ |
33 | UNIV_INLINE |
34 | bool |
35 | trx_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 | /****************************************************************//** |
78 | Retrieves the error_info field from a trx. |
79 | @return the error info */ |
80 | UNIV_INLINE |
81 | const dict_index_t* |
82 | trx_get_error_info( |
83 | /*===============*/ |
84 | const trx_t* trx) /*!< in: trx object */ |
85 | { |
86 | return(trx->error_info); |
87 | } |
88 | |
89 | /*******************************************************************//** |
90 | Retrieves transaction's que state in a human readable string. The string |
91 | should not be free()'d or modified. |
92 | @return string in the data segment */ |
93 | UNIV_INLINE |
94 | const char* |
95 | trx_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. |
115 | In a given point in time it is guaranteed that IDs of the running |
116 | transactions are unique. The values returned by this function for readonly |
117 | transactions may be reused, so a subsequent RO transaction may get the same ID |
118 | as a RO transaction that existed in the past. The values returned by this |
119 | function should be used for printing purposes only. |
120 | @param[in] trx transaction whose id to retrieve |
121 | @return transaction id */ |
122 | UNIV_INLINE |
123 | trx_id_t |
124 | trx_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 | /**********************************************************************//** |
151 | Determine if a transaction is a dictionary operation. |
152 | @return dictionary operation mode */ |
153 | UNIV_INLINE |
154 | enum trx_dict_op_t |
155 | trx_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 | /**********************************************************************//** |
173 | Flag a transaction a dictionary operation. */ |
174 | UNIV_INLINE |
175 | void |
176 | trx_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 | } |
202 | ok: |
203 | #endif /* UNIV_DEBUG */ |
204 | |
205 | trx->ddl = true; |
206 | trx->dict_operation = op; |
207 | } |
208 | |