MySQL 8.3.0
Source Code Documentation
rpl_injector.h
Go to the documentation of this file.
1/* Copyright (c) 2006, 2023, 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 02110-1301 USA */
22
23#ifndef INJECTOR_H
24#define INJECTOR_H
25
26#include <stddef.h>
27
28#include "lex_string.h"
29#include "my_dbug.h"
30#include "my_inttypes.h"
31#include "mysql/binlog/event/control_events.h" // enum_incidents
32#include "sql/table.h" // TABLE
33
34class MYSQL_BIN_LOG;
35class THD;
36struct MY_BITMAP;
37
38/*
39 Injector to inject rows into the MySQL server.
40
41 The injector class is used to notify the MySQL server of new rows that have
42 appeared outside of MySQL control.
43
44 The original purpose of this is to allow clusters---which handle replication
45 inside the cluster through other means---to insert new rows into binary log.
46 Note, however, that the injector should be used whenever rows are altered in
47 any manner that is outside of MySQL server visibility and which therefore
48 are not seen by the MySQL server.
49 */
50class injector {
51 public:
52 /*
53 Get an instance of the injector.
54
55 DESCRIPTION
56 The injector is a Singleton, so this static function return the
57 available instance of the injector.
58
59 RETURN VALUE
60 A pointer to the available injector object.
61 */
62 static injector *instance();
63
64 /*
65 Delete the singleton instance (if allocated). Used during server shutdown.
66 */
67 static void free_instance();
68
69 /*
70 A transaction where rows can be added.
71
72 DESCRIPTION
73 The transaction class satisfy the **CopyConstructible** and
74 **Assignable** requirements. Note that the transaction is *not*
75 default constructible.
76 */
78 friend class injector;
79
80 public:
81 /* Convenience definitions */
84
85 /*
86 Table reference.
87
88 RESPONSIBILITY
89
90 The class contains constructors to handle several forms of
91 references to tables. The constructors can implicitly be used to
92 construct references from, e.g., strings containing table names.
93
94 EXAMPLE
95
96 The class is intended to be used *by value*. Please, do not try to
97 construct objects of this type using 'new'; instead construct an
98 object, possibly a temporary object. For example:
99
100 injector::transaction::table tbl(share->table, true);
101 MY_BITMAP cols;
102 bitmap_init(&cols, NULL, (i + 7) / 8, false);
103 inj->write_row(::server_id, tbl, &cols, row_data);
104
105 or
106
107 MY_BITMAP cols;
108 bitmap_init(&cols, NULL, (i + 7) / 8, false);
109 inj->write_row(::server_id,
110 injector::transaction::table(share->table, true),
111 &cols, row_data);
112
113 This will work, be more efficient, and have greater chance of
114 inlining, not run the risk of losing pointers.
115
116 COLLABORATION
117
118 injector::transaction
119 Provide a flexible interface to the representation of tables.
120
121 */
122 class table {
123 public:
124 class save_sets {
125 public:
126 save_sets(table const &tbl, MY_BITMAP const *new_rs,
127 MY_BITMAP const *new_ws)
128 : m_table(tbl.get_table()),
129 save_read_set(m_table->read_set),
130 save_write_set(m_table->write_set) {
132 const_cast<MY_BITMAP *>(new_rs), const_cast<MY_BITMAP *>(new_ws));
133 }
134
137 }
138
139 private:
143 };
144
146 : m_table(table),
149
150 char const *db_name() const { return m_table->s->db.str; }
151 char const *table_name() const { return m_table->s->table_name.str; }
152 TABLE *get_table() const { return m_table; }
153 bool is_transactional() const { return m_is_transactional; }
154 bool skip_hash() const { return m_skip_hash; }
155
156 private:
159 const bool m_skip_hash;
160 };
161
162 /*
163 Binlog position as a structure.
164 */
166 friend class transaction;
167
168 public:
169 char const *file_name() const { return m_file_name; }
170 my_off_t file_pos() const { return m_file_pos; }
171
172 private:
173 char const *m_file_name;
175 };
176
179 ~transaction();
180
181 /* Clear transaction, i.e., make calls to 'good()' return false. */
182 void clear() { m_thd = nullptr; }
183
184 /* Is the transaction in a good state? */
185 bool good() const { return m_thd != nullptr; }
186
187 /* Default assignment operator: standard implementation */
189 swap(t);
190 return *this;
191 }
192
193 /*
194
195 DESCRIPTION
196
197 Register table for use within the transaction. All tables
198 that are going to be used need to be registered before being
199 used below. The member function will fail with an error if
200 use_table() is called after any *_row() function has been
201 called for the transaction.
202
203 RETURN VALUE
204
205 0 All OK
206 >0 Failure
207
208 */
209 int use_table(server_id_type sid, table tbl);
210
211 /*
212 Add a 'write row' entry to the transaction.
213 */
214 int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
215 record_type record, const unsigned char *extra_row_info);
216 int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
218
219 /*
220 Add a 'delete row' entry to the transaction.
221 */
222 int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
223 record_type record, const unsigned char *extra_row_info);
224 int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
226 /*
227 Add an 'update row' entry to the transaction.
228 */
229 int update_row(server_id_type sid, table tbl, MY_BITMAP const *before_cols,
230 MY_BITMAP const *after_cols, record_type before,
231 record_type after, const unsigned char *extra_row_info);
232 int update_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
233 record_type before, record_type after);
234
235 /*
236 Commit a transaction.
237
238 This member function will clean up after a sequence of *_row calls by,
239 for example, releasing resource and unlocking files.
240 */
241 int commit();
242
243 /*
244 Rollback a transaction.
245
246 This member function will clean up after a sequence of *_row calls by,
247 for example, releasing resource and unlocking files.
248 */
249 int rollback();
250
251 /*
252 Get the position for the start of the transaction.
253
254 This is the current 'tail of Binlog' at the time the transaction
255 was started. The first event recorded by the transaction may
256 be at this, or some subsequent position. The first event recorded
257 by the transaction will not be before this position.
258 */
259 binlog_pos start_pos() const;
260
261 /*
262 Get the next position after the end of the transaction
263
264 This call is only valid after a transaction has been committed.
265 It returns the next Binlog position after the committed transaction.
266 It is guaranteed that no other events will be recorded between the
267 COMMIT event of the Binlog transaction, and this position.
268 Note that this position may be in a different log file to the COMMIT
269 event.
270
271 If the commit had an error, or the transaction was empty and nothing
272 was binlogged then the next_pos will have a NULL file_name(), and
273 0 file_pos().
274
275 */
276 binlog_pos next_pos() const;
277
278 private:
279 /* Only the injector may construct these object */
280 transaction(MYSQL_BIN_LOG *, THD *, bool calc_writeset_hash);
281
282 void swap(transaction &o) {
288 }
289
291 START_STATE, /* Start state */
292 TABLE_STATE, /* At least one table has been registered */
293 ROW_STATE, /* At least one row has been registered */
294 STATE_COUNT /* State count and sink state */
296
297 /*
298 Check and update the state.
299
300 PARAMETER(S)
301
302 target_state
303 The state we are moving to: TABLE_STATE if we are
304 writing a table and ROW_STATE if we are writing a row.
305
306 DESCRIPTION
307
308 The internal state will be updated to the target state if
309 and only if it is a legal move. The only legal moves are:
310
311 START_STATE -> START_STATE
312 START_STATE -> TABLE_STATE
313 TABLE_STATE -> TABLE_STATE
314 TABLE_STATE -> ROW_STATE
315
316 That is:
317 - It is not possible to write any row before having written at
318 least one table
319 - It is not possible to write a table after at least one row
320 has been written
321
322 RETURN VALUE
323
324 0 All OK
325 -1 Incorrect call sequence
326 */
327 int check_state(enum_state const target_state) {
328#ifndef NDEBUG
329 static char const *state_name[] = {"START_STATE", "TABLE_STATE",
330 "ROW_STATE", "STATE_COUNT"};
331
332 assert(0 <= target_state && target_state <= STATE_COUNT);
333 DBUG_PRINT("info", ("In state %s", state_name[m_state]));
334#endif
335
336 if (m_state <= target_state && target_state <= m_state + 1 &&
338 m_state = target_state;
339 else
341 return m_state == STATE_COUNT ? 1 : 0;
342 }
343
348 };
349
350 /*
351 Create a new transaction. This member function will prepare for a
352 sequence of *_row calls by, for example, reserving resources and
353 locking files. The call uses placement semantics and will overwrite
354 the transaction.
355
356 injector::transaction trans2;
357 inj->new_trans(thd, &trans, <calc_writeset_hash>);
358
359 The parameter "calc_writeset_hash" controls wheter writeset hashes for
360 transaction dependencies will be calculated for rows added to the
361 transaction, without this the list of hashes will be empty and thus no
362 dependencies are detected. The ability to control this is important where
363 MTA is not used, calculating writeset hashes is wasted work, and in NDB all
364 binlog content is processed by a single thread and CPU consumption might be
365 a bottleneck.
366 */
367 void new_trans(THD *, transaction *, bool calc_writeset_hash);
368
369 int record_incident(
371 const LEX_CSTRING &message);
372
373 private:
374 explicit injector();
375 ~injector() = default; /* Nothing needs to be done */
376 injector(injector const &); /* You're not allowed to copy injector
377 instances.
378 */
379};
380
381#endif /* INJECTOR_H */
Kerberos Client Authentication nullptr
Definition: auth_kerberos_client_plugin.cc:250
Definition: binlog.h:138
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:35
Definition: rpl_injector.h:165
char const * m_file_name
Definition: rpl_injector.h:173
char const * file_name() const
Definition: rpl_injector.h:169
my_off_t file_pos() const
Definition: rpl_injector.h:170
my_off_t m_file_pos
Definition: rpl_injector.h:174
Definition: rpl_injector.h:124
MY_BITMAP * save_write_set
Definition: rpl_injector.h:142
TABLE *const m_table
Definition: rpl_injector.h:140
~save_sets()
Definition: rpl_injector.h:135
MY_BITMAP * save_read_set
Definition: rpl_injector.h:141
save_sets(table const &tbl, MY_BITMAP const *new_rs, MY_BITMAP const *new_ws)
Definition: rpl_injector.h:126
Definition: rpl_injector.h:122
char const * db_name() const
Definition: rpl_injector.h:150
const bool m_is_transactional
Definition: rpl_injector.h:158
const bool m_skip_hash
Definition: rpl_injector.h:159
TABLE * get_table() const
Definition: rpl_injector.h:152
TABLE *const m_table
Definition: rpl_injector.h:157
table(TABLE *table, bool is_transactional, bool skip_hash=false)
Definition: rpl_injector.h:145
bool skip_hash() const
Definition: rpl_injector.h:154
char const * table_name() const
Definition: rpl_injector.h:151
bool is_transactional() const
Definition: rpl_injector.h:153
Definition: rpl_injector.h:77
uchar * record_type
Definition: rpl_injector.h:82
bool good() const
Definition: rpl_injector.h:185
int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols, record_type record, const unsigned char *extra_row_info)
Definition: rpl_injector.cc:180
void clear()
Definition: rpl_injector.h:182
enum_state
Definition: rpl_injector.h:290
@ ROW_STATE
Definition: rpl_injector.h:293
@ START_STATE
Definition: rpl_injector.h:291
@ STATE_COUNT
Definition: rpl_injector.h:294
@ TABLE_STATE
Definition: rpl_injector.h:292
binlog_pos m_start_pos
Definition: rpl_injector.h:344
binlog_pos next_pos() const
Definition: rpl_injector.cc:282
~transaction()
Definition: rpl_injector.cc:81
binlog_pos m_next_pos
Definition: rpl_injector.h:345
THD * m_thd
Definition: rpl_injector.h:346
int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols, record_type record, const unsigned char *extra_row_info)
Definition: rpl_injector.cc:211
int commit()
Definition: rpl_injector.cc:101
int use_table(server_id_type sid, table tbl)
Definition: rpl_injector.cc:168
uint32 server_id_type
Definition: rpl_injector.h:83
int check_state(enum_state const target_state)
Definition: rpl_injector.h:327
transaction(transaction const &)
binlog_pos start_pos() const
Definition: rpl_injector.cc:278
void swap(transaction &o)
Definition: rpl_injector.h:282
int update_row(server_id_type sid, table tbl, MY_BITMAP const *before_cols, MY_BITMAP const *after_cols, record_type before, record_type after, const unsigned char *extra_row_info)
Definition: rpl_injector.cc:242
bool m_calc_writeset_hash
Definition: rpl_injector.h:347
enum injector::transaction::enum_state m_state
transaction()
Definition: rpl_injector.h:177
int rollback()
Definition: rpl_injector.cc:144
transaction & operator=(transaction t)
Definition: rpl_injector.h:188
Definition: rpl_injector.h:50
static injector * instance()
Definition: rpl_injector.cc:294
void new_trans(THD *, transaction *, bool calc_writeset_hash)
Definition: rpl_injector.cc:309
int record_incident(THD *, mysql::binlog::event::Incident_event::enum_incident incident, const LEX_CSTRING &message)
Definition: rpl_injector.cc:320
static void free_instance()
Definition: rpl_injector.cc:300
injector(injector const &)
~injector()=default
enum_incident
Enumeration of the incidents that can occur for the server.
Definition: control_events.h:444
Contains the classes representing events operating in the replication stream properties.
#define DBUG_PRINT(keyword, arglist)
Definition: my_dbug.h:180
Some integer typedefs for easier portability.
ulonglong my_off_t
Definition: my_inttypes.h:71
unsigned char uchar
Definition: my_inttypes.h:51
uint32_t uint32
Definition: my_inttypes.h:66
static int record
Definition: mysqltest.cc:194
static PFS_engine_table_share_proxy table
Definition: pfs.cc:60
Definition: mysql_lex_string.h:39
const char * str
Definition: mysql_lex_string.h:40
Definition: my_bitmap.h:42
LEX_CSTRING table_name
Definition: table.h:777
LEX_CSTRING db
Definition: table.h:776
Definition: table.h:1403
void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg)
Definition: table.h:1957
TABLE_SHARE * s
Definition: table.h:1404
void swap(const varlen_element &a, const varlen_element &b)
Definition: varlen_sort.h:65