1#ifndef SESSION_TRACKER_INCLUDED
2#define SESSION_TRACKER_INCLUDED
3
4/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
5 Copyright (c) 2016, 2017, MariaDB Corporation.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
19
20#include "m_string.h"
21#include "thr_lock.h"
22
23#ifndef EMBEDDED_LIBRARY
24/* forward declarations */
25class THD;
26class set_var;
27class String;
28
29
30enum enum_session_tracker
31{
32 SESSION_SYSVARS_TRACKER, /* Session system variables */
33 CURRENT_SCHEMA_TRACKER, /* Current schema */
34 SESSION_STATE_CHANGE_TRACKER,
35 SESSION_GTIDS_TRACKER, /* Tracks GTIDs */
36 TRANSACTION_INFO_TRACKER, /* Transaction state */
37 SESSION_TRACKER_END /* must be the last */
38};
39
40/**
41 State_tracker
42
43 An abstract class that defines the interface for any of the server's
44 'session state change tracker'. A tracker, however, is a sub- class of
45 this class which takes care of tracking the change in value of a part-
46 icular session state type and thus defines various methods listed in this
47 interface. The change information is later serialized and transmitted to
48 the client through protocol's OK packet.
49
50 Tracker system variables :-
51 A tracker is normally mapped to a system variable. So in order to enable,
52 disable or modify the sub-entities of a tracker, the user needs to modify
53 the respective system variable either through SET command or via command
54 line option. As required in system variable handling, this interface also
55 includes two functions to help in the verification of the supplied value
56 (ON_UPDATE) of the tracker system variable, namely - update().
57*/
58
59class State_tracker
60{
61protected:
62 /**
63 Is tracking enabled for a particular session state type ?
64
65 @note: it is a cache of the corresponding thd->variables.session_track_xxx
66 variable
67 */
68 bool m_enabled;
69
70 /** Has the session state type changed ? */
71 bool m_changed;
72
73public:
74 /** Constructor */
75 State_tracker() : m_enabled(false), m_changed(false)
76 {}
77
78 /** Destructor */
79 virtual ~State_tracker()
80 {}
81
82 /** Getters */
83 bool is_enabled() const
84 { return m_enabled; }
85
86 bool is_changed() const
87 { return m_changed; }
88
89 /** Called in the constructor of THD*/
90 virtual bool enable(THD *thd)= 0;
91
92 /** To be invoked when the tracker's system variable is updated (ON_UPDATE).*/
93 virtual bool update(THD *thd, set_var *var)= 0;
94
95 /** Store changed data into the given buffer. */
96 virtual bool store(THD *thd, String *buf)= 0;
97
98 /** Mark the entity as changed. */
99 virtual void mark_as_changed(THD *thd, LEX_CSTRING *name);
100};
101
102bool sysvartrack_validate_value(THD *thd, const char *str, size_t len);
103bool sysvartrack_reprint_value(THD *thd, char *str, size_t len);
104bool sysvartrack_update(THD *thd, set_var *var);
105size_t sysvartrack_value_len(THD *thd);
106bool sysvartrack_value_construct(THD *thd, char *val, size_t len);
107
108
109/**
110 Session_tracker
111
112 This class holds an object each for all tracker classes and provides
113 methods necessary for systematic detection and generation of session
114 state change information.
115*/
116
117class Session_tracker
118{
119private:
120 State_tracker *m_trackers[SESSION_TRACKER_END];
121
122 /* The following two functions are private to disable copying. */
123 Session_tracker(Session_tracker const &other)
124 {
125 DBUG_ASSERT(FALSE);
126 }
127 Session_tracker& operator= (Session_tracker const &rhs)
128 {
129 DBUG_ASSERT(FALSE);
130 return *this;
131 }
132
133public:
134
135 Session_tracker();
136 ~Session_tracker()
137 {
138 deinit();
139 }
140
141 /* trick to make happy memory accounting system */
142 void deinit()
143 {
144 for (int i= 0; i < SESSION_TRACKER_END; i++)
145 {
146 if (m_trackers[i])
147 delete m_trackers[i];
148 m_trackers[i]= NULL;
149 }
150 }
151
152 void enable(THD *thd);
153 static bool server_boot_verify(CHARSET_INFO *char_set);
154
155 /** Returns the pointer to the tracker object for the specified tracker. */
156 inline State_tracker *get_tracker(enum_session_tracker tracker) const
157 {
158 return m_trackers[tracker];
159 }
160
161 inline void mark_as_changed(THD *thd, enum enum_session_tracker tracker,
162 LEX_CSTRING *data)
163 {
164 if (m_trackers[tracker]->is_enabled())
165 m_trackers[tracker]->mark_as_changed(thd, data);
166 }
167
168
169 void store(THD *thd, String *main_buf);
170};
171
172
173/*
174 Transaction_state_tracker
175*/
176
177/**
178 Transaction state (no transaction, transaction active, work attached, etc.)
179*/
180enum enum_tx_state {
181 TX_EMPTY = 0, ///< "none of the below"
182 TX_EXPLICIT = 1, ///< an explicit transaction is active
183 TX_IMPLICIT = 2, ///< an implicit transaction is active
184 TX_READ_TRX = 4, ///< transactional reads were done
185 TX_READ_UNSAFE = 8, ///< non-transaction reads were done
186 TX_WRITE_TRX = 16, ///< transactional writes were done
187 TX_WRITE_UNSAFE = 32, ///< non-transactional writes were done
188 TX_STMT_UNSAFE = 64, ///< "unsafe" (non-deterministic like UUID()) stmts
189 TX_RESULT_SET = 128, ///< result set was sent
190 TX_WITH_SNAPSHOT= 256, ///< WITH CONSISTENT SNAPSHOT was used
191 TX_LOCKED_TABLES= 512 ///< LOCK TABLES is active
192};
193
194
195/**
196 Transaction access mode
197*/
198enum enum_tx_read_flags {
199 TX_READ_INHERIT = 0, ///< not explicitly set, inherit session.tx_read_only
200 TX_READ_ONLY = 1, ///< START TRANSACTION READ ONLY, or tx_read_only=1
201 TX_READ_WRITE = 2, ///< START TRANSACTION READ WRITE, or tx_read_only=0
202};
203
204
205/**
206 Transaction isolation level
207*/
208enum enum_tx_isol_level {
209 TX_ISOL_INHERIT = 0, ///< not explicitly set, inherit session.tx_isolation
210 TX_ISOL_UNCOMMITTED = 1,
211 TX_ISOL_COMMITTED = 2,
212 TX_ISOL_REPEATABLE = 3,
213 TX_ISOL_SERIALIZABLE= 4
214};
215
216
217/**
218 Transaction tracking level
219*/
220enum enum_session_track_transaction_info {
221 TX_TRACK_NONE = 0, ///< do not send tracker items on transaction info
222 TX_TRACK_STATE = 1, ///< track transaction status
223 TX_TRACK_CHISTICS = 2 ///< track status and characteristics
224};
225
226
227/**
228 This is a tracker class that enables & manages the tracking of
229 current transaction info for a particular connection.
230*/
231
232class Transaction_state_tracker : public State_tracker
233{
234private:
235 /** Helper function: turn table info into table access flag */
236 enum_tx_state calc_trx_state(THD *thd, thr_lock_type l, bool has_trx);
237public:
238 /** Constructor */
239 Transaction_state_tracker();
240 bool enable(THD *thd)
241 { return update(thd, NULL); }
242 bool update(THD *thd, set_var *var);
243 bool store(THD *thd, String *buf);
244
245 /** Change transaction characteristics */
246 void set_read_flags(THD *thd, enum enum_tx_read_flags flags);
247 void set_isol_level(THD *thd, enum enum_tx_isol_level level);
248
249 /** Change transaction state */
250 void clear_trx_state(THD *thd, uint clear);
251 void add_trx_state(THD *thd, uint add);
252 void inline add_trx_state(THD *thd, thr_lock_type l, bool has_trx)
253 {
254 add_trx_state(thd, calc_trx_state(thd, l, has_trx));
255 }
256 void add_trx_state_from_thd(THD *thd);
257 void end_trx(THD *thd);
258
259
260private:
261 enum enum_tx_changed {
262 TX_CHG_NONE = 0, ///< no changes from previous stmt
263 TX_CHG_STATE = 1, ///< state has changed from previous stmt
264 TX_CHG_CHISTICS = 2 ///< characteristics have changed from previous stmt
265 };
266
267 /** any trackable changes caused by this statement? */
268 uint tx_changed;
269
270 /** transaction state */
271 uint tx_curr_state, tx_reported_state;
272
273 /** r/w or r/o set? session default? */
274 enum enum_tx_read_flags tx_read_flags;
275
276 /** isolation level */
277 enum enum_tx_isol_level tx_isol_level;
278
279 void reset();
280
281 inline void update_change_flags(THD *thd)
282 {
283 tx_changed &= uint(~TX_CHG_STATE);
284 tx_changed |= (tx_curr_state != tx_reported_state) ? TX_CHG_STATE : 0;
285 if (tx_changed != TX_CHG_NONE)
286 mark_as_changed(thd, NULL);
287 }
288};
289
290#define TRANSACT_TRACKER(X) \
291 do { if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) \
292 {((Transaction_state_tracker *) \
293 thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER)) \
294 ->X; } } while(0)
295#define SESSION_TRACKER_CHANGED(A,B,C) \
296 thd->session_tracker.mark_as_changed(A,B,C)
297#else
298
299#define TRANSACT_TRACKER(X) do{}while(0)
300#define SESSION_TRACKER_CHANGED(A,B,C) do{}while(0)
301
302#endif //EMBEDDED_LIBRARY
303
304#endif /* SESSION_TRACKER_INCLUDED */
305