MySQL  8.0.17
Source Code Documentation
rpl_injector.h
Go to the documentation of this file.
1 /* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
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 "control_events.h" // enum_incidents
29 #include "lex_string.h"
30 #include "my_dbug.h"
31 #include "my_inttypes.h"
32 #include "sql/table.h" // TABLE
33 
34 class MYSQL_BIN_LOG;
35 class THD;
36 struct 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  */
50 class 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  */
77  class transaction {
78  friend class injector;
79 
80  public:
81  /* Convenience definitions */
82  typedef uchar *record_type;
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 
147 
148  char const *db_name() const { return m_table->s->db.str; }
149  char const *table_name() const { return m_table->s->table_name.str; }
150  TABLE *get_table() const { return m_table; }
151  bool is_transactional() const { return m_is_transactional; }
152 
153  private:
156  };
157 
158  /*
159  Binlog position as a structure.
160  */
161  class binlog_pos {
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  transaction() : m_thd(nullptr) {}
174  transaction(transaction const &);
175  ~transaction();
176 
177  /* Clear transaction, i.e., make calls to 'good()' return false. */
178  void clear() { m_thd = nullptr; }
179 
180  /* Is the transaction in a good state? */
181  bool good() const { return m_thd != nullptr; }
182 
183  /* Default assignment operator: standard implementation */
185  swap(t);
186  return *this;
187  }
188 
189  /*
190 
191  DESCRIPTION
192 
193  Register table for use within the transaction. All tables
194  that are going to be used need to be registered before being
195  used below. The member function will fail with an error if
196  use_table() is called after any *_row() function has been
197  called for the transaction.
198 
199  RETURN VALUE
200 
201  0 All OK
202  >0 Failure
203 
204  */
205  int use_table(server_id_type sid, table tbl);
206 
207  /*
208  Add a 'write row' entry to the transaction.
209  */
210  int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
211  record_type record, const unsigned char *extra_row_info);
212  int write_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
214 
215  /*
216  Add a 'delete row' entry to the transaction.
217  */
218  int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
219  record_type record, const unsigned char *extra_row_info);
220  int delete_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
222  /*
223  Add an 'update row' entry to the transaction.
224  */
225  int update_row(server_id_type sid, table tbl, MY_BITMAP const *before_cols,
226  MY_BITMAP const *after_cols, record_type before,
227  record_type after, const unsigned char *extra_row_info);
228  int update_row(server_id_type sid, table tbl, MY_BITMAP const *cols,
229  record_type before, record_type after);
230 
231  /*
232  Commit a transaction.
233 
234  This member function will clean up after a sequence of *_row calls by,
235  for example, releasing resource and unlocking files.
236  */
237  int commit();
238 
239  /*
240  Rollback a transaction.
241 
242  This member function will clean up after a sequence of *_row calls by,
243  for example, releasing resource and unlocking files.
244  */
245  int rollback();
246 
247  /*
248  Get the position for the start of the transaction.
249 
250  This is the current 'tail of Binlog' at the time the transaction
251  was started. The first event recorded by the transaction may
252  be at this, or some subsequent position. The first event recorded
253  by the transaction will not be before this position.
254  */
255  binlog_pos start_pos() const;
256 
257  /*
258  Get the next position after the end of the transaction
259 
260  This call is only valid after a transaction has been committed.
261  It returns the next Binlog position after the committed transaction.
262  It is guaranteed that no other events will be recorded between the
263  COMMIT event of the Binlog transaction, and this position.
264  Note that this position may be in a different log file to the COMMIT
265  event.
266 
267  If the commit had an error, or the transaction was empty and nothing
268  was binlogged then the next_pos will have a NULL file_name(), and
269  0 file_pos().
270 
271  */
272  binlog_pos next_pos() const;
273 
274  private:
275  /* Only the injector may construct these object */
277 
278  void swap(transaction &o) {
279  /* std::swap(m_start_pos, o.m_start_pos); */
280  {
281  binlog_pos const tmp = m_start_pos;
283  o.m_start_pos = tmp;
284  }
285 
286  /* std::swap(m_end_pos, o.m_end_pos); */
287  {
288  binlog_pos const tmp = m_next_pos;
290  o.m_next_pos = tmp;
291  }
292 
293  /* std::swap(m_thd, o.m_thd); */
294  {
295  THD *const tmp = m_thd;
296  m_thd = o.m_thd;
297  o.m_thd = tmp;
298  }
299  {
300  enum_state const tmp = m_state;
301  m_state = o.m_state;
302  o.m_state = tmp;
303  }
304  }
305 
306  enum enum_state {
307  START_STATE, /* Start state */
308  TABLE_STATE, /* At least one table has been registered */
309  ROW_STATE, /* At least one row has been registered */
310  STATE_COUNT /* State count and sink state */
311  } m_state;
312 
313  /*
314  Check and update the state.
315 
316  PARAMETER(S)
317 
318  target_state
319  The state we are moving to: TABLE_STATE if we are
320  writing a table and ROW_STATE if we are writing a row.
321 
322  DESCRIPTION
323 
324  The internal state will be updated to the target state if
325  and only if it is a legal move. The only legal moves are:
326 
327  START_STATE -> START_STATE
328  START_STATE -> TABLE_STATE
329  TABLE_STATE -> TABLE_STATE
330  TABLE_STATE -> ROW_STATE
331 
332  That is:
333  - It is not possible to write any row before having written at
334  least one table
335  - It is not possible to write a table after at least one row
336  has been written
337 
338  RETURN VALUE
339 
340  0 All OK
341  -1 Incorrect call sequence
342  */
343  int check_state(enum_state const target_state) {
344 #ifndef DBUG_OFF
345  static char const *state_name[] = {"START_STATE", "TABLE_STATE",
346  "ROW_STATE", "STATE_COUNT"};
347 
348  DBUG_ASSERT(0 <= target_state && target_state <= STATE_COUNT);
349  DBUG_PRINT("info", ("In state %s", state_name[m_state]));
350 #endif
351 
352  if (m_state <= target_state && target_state <= m_state + 1 &&
354  m_state = target_state;
355  else
357  return m_state == STATE_COUNT ? 1 : 0;
358  }
359 
363  };
364 
365  /*
366  Create a new transaction. This member function will prepare for a
367  sequence of *_row calls by, for example, reserving resources and
368  locking files. The call uses placement semantics and will overwrite
369  the transaction.
370 
371  injector::transaction trans2;
372  inj->new_trans(thd, &trans);
373  */
374  void new_trans(THD *, transaction *);
375 
377  LEX_CSTRING const message);
378 
379  private:
380  explicit injector();
381  ~injector() {} /* Nothing needs to be done */
382  injector(injector const &); /* You're not allowed to copy injector
383  instances.
384  */
385 };
386 
387 #endif /* INJECTOR_H */
binlog_pos m_next_pos
Definition: rpl_injector.h:361
unsigned char uchar
Definition: my_inttypes.h:51
MY_BITMAP * save_read_set
Definition: rpl_injector.h:141
Definition: mi_test3.cc:54
enum injector::transaction::enum_state m_state
enum_incident
Enumeration of the incidents that can occur for the server.
Definition: control_events.h:434
Some integer typedefs for easier portability.
Definition: binlog.h:325
transaction()
Definition: rpl_injector.h:173
int record_incident(THD *, binary_log::Incident_event::enum_incident incident, LEX_CSTRING const message)
Definition: rpl_injector.cc:283
char const * table_name() const
Definition: rpl_injector.h:149
Definition: rpl_injector.h:307
const char * str
Definition: mysql_lex_string.h:40
save_sets(table const &tbl, MY_BITMAP const *new_rs, MY_BITMAP const *new_ws)
Definition: rpl_injector.h:126
void clear()
Definition: rpl_injector.h:178
LEX_CSTRING table_name
Definition: table.h:725
Definition: mysql_lex_string.h:39
TABLE * get_table() const
Definition: rpl_injector.h:150
uchar * record_type
Definition: rpl_injector.h:82
binlog_pos m_start_pos
Definition: rpl_injector.h:360
Definition: rpl_injector.h:124
bool m_is_transactional
Definition: rpl_injector.h:155
TABLE * m_table
Definition: rpl_injector.h:154
my_off_t m_file_pos
Definition: rpl_injector.h:170
int commit()
Definition: rpl_injector.cc:97
bool is_transactional() const
Definition: rpl_injector.h:151
Definition: table.h:1294
static injector * instance()
Definition: rpl_injector.cc:256
#define DBUG_PRINT(keyword, arglist)
Definition: my_dbug.h:165
~save_sets()
Definition: rpl_injector.h:135
char const * db_name() const
Definition: rpl_injector.h:148
#define DBUG_ASSERT(A)
Definition: my_dbug.h:183
char const * m_file_name
Definition: rpl_injector.h:169
bool good() const
Definition: rpl_injector.h:181
static void free_instance()
Definition: rpl_injector.cc:262
Definition: rpl_injector.h:310
Definition: rpl_injector.h:77
Definition: rpl_injector.h:309
Definition: my_bitmap.h:42
injector()
Definition: rpl_injector.cc:253
TABLE_SHARE * s
Definition: table.h:1295
void new_trans(THD *, transaction *)
Definition: rpl_injector.cc:271
Definition: rpl_injector.h:122
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:213
~transaction()
Definition: rpl_injector.cc:77
t
Definition: dbug_analyze.cc:147
uint32_t uint32
Definition: my_inttypes.h:62
transaction & operator=(transaction t)
Definition: rpl_injector.h:184
int rollback()
Definition: rpl_injector.cc:140
binlog_pos next_pos() const
Definition: rpl_injector.cc:244
THD * m_thd
Definition: rpl_injector.h:362
unsigned long my_off_t
Definition: my_inttypes.h:87
Definition: rpl_injector.h:50
Definition: rpl_injector.h:308
int use_table(server_id_type sid, table tbl)
Definition: rpl_injector.cc:151
TABLE * m_table
Definition: rpl_injector.h:140
table(TABLE *table, bool is_transactional)
Definition: rpl_injector.h:145
uint32 server_id_type
Definition: rpl_injector.h:83
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:190
~injector()
Definition: rpl_injector.h:381
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:166
binlog_pos start_pos() const
Definition: rpl_injector.cc:240
int check_state(enum_state const target_state)
Definition: rpl_injector.h:343
void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg)
Definition: table.h:1644
void swap(transaction &o)
Definition: rpl_injector.h:278
LEX_CSTRING db
Definition: table.h:724
MY_BITMAP * save_write_set
Definition: rpl_injector.h:142
my_off_t file_pos() const
Definition: rpl_injector.h:166
Contains the classes representing events operating in the replication stream properties.
enum_state
Definition: rpl_injector.h:306
Definition: rpl_injector.h:161
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_class.h:777
char const * file_name() const
Definition: rpl_injector.h:165