MySQL 8.4.2
Source Code Documentation
rpl_injector.h
Go to the documentation of this file.
1/* Copyright (c) 2006, 2024, 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 designed to work 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 either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef INJECTOR_H
25#define INJECTOR_H
26
27#include <stddef.h>
28#include <string_view>
29
30#include "my_dbug.h"
31#include "my_inttypes.h"
32#include "my_io.h" // FN_REFLEN
33#include "sql/table.h" // TABLE
34
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 public:
79 /* Convenience definitions */
82
83 /*
84 Table reference.
85
86 RESPONSIBILITY
87
88 The class contains constructors to handle several forms of
89 references to tables. The constructors can implicitly be used to
90 construct references from, e.g., strings containing table names.
91
92 EXAMPLE
93
94 The class is intended to be used *by value*. Please, do not try to
95 construct objects of this type using 'new'; instead construct an
96 object, possibly a temporary object. For example:
97
98 injector::transaction::table tbl(share->table, true);
99 MY_BITMAP cols;
100 bitmap_init(&cols, NULL, (i + 7) / 8, false);
101 inj->write_row(::server_id, tbl, &cols, row_data);
102
103 or
104
105 MY_BITMAP cols;
106 bitmap_init(&cols, NULL, (i + 7) / 8, false);
107 inj->write_row(::server_id,
108 injector::transaction::table(share->table, true),
109 &cols, row_data);
110
111 This will work, be more efficient, and have greater chance of
112 inlining, not run the risk of losing pointers.
113
114 COLLABORATION
115
116 injector::transaction
117 Provide a flexible interface to the representation of tables.
118
119 */
120 class table {
121 public:
122 class save_sets {
123 public:
124 save_sets(table const &tbl, MY_BITMAP const *new_rs,
125 MY_BITMAP const *new_ws)
126 : m_table(tbl.get_table()),
127 save_read_set(m_table->read_set),
128 save_write_set(m_table->write_set) {
130 const_cast<MY_BITMAP *>(new_rs), const_cast<MY_BITMAP *>(new_ws));
131 }
132
135 }
136
137 private:
141 };
142
144 : m_table(table),
147
148 TABLE *get_table() const { return m_table; }
149 bool is_transactional() const { return m_is_transactional; }
150 bool skip_hash() const { return m_skip_hash; }
151
152 private:
155 const bool m_skip_hash;
156 };
157
158 /*
159 Binlog position as a structure.
160 */
162 friend class transaction;
163
164 public:
165 char const *file_name() const { return m_file_name; }
166 my_off_t file_pos() const { return m_file_pos; }
167
168 private:
169 char const *m_file_name;
171 };
172
173 /*
174 Create a new transaction.
175
176 The parameter "calc_writeset_hash" controls whether writeset hashes for
177 transaction dependencies will be calculated for rows added to the
178 transaction, without this the list of hashes will be empty and thus no
179 dependencies are detected. The ability to control this is important where
180 MTA is not used, calculating writeset hashes is wasted work, and in NDB
181 all binlog content is processed by a single thread and CPU consumption
182 might be a bottleneck.
183 */
184 transaction(THD *thd, bool calc_writeset_hash);
185 transaction(const transaction &) = delete;
186 transaction(const transaction &&) = delete;
188 transaction &operator=(const transaction &&) = delete;
189
191
192 /*
193
194 DESCRIPTION
195
196 Register table for use within the transaction. All tables
197 that are going to be used need to be registered before being
198 used below. The member function will fail with an error if
199 use_table() is called after any *_row() function has been
200 called for the transaction.
201
202 RETURN VALUE
203
204 0 All OK
205 >0 Failure
206
207 */
208 int use_table(server_id_type sid, table tbl);
209
210 /*
211 Add a 'write row' entry to the transaction.
212 */
213 int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
214 record_type record, const unsigned char *extra_row_info);
215
216 /*
217 Add a 'delete row' entry to the transaction.
218 */
219 int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
220 record_type record, const unsigned char *extra_row_info);
221 /*
222 Add an 'update row' entry to the transaction.
223 */
224 int update_row(server_id_type sid, table tbl, MY_BITMAP const *before_cols,
225 MY_BITMAP const *after_cols, record_type before,
226 record_type after, const unsigned char *extra_row_info);
227
228 /*
229 Commit a transaction.
230
231 This member function will clean up after a sequence of *_row calls by,
232 for example, releasing resource and unlocking files.
233 */
234 int commit();
235
236 /*
237 Rollback a transaction.
238
239 This member function will clean up after a sequence of *_row calls by,
240 for example, releasing resource and unlocking files.
241 */
242 int rollback();
243
244 /*
245 Get the position for the start of the transaction.
246
247 This is the current 'tail of Binlog' at the time the transaction
248 was started. The first event recorded by the transaction may
249 be at this, or some subsequent position. The first event recorded
250 by the transaction will not be before this position.
251 */
252 binlog_pos start_pos() const;
253
254 /*
255 Get the next position after the end of the transaction
256
257 This call is only valid after a transaction has been committed.
258 It returns the next Binlog position after the committed transaction.
259 It is guaranteed that no other events will be recorded between the
260 COMMIT event of the Binlog transaction, and this position.
261 Note that this position may be in a different log file to the COMMIT
262 event.
263
264 If the commit had an error, or the transaction was empty and nothing
265 was binlogged then the next_pos will have a NULL file_name(), and
266 0 file_pos().
267
268 */
269 binlog_pos next_pos() const;
270
271 private:
273 START_STATE, /* Start state */
274 TABLE_STATE, /* At least one table has been registered */
275 ROW_STATE, /* At least one row has been registered */
276 STATE_COUNT /* State count and sink state */
278
279 /*
280 Check and update the state.
281
282 PARAMETER(S)
283
284 target_state
285 The state we are moving to: TABLE_STATE if we are
286 writing a table and ROW_STATE if we are writing a row.
287
288 DESCRIPTION
289
290 The internal state will be updated to the target state if
291 and only if it is a legal move. The only legal moves are:
292
293 START_STATE -> START_STATE
294 START_STATE -> TABLE_STATE
295 TABLE_STATE -> TABLE_STATE
296 TABLE_STATE -> ROW_STATE
297
298 That is:
299 - It is not possible to write any row before having written at
300 least one table
301 - It is not possible to write a table after at least one row
302 has been written
303
304 RETURN VALUE
305
306 0 All OK
307 -1 Incorrect call sequence
308 */
309 int check_state(enum_state const target_state) {
310#ifndef NDEBUG
311 static char const *state_name[] = {"START_STATE", "TABLE_STATE",
312 "ROW_STATE", "STATE_COUNT"};
313
314 assert(0 <= target_state && target_state <= STATE_COUNT);
315 DBUG_PRINT("info", ("In state %s", state_name[m_state]));
316#endif
317
318 if (m_state <= target_state && target_state <= m_state + 1 &&
320 m_state = target_state;
321 else
323 return m_state == STATE_COUNT ? 1 : 0;
324 }
325
330 THD *const m_thd;
331 const bool m_calc_writeset_hash{false};
332 };
333
334 int record_incident(THD *, std::string_view message);
335
336 private:
337 explicit injector();
338 ~injector() = default; /* Nothing needs to be done */
339 injector(injector const &); /* You're not allowed to copy injector
340 instances.
341 */
342};
343
344#endif /* INJECTOR_H */
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
Definition: rpl_injector.h:161
char const * m_file_name
Definition: rpl_injector.h:169
char const * file_name() const
Definition: rpl_injector.h:165
my_off_t file_pos() const
Definition: rpl_injector.h:166
my_off_t m_file_pos
Definition: rpl_injector.h:170
Definition: rpl_injector.h:122
MY_BITMAP * save_write_set
Definition: rpl_injector.h:140
TABLE *const m_table
Definition: rpl_injector.h:138
~save_sets()
Definition: rpl_injector.h:133
MY_BITMAP * save_read_set
Definition: rpl_injector.h:139
save_sets(table const &tbl, MY_BITMAP const *new_rs, MY_BITMAP const *new_ws)
Definition: rpl_injector.h:124
Definition: rpl_injector.h:120
const bool m_is_transactional
Definition: rpl_injector.h:154
const bool m_skip_hash
Definition: rpl_injector.h:155
TABLE * get_table() const
Definition: rpl_injector.h:148
TABLE *const m_table
Definition: rpl_injector.h:153
table(TABLE *table, bool is_transactional, bool skip_hash=false)
Definition: rpl_injector.h:143
bool skip_hash() const
Definition: rpl_injector.h:150
bool is_transactional() const
Definition: rpl_injector.h:149
Definition: rpl_injector.h:77
transaction(const transaction &)=delete
uchar * record_type
Definition: rpl_injector.h:80
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:151
enum_state
Definition: rpl_injector.h:272
@ ROW_STATE
Definition: rpl_injector.h:275
@ START_STATE
Definition: rpl_injector.h:273
@ STATE_COUNT
Definition: rpl_injector.h:276
@ TABLE_STATE
Definition: rpl_injector.h:274
binlog_pos m_start_pos
Definition: rpl_injector.h:328
transaction & operator=(const transaction &&)=delete
binlog_pos next_pos() const
Definition: rpl_injector.cc:235
~transaction()
Definition: rpl_injector.h:190
binlog_pos m_next_pos
Definition: rpl_injector.h:329
THD *const m_thd
Definition: rpl_injector.h:330
char m_end_name_buf[FN_REFLEN]
Definition: rpl_injector.h:327
transaction & operator=(const transaction &)=delete
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:176
int commit()
Definition: rpl_injector.cc:72
int use_table(server_id_type sid, table tbl)
Definition: rpl_injector.cc:139
transaction(const transaction &&)=delete
uint32 server_id_type
Definition: rpl_injector.h:81
int check_state(enum_state const target_state)
Definition: rpl_injector.h:309
transaction(THD *thd, bool calc_writeset_hash)
Definition: rpl_injector.cc:37
binlog_pos start_pos() const
Definition: rpl_injector.cc:231
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:201
char m_start_name_buf[FN_REFLEN]
Definition: rpl_injector.h:326
enum injector::transaction::enum_state m_state
int rollback()
Definition: rpl_injector.cc:115
const bool m_calc_writeset_hash
Definition: rpl_injector.h:331
Definition: rpl_injector.h:50
static injector * instance()
Definition: rpl_injector.cc:247
int record_incident(THD *, std::string_view message)
Definition: rpl_injector.cc:262
static void free_instance()
Definition: rpl_injector.cc:253
injector(injector const &)
~injector()=default
#define DBUG_PRINT(keyword, arglist)
Definition: my_dbug.h:181
Some integer typedefs for easier portability.
ulonglong my_off_t
Definition: my_inttypes.h:72
unsigned char uchar
Definition: my_inttypes.h:52
uint32_t uint32
Definition: my_inttypes.h:67
Common #defines and includes for file and socket I/O.
#define FN_REFLEN
Definition: my_io.h:83
static int record
Definition: mysqltest.cc:195
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
Definition: my_bitmap.h:43
Definition: table.h:1406
void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg)
Definition: table.h:1962