1
/* Copyright (C) 2000-2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24
Abort logging when we get an error in reading or writing log files
27
#include <drizzled/server_includes.h>
28
#include <libdrizzle/libdrizzle.h>
29
#include <drizzled/replicator.h>
30
#include <mysys/hash.h>
32
#include <mysys/my_dir.h>
35
#include <drizzled/plugin.h>
36
#include <drizzled/error.h>
37
#include <drizzled/errmsg_print.h>
38
#include <drizzled/gettext.h>
39
#include <drizzled/data_home.h>
40
#include <drizzled/session.h>
41
#include <drizzled/handler.h>
43
/* max size of the log message */
44
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
46
static int binlog_init(void *p);
47
static int binlog_close_connection(handlerton *hton, Session *session);
48
static int binlog_savepoint_set(handlerton *hton, Session *session, void *sv);
49
static int binlog_savepoint_rollback(handlerton *hton, Session *session, void *sv);
50
static int binlog_commit(handlerton *hton, Session *session, bool all);
51
static int binlog_rollback(handlerton *hton, Session *session, bool all);
52
static int binlog_prepare(handlerton *hton, Session *session, bool all);
55
handlerton *binlog_hton;
59
Save position of binary log transaction cache.
62
binlog_trans_log_savepos()
64
session The thread to take the binlog data from
65
pos Pointer to variable where the position will be stored
69
Save the current position in the binary log transaction cache into
70
the variable pointed to by 'pos'
74
binlog_trans_log_savepos(Session *, my_off_t *pos)
83
this function is mostly a placeholder.
84
conceptually, binlog initialization (now mostly done in DRIZZLE_BIN_LOG::open)
88
int binlog_init(void *p)
90
binlog_hton= (handlerton *)p;
91
binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO;
92
binlog_hton->savepoint_offset= sizeof(my_off_t);
93
binlog_hton->close_connection= binlog_close_connection;
94
binlog_hton->savepoint_set= binlog_savepoint_set;
95
binlog_hton->savepoint_rollback= binlog_savepoint_rollback;
96
binlog_hton->commit= binlog_commit;
97
binlog_hton->rollback= binlog_rollback;
98
binlog_hton->prepare= binlog_prepare;
99
binlog_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN;
104
static int binlog_close_connection(handlerton *, Session *)
110
static int binlog_prepare(handlerton *, Session *session, bool)
114
just pretend we can do 2pc, so that MySQL won't
116
real work will be done in DRIZZLE_BIN_LOG::log_xid()
119
(void)replicator_prepare(session);
125
This function is called once after each statement.
127
It has the responsibility to flush the transaction cache to the
128
binlog file on commits.
130
@param hton The binlog handlerton.
131
@param session The client thread that executes the transaction.
132
@param all This is @c true if this is a real transaction commit, and
135
@see handlerton::commit
137
static int binlog_commit(handlerton *, Session *session, bool all)
140
Decision table for committing a transaction. The top part, the
141
*conditions* represent different cases that can occur, and hte
142
bottom part, the *actions*, represent what should be done in that
145
Real transaction 'all' was true
147
Statement in cache There were at least one statement in the
150
In transaction We are inside a transaction
152
Stmt modified non-trans The statement being committed modified a
153
non-transactional table
155
All modified non-trans Some statement before this one in the
156
transaction modified a non-transactional
160
============================= = = = = = = = = = = = = = = = =
161
Real transaction N N N N N N N N N N N N N N N N
162
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
163
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
164
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
165
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
167
Action: (C)ommit/(A)ccumulate C C - C A C - C - - - - A A - A
168
============================= = = = = = = = = = = = = = = = =
171
============================= = = = = = = = = = = = = = = = =
172
Real transaction Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
173
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
174
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
175
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
176
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
178
(C)ommit/(A)ccumulate/(-) - - - - C C - C - - - - C C - C
179
============================= = = = = = = = = = = = = = = = =
181
In other words, we commit the transaction if and only if both of
182
the following are true:
183
- We are not in a transaction and committing a statement
185
- We are in a transaction and one (or more) of the following are
188
- A full transaction is committed
192
- A non-transactional statement is committed and there is
195
Otherwise, we accumulate the statement
198
if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
200
return replicator_end_transaction(session, all, true);
207
This function is called when a transaction involving a transactional
208
table is rolled back.
210
It has the responsibility to flush the transaction cache to the
211
binlog file. However, if the transaction does not involve
212
non-transactional tables, nothing needs to be logged.
214
@param hton The binlog handlerton.
215
@param session The client thread that executes the transaction.
216
@param all This is @c true if this is a real transaction rollback, and
219
@see handlerton::rollback
221
static int binlog_rollback(handlerton *, Session *session, bool all)
225
/* TODO: Fix return type */
226
(void)replicator_end_transaction(session, all, false);
233
How do we handle this (unlikely but legal) case:
235
[transaction] + [update to non-trans table] + [rollback to savepoint] ?
237
The problem occurs when a savepoint is before the update to the
238
non-transactional table. Then when there's a rollback to the savepoint, if we
239
simply truncate the binlog cache, we lose the part of the binlog cache where
240
the update is. If we want to not lose it, we need to write the SAVEPOINT
241
command and the ROLLBACK TO SAVEPOINT command to the binlog cache. The latter
242
is easy: it's just write at the end of the binlog cache, but the former
243
should be *inserted* to the place where the user called SAVEPOINT. The
244
solution is that when the user calls SAVEPOINT, we write it to the binlog
245
cache (so no need to later insert it). As transactions are never intermixed
246
in the binary log (i.e. they are serialized), we won't have conflicts with
247
savepoint names when using mysqlbinlog or in the slave SQL thread.
248
Then when ROLLBACK TO SAVEPOINT is called, if we updated some
249
non-transactional table, we don't truncate the binlog cache but instead write
250
ROLLBACK TO SAVEPOINT to it; otherwise we truncate the binlog cache (which
251
will chop the SAVEPOINT command from the binlog cache, which is good as in
252
that case there is no need to have it in the binlog).
255
static int binlog_savepoint_set(handlerton *, Session *session, void *sv)
258
binlog_trans_log_savepos(session, (my_off_t*) sv);
259
/* Write it to the binary log */
261
error= replicator_statement(session, session->query, session->query_length);
266
static int binlog_savepoint_rollback(handlerton *, Session *session, void *)
270
error= replicator_statement(session, session->query, session->query_length);
275
mysql_declare_plugin(binlog)
277
DRIZZLE_STORAGE_ENGINE_PLUGIN,
281
"This is a pseudo storage engine to represent the binlog in a transaction",
283
binlog_init, /* Plugin Init */
284
NULL, /* Plugin Deinit */
285
NULL, /* status variables */
286
NULL, /* system variables */
287
NULL /* config options */
289
mysql_declare_plugin_end;