~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/log.cc

Small fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2003 MySQL AB
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
 
17
 
/**
18
 
  @file
19
 
 
20
 
  @brief
21
 
  logging of commands
22
 
 
23
 
  @todo
24
 
    Abort logging when we get an error in reading or writing log files
25
 
*/
26
 
 
27
 
#include <drizzled/server_includes.h>
28
 
#include <libdrizzle/libdrizzle.h>
29
 
#include <drizzled/replicator.h>
30
 
#include <mysys/hash.h>
31
 
 
32
 
#include <mysys/my_dir.h>
33
 
#include <stdarg.h>
34
 
 
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>
42
 
 
43
 
/* max size of the log message */
44
 
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
45
 
 
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);
53
 
 
54
 
 
55
 
handlerton *binlog_hton;
56
 
 
57
 
 
58
 
 /*
59
 
  Save position of binary log transaction cache.
60
 
 
61
 
  SYNPOSIS
62
 
    binlog_trans_log_savepos()
63
 
 
64
 
    session      The thread to take the binlog data from
65
 
    pos      Pointer to variable where the position will be stored
66
 
 
67
 
  DESCRIPTION
68
 
 
69
 
    Save the current position in the binary log transaction cache into
70
 
    the variable pointed to by 'pos'
71
 
 */
72
 
 
73
 
static void
74
 
binlog_trans_log_savepos(Session *, my_off_t *pos)
75
 
{
76
 
  assert(pos != NULL);
77
 
 
78
 
  return;
79
 
}
80
 
 
81
 
 
82
 
/*
83
 
  this function is mostly a placeholder.
84
 
  conceptually, binlog initialization (now mostly done in DRIZZLE_BIN_LOG::open)
85
 
  should be moved here.
86
 
*/
87
 
 
88
 
int binlog_init(void *p)
89
 
{
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;
100
 
 
101
 
  return 0;
102
 
}
103
 
 
104
 
static int binlog_close_connection(handlerton *, Session *)
105
 
{
106
 
 
107
 
  return 0;
108
 
}
109
 
 
110
 
static int binlog_prepare(handlerton *, Session *session, bool)
111
 
{
112
 
  /*
113
 
    do nothing.
114
 
    just pretend we can do 2pc, so that MySQL won't
115
 
    switch to 1pc.
116
 
    real work will be done in DRIZZLE_BIN_LOG::log_xid()
117
 
  */
118
 
 
119
 
  (void)replicator_prepare(session);
120
 
 
121
 
  return 0;
122
 
}
123
 
 
124
 
/**
125
 
  This function is called once after each statement.
126
 
 
127
 
  It has the responsibility to flush the transaction cache to the
128
 
  binlog file on commits.
129
 
 
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
133
 
               @false otherwise.
134
 
 
135
 
  @see handlerton::commit
136
 
*/
137
 
static int binlog_commit(handlerton *, Session *session, bool all)
138
 
{
139
 
  /*
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
143
 
    particular case.
144
 
 
145
 
    Real transaction        'all' was true
146
 
 
147
 
    Statement in cache      There were at least one statement in the
148
 
                            transaction cache
149
 
 
150
 
    In transaction          We are inside a transaction
151
 
 
152
 
    Stmt modified non-trans The statement being committed modified a
153
 
                            non-transactional table
154
 
 
155
 
    All modified non-trans  Some statement before this one in the
156
 
                            transaction modified a non-transactional
157
 
                            table
158
 
 
159
 
 
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
166
 
 
167
 
    Action: (C)ommit/(A)ccumulate  C C - C A C - C - - - - A A - A
168
 
    =============================  = = = = = = = = = = = = = = = =
169
 
 
170
 
 
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
177
 
 
178
 
    (C)ommit/(A)ccumulate/(-)      - - - - C C - C - - - - C C - C
179
 
    =============================  = = = = = = = = = = = = = = = =
180
 
 
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
184
 
 
185
 
     - We are in a transaction and one (or more) of the following are
186
 
       true:
187
 
 
188
 
       - A full transaction is committed
189
 
 
190
 
         OR
191
 
 
192
 
       - A non-transactional statement is committed and there is
193
 
         no statement cached
194
 
 
195
 
    Otherwise, we accumulate the statement
196
 
  */
197
 
 
198
 
  if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) 
199
 
  {
200
 
    return replicator_end_transaction(session, all, true);
201
 
  }
202
 
 
203
 
  return(0);
204
 
}
205
 
 
206
 
/**
207
 
  This function is called when a transaction involving a transactional
208
 
  table is rolled back.
209
 
 
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.
213
 
 
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
217
 
               @false otherwise.
218
 
 
219
 
  @see handlerton::rollback
220
 
*/
221
 
static int binlog_rollback(handlerton *, Session *session, bool all)
222
 
{
223
 
  int error=0;
224
 
 
225
 
  /* TODO: Fix return type */
226
 
  (void)replicator_end_transaction(session, all, false);
227
 
 
228
 
  return(error);
229
 
}
230
 
 
231
 
/**
232
 
  @note
233
 
  How do we handle this (unlikely but legal) case:
234
 
  @verbatim
235
 
    [transaction] + [update to non-trans table] + [rollback to savepoint] ?
236
 
  @endverbatim
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).
253
 
*/
254
 
 
255
 
static int binlog_savepoint_set(handlerton *, Session *session, void *sv)
256
 
{
257
 
  bool error;
258
 
  binlog_trans_log_savepos(session, (my_off_t*) sv);
259
 
  /* Write it to the binary log */
260
 
 
261
 
  error= replicator_statement(session, session->query, session->query_length);
262
 
 
263
 
  return(error);
264
 
}
265
 
 
266
 
static int binlog_savepoint_rollback(handlerton *, Session *session, void *)
267
 
{
268
 
  bool error;
269
 
 
270
 
  error= replicator_statement(session, session->query, session->query_length);
271
 
 
272
 
  return error;
273
 
}
274
 
 
275
 
mysql_declare_plugin(binlog)
276
 
{
277
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
278
 
  "binlog",
279
 
  "1.0",
280
 
  "MySQL AB",
281
 
  "This is a pseudo storage engine to represent the binlog in a transaction",
282
 
  PLUGIN_LICENSE_GPL,
283
 
  binlog_init, /* Plugin Init */
284
 
  NULL, /* Plugin Deinit */
285
 
  NULL,                       /* status variables                */
286
 
  NULL,                       /* system variables                */
287
 
  NULL                        /* config options                  */
288
 
}
289
 
mysql_declare_plugin_end;