1 /* Copyright (c) 2006, 2007 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 */