1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program 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, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 02110-1301 USA */ 23 24 #ifndef RPL_SESSION_H 25 #define RPL_SESSION_H 26 27 #include "my_global.h" 28 29 class Gtid_set; 30 class Sid_map; 31 class THD; 32 33 /** Type of replication channel thread/transaction might be associated to*/ 34 enum enum_rpl_channel_type { 35 NO_CHANNEL_INFO = 0, // No information exists about the channel 36 RPL_STANDARD_CHANNEL = 1, // It is a standard replication channel 37 GR_APPLIER_CHANNEL = 2, // It is a GR applier channel 38 GR_RECOVERY_CHANNEL = 3 // It is a GR recovery channel 39 }; 40 41 /** 42 This class is an interface for session consistency instrumentation 43 in the server. It holds the context information for a given session. 44 45 It does not require locking since access to this content is mutually 46 exclusive by design (only one thread reading or writing to this object 47 at a time). 48 */ 49 class Session_consistency_gtids_ctx 50 { 51 public: 52 /** 53 This is an interface to be implemented by classes that want to listen 54 to changes to this context. This can be used, for instance, by the 55 session tracker gtids to become aware of ctx modifications. 56 */ 57 class Ctx_change_listener 58 { 59 public: Ctx_change_listener()60 Ctx_change_listener() {} 61 virtual void notify_session_gtids_ctx_change()= 0; 62 private: 63 // not implemented 64 Ctx_change_listener(const Ctx_change_listener& rsc); 65 Ctx_change_listener& operator=(const Ctx_change_listener& rsc); 66 }; 67 68 private: 69 70 /* 71 Local sid_map to enable a lock free m_gtid_set. 72 */ 73 Sid_map* m_sid_map; 74 75 /** 76 Set holding the transaction identifiers of the gtids 77 to reply back on the response packet. 78 79 Lifecycle: Emptied after the reply is sent back to the application. Remains 80 empty until: 81 - a RW transaction commits and a GTID is written to the binary log. 82 - a RO transaction is issued, the consistency level is set to "Check 83 Potential Writes" and the transaction is committed. 84 */ 85 Gtid_set* m_gtid_set; 86 87 /** 88 If a listener is registered, e.g., the session track gtids, then this 89 points to an instance of such listener. 90 91 Since this context is valid only for one session, there is no need 92 to protect this with locks. 93 */ 94 Session_consistency_gtids_ctx::Ctx_change_listener* m_listener; 95 96 /** 97 Keeps track of the current session track gtids, so that we capture 98 according to what was set before. For instance, if the user does: 99 SET @@SESSION.SESSION_TRACK_GTIDS='ALL_GTIDS'; 100 ... 101 SET @@SESSION.SESSION_TRACK_GTIDS='OWN_GTID'; 102 103 The last statement should return a set of GTIDs. 104 */ 105 ulong m_curr_session_track_gtids; 106 107 protected: 108 109 /* 110 Auxiliary function to determine if GTID collection should take place 111 when it is invoked. It takes into consideration the gtid_mode and 112 the current session context. 113 114 @param thd the thread context. 115 @return true if should collect gtids, false otherwise. 116 */ 117 inline bool shall_collect(const THD* thd); 118 119 /** 120 Auxiliary function that allows notification of ctx change listeners. 121 */ notify_ctx_change_listener()122 inline void notify_ctx_change_listener() 123 { 124 m_listener->notify_session_gtids_ctx_change(); 125 } 126 127 public: 128 129 /** 130 Simple constructor. 131 */ 132 Session_consistency_gtids_ctx(); 133 134 /** 135 The destructor. Deletes the m_gtid_set and the sid_map. 136 */ 137 virtual ~Session_consistency_gtids_ctx(); 138 139 /** 140 Registers the listener. The pointer MUST not be NULL. 141 142 @param listener a pointer to the listener to register. 143 @param thd THD context associated to this listener. 144 */ 145 void register_ctx_change_listener( 146 Session_consistency_gtids_ctx::Ctx_change_listener* listener, 147 THD* thd); 148 149 /** 150 Unregisters the listener. The listener MUST have registered previously. 151 152 @param listener a pointer to the listener to register. 153 */ 154 void unregister_ctx_change_listener( 155 Session_consistency_gtids_ctx::Ctx_change_listener* listener); 156 157 /** 158 This member function MUST return a reference to the set of collected 159 GTIDs so far. 160 161 @return the set of collected GTIDs so far. 162 */ state()163 inline Gtid_set* state() { return m_gtid_set; } 164 165 /** 166 This function MUST be called after the response packet is set to the 167 client connected. The implementation may act on the collected state 168 for instance to do garbage collection. 169 170 @param thd The thread context. 171 * @return true on error, false otherwise. 172 */ 173 virtual bool notify_after_response_packet(const THD* thd); 174 175 /** 176 This function SHALL be called once the GTID for the given transaction has 177 has been added to GTID_EXECUTED. 178 179 This function SHALL store the data if the thd->variables.session_track_gtids 180 is set to a value other than NONE. 181 182 @param thd The thread context. 183 @return true on error, false otherwise. 184 */ 185 virtual bool notify_after_gtid_executed_update(const THD *thd); 186 187 /** 188 This function MUST be called after a transaction is committed 189 in the server. It should be called regardless whether it is a 190 RO or RW transaction. Also, DDLs, DDS are considered transaction 191 for what is worth. 192 193 This function SHALL store relevant data for the session consistency. 194 195 @param thd The thread context. 196 @return true on error, false otherwise. 197 */ 198 virtual bool notify_after_transaction_commit(const THD* thd); 199 notify_after_xa_prepare(const THD * thd)200 virtual bool notify_after_xa_prepare(const THD* thd) 201 { 202 return notify_after_transaction_commit(thd); 203 } 204 205 /** 206 Update session tracker (m_curr_session_track_gtids) from thd. 207 */ 208 void update_tracking_activeness_from_session_variable(const THD* thd); 209 210 private: 211 // not implemented 212 Session_consistency_gtids_ctx(const Session_consistency_gtids_ctx& rsc); 213 Session_consistency_gtids_ctx& operator=(const Session_consistency_gtids_ctx& rsc); 214 }; 215 216 /* 217 This object encapsulates the state kept between transactions of the same client in 218 order to compute logical timestamps based on WRITESET_SESSION. 219 */ 220 class Dependency_tracker_ctx 221 { 222 public: Dependency_tracker_ctx()223 Dependency_tracker_ctx(): m_last_session_sequence_number(0) { } 224 set_last_session_sequence_number(int64 sequence_number)225 void set_last_session_sequence_number(int64 sequence_number) 226 { 227 m_last_session_sequence_number= sequence_number; 228 } 229 get_last_session_sequence_number()230 int64 get_last_session_sequence_number() 231 { 232 return m_last_session_sequence_number; 233 } 234 235 private: 236 int64 m_last_session_sequence_number; 237 }; 238 239 /* 240 This class SHALL encapsulate the replication context associated with the THD 241 object. 242 */ 243 class Rpl_thd_context 244 { 245 private: 246 Session_consistency_gtids_ctx m_session_gtids_ctx; 247 Dependency_tracker_ctx m_dependency_tracker_ctx; 248 /** If this thread is a channel, what is its type*/ 249 enum_rpl_channel_type rpl_channel_type; 250 251 Rpl_thd_context(const Rpl_thd_context& rsc); 252 Rpl_thd_context& operator=(const Rpl_thd_context& rsc); 253 public: 254 Rpl_thd_context()255 Rpl_thd_context() : rpl_channel_type(NO_CHANNEL_INFO) {} 256 session_gtids_ctx()257 inline Session_consistency_gtids_ctx& session_gtids_ctx() 258 { 259 return m_session_gtids_ctx; 260 } 261 dependency_tracker_ctx()262 inline Dependency_tracker_ctx& dependency_tracker_ctx() 263 { 264 return m_dependency_tracker_ctx; 265 } 266 get_rpl_channel_type()267 enum_rpl_channel_type get_rpl_channel_type() { return rpl_channel_type; } 268 set_rpl_channel_type(enum_rpl_channel_type rpl_channel_type_arg)269 void set_rpl_channel_type(enum_rpl_channel_type rpl_channel_type_arg) { 270 rpl_channel_type = rpl_channel_type_arg; 271 } 272 }; 273 274 #endif /* RPL_SESSION_H */ 275