00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <drizzled/message.h>
00024 #include "read_replication.h"
00025 #include "create_replication.h"
00026
00027 #ifdef UNIV_NONINL
00028 #include "dict0crea.ic"
00029 #endif
00030
00031 #include "btr0pcur.h"
00032 #include "btr0btr.h"
00033 #include "page0page.h"
00034 #include "mach0data.h"
00035 #include "dict0boot.h"
00036 #include "dict0dict.h"
00037 #include "que0que.h"
00038 #include "row0ins.h"
00039 #include "row0mysql.h"
00040 #include "pars0pars.h"
00041 #include "trx0roll.h"
00042 #include "usr0sess.h"
00043 #include "ut0vec.h"
00044 #include "row0merge.h"
00045 #include "row0mysql.h"
00046
00047 UNIV_INTERN ulint dict_create_sys_replication_log(void)
00048 {
00049 dict_table_t* table1;
00050 ulint error;
00051 trx_t *trx;
00052
00053 mutex_enter(&(dict_sys->mutex));
00054
00055 table1 = dict_table_get_low("SYS_REPLICATION_LOG");
00056
00057 trx_sys_read_commit_id();
00058
00059 if (table1)
00060 {
00061 mutex_exit(&(dict_sys->mutex));
00062
00063 return(DB_SUCCESS);
00064 }
00065
00066 mutex_exit(&(dict_sys->mutex));
00067
00068 trx= trx_allocate_for_mysql();
00069
00070 trx->op_info= "creating replication sys table";
00071
00072 row_mysql_lock_data_dictionary(trx);
00073
00074 pars_info_t *info= pars_info_create();
00075
00076
00077 error = que_eval_sql(info,
00078 "PROCEDURE CREATE_SYS_REPLICATION_LOG_PROC () IS\n"
00079 "BEGIN\n"
00080 "CREATE TABLE SYS_REPLICATION_LOG(ID INT(8), SEGID INT, COMMIT_ID INT(8), END_TIMESTAMP INT(8), ORIGINATING_SERVER_UUID BLOB, ORIGINATING_COMMIT_ID INT(8), MESSAGE_LEN INT, MESSAGE BLOB);\n"
00081 "CREATE UNIQUE CLUSTERED INDEX PRIMARY ON SYS_REPLICATION_LOG (ID, SEGID);\n"
00082 "CREATE INDEX COMMIT_IDX ON SYS_REPLICATION_LOG (COMMIT_ID, ID);\n"
00083 "END;\n"
00084 , FALSE, trx);
00085
00086
00087
00088 if (error != DB_SUCCESS)
00089 {
00090 fprintf(stderr, "InnoDB: error %lu in creation.\n", (ulong) error);
00091
00092 ut_a(error == DB_OUT_OF_FILE_SPACE || error == DB_TOO_MANY_CONCURRENT_TRXS);
00093
00094 fprintf(stderr,
00095 "InnoDB: creation failed\n"
00096 "InnoDB: tablespace is full\n"
00097 "InnoDB: dropping incompletely created SYS_REPLICATION_LOG table.\n");
00098
00099 row_drop_table_for_mysql("SYS_REPLICATION_LOG", trx, TRUE);
00100
00101 error = DB_MUST_GET_MORE_FILE_SPACE;
00102 }
00103
00104 trx_commit_for_mysql(trx);
00105
00106 row_mysql_unlock_data_dictionary(trx);
00107
00108 trx_free_for_mysql(trx);
00109
00110 return(error);
00111 }
00112
00113 UNIV_INTERN int read_replication_log_table_message(const char* table_name, drizzled::message::Table *table_message)
00114 {
00115 std::string search_string(table_name);
00116 boost::algorithm::to_lower(search_string);
00117
00118 if (search_string.compare("sys_replication_log") != 0)
00119 return -1;
00120
00121 drizzled::message::Engine *engine= table_message->mutable_engine();
00122 engine->set_name("InnoDB");
00123 table_message->set_name("SYS_REPLICATION_LOG");
00124 table_message->set_schema("DATA_DICTIONARY");
00125 table_message->set_type(drizzled::message::Table::STANDARD);
00126 table_message->set_creation_timestamp(0);
00127 table_message->set_update_timestamp(0);
00128
00129 drizzled::message::Table::TableOptions *options= table_message->mutable_options();
00130 options->set_collation_id(drizzled::my_charset_bin.number);
00131 options->set_collation(drizzled::my_charset_bin.name);
00132 drizzled::message::set_is_replicated(*table_message, false);
00133
00134 drizzled::message::Table::Field *field= table_message->add_field();
00135 field->set_name("ID");
00136 field->set_type(drizzled::message::Table::Field::BIGINT);
00137
00138 field= table_message->add_field();
00139 field->set_name("SEGID");
00140 field->set_type(drizzled::message::Table::Field::INTEGER);
00141
00142 field= table_message->add_field();
00143 field->set_name("COMMIT_ID");
00144 field->set_type(drizzled::message::Table::Field::BIGINT);
00145
00146 field= table_message->add_field();
00147 field->set_name("END_TIMESTAMP");
00148 field->set_type(drizzled::message::Table::Field::BIGINT);
00149
00150 field= table_message->add_field();
00151 field->set_name("ORIGINATING_SERVER_UUID");
00152 field->set_type(drizzled::message::Table::Field::BLOB);
00153
00154 field= table_message->add_field();
00155 field->set_name("ORIGINATING_COMMIT_ID");
00156 field->set_type(drizzled::message::Table::Field::BIGINT);
00157
00158 field= table_message->add_field();
00159 field->set_name("MESSAGE_LEN");
00160 field->set_type(drizzled::message::Table::Field::INTEGER);
00161
00162 field= table_message->add_field();
00163 field->set_name("MESSAGE");
00164 field->set_type(drizzled::message::Table::Field::BLOB);
00165 drizzled::message::Table::Field::StringFieldOptions *stropt= field->mutable_string_options();
00166 stropt->set_collation_id(drizzled::my_charset_bin.number);
00167 stropt->set_collation(drizzled::my_charset_bin.name);
00168
00169 drizzled::message::Table::Index *index= table_message->add_indexes();
00170 index->set_name("PRIMARY");
00171 index->set_is_primary(true);
00172 index->set_is_unique(true);
00173 index->set_type(drizzled::message::Table::Index::BTREE);
00174 index->set_key_length(12);
00175 drizzled::message::Table::Index::IndexPart *part= index->add_index_part();
00176 part->set_fieldnr(0);
00177 part->set_compare_length(8);
00178 part= index->add_index_part();
00179 part->set_fieldnr(1);
00180 part->set_compare_length(4);
00181
00182 index= table_message->add_indexes();
00183 index->set_name("COMMIT_IDX");
00184 index->set_is_primary(false);
00185 index->set_is_unique(false);
00186 index->set_type(drizzled::message::Table::Index::BTREE);
00187 index->set_key_length(16);
00188 part= index->add_index_part();
00189 part->set_fieldnr(2);
00190 part->set_compare_length(8);
00191 part= index->add_index_part();
00192 part->set_fieldnr(0);
00193 part->set_compare_length(8);
00194
00195 return 0;
00196 }
00197
00198 extern dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t* prebuilt);
00199
00200 ulint insert_replication_message(const char *message, size_t size,
00201 trx_t *trx, uint64_t trx_id,
00202 uint64_t end_timestamp, bool is_end_segment,
00203 uint32_t seg_id, const char *server_uuid,
00204 bool use_originating_server_uuid,
00205 const char *originating_server_uuid,
00206 uint64_t originating_commit_id)
00207 {
00208 ulint error;
00209 row_prebuilt_t* prebuilt;
00210 dict_table_t *table;
00211 que_thr_t* thr;
00212 byte* data;
00213
00214 table = dict_table_get("SYS_REPLICATION_LOG",TRUE);
00215
00216 prebuilt = row_create_prebuilt(table);
00217
00218 if (prebuilt->trx != trx)
00219 {
00220 row_update_prebuilt_trx(prebuilt, trx);
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230 bool is_started= true;
00231 if (trx->conc_state == TRX_NOT_STARTED)
00232 {
00233 is_started= false;
00234 }
00235
00236 dtuple_t* dtuple= row_get_prebuilt_insert_row(prebuilt);
00237 dfield_t *dfield;
00238
00239 dfield = dtuple_get_nth_field(dtuple, 0);
00240 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 8));
00241 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&trx_id, 8, dict_table_is_comp(prebuilt->table));
00242 dfield_set_data(dfield, data, 8);
00243
00244 dfield = dtuple_get_nth_field(dtuple, 1);
00245
00246 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 4));
00247 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&seg_id, 4, dict_table_is_comp(prebuilt->table));
00248 dfield_set_data(dfield, data, 4);
00249
00250 uint64_t commit_id= 0;
00251 if (is_end_segment)
00252 {
00253 commit_id= trx_sys_commit_id.increment();
00254 }
00255
00256 dfield = dtuple_get_nth_field(dtuple, 2);
00257 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 8));
00258 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&commit_id, 8, dict_table_is_comp(prebuilt->table));
00259 dfield_set_data(dfield, data, 8);
00260
00261 dfield = dtuple_get_nth_field(dtuple, 3);
00262 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 8));
00263 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&end_timestamp, 8, dict_table_is_comp(prebuilt->table));
00264 dfield_set_data(dfield, data, 8);
00265
00266 if (not use_originating_server_uuid)
00267 {
00268
00269
00270 originating_server_uuid= server_uuid;
00271 originating_commit_id= commit_id;
00272 }
00273
00274 dfield = dtuple_get_nth_field(dtuple, 4);
00275 dfield_set_data(dfield, originating_server_uuid, 36);
00276
00277 dfield = dtuple_get_nth_field(dtuple, 5);
00278 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 8));
00279 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&originating_commit_id, 8, dict_table_is_comp(prebuilt->table));
00280 dfield_set_data(dfield, data, 8);
00281
00282 dfield = dtuple_get_nth_field(dtuple, 6);
00283 data= static_cast<byte*>(mem_heap_alloc(prebuilt->heap, 4));
00284 row_mysql_store_col_in_innobase_format(dfield, data, TRUE, (byte*)&size, 4, dict_table_is_comp(prebuilt->table));
00285 dfield_set_data(dfield, data, 4);
00286
00287 dfield = dtuple_get_nth_field(dtuple, 7);
00288 dfield_set_data(dfield, message, size);
00289
00290 ins_node_t* node = prebuilt->ins_node;
00291
00292 thr = que_fork_get_first_thr(prebuilt->ins_graph);
00293
00294 if (prebuilt->sql_stat_start) {
00295 node->state = INS_NODE_SET_IX_LOCK;
00296 prebuilt->sql_stat_start = FALSE;
00297 } else {
00298 node->state = INS_NODE_ALLOC_ROW_ID;
00299 }
00300
00301 que_thr_move_to_run_state_for_mysql(thr, trx);
00302
00303
00304 thr->run_node = node;
00305 thr->prev_node = node;
00306
00307 row_ins_step(thr);
00308
00309 error = trx->error_state;
00310
00311 que_thr_stop_for_mysql_no_error(thr, trx);
00312 row_prebuilt_free(prebuilt, FALSE);
00313
00314 if (! is_started)
00315 {
00316 trx_commit_for_mysql(trx);
00317 }
00318
00319 return error;
00320 }
00321
00322 UNIV_INTERN read_replication_state_st *replication_read_init(void)
00323 {
00324 read_replication_state_st *state= new read_replication_state_st;
00325
00326 mutex_enter(&(dict_sys->mutex));
00327
00328 mtr_start(&state->mtr);
00329 state->sys_tables= dict_table_get_low("SYS_REPLICATION_LOG");
00330 state->sys_index= UT_LIST_GET_FIRST(state->sys_tables->indexes);
00331
00332 mutex_exit(&(dict_sys->mutex));
00333
00334 btr_pcur_open_at_index_side(TRUE, state->sys_index, BTR_SEARCH_LEAF, &state->pcur, TRUE, &state->mtr);
00335
00336 return state;
00337 }
00338
00339 UNIV_INTERN void replication_read_deinit(struct read_replication_state_st *state)
00340 {
00341 btr_pcur_close(&state->pcur);
00342 mtr_commit(&state->mtr);
00343 delete state;
00344 }
00345
00346 UNIV_INTERN struct read_replication_return_st replication_read_next(struct read_replication_state_st *state)
00347 {
00348 struct read_replication_return_st ret;
00349 const rec_t *rec;
00350
00351 btr_pcur_move_to_next_user_rec(&state->pcur, &state->mtr);
00352
00353 rec= btr_pcur_get_rec(&state->pcur);
00354
00355 while (btr_pcur_is_on_user_rec(&state->pcur))
00356 {
00357 const byte* field;
00358 ulint len;
00359
00360
00361 if (rec_get_deleted_flag(rec, 0))
00362 continue;
00363
00364
00365 field = rec_get_nth_field_old(rec, 0, &len);
00366 byte idbyte[8];
00367 convert_to_mysql_format(idbyte, field, 8);
00368 ret.id= *(uint64_t *)idbyte;
00369
00370
00371 field = rec_get_nth_field_old(rec, 1, &len);
00372 byte segbyte[4];
00373 convert_to_mysql_format(segbyte, field, 4);
00374 ret.seg_id= *(uint32_t *)segbyte;
00375
00376 field = rec_get_nth_field_old(rec, 4, &len);
00377 byte commitbyte[8];
00378 convert_to_mysql_format(commitbyte, field, 8);
00379 ret.commit_id= *(uint64_t *)commitbyte;
00380
00381 field = rec_get_nth_field_old(rec, 5, &len);
00382 byte timestampbyte[8];
00383 convert_to_mysql_format(timestampbyte, field, 8);
00384 ret.end_timestamp= *(uint64_t *)timestampbyte;
00385
00386 field = rec_get_nth_field_old(rec, 6, &len);
00387 ret.originating_server_uuid= (char *)field;
00388
00389 field = rec_get_nth_field_old(rec, 7, &len);
00390 byte originatingcommitbyte[8];
00391 convert_to_mysql_format(originatingcommitbyte, field, 8);
00392 ret.originating_commit_id= *(uint64_t *)originatingcommitbyte;
00393
00394
00395 field = rec_get_nth_field_old(rec, 9, &len);
00396 ret.message= (char *)field;
00397 ret.message_length= len;
00398
00399
00400
00401 btr_pcur_store_position(&state->pcur, &state->mtr);
00402 mtr_commit(&state->mtr);
00403
00404 mtr_start(&state->mtr);
00405
00406 btr_pcur_restore_position(BTR_SEARCH_LEAF, &state->pcur, &state->mtr);
00407
00408 return ret;
00409 }
00410
00411
00412 memset(&ret, 0, sizeof(ret));
00413
00414 return ret;
00415 }
00416
00417 UNIV_INTERN void convert_to_mysql_format(byte* out, const byte* in, int len)
00418 {
00419 byte *ptr;
00420 ptr = out + len;
00421
00422 for (;;) {
00423 ptr--;
00424 *ptr = *in;
00425 if (ptr == out) {
00426 break;
00427 }
00428 in++;
00429 }
00430
00431 out[len - 1] = (byte) (out[len - 1] ^ 128);
00432
00433 }