My Project
|
00001 /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software 00014 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00015 00016 #ifndef INJECTOR_H 00017 #define INJECTOR_H 00018 00019 /* Pull in 'byte', 'my_off_t', and 'uint32' */ 00020 #include <my_global.h> 00021 #include <my_bitmap.h> 00022 00023 #include "rpl_constants.h" 00024 #include "table.h" /* TABLE */ 00025 00026 /* Forward declarations */ 00027 class handler; 00028 class MYSQL_BIN_LOG; 00029 struct TABLE; 00030 00031 00032 /* 00033 Injector to inject rows into the MySQL server. 00034 00035 The injector class is used to notify the MySQL server of new rows that have 00036 appeared outside of MySQL control. 00037 00038 The original purpose of this is to allow clusters---which handle replication 00039 inside the cluster through other means---to insert new rows into binary log. 00040 Note, however, that the injector should be used whenever rows are altered in 00041 any manner that is outside of MySQL server visibility and which therefore 00042 are not seen by the MySQL server. 00043 */ 00044 class injector 00045 { 00046 public: 00047 00048 /* 00049 Get an instance of the injector. 00050 00051 DESCRIPTION 00052 The injector is a Singleton, so this static function return the 00053 available instance of the injector. 00054 00055 RETURN VALUE 00056 A pointer to the available injector object. 00057 */ 00058 static injector *instance(); 00059 00060 /* 00061 Delete the singleton instance (if allocated). Used during server shutdown. 00062 */ 00063 static void free_instance(); 00064 00065 /* 00066 A transaction where rows can be added. 00067 00068 DESCRIPTION 00069 The transaction class satisfy the **CopyConstructible** and 00070 **Assignable** requirements. Note that the transaction is *not* 00071 default constructible. 00072 */ 00073 class transaction { 00074 friend class injector; 00075 public: 00076 /* Convenience definitions */ 00077 typedef uchar* record_type; 00078 typedef uint32 server_id_type; 00079 00080 /* 00081 Table reference. 00082 00083 RESPONSIBILITY 00084 00085 The class contains constructors to handle several forms of 00086 references to tables. The constructors can implicitly be used to 00087 construct references from, e.g., strings containing table names. 00088 00089 EXAMPLE 00090 00091 The class is intended to be used *by value*. Please, do not try to 00092 construct objects of this type using 'new'; instead construct an 00093 object, possibly a temporary object. For example: 00094 00095 injector::transaction::table tbl(share->table, true); 00096 MY_BITMAP cols; 00097 bitmap_init(&cols, NULL, (i + 7) / 8, false); 00098 inj->write_row(::server_id, tbl, &cols, row_data); 00099 00100 or 00101 00102 MY_BITMAP cols; 00103 bitmap_init(&cols, NULL, (i + 7) / 8, false); 00104 inj->write_row(::server_id, 00105 injector::transaction::table(share->table, true), 00106 &cols, row_data); 00107 00108 This will work, be more efficient, and have greater chance of 00109 inlining, not run the risk of losing pointers. 00110 00111 COLLABORATION 00112 00113 injector::transaction 00114 Provide a flexible interface to the representation of tables. 00115 00116 */ 00117 class table 00118 { 00119 public: 00120 class save_sets { 00121 public: 00122 save_sets(table const &tbl, MY_BITMAP const *new_rs, MY_BITMAP const *new_ws) 00123 : m_table(tbl.get_table()), 00124 save_read_set(m_table->read_set), 00125 save_write_set(m_table->write_set) 00126 { 00127 m_table->column_bitmaps_set_no_signal(const_cast<MY_BITMAP*>(new_rs), 00128 const_cast<MY_BITMAP*>(new_ws)); 00129 } 00130 00131 ~save_sets() { 00132 m_table->column_bitmaps_set_no_signal(save_read_set, save_write_set); 00133 } 00134 00135 private: 00136 TABLE *m_table; 00137 MY_BITMAP *save_read_set; 00138 MY_BITMAP *save_write_set; 00139 }; 00140 00141 table(TABLE *table, bool is_transactional) 00142 : m_table(table), m_is_transactional(is_transactional) 00143 { 00144 } 00145 00146 char const *db_name() const { return m_table->s->db.str; } 00147 char const *table_name() const { return m_table->s->table_name.str; } 00148 TABLE *get_table() const { return m_table; } 00149 bool is_transactional() const { return m_is_transactional; } 00150 00151 private: 00152 TABLE *m_table; 00153 bool m_is_transactional; 00154 }; 00155 00156 /* 00157 Binlog position as a structure. 00158 */ 00159 class binlog_pos { 00160 friend class transaction; 00161 public: 00162 char const *file_name() const { return m_file_name; } 00163 my_off_t file_pos() const { return m_file_pos; } 00164 00165 private: 00166 char const *m_file_name; 00167 my_off_t m_file_pos; 00168 }; 00169 00170 transaction() : m_thd(NULL) { } 00171 transaction(transaction const&); 00172 ~transaction(); 00173 00174 /* Clear transaction, i.e., make calls to 'good()' return false. */ 00175 void clear() { m_thd= NULL; } 00176 00177 /* Is the transaction in a good state? */ 00178 bool good() const { return m_thd != NULL; } 00179 00180 /* Default assignment operator: standard implementation */ 00181 transaction& operator=(transaction t) { 00182 swap(t); 00183 return *this; 00184 } 00185 00186 /* 00187 00188 DESCRIPTION 00189 00190 Register table for use within the transaction. All tables 00191 that are going to be used need to be registered before being 00192 used below. The member function will fail with an error if 00193 use_table() is called after any *_row() function has been 00194 called for the transaction. 00195 00196 RETURN VALUE 00197 00198 0 All OK 00199 >0 Failure 00200 00201 */ 00202 int use_table(server_id_type sid, table tbl); 00203 00204 /* 00205 Add a 'write row' entry to the transaction. 00206 */ 00207 int write_row (server_id_type sid, table tbl, 00208 MY_BITMAP const *cols, size_t colcnt, 00209 record_type record, 00210 const uchar* extra_row_info); 00211 int write_row (server_id_type sid, table tbl, 00212 MY_BITMAP const *cols, size_t colcnt, 00213 record_type record); 00214 00215 /* 00216 Add a 'delete row' entry to the transaction. 00217 */ 00218 int delete_row(server_id_type sid, table tbl, 00219 MY_BITMAP const *cols, size_t colcnt, 00220 record_type record, 00221 const uchar* extra_row_info); 00222 int delete_row(server_id_type sid, table tbl, 00223 MY_BITMAP const *cols, size_t colcnt, 00224 record_type record); 00225 /* 00226 Add an 'update row' entry to the transaction. 00227 */ 00228 int update_row(server_id_type sid, table tbl, 00229 MY_BITMAP const *cols, size_t colcnt, 00230 record_type before, record_type after, 00231 const uchar* extra_row_info); 00232 int update_row(server_id_type sid, table tbl, 00233 MY_BITMAP const *cols, size_t colcnt, 00234 record_type before, record_type after); 00235 00236 /* 00237 Commit a transaction. 00238 00239 This member function will clean up after a sequence of *_row calls by, 00240 for example, releasing resource and unlocking files. 00241 */ 00242 int commit(); 00243 00244 /* 00245 Rollback a transaction. 00246 00247 This member function will clean up after a sequence of *_row calls by, 00248 for example, releasing resource and unlocking files. 00249 */ 00250 int rollback(); 00251 00252 /* 00253 Get the position for the start of the transaction. 00254 00255 This is the current 'tail of Binlog' at the time the transaction 00256 was started. The first event recorded by the transaction may 00257 be at this, or some subsequent position. The first event recorded 00258 by the transaction will not be before this position. 00259 */ 00260 binlog_pos start_pos() const; 00261 00262 /* 00263 Get the next position after the end of the transaction 00264 00265 This call is only valid after a transaction has been committed. 00266 It returns the next Binlog position after the committed transaction. 00267 It is guaranteed that no other events will be recorded between the 00268 COMMIT event of the Binlog transaction, and this position. 00269 Note that this position may be in a different log file to the COMMIT 00270 event. 00271 00272 If the commit had an error, or the transaction was empty and nothing 00273 was binlogged then the next_pos will have a NULL file_name(), and 00274 0 file_pos(). 00275 00276 */ 00277 binlog_pos next_pos() const; 00278 00279 private: 00280 /* Only the injector may construct these object */ 00281 transaction(MYSQL_BIN_LOG *, THD *); 00282 00283 void swap(transaction& o) { 00284 /* std::swap(m_start_pos, o.m_start_pos); */ 00285 { 00286 binlog_pos const tmp= m_start_pos; 00287 m_start_pos= o.m_start_pos; 00288 o.m_start_pos= tmp; 00289 } 00290 00291 /* std::swap(m_end_pos, o.m_end_pos); */ 00292 { 00293 binlog_pos const tmp= m_next_pos; 00294 m_next_pos= o.m_next_pos; 00295 o.m_next_pos= tmp; 00296 } 00297 00298 /* std::swap(m_thd, o.m_thd); */ 00299 { 00300 THD* const tmp= m_thd; 00301 m_thd= o.m_thd; 00302 o.m_thd= tmp; 00303 } 00304 { 00305 enum_state const tmp= m_state; 00306 m_state= o.m_state; 00307 o.m_state= tmp; 00308 } 00309 } 00310 00311 enum enum_state 00312 { 00313 START_STATE, /* Start state */ 00314 TABLE_STATE, /* At least one table has been registered */ 00315 ROW_STATE, /* At least one row has been registered */ 00316 STATE_COUNT /* State count and sink state */ 00317 } m_state; 00318 00319 /* 00320 Check and update the state. 00321 00322 PARAMETER(S) 00323 00324 target_state 00325 The state we are moving to: TABLE_STATE if we are 00326 writing a table and ROW_STATE if we are writing a row. 00327 00328 DESCRIPTION 00329 00330 The internal state will be updated to the target state if 00331 and only if it is a legal move. The only legal moves are: 00332 00333 START_STATE -> START_STATE 00334 START_STATE -> TABLE_STATE 00335 TABLE_STATE -> TABLE_STATE 00336 TABLE_STATE -> ROW_STATE 00337 00338 That is: 00339 - It is not possible to write any row before having written at 00340 least one table 00341 - It is not possible to write a table after at least one row 00342 has been written 00343 00344 RETURN VALUE 00345 00346 0 All OK 00347 -1 Incorrect call sequence 00348 */ 00349 int check_state(enum_state const target_state) 00350 { 00351 #ifndef DBUG_OFF 00352 static char const *state_name[] = { 00353 "START_STATE", "TABLE_STATE", "ROW_STATE", "STATE_COUNT" 00354 }; 00355 00356 DBUG_ASSERT(0 <= target_state && target_state <= STATE_COUNT); 00357 DBUG_PRINT("info", ("In state %s", state_name[m_state])); 00358 #endif 00359 00360 if (m_state <= target_state && target_state <= m_state + 1 && 00361 m_state < STATE_COUNT) 00362 m_state= target_state; 00363 else 00364 m_state= STATE_COUNT; 00365 return m_state == STATE_COUNT ? 1 : 0; 00366 } 00367 00368 00369 binlog_pos m_start_pos; 00370 binlog_pos m_next_pos; 00371 THD *m_thd; 00372 }; 00373 00374 /* 00375 Create a new transaction. This member function will prepare for a 00376 sequence of *_row calls by, for example, reserving resources and 00377 locking files. The call uses placement semantics and will overwrite 00378 the transaction. 00379 00380 injector::transaction trans2; 00381 inj->new_trans(thd, &trans); 00382 */ 00383 void new_trans(THD *, transaction *); 00384 00385 int record_incident(THD*, Incident incident); 00386 int record_incident(THD*, Incident incident, LEX_STRING const message); 00387 00388 private: 00389 explicit injector(); 00390 ~injector() { } /* Nothing needs to be done */ 00391 injector(injector const&); /* You're not allowed to copy injector 00392 instances. 00393 */ 00394 }; 00395 00396 #endif /* INJECTOR_H */