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