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