1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
1 |
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
4 |
* Copyright (C) 2010 Brian Aker
|
|
5 |
*
|
|
6 |
* This program is free software; you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation; either version 2 of the License, or
|
|
9 |
* (at your option) any later version.
|
|
10 |
*
|
|
11 |
* This program is distributed in the hope that it will be useful,
|
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
* GNU General Public License for more details.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
17 |
* along with this program; if not, write to the Free Software
|
|
18 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
19 |
*/
|
|
20 |
||
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
21 |
#include "config.h" |
22 |
||
23 |
#include "read_replication.h" |
|
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
24 |
#include "create_replication.h" |
25 |
||
26 |
#ifdef UNIV_NONINL
|
|
27 |
#include "dict0crea.ic" |
|
28 |
#endif
|
|
29 |
||
30 |
#include "btr0pcur.h" |
|
31 |
#include "btr0btr.h" |
|
32 |
#include "page0page.h" |
|
33 |
#include "mach0data.h" |
|
34 |
#include "dict0boot.h" |
|
35 |
#include "dict0dict.h" |
|
36 |
#include "que0que.h" |
|
37 |
#include "row0ins.h" |
|
38 |
#include "row0mysql.h" |
|
39 |
#include "pars0pars.h" |
|
40 |
#include "trx0roll.h" |
|
41 |
#include "usr0sess.h" |
|
42 |
#include "ut0vec.h" |
|
1802.18.1
by Stewart Smith
migrate innobase insert_replication_mesasge to instead use the INNOBASE API directly instead of through the InnoDB parser. This means it should be reentrant. We construct our own prebuilt structure, set the row data and write the row as part of the transaction (as before). We currently do *NOT* handle any row lock conflicts. i.e. if you ever write code that can block the insert into the table, this will explode horribly. You also probably want to take note that the create table statement for the innobase parser only creates 4 byte integers, so i've had to just take the low 32bits of txn id. |
43 |
#include "row0merge.h" |
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
44 |
|
45 |
UNIV_INTERN ulint dict_create_sys_replication_log(void) |
|
46 |
{
|
|
47 |
dict_table_t* table1; |
|
48 |
ulint error; |
|
49 |
trx_t *trx; |
|
50 |
||
51 |
mutex_enter(&(dict_sys->mutex)); |
|
52 |
||
53 |
table1 = dict_table_get_low("SYS_REPLICATION_LOG"); |
|
54 |
||
55 |
if (table1) |
|
56 |
{
|
|
57 |
mutex_exit(&(dict_sys->mutex)); |
|
58 |
||
59 |
return(DB_SUCCESS); |
|
60 |
}
|
|
61 |
||
62 |
mutex_exit(&(dict_sys->mutex)); |
|
63 |
||
64 |
trx= trx_allocate_for_mysql(); |
|
65 |
||
66 |
trx->op_info= "creating replication sys table"; |
|
67 |
||
68 |
row_mysql_lock_data_dictionary(trx); |
|
69 |
||
70 |
pars_info_t *info= pars_info_create(); |
|
1802.17.8
by Joseph Daly
fix up transaction log column |
71 |
|
72 |
||
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
73 |
error = que_eval_sql(info, |
74 |
"PROCEDURE CREATE_SYS_REPLICATION_LOG_PROC () IS\n" |
|
75 |
"BEGIN\n" |
|
1802.17.8
by Joseph Daly
fix up transaction log column |
76 |
"CREATE TABLE SYS_REPLICATION_LOG(ID BINARY(8), MESSAGE BLOB);\n" |
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
77 |
"CREATE UNIQUE CLUSTERED INDEX ID_IND ON SYS_REPLICATION_LOG (ID);\n" |
78 |
"END;\n" |
|
79 |
, FALSE, trx); |
|
80 |
||
1802.17.8
by Joseph Daly
fix up transaction log column |
81 |
|
82 |
||
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
83 |
if (error != DB_SUCCESS) |
84 |
{
|
|
85 |
fprintf(stderr, "InnoDB: error %lu in creation.\n", (ulong) error); |
|
86 |
||
87 |
ut_a(error == DB_OUT_OF_FILE_SPACE || error == DB_TOO_MANY_CONCURRENT_TRXS); |
|
88 |
||
89 |
fprintf(stderr, |
|
90 |
"InnoDB: creation failed\n" |
|
91 |
"InnoDB: tablespace is full\n" |
|
92 |
"InnoDB: dropping incompletely created SYS_REPLICATION_LOG table.\n"); |
|
93 |
||
94 |
row_drop_table_for_mysql("SYS_REPLICATION_LOG", trx, TRUE); |
|
95 |
||
96 |
error = DB_MUST_GET_MORE_FILE_SPACE; |
|
97 |
}
|
|
98 |
||
99 |
trx_commit_for_mysql(trx); |
|
100 |
||
101 |
row_mysql_unlock_data_dictionary(trx); |
|
102 |
||
103 |
trx_free_for_mysql(trx); |
|
104 |
||
105 |
return(error); |
|
106 |
}
|
|
107 |
||
1802.18.1
by Stewart Smith
migrate innobase insert_replication_mesasge to instead use the INNOBASE API directly instead of through the InnoDB parser. This means it should be reentrant. We construct our own prebuilt structure, set the row data and write the row as part of the transaction (as before). We currently do *NOT* handle any row lock conflicts. i.e. if you ever write code that can block the insert into the table, this will explode horribly. You also probably want to take note that the create table statement for the innobase parser only creates 4 byte integers, so i've had to just take the low 32bits of txn id. |
108 |
extern dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t* prebuilt); |
109 |
||
1802.17.11
by Joseph Daly
use trx_id from message |
110 |
ulint insert_replication_message(const char *message, size_t size, |
111 |
trx_t *trx, uint64_t trx_id) |
|
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
112 |
{
|
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
113 |
ulint error; |
1802.18.1
by Stewart Smith
migrate innobase insert_replication_mesasge to instead use the INNOBASE API directly instead of through the InnoDB parser. This means it should be reentrant. We construct our own prebuilt structure, set the row data and write the row as part of the transaction (as before). We currently do *NOT* handle any row lock conflicts. i.e. if you ever write code that can block the insert into the table, this will explode horribly. You also probably want to take note that the create table statement for the innobase parser only creates 4 byte integers, so i've had to just take the low 32bits of txn id. |
114 |
row_prebuilt_t* prebuilt; /* For reading rows */ |
115 |
dict_table_t *table; |
|
116 |
que_thr_t* thr; |
|
117 |
||
118 |
table = dict_table_get("SYS_REPLICATION_LOG",TRUE); |
|
119 |
||
120 |
prebuilt = row_create_prebuilt(table); |
|
121 |
||
1802.17.14
by Joseph Daly
fix a problem where a create table A, and insert into A were having a trx number that was lower for the insert then the create. |
122 |
if (prebuilt->trx != trx) |
123 |
{
|
|
124 |
row_update_prebuilt_trx(prebuilt, trx); |
|
125 |
}
|
|
126 |
||
127 |
/* DDL operations create table/drop table call
|
|
128 |
* innobase_commit_low() which will commit the trx
|
|
129 |
* that leaves the operation of committing to the
|
|
130 |
* log in a new trx. If that is the case we need
|
|
131 |
* to keep track and commit the trx later in this
|
|
132 |
* function.
|
|
133 |
*/
|
|
134 |
bool is_started= true; |
|
135 |
if (trx->conc_state == TRX_NOT_STARTED) |
|
136 |
{
|
|
137 |
is_started= false; |
|
138 |
}
|
|
139 |
||
1802.18.1
by Stewart Smith
migrate innobase insert_replication_mesasge to instead use the INNOBASE API directly instead of through the InnoDB parser. This means it should be reentrant. We construct our own prebuilt structure, set the row data and write the row as part of the transaction (as before). We currently do *NOT* handle any row lock conflicts. i.e. if you ever write code that can block the insert into the table, this will explode horribly. You also probably want to take note that the create table statement for the innobase parser only creates 4 byte integers, so i've had to just take the low 32bits of txn id. |
140 |
dtuple_t* dtuple= row_get_prebuilt_insert_row(prebuilt); |
141 |
dfield_t *dfield; |
|
142 |
dfield = dtuple_get_nth_field(dtuple, 0); |
|
1802.17.8
by Joseph Daly
fix up transaction log column |
143 |
|
144 |
dfield_set_data(dfield, &trx_id, 8); |
|
145 |
||
1802.18.1
by Stewart Smith
migrate innobase insert_replication_mesasge to instead use the INNOBASE API directly instead of through the InnoDB parser. This means it should be reentrant. We construct our own prebuilt structure, set the row data and write the row as part of the transaction (as before). We currently do *NOT* handle any row lock conflicts. i.e. if you ever write code that can block the insert into the table, this will explode horribly. You also probably want to take note that the create table statement for the innobase parser only creates 4 byte integers, so i've had to just take the low 32bits of txn id. |
146 |
dfield = dtuple_get_nth_field(dtuple, 1); |
147 |
dfield_set_data(dfield, message, size); |
|
148 |
||
149 |
ins_node_t* node = prebuilt->ins_node; |
|
150 |
||
151 |
thr = que_fork_get_first_thr(prebuilt->ins_graph); |
|
152 |
||
153 |
if (prebuilt->sql_stat_start) { |
|
154 |
node->state = INS_NODE_SET_IX_LOCK; |
|
155 |
prebuilt->sql_stat_start = FALSE; |
|
156 |
} else { |
|
157 |
node->state = INS_NODE_ALLOC_ROW_ID; |
|
158 |
}
|
|
159 |
||
160 |
que_thr_move_to_run_state_for_mysql(thr, trx); |
|
161 |
||
162 |
//run_again:
|
|
163 |
thr->run_node = node; |
|
164 |
thr->prev_node = node; |
|
165 |
||
166 |
row_ins_step(thr); |
|
167 |
||
168 |
error = trx->error_state; |
|
169 |
||
170 |
que_thr_stop_for_mysql_no_error(thr, trx); |
|
171 |
row_prebuilt_free(prebuilt, FALSE); |
|
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
172 |
|
1802.17.14
by Joseph Daly
fix a problem where a create table A, and insert into A were having a trx number that was lower for the insert then the create. |
173 |
if (! is_started) |
174 |
{
|
|
175 |
trx_commit_for_mysql(trx); |
|
176 |
}
|
|
177 |
||
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
178 |
return error; |
179 |
}
|
|
180 |
||
2023.3.7
by Monty Taylor
More casting. |
181 |
UNIV_INTERN read_replication_state_st *replication_read_init(void) |
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
182 |
{
|
2023.3.7
by Monty Taylor
More casting. |
183 |
read_replication_state_st *state= new read_replication_state_st; |
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
184 |
|
185 |
mutex_enter(&(dict_sys->mutex)); |
|
186 |
||
187 |
mtr_start(&state->mtr); |
|
188 |
state->sys_tables= dict_table_get_low("SYS_REPLICATION_LOG"); |
|
189 |
state->sys_index= UT_LIST_GET_FIRST(state->sys_tables->indexes); |
|
190 |
||
191 |
mutex_exit(&(dict_sys->mutex)); |
|
192 |
||
193 |
btr_pcur_open_at_index_side(TRUE, state->sys_index, BTR_SEARCH_LEAF, &state->pcur, TRUE, &state->mtr); |
|
194 |
||
195 |
return state; |
|
196 |
}
|
|
197 |
||
198 |
UNIV_INTERN void replication_read_deinit(struct read_replication_state_st *state) |
|
199 |
{
|
|
200 |
btr_pcur_close(&state->pcur); |
|
201 |
mtr_commit(&state->mtr); |
|
2023.3.7
by Monty Taylor
More casting. |
202 |
delete state; |
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
203 |
}
|
204 |
||
205 |
UNIV_INTERN struct read_replication_return_st replication_read_next(struct read_replication_state_st *state) |
|
206 |
{
|
|
207 |
struct read_replication_return_st ret; |
|
208 |
const rec_t *rec; |
|
209 |
||
210 |
btr_pcur_move_to_next_user_rec(&state->pcur, &state->mtr); |
|
211 |
||
212 |
rec= btr_pcur_get_rec(&state->pcur); |
|
213 |
||
214 |
while (btr_pcur_is_on_user_rec(&state->pcur)) |
|
215 |
{
|
|
216 |
const byte* field; |
|
217 |
ulint len; |
|
218 |
||
219 |
// Is the row deleted? If so go fetch the next
|
|
220 |
if (rec_get_deleted_flag(rec, 0)) |
|
221 |
continue; |
|
222 |
||
223 |
// Store transaction id
|
|
224 |
field = rec_get_nth_field_old(rec, 0, &len); |
|
1802.17.8
by Joseph Daly
fix up transaction log column |
225 |
ret.id= *(uint64_t *)field; |
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
226 |
|
227 |
// Handler message
|
|
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
228 |
field = rec_get_nth_field_old(rec, 3, &len); |
1802.17.2
by Brian Aker
Clean up some of the worst of the memory abuses in the plugin. |
229 |
ret.message= (char *)field; |
230 |
ret.message_length= len; |
|
231 |
||
232 |
// @todo double check that "field" will continue to be value past this
|
|
233 |
// point.
|
|
234 |
btr_pcur_store_position(&state->pcur, &state->mtr); |
|
235 |
mtr_commit(&state->mtr); |
|
236 |
||
237 |
mtr_start(&state->mtr); |
|
238 |
||
239 |
btr_pcur_restore_position(BTR_SEARCH_LEAF, &state->pcur, &state->mtr); |
|
240 |
||
241 |
return ret; |
|
242 |
}
|
|
243 |
||
244 |
/* end of index */
|
|
245 |
memset(&ret, 0, sizeof(ret)); |
|
246 |
||
247 |
return ret; |
|
1802.17.1
by Brian Aker
First pass over replicating to the guts of Innodb. |
248 |
}
|