1
/* Copyright (C) 2006 MySQL AB
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.
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.
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 */
19
/* Pull in 'byte', 'my_off_t', and 'uint32' */
20
#include <my_global.h>
21
#include <my_bitmap.h>
23
#include "rpl_constants.h"
25
/* Forward declarations */
30
typedef st_table TABLE;
33
Injector to inject rows into the MySQL server.
35
The injector class is used to notify the MySQL server of new rows that have
36
appeared outside of MySQL control.
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.
49
Get an instance of the injector.
52
The injector is a Singleton, so this static function return the
53
available instance of the injector.
56
A pointer to the available injector object.
58
static injector *instance();
61
Delete the singleton instance (if allocated). Used during server shutdown.
63
static void free_instance();
66
A transaction where rows can be added.
69
The transaction class satisfy the **CopyConstructible** and
70
**Assignable** requirements. Note that the transaction is *not*
71
default constructible.
74
friend class injector;
76
/* Convenience definitions */
77
typedef uchar* record_type;
78
typedef uint32 server_id_type;
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.
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:
95
injector::transaction::table tbl(share->table, true);
97
bitmap_init(&cols, NULL, (i + 7) / 8, false);
98
inj->write_row(::server_id, tbl, &cols, row_data);
103
bitmap_init(&cols, NULL, (i + 7) / 8, false);
104
inj->write_row(::server_id,
105
injector::transaction::table(share->table, true),
108
This will work, be more efficient, and have greater chance of
109
inlining, not run the risk of losing pointers.
113
injector::transaction
114
Provide a flexible interface to the representation of tables.
120
table(TABLE *table, bool is_transactional)
121
: m_table(table), m_is_transactional(is_transactional)
125
char const *db_name() const { return m_table->s->db.str; }
126
char const *table_name() const { return m_table->s->table_name.str; }
127
TABLE *get_table() const { return m_table; }
128
bool is_transactional() const { return m_is_transactional; }
132
bool m_is_transactional;
136
Binlog position as a structure.
139
friend class transaction;
141
char const *file_name() const { return m_file_name; }
142
my_off_t file_pos() const { return m_file_pos; }
145
char const *m_file_name;
149
transaction() : m_thd(NULL) { }
150
transaction(transaction const&);
153
/* Clear transaction, i.e., make calls to 'good()' return false. */
154
void clear() { m_thd= NULL; }
156
/* Is the transaction in a good state? */
157
bool good() const { return m_thd != NULL; }
159
/* Default assignment operator: standard implementation */
160
transaction& operator=(transaction t) {
169
Register table for use within the transaction. All tables
170
that are going to be used need to be registered before being
171
used below. The member function will fail with an error if
172
use_table() is called after any *_row() function has been
173
called for the transaction.
181
int use_table(server_id_type sid, table tbl);
184
Add a 'write row' entry to the transaction.
186
int write_row (server_id_type sid, table tbl,
187
MY_BITMAP const *cols, size_t colcnt,
191
Add a 'delete row' entry to the transaction.
193
int delete_row(server_id_type sid, table tbl,
194
MY_BITMAP const *cols, size_t colcnt,
198
Add an 'update row' entry to the transaction.
200
int update_row(server_id_type sid, table tbl,
201
MY_BITMAP const *cols, size_t colcnt,
202
record_type before, record_type after);
205
Commit a transaction.
207
This member function will clean up after a sequence of *_row calls by,
208
for example, releasing resource and unlocking files.
213
Get the position for the start of the transaction.
215
Returns the position in the binary log of the first event in this
216
transaction. If no event is yet written, the position where the event
217
*will* be written is returned. This position is known, since a
218
new_transaction() will lock the binary log and prevent any other
219
writes to the binary log.
221
binlog_pos start_pos() const;
224
/* Only the injector may construct these object */
225
transaction(MYSQL_BIN_LOG *, THD *);
227
void swap(transaction& o) {
228
/* std::swap(m_start_pos, o.m_start_pos); */
230
binlog_pos const tmp= m_start_pos;
231
m_start_pos= o.m_start_pos;
235
/* std::swap(m_thd, o.m_thd); */
237
THD* const tmp= m_thd;
242
enum_state const tmp= m_state;
250
START_STATE, /* Start state */
251
TABLE_STATE, /* At least one table has been registered */
252
ROW_STATE, /* At least one row has been registered */
253
STATE_COUNT /* State count and sink state */
257
Check and update the state.
262
The state we are moving to: TABLE_STATE if we are
263
writing a table and ROW_STATE if we are writing a row.
267
The internal state will be updated to the target state if
268
and only if it is a legal move. The only legal moves are:
270
START_STATE -> START_STATE
271
START_STATE -> TABLE_STATE
272
TABLE_STATE -> TABLE_STATE
273
TABLE_STATE -> ROW_STATE
276
- It is not possible to write any row before having written at
278
- It is not possible to write a table after at least one row
284
-1 Incorrect call sequence
286
int check_state(enum_state const target_state)
289
static char const *state_name[] = {
290
"START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT"
293
DBUG_ASSERT(0 <= target_state && target_state <= STATE_COUNT);
294
DBUG_PRINT("info", ("In state %s", state_name[m_state]));
297
if (m_state <= target_state && target_state <= m_state + 1 &&
298
m_state < STATE_COUNT)
299
m_state= target_state;
301
m_state= STATE_COUNT;
302
return m_state == STATE_COUNT ? 1 : 0;
306
binlog_pos m_start_pos;
311
Create a new transaction. This member function will prepare for a
312
sequence of *_row calls by, for example, reserving resources and
313
locking files. There are two overloaded alternatives: one returning a
314
transaction by value and one using placement semantics. The following
315
two calls are equivalent, with the exception that the latter will
316
overwrite the transaction.
318
injector::transaction trans1= inj->new_trans(thd);
320
injector::transaction trans2;
321
inj->new_trans(thd, &trans);
323
transaction new_trans(THD *);
324
void new_trans(THD *, transaction *);
326
int record_incident(THD*, Incident incident);
327
int record_incident(THD*, Incident incident, LEX_STRING const message);
331
~injector() { } /* Nothing needs to be done */
332
injector(injector const&); /* You're not allowed to copy injector
337
#endif /* INJECTOR_H */