MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rpl_injector.h
1 /* Copyright (c) 2006, 2011, 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 as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #ifndef INJECTOR_H
17 #define INJECTOR_H
18 
19 /* Pull in 'byte', 'my_off_t', and 'uint32' */
20 #include <my_global.h>
21 #include <my_bitmap.h>
22 
23 #include "rpl_constants.h"
24 #include "table.h" /* TABLE */
25 
26 /* Forward declarations */
27 class handler;
28 class MYSQL_BIN_LOG;
29 struct TABLE;
30 
31 
32 /*
33  Injector to inject rows into the MySQL server.
34 
35  The injector class is used to notify the MySQL server of new rows that have
36  appeared outside of MySQL control.
37 
38  The original purpose of this is to allow clusters---which handle replication
39  inside the cluster through other means---to insert new rows into binary log.
40  Note, however, that the injector should be used whenever rows are altered in
41  any manner that is outside of MySQL server visibility and which therefore
42  are not seen by the MySQL server.
43  */
44 class injector
45 {
46 public:
47 
48  /*
49  Get an instance of the injector.
50 
51  DESCRIPTION
52  The injector is a Singleton, so this static function return the
53  available instance of the injector.
54 
55  RETURN VALUE
56  A pointer to the available injector object.
57  */
58  static injector *instance();
59 
60  /*
61  Delete the singleton instance (if allocated). Used during server shutdown.
62  */
63  static void free_instance();
64 
65  /*
66  A transaction where rows can be added.
67 
68  DESCRIPTION
69  The transaction class satisfy the **CopyConstructible** and
70  **Assignable** requirements. Note that the transaction is *not*
71  default constructible.
72  */
73  class transaction {
74  friend class injector;
75  public:
76  /* Convenience definitions */
77  typedef uchar* record_type;
78  typedef uint32 server_id_type;
79 
80  /*
81  Table reference.
82 
83  RESPONSIBILITY
84 
85  The class contains constructors to handle several forms of
86  references to tables. The constructors can implicitly be used to
87  construct references from, e.g., strings containing table names.
88 
89  EXAMPLE
90 
91  The class is intended to be used *by value*. Please, do not try to
92  construct objects of this type using 'new'; instead construct an
93  object, possibly a temporary object. For example:
94 
95  injector::transaction::table tbl(share->table, true);
96  MY_BITMAP cols;
97  bitmap_init(&cols, NULL, (i + 7) / 8, false);
98  inj->write_row(::server_id, tbl, &cols, row_data);
99 
100  or
101 
102  MY_BITMAP cols;
103  bitmap_init(&cols, NULL, (i + 7) / 8, false);
104  inj->write_row(::server_id,
105  injector::transaction::table(share->table, true),
106  &cols, row_data);
107 
108  This will work, be more efficient, and have greater chance of
109  inlining, not run the risk of losing pointers.
110 
111  COLLABORATION
112 
113  injector::transaction
114  Provide a flexible interface to the representation of tables.
115 
116  */
117  class table
118  {
119  public:
120  class save_sets {
121  public:
122  save_sets(table const &tbl, MY_BITMAP const *new_rs, MY_BITMAP const *new_ws)
123  : m_table(tbl.get_table()),
124  save_read_set(m_table->read_set),
125  save_write_set(m_table->write_set)
126  {
127  m_table->column_bitmaps_set_no_signal(const_cast<MY_BITMAP*>(new_rs),
128  const_cast<MY_BITMAP*>(new_ws));
129  }
130 
131  ~save_sets() {
132  m_table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
133  }
134 
135  private:
136  TABLE *m_table;
137  MY_BITMAP *save_read_set;
138  MY_BITMAP *save_write_set;
139  };
140 
141  table(TABLE *table, bool is_transactional)
142  : m_table(table), m_is_transactional(is_transactional)
143  {
144  }
145 
146  char const *db_name() const { return m_table->s->db.str; }
147  char const *table_name() const { return m_table->s->table_name.str; }
148  TABLE *get_table() const { return m_table; }
149  bool is_transactional() const { return m_is_transactional; }
150 
151  private:
152  TABLE *m_table;
153  bool m_is_transactional;
154  };
155 
156  /*
157  Binlog position as a structure.
158  */
159  class binlog_pos {
160  friend class transaction;
161  public:
162  char const *file_name() const { return m_file_name; }
163  my_off_t file_pos() const { return m_file_pos; }
164 
165  private:
166  char const *m_file_name;
167  my_off_t m_file_pos;
168  };
169 
170  transaction() : m_thd(NULL) { }
171  transaction(transaction const&);
172  ~transaction();
173 
174  /* Clear transaction, i.e., make calls to 'good()' return false. */
175  void clear() { m_thd= NULL; }
176 
177  /* Is the transaction in a good state? */
178  bool good() const { return m_thd != NULL; }
179 
180  /* Default assignment operator: standard implementation */
181  transaction& operator=(transaction t) {
182  swap(t);
183  return *this;
184  }
185 
186  /*
187 
188  DESCRIPTION
189 
190  Register table for use within the transaction. All tables
191  that are going to be used need to be registered before being
192  used below. The member function will fail with an error if
193  use_table() is called after any *_row() function has been
194  called for the transaction.
195 
196  RETURN VALUE
197 
198  0 All OK
199  >0 Failure
200 
201  */
202  int use_table(server_id_type sid, table tbl);
203 
204  /*
205  Add a 'write row' entry to the transaction.
206  */
207  int write_row (server_id_type sid, table tbl,
208  MY_BITMAP const *cols, size_t colcnt,
209  record_type record,
210  const uchar* extra_row_info);
211  int write_row (server_id_type sid, table tbl,
212  MY_BITMAP const *cols, size_t colcnt,
213  record_type record);
214 
215  /*
216  Add a 'delete row' entry to the transaction.
217  */
218  int delete_row(server_id_type sid, table tbl,
219  MY_BITMAP const *cols, size_t colcnt,
220  record_type record,
221  const uchar* extra_row_info);
222  int delete_row(server_id_type sid, table tbl,
223  MY_BITMAP const *cols, size_t colcnt,
224  record_type record);
225  /*
226  Add an 'update row' entry to the transaction.
227  */
228  int update_row(server_id_type sid, table tbl,
229  MY_BITMAP const *cols, size_t colcnt,
230  record_type before, record_type after,
231  const uchar* extra_row_info);
232  int update_row(server_id_type sid, table tbl,
233  MY_BITMAP const *cols, size_t colcnt,
234  record_type before, record_type after);
235 
236  /*
237  Commit 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 commit();
243 
244  /*
245  Rollback a transaction.
246 
247  This member function will clean up after a sequence of *_row calls by,
248  for example, releasing resource and unlocking files.
249  */
250  int rollback();
251 
252  /*
253  Get the position for the start of the transaction.
254 
255  This is the current 'tail of Binlog' at the time the transaction
256  was started. The first event recorded by the transaction may
257  be at this, or some subsequent position. The first event recorded
258  by the transaction will not be before this position.
259  */
260  binlog_pos start_pos() const;
261 
262  /*
263  Get the next position after the end of the transaction
264 
265  This call is only valid after a transaction has been committed.
266  It returns the next Binlog position after the committed transaction.
267  It is guaranteed that no other events will be recorded between the
268  COMMIT event of the Binlog transaction, and this position.
269  Note that this position may be in a different log file to the COMMIT
270  event.
271 
272  If the commit had an error, or the transaction was empty and nothing
273  was binlogged then the next_pos will have a NULL file_name(), and
274  0 file_pos().
275 
276  */
277  binlog_pos next_pos() const;
278 
279  private:
280  /* Only the injector may construct these object */
281  transaction(MYSQL_BIN_LOG *, THD *);
282 
283  void swap(transaction& o) {
284  /* std::swap(m_start_pos, o.m_start_pos); */
285  {
286  binlog_pos const tmp= m_start_pos;
287  m_start_pos= o.m_start_pos;
288  o.m_start_pos= tmp;
289  }
290 
291  /* std::swap(m_end_pos, o.m_end_pos); */
292  {
293  binlog_pos const tmp= m_next_pos;
294  m_next_pos= o.m_next_pos;
295  o.m_next_pos= tmp;
296  }
297 
298  /* std::swap(m_thd, o.m_thd); */
299  {
300  THD* const tmp= m_thd;
301  m_thd= o.m_thd;
302  o.m_thd= tmp;
303  }
304  {
305  enum_state const tmp= m_state;
306  m_state= o.m_state;
307  o.m_state= tmp;
308  }
309  }
310 
311  enum enum_state
312  {
313  START_STATE, /* Start state */
314  TABLE_STATE, /* At least one table has been registered */
315  ROW_STATE, /* At least one row has been registered */
316  STATE_COUNT /* State count and sink state */
317  } m_state;
318 
319  /*
320  Check and update the state.
321 
322  PARAMETER(S)
323 
324  target_state
325  The state we are moving to: TABLE_STATE if we are
326  writing a table and ROW_STATE if we are writing a row.
327 
328  DESCRIPTION
329 
330  The internal state will be updated to the target state if
331  and only if it is a legal move. The only legal moves are:
332 
333  START_STATE -> START_STATE
334  START_STATE -> TABLE_STATE
335  TABLE_STATE -> TABLE_STATE
336  TABLE_STATE -> ROW_STATE
337 
338  That is:
339  - It is not possible to write any row before having written at
340  least one table
341  - It is not possible to write a table after at least one row
342  has been written
343 
344  RETURN VALUE
345 
346  0 All OK
347  -1 Incorrect call sequence
348  */
349  int check_state(enum_state const target_state)
350  {
351 #ifndef DBUG_OFF
352  static char const *state_name[] = {
353  "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT"
354  };
355 
356  DBUG_ASSERT(0 <= target_state && target_state <= STATE_COUNT);
357  DBUG_PRINT("info", ("In state %s", state_name[m_state]));
358 #endif
359 
360  if (m_state <= target_state && target_state <= m_state + 1 &&
361  m_state < STATE_COUNT)
362  m_state= target_state;
363  else
364  m_state= STATE_COUNT;
365  return m_state == STATE_COUNT ? 1 : 0;
366  }
367 
368 
369  binlog_pos m_start_pos;
370  binlog_pos m_next_pos;
371  THD *m_thd;
372  };
373 
374  /*
375  Create a new transaction. This member function will prepare for a
376  sequence of *_row calls by, for example, reserving resources and
377  locking files. The call uses placement semantics and will overwrite
378  the transaction.
379 
380  injector::transaction trans2;
381  inj->new_trans(thd, &trans);
382  */
383  void new_trans(THD *, transaction *);
384 
385  int record_incident(THD*, Incident incident);
386  int record_incident(THD*, Incident incident, LEX_STRING const message);
387 
388 private:
389  explicit injector();
390  ~injector() { } /* Nothing needs to be done */
391  injector(injector const&); /* You're not allowed to copy injector
392  instances.
393  */
394 };
395 
396 #endif /* INJECTOR_H */