1/* Copyright (c) 2006, 2010, 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_bitmap.h>
21
22#include "rpl_constants.h"
23#include "table.h" /* TABLE */
24
25/* Forward declarations */
26class handler;
27class MYSQL_BIN_LOG;
28struct TABLE;
29
30
31/*
32 Injector to inject rows into the MySQL server.
33
34 The injector class is used to notify the MySQL server of new rows that have
35 appeared outside of MySQL control.
36
37 The original purpose of this is to allow clusters---which handle replication
38 inside the cluster through other means---to insert new rows into binary log.
39 Note, however, that the injector should be used whenever rows are altered in
40 any manner that is outside of MySQL server visibility and which therefore
41 are not seen by the MySQL server.
42 */
43class injector
44{
45public:
46
47 /*
48 Get an instance of the injector.
49
50 DESCRIPTION
51 The injector is a Singleton, so this static function return the
52 available instance of the injector.
53
54 RETURN VALUE
55 A pointer to the available injector object.
56 */
57 static injector *instance();
58
59 /*
60 Delete the singleton instance (if allocated). Used during server shutdown.
61 */
62 static void free_instance();
63
64 /*
65 A transaction where rows can be added.
66
67 DESCRIPTION
68 The transaction class satisfy the **CopyConstructible** and
69 **Assignable** requirements. Note that the transaction is *not*
70 default constructible.
71 */
72 class transaction {
73 friend class injector;
74 public:
75 /* Convenience definitions */
76 typedef uchar* record_type;
77 typedef uint32 server_id_type;
78
79 /*
80 Table reference.
81
82 RESPONSIBILITY
83
84 The class contains constructors to handle several forms of
85 references to tables. The constructors can implicitly be used to
86 construct references from, e.g., strings containing table names.
87
88 EXAMPLE
89
90 The class is intended to be used *by value*. Please, do not try to
91 construct objects of this type using 'new'; instead construct an
92 object, possibly a temporary object. For example:
93
94 injector::transaction::table tbl(share->table, true);
95 MY_BITMAP cols;
96 my_bitmap_init(&cols, NULL, (i + 7) / 8, false);
97 inj->write_row(::server_id, tbl, &cols, row_data);
98
99 or
100
101 MY_BITMAP cols;
102 my_bitmap_init(&cols, NULL, (i + 7) / 8, false);
103 inj->write_row(::server_id,
104 injector::transaction::table(share->table, true),
105 &cols, row_data);
106
107 This will work, be more efficient, and have greater chance of
108 inlining, not run the risk of losing pointers.
109
110 COLLABORATION
111
112 injector::transaction
113 Provide a flexible interface to the representation of tables.
114
115 */
116 class table
117 {
118 public:
119 table(TABLE *table, bool is_transactional_arg)
120 : m_table(table), m_is_transactional(is_transactional_arg)
121 {
122 }
123
124 char const *db_name() const { return m_table->s->db.str; }
125 char const *table_name() const { return m_table->s->table_name.str; }
126 TABLE *get_table() const { return m_table; }
127 bool is_transactional() const { return m_is_transactional; }
128
129 private:
130 TABLE *m_table;
131 bool m_is_transactional;
132 };
133
134 /*
135 Binlog position as a structure.
136 */
137 class binlog_pos {
138 friend class transaction;
139 public:
140 char const *file_name() const { return m_file_name; }
141 my_off_t file_pos() const { return m_file_pos; }
142
143 private:
144 char const *m_file_name;
145 my_off_t m_file_pos;
146 };
147
148 transaction() : m_thd(NULL) { }
149 transaction(transaction const&);
150 ~transaction();
151
152 /* Clear transaction, i.e., make calls to 'good()' return false. */
153 void clear() { m_thd= NULL; }
154
155 /* Is the transaction in a good state? */
156 bool good() const { return m_thd != NULL; }
157
158 /* Default assignment operator: standard implementation */
159 transaction& operator=(transaction t) {
160 swap(t);
161 return *this;
162 }
163
164 /*
165
166 DESCRIPTION
167
168 Register table for use within the transaction. All tables
169 that are going to be used need to be registered before being
170 used below. The member function will fail with an error if
171 use_table() is called after any *_row() function has been
172 called for the transaction.
173
174 RETURN VALUE
175
176 0 All OK
177 >0 Failure
178
179 */
180 int use_table(server_id_type sid, table tbl);
181
182 /*
183 Commit a transaction.
184
185 This member function will clean up after a sequence of *_row calls by,
186 for example, releasing resource and unlocking files.
187 */
188 int commit();
189
190 /*
191 Get the position for the start of the transaction.
192
193 Returns the position in the binary log of the first event in this
194 transaction. If no event is yet written, the position where the event
195 *will* be written is returned. This position is known, since a
196 new_transaction() will lock the binary log and prevent any other
197 writes to the binary log.
198 */
199 binlog_pos start_pos() const;
200
201 private:
202 /* Only the injector may construct these object */
203 transaction(MYSQL_BIN_LOG *, THD *);
204
205 void swap(transaction& o) {
206 /* std::swap(m_start_pos, o.m_start_pos); */
207 {
208 binlog_pos const tmp= m_start_pos;
209 m_start_pos= o.m_start_pos;
210 o.m_start_pos= tmp;
211 }
212
213 /* std::swap(m_thd, o.m_thd); */
214 {
215 THD* const tmp= m_thd;
216 m_thd= o.m_thd;
217 o.m_thd= tmp;
218 }
219 {
220 enum_state const tmp= m_state;
221 m_state= o.m_state;
222 o.m_state= tmp;
223 }
224 }
225
226 enum enum_state
227 {
228 START_STATE, /* Start state */
229 TABLE_STATE, /* At least one table has been registered */
230 ROW_STATE, /* At least one row has been registered */
231 STATE_COUNT /* State count and sink state */
232 } m_state;
233
234 /*
235 Check and update the state.
236
237 PARAMETER(S)
238
239 target_state
240 The state we are moving to: TABLE_STATE if we are
241 writing a table and ROW_STATE if we are writing a row.
242
243 DESCRIPTION
244
245 The internal state will be updated to the target state if
246 and only if it is a legal move. The only legal moves are:
247
248 START_STATE -> START_STATE
249 START_STATE -> TABLE_STATE
250 TABLE_STATE -> TABLE_STATE
251 TABLE_STATE -> ROW_STATE
252
253 That is:
254 - It is not possible to write any row before having written at
255 least one table
256 - It is not possible to write a table after at least one row
257 has been written
258
259 RETURN VALUE
260
261 0 All OK
262 -1 Incorrect call sequence
263 */
264 int check_state(enum_state const target_state)
265 {
266#ifndef DBUG_OFF
267 static char const *state_name[] = {
268 "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT"
269 };
270
271 DBUG_ASSERT(target_state <= STATE_COUNT);
272 DBUG_PRINT("info", ("In state %s", state_name[m_state]));
273#endif
274
275 if (m_state <= target_state && target_state <= m_state + 1 &&
276 m_state < STATE_COUNT)
277 m_state= target_state;
278 else
279 m_state= STATE_COUNT;
280 return m_state == STATE_COUNT ? 1 : 0;
281 }
282
283
284 binlog_pos m_start_pos;
285 THD *m_thd;
286 };
287
288 /*
289 Create a new transaction. This member function will prepare for a
290 sequence of *_row calls by, for example, reserving resources and
291 locking files. There are two overloaded alternatives: one returning a
292 transaction by value and one using placement semantics. The following
293 two calls are equivalent, with the exception that the latter will
294 overwrite the transaction.
295
296 injector::transaction trans1= inj->new_trans(thd);
297
298 injector::transaction trans2;
299 inj->new_trans(thd, &trans);
300 */
301 transaction new_trans(THD *);
302 void new_trans(THD *, transaction *);
303
304 int record_incident(THD*, Incident incident);
305 int record_incident(THD*, Incident incident, const LEX_CSTRING *message);
306
307private:
308 explicit injector();
309 ~injector() { } /* Nothing needs to be done */
310 injector(injector const&); /* You're not allowed to copy injector
311 instances.
312 */
313};
314
315#endif /* INJECTOR_H */
316