~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
27
#include <drizzled/server_includes.h>
575.4.6 by Monty Taylor
Removed my_getwd.
28
#include <drizzled/replication/replication.h>
614 by Brian Aker
Remove filtering (wrong layer, belongs in plugin).
29
#include <libdrizzle/libdrizzle.h>
30
#include <mysys/hash.h>
575.4.6 by Monty Taylor
Removed my_getwd.
31
#include <drizzled/replication/rli.h>
1 by brian
clean slate
32
212.5.38 by Monty Taylor
Moved my_dir (and removed references to a lot of places)
33
#include <mysys/my_dir.h>
1 by brian
clean slate
34
#include <stdarg.h>
35
212.5.10 by Monty Taylor
Moved drizzle/plugin*h to drizzled
36
#include <drizzled/plugin.h>
549 by Monty Taylor
Took gettext.h out of header files.
37
#include <drizzled/error.h>
538 by Monty Taylor
Moved gettext.h into drizzled in anticipation of the new client lib.
38
#include <drizzled/gettext.h>
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
39
#include <drizzled/data_home.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
40
#include <drizzled/log_event.h>
572.1.4 by Monty Taylor
Removed a bunch of unusued tests and defines from autoconf.
41
602.1.1 by Mark Atwood
hook up the errmsg plugin to the sql_print_error function
42
#include <drizzled/errmsg.h>
43
1 by brian
clean slate
44
/* max size of the log message */
45
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
46
47
LOGGER logger;
48
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
49
DRIZZLE_BIN_LOG drizzle_bin_log;
1 by brian
clean slate
50
ulong sync_binlog_counter= 0;
51
52
static bool test_if_number(const char *str,
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
53
                           long *res, bool allow_wildcards);
1 by brian
clean slate
54
static int binlog_init(void *p);
520.1.22 by Brian Aker
Second pass of thd cleanup
55
static int binlog_close_connection(handlerton *hton, Session *session);
56
static int binlog_savepoint_set(handlerton *hton, Session *session, void *sv);
57
static int binlog_savepoint_rollback(handlerton *hton, Session *session, void *sv);
58
static int binlog_commit(handlerton *hton, Session *session, bool all);
59
static int binlog_rollback(handlerton *hton, Session *session, bool all);
60
static int binlog_prepare(handlerton *hton, Session *session, bool all);
1 by brian
clean slate
61
62
63
sql_print_message_func sql_print_message_handlers[3] =
64
{
65
  sql_print_information,
66
  sql_print_warning,
67
  sql_print_error
68
};
69
70
71
char *make_default_log_name(char *buff,const char* log_ext)
72
{
73
  strmake(buff, pidfile_name, FN_REFLEN-5);
575.4.1 by ysano
Rename mysql to drizzle.
74
  return fn_format(buff, buff, drizzle_data_home, log_ext,
1 by brian
clean slate
75
                   MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
76
}
77
78
/*
79
  Helper class to hold a mutex for the duration of the
80
  block.
81
82
  Eliminates the need for explicit unlocking of mutexes on, e.g.,
83
  error returns.  On passing a null pointer, the sentry will not do
84
  anything.
85
 */
86
class Mutex_sentry
87
{
88
public:
89
  Mutex_sentry(pthread_mutex_t *mutex)
90
    : m_mutex(mutex)
91
  {
92
    if (m_mutex)
93
      pthread_mutex_lock(mutex);
94
  }
95
96
  ~Mutex_sentry()
97
  {
98
    if (m_mutex)
99
      pthread_mutex_unlock(m_mutex);
100
    m_mutex= 0;
101
  }
102
103
private:
104
  pthread_mutex_t *m_mutex;
105
106
  // It's not allowed to copy this object in any way
107
  Mutex_sentry(Mutex_sentry const&);
108
  void operator=(Mutex_sentry const&);
109
};
110
111
/*
112
  Helper class to store binary log transaction data.
113
*/
114
class binlog_trx_data {
115
public:
116
  binlog_trx_data()
117
    : at_least_one_stmt(0), m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF)
118
  {
119
    trans_log.end_of_file= max_binlog_cache_size;
120
  }
121
122
  ~binlog_trx_data()
123
  {
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
124
    assert(pending() == NULL);
1 by brian
clean slate
125
    close_cached_file(&trans_log);
126
  }
127
128
  my_off_t position() const {
129
    return my_b_tell(&trans_log);
130
  }
131
132
  bool empty() const
133
  {
134
    return pending() == NULL && my_b_tell(&trans_log) == 0;
135
  }
136
137
  /*
138
    Truncate the transaction cache to a certain position. This
139
    includes deleting the pending event.
140
   */
141
  void truncate(my_off_t pos)
142
  {
143
    delete pending();
144
    set_pending(0);
145
    reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
146
    if (pos < before_stmt_pos)
147
      before_stmt_pos= MY_OFF_T_UNDEF;
148
149
    /*
150
      The only valid positions that can be truncated to are at the
151
      beginning of a statement. We are relying on this fact to be able
152
      to set the at_least_one_stmt flag correctly. In other word, if
153
      we are truncating to the beginning of the transaction cache,
154
      there will be no statements in the cache, otherwhise, we will
155
      have at least one statement in the transaction cache.
156
     */
157
    at_least_one_stmt= (pos > 0);
158
  }
159
160
  /*
161
    Reset the entire contents of the transaction cache, emptying it
162
    completely.
163
   */
164
  void reset() {
165
    if (!empty())
166
      truncate(0);
167
    before_stmt_pos= MY_OFF_T_UNDEF;
168
    trans_log.end_of_file= max_binlog_cache_size;
169
  }
170
171
  Rows_log_event *pending() const
172
  {
173
    return m_pending;
174
  }
175
176
  void set_pending(Rows_log_event *const pending)
177
  {
178
    m_pending= pending;
179
  }
180
181
  IO_CACHE trans_log;                         // The transaction cache
182
183
  /**
184
    Boolean that is true if there is at least one statement in the
185
    transaction cache.
186
  */
187
  bool at_least_one_stmt;
188
189
private:
190
  /*
191
    Pending binrows event. This event is the event where the rows are
192
    currently written.
193
   */
194
  Rows_log_event *m_pending;
195
196
public:
197
  /*
198
    Binlog position before the start of the current statement.
199
  */
200
  my_off_t before_stmt_pos;
201
};
202
203
handlerton *binlog_hton;
204
205
206
/*
207
  Log error with all enabled log event handlers
208
209
  SYNOPSIS
210
    error_log_print()
211
212
    level             The level of the error significance: NOTE,
213
                      WARNING or ERROR.
214
    format            format string for the error message
215
    args              list of arguments for the format string
216
217
  RETURN
218
    FALSE - OK
219
    TRUE - error occured
220
*/
221
222
bool LOGGER::error_log_print(enum loglevel level, const char *format,
223
                             va_list args)
224
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
225
  bool error= false;
1 by brian
clean slate
226
  Log_event_handler **current_handler;
227
228
  /* currently we don't need locking here as there is no error_log table */
229
  for (current_handler= error_log_handler_list ; *current_handler ;)
230
    error= (*current_handler++)->log_error(level, format, args) || error;
231
232
  return error;
233
}
234
235
236
void LOGGER::cleanup_base()
237
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
238
  assert(inited == 1);
1 by brian
clean slate
239
  rwlock_destroy(&LOCK_logger);
240
}
241
242
243
void LOGGER::cleanup_end()
244
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
245
  assert(inited == 1);
1 by brian
clean slate
246
}
247
248
249
/**
250
  Perform basic log initialization: create file-based log handler and
251
  init error log.
252
*/
253
void LOGGER::init_base()
254
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
255
  assert(inited == 0);
1 by brian
clean slate
256
  inited= 1;
257
258
  /* by default we use traditional error log */
259
  init_error_log(LOG_FILE);
260
261
  my_rwlock_init(&LOCK_logger, NULL);
262
}
263
264
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
265
bool LOGGER::flush_logs(Session *)
1 by brian
clean slate
266
{
267
  int rc= 0;
268
269
  /*
270
    Now we lock logger, as nobody should be able to use logging routines while
271
    log tables are closed
272
  */
273
  logger.lock_exclusive();
274
275
  /* end of log flush */
276
  logger.unlock();
277
  return rc;
278
}
279
482 by Brian Aker
Remove uint.
280
void LOGGER::init_error_log(uint32_t error_log_printer)
1 by brian
clean slate
281
{
282
  if (error_log_printer & LOG_NONE)
283
  {
284
    error_log_handler_list[0]= 0;
285
    return;
286
  }
287
438.1.1 by Brian Aker
First pass of removing historical logging.
288
}
1 by brian
clean slate
289
482 by Brian Aker
Remove uint.
290
int LOGGER::set_handlers(uint32_t error_log_printer)
1 by brian
clean slate
291
{
292
  /* error log table is not supported yet */
293
  lock_exclusive();
294
295
  init_error_log(error_log_printer);
296
  unlock();
297
298
  return 0;
299
}
300
301
302
 /*
303
  Save position of binary log transaction cache.
304
305
  SYNPOSIS
306
    binlog_trans_log_savepos()
307
520.1.22 by Brian Aker
Second pass of thd cleanup
308
    session      The thread to take the binlog data from
1 by brian
clean slate
309
    pos      Pointer to variable where the position will be stored
310
311
  DESCRIPTION
312
313
    Save the current position in the binary log transaction cache into
314
    the variable pointed to by 'pos'
315
 */
316
317
static void
520.1.22 by Brian Aker
Second pass of thd cleanup
318
binlog_trans_log_savepos(Session *session, my_off_t *pos)
1 by brian
clean slate
319
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
320
  assert(pos != NULL);
520.1.22 by Brian Aker
Second pass of thd cleanup
321
  if (session_get_ha_data(session, binlog_hton) == NULL)
322
    session->binlog_setup_trx_data();
1 by brian
clean slate
323
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
324
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
325
  assert(drizzle_bin_log.is_open());
1 by brian
clean slate
326
  *pos= trx_data->position();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
327
  return;
1 by brian
clean slate
328
}
329
330
331
/*
332
  Truncate the binary log transaction cache.
333
334
  SYNPOSIS
335
    binlog_trans_log_truncate()
336
520.1.22 by Brian Aker
Second pass of thd cleanup
337
    session      The thread to take the binlog data from
1 by brian
clean slate
338
    pos      Position to truncate to
339
340
  DESCRIPTION
341
342
    Truncate the binary log to the given position. Will not change
343
    anything else.
344
345
 */
346
static void
520.1.22 by Brian Aker
Second pass of thd cleanup
347
binlog_trans_log_truncate(Session *session, my_off_t pos)
1 by brian
clean slate
348
{
520.1.22 by Brian Aker
Second pass of thd cleanup
349
  assert(session_get_ha_data(session, binlog_hton) != NULL);
1 by brian
clean slate
350
  /* Only true if binlog_trans_log_savepos() wasn't called before */
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
351
  assert(pos != ~(my_off_t) 0);
1 by brian
clean slate
352
353
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
354
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
355
  trx_data->truncate(pos);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
356
  return;
1 by brian
clean slate
357
}
358
359
360
/*
361
  this function is mostly a placeholder.
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
362
  conceptually, binlog initialization (now mostly done in DRIZZLE_BIN_LOG::open)
1 by brian
clean slate
363
  should be moved here.
364
*/
365
366
int binlog_init(void *p)
367
{
368
  binlog_hton= (handlerton *)p;
369
  binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO;
370
  binlog_hton->savepoint_offset= sizeof(my_off_t);
371
  binlog_hton->close_connection= binlog_close_connection;
372
  binlog_hton->savepoint_set= binlog_savepoint_set;
373
  binlog_hton->savepoint_rollback= binlog_savepoint_rollback;
374
  binlog_hton->commit= binlog_commit;
375
  binlog_hton->rollback= binlog_rollback;
376
  binlog_hton->prepare= binlog_prepare;
377
  binlog_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN;
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
378
1 by brian
clean slate
379
  return 0;
380
}
381
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
382
static int binlog_close_connection(handlerton *, Session *session)
1 by brian
clean slate
383
{
384
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
385
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
386
  assert(trx_data->empty());
520.1.22 by Brian Aker
Second pass of thd cleanup
387
  session_set_ha_data(session, binlog_hton, NULL);
1 by brian
clean slate
388
  trx_data->~binlog_trx_data();
481 by Brian Aker
Remove all of uchar.
389
  free((unsigned char*)trx_data);
1 by brian
clean slate
390
  return 0;
391
}
392
393
/*
394
  End a transaction.
395
396
  SYNOPSIS
397
    binlog_end_trans()
398
520.1.22 by Brian Aker
Second pass of thd cleanup
399
    session      The thread whose transaction should be ended
1 by brian
clean slate
400
    trx_data Pointer to the transaction data to use
401
    end_ev   The end event to use, or NULL
402
    all      True if the entire transaction should be ended, false if
403
             only the statement transaction should be ended.
404
405
  DESCRIPTION
406
407
    End the currently open transaction. The transaction can be either
408
    a real transaction (if 'all' is true) or a statement transaction
409
    (if 'all' is false).
410
411
    If 'end_ev' is NULL, the transaction is a rollback of only
412
    transactional tables, so the transaction cache will be truncated
413
    to either just before the last opened statement transaction (if
414
    'all' is false), or reset completely (if 'all' is true).
415
 */
416
static int
520.1.22 by Brian Aker
Second pass of thd cleanup
417
binlog_end_trans(Session *session, binlog_trx_data *trx_data,
1 by brian
clean slate
418
                 Log_event *end_ev, bool all)
419
{
420
  int error=0;
421
  IO_CACHE *trans_log= &trx_data->trans_log;
422
423
  /*
424
    NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
425
    only transactional tables.  If the transaction contain changes to
426
    any non-transactiona tables, we need write the transaction and log
427
    a ROLLBACK last.
428
  */
429
  if (end_ev != NULL)
430
  {
431
    /*
432
      Doing a commit or a rollback including non-transactional tables,
433
      i.e., ending a transaction where we might write the transaction
434
      cache to the binary log.
435
436
      We can always end the statement when ending a transaction since
437
      transactions are not allowed inside stored functions.  If they
438
      were, we would have to ensure that we're not ending a statement
439
      inside a stored function.
440
     */
520.1.22 by Brian Aker
Second pass of thd cleanup
441
    session->binlog_flush_pending_rows_event(true);
1 by brian
clean slate
442
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
443
    error= drizzle_bin_log.write(session, &trx_data->trans_log, end_ev);
1 by brian
clean slate
444
    trx_data->reset();
445
446
    /*
447
      We need to step the table map version after writing the
448
      transaction cache to disk.
449
    */
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
450
    drizzle_bin_log.update_table_map_version();
1 by brian
clean slate
451
    statistic_increment(binlog_cache_use, &LOCK_status);
452
    if (trans_log->disk_writes != 0)
453
    {
454
      statistic_increment(binlog_cache_disk_use, &LOCK_status);
455
      trans_log->disk_writes= 0;
456
    }
457
  }
458
  else
459
  {
460
    /*
461
      If rolling back an entire transaction or a single statement not
462
      inside a transaction, we reset the transaction cache.
463
464
      If rolling back a statement in a transaction, we truncate the
465
      transaction cache to remove the statement.
466
     */
520.1.22 by Brian Aker
Second pass of thd cleanup
467
    if (all || !(session->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
1 by brian
clean slate
468
    {
469
      trx_data->reset();
470
520.1.22 by Brian Aker
Second pass of thd cleanup
471
      assert(!session->binlog_get_pending_rows_event());
472
      session->clear_binlog_table_maps();
1 by brian
clean slate
473
    }
474
    else                                        // ...statement
475
      trx_data->truncate(trx_data->before_stmt_pos);
476
477
    /*
478
      We need to step the table map version on a rollback to ensure
479
      that a new table map event is generated instead of the one that
480
      was written to the thrown-away transaction cache.
481
    */
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
482
    drizzle_bin_log.update_table_map_version();
1 by brian
clean slate
483
  }
484
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
485
  return(error);
1 by brian
clean slate
486
}
487
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
488
static int binlog_prepare(handlerton *, Session *, bool)
1 by brian
clean slate
489
{
490
  /*
491
    do nothing.
492
    just pretend we can do 2pc, so that MySQL won't
493
    switch to 1pc.
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
494
    real work will be done in DRIZZLE_BIN_LOG::log_xid()
1 by brian
clean slate
495
  */
496
  return 0;
497
}
498
499
/**
500
  This function is called once after each statement.
501
502
  It has the responsibility to flush the transaction cache to the
503
  binlog file on commits.
504
505
  @param hton  The binlog handlerton.
520.1.22 by Brian Aker
Second pass of thd cleanup
506
  @param session   The client thread that executes the transaction.
1 by brian
clean slate
507
  @param all   This is @c true if this is a real transaction commit, and
508
               @false otherwise.
509
510
  @see handlerton::commit
511
*/
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
512
static int binlog_commit(handlerton *, Session *session, bool all)
1 by brian
clean slate
513
{
514
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
515
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
516
517
  if (trx_data->empty())
518
  {
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
519
    // we're here because trans_log was flushed in DRIZZLE_BIN_LOG::log_xid()
1 by brian
clean slate
520
    trx_data->reset();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
521
    return(0);
1 by brian
clean slate
522
  }
523
524
  /*
525
    Decision table for committing a transaction. The top part, the
526
    *conditions* represent different cases that can occur, and hte
527
    bottom part, the *actions*, represent what should be done in that
528
    particular case.
529
530
    Real transaction        'all' was true
531
532
    Statement in cache      There were at least one statement in the
533
                            transaction cache
534
535
    In transaction          We are inside a transaction
536
537
    Stmt modified non-trans The statement being committed modified a
538
                            non-transactional table
539
540
    All modified non-trans  Some statement before this one in the
541
                            transaction modified a non-transactional
542
                            table
543
544
545
    =============================  = = = = = = = = = = = = = = = =
546
    Real transaction               N N N N N N N N N N N N N N N N
547
    Statement in cache             N N N N N N N N Y Y Y Y Y Y Y Y
548
    In transaction                 N N N N Y Y Y Y N N N N Y Y Y Y
549
    Stmt modified non-trans        N N Y Y N N Y Y N N Y Y N N Y Y
550
    All modified non-trans         N Y N Y N Y N Y N Y N Y N Y N Y
551
552
    Action: (C)ommit/(A)ccumulate  C C - C A C - C - - - - A A - A
553
    =============================  = = = = = = = = = = = = = = = =
554
555
556
    =============================  = = = = = = = = = = = = = = = =
557
    Real transaction               Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
558
    Statement in cache             N N N N N N N N Y Y Y Y Y Y Y Y
559
    In transaction                 N N N N Y Y Y Y N N N N Y Y Y Y
560
    Stmt modified non-trans        N N Y Y N N Y Y N N Y Y N N Y Y
561
    All modified non-trans         N Y N Y N Y N Y N Y N Y N Y N Y
562
563
    (C)ommit/(A)ccumulate/(-)      - - - - C C - C - - - - C C - C
564
    =============================  = = = = = = = = = = = = = = = =
565
566
    In other words, we commit the transaction if and only if both of
567
    the following are true:
568
     - We are not in a transaction and committing a statement
569
570
     - We are in a transaction and one (or more) of the following are
571
       true:
572
573
       - A full transaction is committed
574
575
         OR
576
577
       - A non-transactional statement is committed and there is
578
         no statement cached
579
580
    Otherwise, we accumulate the statement
581
  */
151 by Brian Aker
Ulonglong to uint64_t
582
  uint64_t const in_transaction=
520.1.22 by Brian Aker
Second pass of thd cleanup
583
    session->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
584
  if ((in_transaction && (all || (!trx_data->at_least_one_stmt && session->transaction.stmt.modified_non_trans_table))) || (!in_transaction && !all))
1 by brian
clean slate
585
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
586
    Query_log_event qev(session, STRING_WITH_LEN("COMMIT"), true, false);
520.1.21 by Brian Aker
THD -> Session rename
587
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(Session, IO_CACHE)
520.1.22 by Brian Aker
Second pass of thd cleanup
588
    int error= binlog_end_trans(session, trx_data, &qev, all);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
589
    return(error);
1 by brian
clean slate
590
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
591
  return(0);
1 by brian
clean slate
592
}
593
594
/**
595
  This function is called when a transaction involving a transactional
596
  table is rolled back.
597
598
  It has the responsibility to flush the transaction cache to the
599
  binlog file. However, if the transaction does not involve
600
  non-transactional tables, nothing needs to be logged.
601
602
  @param hton  The binlog handlerton.
520.1.22 by Brian Aker
Second pass of thd cleanup
603
  @param session   The client thread that executes the transaction.
1 by brian
clean slate
604
  @param all   This is @c true if this is a real transaction rollback, and
605
               @false otherwise.
606
607
  @see handlerton::rollback
608
*/
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
609
static int binlog_rollback(handlerton *, Session *session, bool all)
1 by brian
clean slate
610
{
611
  int error=0;
612
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
613
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
614
615
  if (trx_data->empty()) {
616
    trx_data->reset();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
617
    return(0);
1 by brian
clean slate
618
  }
619
520.1.22 by Brian Aker
Second pass of thd cleanup
620
  if ((all && session->transaction.all.modified_non_trans_table) ||
621
      (!all && session->transaction.stmt.modified_non_trans_table) ||
622
      (session->options & OPTION_KEEP_LOG))
1 by brian
clean slate
623
  {
624
    /*
625
      We write the transaction cache with a rollback last if we have
626
      modified any non-transactional table. We do this even if we are
627
      committing a single statement that has modified a
628
      non-transactional table since it can have modified a
629
      transactional table in that statement as well, which needs to be
630
      rolled back on the slave.
631
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
632
    Query_log_event qev(session, STRING_WITH_LEN("ROLLBACK"), true, false);
520.1.21 by Brian Aker
THD -> Session rename
633
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(Session, IO_CACHE)
520.1.22 by Brian Aker
Second pass of thd cleanup
634
    error= binlog_end_trans(session, trx_data, &qev, all);
1 by brian
clean slate
635
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
636
  else if ((all && !session->transaction.all.modified_non_trans_table) ||
637
           (!all && !session->transaction.stmt.modified_non_trans_table))
1 by brian
clean slate
638
  {
639
    /*
640
      If we have modified only transactional tables, we can truncate
641
      the transaction cache without writing anything to the binary
642
      log.
643
     */
520.1.22 by Brian Aker
Second pass of thd cleanup
644
    error= binlog_end_trans(session, trx_data, 0, all);
1 by brian
clean slate
645
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
646
  return(error);
1 by brian
clean slate
647
}
648
649
/**
650
  @note
651
  How do we handle this (unlikely but legal) case:
652
  @verbatim
653
    [transaction] + [update to non-trans table] + [rollback to savepoint] ?
654
  @endverbatim
655
  The problem occurs when a savepoint is before the update to the
656
  non-transactional table. Then when there's a rollback to the savepoint, if we
657
  simply truncate the binlog cache, we lose the part of the binlog cache where
658
  the update is. If we want to not lose it, we need to write the SAVEPOINT
659
  command and the ROLLBACK TO SAVEPOINT command to the binlog cache. The latter
660
  is easy: it's just write at the end of the binlog cache, but the former
661
  should be *inserted* to the place where the user called SAVEPOINT. The
662
  solution is that when the user calls SAVEPOINT, we write it to the binlog
663
  cache (so no need to later insert it). As transactions are never intermixed
664
  in the binary log (i.e. they are serialized), we won't have conflicts with
665
  savepoint names when using mysqlbinlog or in the slave SQL thread.
666
  Then when ROLLBACK TO SAVEPOINT is called, if we updated some
667
  non-transactional table, we don't truncate the binlog cache but instead write
668
  ROLLBACK TO SAVEPOINT to it; otherwise we truncate the binlog cache (which
669
  will chop the SAVEPOINT command from the binlog cache, which is good as in
670
  that case there is no need to have it in the binlog).
671
*/
672
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
673
static int binlog_savepoint_set(handlerton *, Session *session, void *sv)
1 by brian
clean slate
674
{
520.1.22 by Brian Aker
Second pass of thd cleanup
675
  binlog_trans_log_savepos(session, (my_off_t*) sv);
1 by brian
clean slate
676
  /* Write it to the binary log */
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
677
1 by brian
clean slate
678
  int const error=
520.1.22 by Brian Aker
Second pass of thd cleanup
679
    session->binlog_query(Session::STMT_QUERY_TYPE,
680
                      session->query, session->query_length, true, false);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
681
  return(error);
1 by brian
clean slate
682
}
683
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
684
static int binlog_savepoint_rollback(handlerton *, Session *session, void *sv)
1 by brian
clean slate
685
{
686
  /*
687
    Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
688
    non-transactional table. Otherwise, truncate the binlog cache starting
689
    from the SAVEPOINT command.
690
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
691
  if (unlikely(session->transaction.all.modified_non_trans_table || 
692
               (session->options & OPTION_KEEP_LOG)))
1 by brian
clean slate
693
  {
694
    int error=
520.1.22 by Brian Aker
Second pass of thd cleanup
695
      session->binlog_query(Session::STMT_QUERY_TYPE,
696
                        session->query, session->query_length, true, false);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
697
    return(error);
1 by brian
clean slate
698
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
699
  binlog_trans_log_truncate(session, *(my_off_t*)sv);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
700
  return(0);
1 by brian
clean slate
701
}
702
703
704
int check_binlog_magic(IO_CACHE* log, const char** errmsg)
705
{
706
  char magic[4];
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
707
  assert(my_b_tell(log) == 0);
1 by brian
clean slate
708
481 by Brian Aker
Remove all of uchar.
709
  if (my_b_read(log, (unsigned char*) magic, sizeof(magic)))
1 by brian
clean slate
710
  {
338 by Monty Taylor
Tagged more strings.
711
    *errmsg = _("I/O error reading the header from the binary log");
1 by brian
clean slate
712
    sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
713
		    log->error);
714
    return 1;
715
  }
716
  if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
717
  {
338 by Monty Taylor
Tagged more strings.
718
    *errmsg = _("Binlog has bad magic number;  It's not a binary log file "
719
		"that can be used by this version of Drizzle");
1 by brian
clean slate
720
    return 1;
721
  }
722
  return 0;
723
}
724
725
726
File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
727
{
728
  File file;
729
492.1.14 by Monty Taylor
Removed O_BINARY and FILE_BINARY.
730
  if ((file = my_open(log_file_name, O_RDONLY, 
1 by brian
clean slate
731
                      MYF(MY_WME))) < 0)
732
  {
338 by Monty Taylor
Tagged more strings.
733
    sql_print_error(_("Failed to open log (file '%s', errno %d)"),
1 by brian
clean slate
734
                    log_file_name, my_errno);
338 by Monty Taylor
Tagged more strings.
735
    *errmsg = _("Could not open log file");
1 by brian
clean slate
736
    goto err;
737
  }
738
  if (init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
739
                    MYF(MY_WME|MY_DONT_CHECK_FILESIZE)))
740
  {
338 by Monty Taylor
Tagged more strings.
741
    sql_print_error(_("Failed to create a cache on log (file '%s')"),
1 by brian
clean slate
742
                    log_file_name);
338 by Monty Taylor
Tagged more strings.
743
    *errmsg = _("Could not open log file");
1 by brian
clean slate
744
    goto err;
745
  }
746
  if (check_binlog_magic(log,errmsg))
747
    goto err;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
748
  return(file);
1 by brian
clean slate
749
750
err:
751
  if (file >= 0)
752
  {
753
    my_close(file,MYF(0));
754
    end_io_cache(log);
755
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
756
  return(-1);
1 by brian
clean slate
757
}
758
759
760
/**
761
  Find a unique filename for 'filename.#'.
762
763
  Set '#' to a number as low as possible.
764
765
  @return
766
    nonzero if not possible to get unique filename
767
*/
768
769
static int find_uniq_filename(char *name)
770
{
771
  long                  number;
482 by Brian Aker
Remove uint.
772
  uint32_t                  i;
1 by brian
clean slate
773
  char                  buff[FN_REFLEN];
774
  struct st_my_dir     *dir_info;
775
  register struct fileinfo *file_info;
776
  ulong                 max_found=0;
777
  size_t		buf_length, length;
778
  char			*start, *end;
779
780
  length= dirname_part(buff, name, &buf_length);
781
  start=  name + length;
376 by Brian Aker
strend remove
782
  end= strchr(start, '\0');
1 by brian
clean slate
783
784
  *end='.';
785
  length= (size_t) (end-start+1);
786
787
  if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
788
  {						// This shouldn't happen
411.1.1 by Brian Aker
Work on removing GNU specific calls.
789
    my_stpcpy(end,".1");				// use name+1
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
790
    return(0);
1 by brian
clean slate
791
  }
792
  file_info= dir_info->dir_entry;
793
  for (i=dir_info->number_off_files ; i-- ; file_info++)
794
  {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
795
    if (memcmp(file_info->name, start, length) == 0 &&
1 by brian
clean slate
796
	test_if_number(file_info->name+length, &number,0))
797
    {
798
      set_if_bigger(max_found,(ulong) number);
799
    }
800
  }
801
  my_dirend(dir_info);
802
803
  *end++='.';
804
  sprintf(end,"%06ld",max_found+1);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
805
  return(0);
1 by brian
clean slate
806
}
807
808
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
809
void DRIZZLE_LOG::init(enum_log_type log_type_arg,
1 by brian
clean slate
810
                     enum cache_type io_cache_type_arg)
811
{
812
  log_type= log_type_arg;
813
  io_cache_type= io_cache_type_arg;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
814
  return;
1 by brian
clean slate
815
}
816
817
818
/*
819
  Open a (new) log file.
820
821
  SYNOPSIS
822
    open()
823
824
    log_name            The name of the log to open
825
    log_type_arg        The type of the log. E.g. LOG_NORMAL
826
    new_name            The new name for the logfile. This is only needed
827
                        when the method is used to open the binlog file.
828
    io_cache_type_arg   The type of the IO_CACHE to use for this log file
829
830
  DESCRIPTION
831
    Open the logfile, init IO_CACHE and write startup messages
832
    (in case of general and slow query logs).
833
834
  RETURN VALUES
835
    0   ok
836
    1   error
837
*/
838
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
839
bool DRIZZLE_LOG::open(const char *log_name, enum_log_type log_type_arg,
1 by brian
clean slate
840
                     const char *new_name, enum cache_type io_cache_type_arg)
841
{
842
  char buff[FN_REFLEN];
843
  File file= -1;
492.1.14 by Monty Taylor
Removed O_BINARY and FILE_BINARY.
844
  int open_flags= O_CREAT;
1 by brian
clean slate
845
846
  write_error= 0;
847
848
  init(log_type_arg, io_cache_type_arg);
849
850
  if (!(name= my_strdup(log_name, MYF(MY_WME))))
851
  {
852
    name= (char *)log_name; // for the error message
853
    goto err;
854
  }
855
856
  if (new_name)
411.1.1 by Brian Aker
Work on removing GNU specific calls.
857
    my_stpcpy(log_file_name, new_name);
1 by brian
clean slate
858
  else if (generate_new_name(log_file_name, name))
859
    goto err;
860
861
  if (io_cache_type == SEQ_READ_APPEND)
862
    open_flags |= O_RDWR | O_APPEND;
863
  else
864
    open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
865
866
  db[0]= 0;
867
868
  if ((file= my_open(log_file_name, open_flags,
869
                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
870
      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
871
                    my_tell(file, MYF(MY_WME)), 0,
872
                    MYF(MY_WME | MY_NABP |
873
                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
874
    goto err;
875
876
  if (log_type == LOG_NORMAL)
877
  {
878
    char *end;
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
879
    int len=snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
880
		     "started with:\nTCP Port: %d, Named Pipe: %s\n",
546 by Monty Taylor
Cleaned up version.h. (And by cleaned, I mean removed)
881
                     my_progname, server_version, COMPILATION_COMMENT,
574.2.1 by ysano
Rename mysql to drizzle.
882
                     drizzled_port, ""
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
883
                     );
411.1.1 by Brian Aker
Work on removing GNU specific calls.
884
    end= my_stpncpy(buff + len, "Time                 Id Command    Argument\n",
1 by brian
clean slate
885
                 sizeof(buff) - len);
481 by Brian Aker
Remove all of uchar.
886
    if (my_b_write(&log_file, (unsigned char*) buff, (uint) (end-buff)) ||
1 by brian
clean slate
887
	flush_io_cache(&log_file))
888
      goto err;
889
  }
890
891
  log_state= LOG_OPENED;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
892
  return(0);
1 by brian
clean slate
893
894
err:
338 by Monty Taylor
Tagged more strings.
895
  sql_print_error(_("Could not use %s for logging (error %d). "
896
                    "Turning logging off for the whole duration of the "
897
                    "Drizzle server process. "
898
                    "To turn it on again: fix the cause, "
899
                    "shutdown the Drizzle server and restart it."),
900
                    name, errno);
1 by brian
clean slate
901
  if (file >= 0)
902
    my_close(file, MYF(0));
903
  end_io_cache(&log_file);
462 by Monty Taylor
Removed safeFree.
904
  if (name)
905
  {
906
    free(name);
907
    name= NULL;
908
  }
1 by brian
clean slate
909
  log_state= LOG_CLOSED;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
910
  return(1);
1 by brian
clean slate
911
}
912
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
913
DRIZZLE_LOG::DRIZZLE_LOG()
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
914
  : name(0), write_error(false), inited(false), log_type(LOG_UNKNOWN),
1 by brian
clean slate
915
    log_state(LOG_CLOSED)
916
{
917
  /*
918
    We don't want to initialize LOCK_Log here as such initialization depends on
919
    safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
920
    called only in main(). Doing initialization here would make it happen
921
    before main().
922
  */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
923
  memset(&log_file, 0, sizeof(log_file));
1 by brian
clean slate
924
}
925
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
926
void DRIZZLE_LOG::init_pthread_objects()
1 by brian
clean slate
927
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
928
  assert(inited == 0);
1 by brian
clean slate
929
  inited= 1;
930
  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
931
}
932
933
/*
934
  Close the log file
935
936
  SYNOPSIS
937
    close()
938
    exiting     Bitmask. For the slow and general logs the only used bit is
939
                LOG_CLOSE_TO_BE_OPENED. This is used if we intend to call
940
                open at once after close.
941
942
  NOTES
943
    One can do an open on the object at once after doing a close.
944
    The internal structures are not freed until cleanup() is called
945
*/
946
482 by Brian Aker
Remove uint.
947
void DRIZZLE_LOG::close(uint32_t exiting)
1 by brian
clean slate
948
{					// One can't set log_type here!
949
  if (log_state == LOG_OPENED)
950
  {
951
    end_io_cache(&log_file);
952
953
    if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error)
954
    {
955
      write_error= 1;
956
      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
957
    }
958
959
    if (my_close(log_file.file, MYF(MY_WME)) && ! write_error)
960
    {
961
      write_error= 1;
962
      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
963
    }
964
  }
965
966
  log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
462 by Monty Taylor
Removed safeFree.
967
  if (name)
968
  {
969
    free(name);
970
    name= NULL;
971
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
972
  return;
1 by brian
clean slate
973
}
974
975
/** This is called only once. */
976
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
977
void DRIZZLE_LOG::cleanup()
1 by brian
clean slate
978
{
979
  if (inited)
980
  {
981
    inited= 0;
982
    (void) pthread_mutex_destroy(&LOCK_log);
983
    close(0);
984
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
985
  return;
1 by brian
clean slate
986
}
987
988
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
989
int DRIZZLE_LOG::generate_new_name(char *new_name, const char *log_name)
1 by brian
clean slate
990
{
575.4.1 by ysano
Rename mysql to drizzle.
991
  fn_format(new_name, log_name, drizzle_data_home, "", 4);
1 by brian
clean slate
992
  if (log_type == LOG_BIN)
993
  {
994
    if (!fn_ext(log_name)[0])
995
    {
996
      if (find_uniq_filename(new_name))
997
      {
998
	sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
999
	return 1;
1000
      }
1001
    }
1002
  }
1003
  return 0;
1004
}
1005
1006
1007
/**
1008
  @todo
1009
  The following should be using fn_format();  We just need to
1010
  first change fn_format() to cut the file name if it's too long.
1011
*/
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1012
const char *DRIZZLE_LOG::generate_name(const char *log_name,
1 by brian
clean slate
1013
                                      const char *suffix,
1014
                                      bool strip_ext, char *buff)
1015
{
1016
  if (!log_name || !log_name[0])
1017
  {
1018
    strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
1019
    return (const char *)
1020
      fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR));
1021
  }
1022
  // get rid of extension if the log is binary to avoid problems
1023
  if (strip_ext)
1024
  {
1025
    char *p= fn_ext(log_name);
482 by Brian Aker
Remove uint.
1026
    uint32_t length= (uint) (p - log_name);
398.1.4 by Monty Taylor
Renamed max/min.
1027
    strmake(buff, log_name, cmin(length, (uint)FN_REFLEN));
1 by brian
clean slate
1028
    return (const char*)buff;
1029
  }
1030
  return log_name;
1031
}
1032
1033
1034
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1035
DRIZZLE_BIN_LOG::DRIZZLE_BIN_LOG()
1 by brian
clean slate
1036
  :bytes_written(0), prepared_xids(0), file_id(1), open_count(1),
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1037
   need_start_event(true), m_table_map_version(0),
1 by brian
clean slate
1038
   description_event_for_exec(0), description_event_for_queue(0)
1039
{
1040
  /*
1041
    We don't want to initialize locks here as such initialization depends on
1042
    safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
1043
    called only in main(). Doing initialization here would make it happen
1044
    before main().
1045
  */
1046
  index_file_name[0] = 0;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1047
  memset(&index_file, 0, sizeof(index_file));
1 by brian
clean slate
1048
}
1049
1050
/* this is called only once */
1051
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1052
void DRIZZLE_BIN_LOG::cleanup()
1 by brian
clean slate
1053
{
1054
  if (inited)
1055
  {
1056
    inited= 0;
1057
    close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
1058
    delete description_event_for_queue;
1059
    delete description_event_for_exec;
1060
    (void) pthread_mutex_destroy(&LOCK_log);
1061
    (void) pthread_mutex_destroy(&LOCK_index);
1062
    (void) pthread_cond_destroy(&update_cond);
1063
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1064
  return;
1 by brian
clean slate
1065
}
1066
1067
1068
/* Init binlog-specific vars */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1069
void DRIZZLE_BIN_LOG::init(bool no_auto_events_arg, ulong max_size_arg)
1 by brian
clean slate
1070
{
1071
  no_auto_events= no_auto_events_arg;
1072
  max_size= max_size_arg;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1073
  return;
1 by brian
clean slate
1074
}
1075
1076
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1077
void DRIZZLE_BIN_LOG::init_pthread_objects()
1 by brian
clean slate
1078
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1079
  assert(inited == 0);
1 by brian
clean slate
1080
  inited= 1;
1081
  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
1082
  (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
1083
  (void) pthread_cond_init(&update_cond, 0);
1084
}
1085
1086
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1087
bool DRIZZLE_BIN_LOG::open_index_file(const char *index_file_name_arg,
1 by brian
clean slate
1088
                                const char *log_name)
1089
{
1090
  File index_file_nr= -1;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1091
  assert(!my_b_inited(&index_file));
1 by brian
clean slate
1092
1093
  /*
1094
    First open of this class instance
1095
    Create an index file that will hold all file names uses for logging.
1096
    Add new entries to the end of it.
1097
  */
1098
  myf opt= MY_UNPACK_FILENAME;
1099
  if (!index_file_name_arg)
1100
  {
1101
    index_file_name_arg= log_name;    // Use same basename for index file
1102
    opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
1103
  }
575.4.1 by ysano
Rename mysql to drizzle.
1104
  fn_format(index_file_name, index_file_name_arg, drizzle_data_home,
1 by brian
clean slate
1105
            ".index", opt);
1106
  if ((index_file_nr= my_open(index_file_name,
492.1.14 by Monty Taylor
Removed O_BINARY and FILE_BINARY.
1107
                              O_RDWR | O_CREAT,
1 by brian
clean slate
1108
                              MYF(MY_WME))) < 0 ||
1109
       my_sync(index_file_nr, MYF(MY_WME)) ||
1110
       init_io_cache(&index_file, index_file_nr,
1111
                     IO_SIZE, WRITE_CACHE,
1112
                     my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
1113
			0, MYF(MY_WME | MY_WAIT_IF_FULL)))
1114
  {
1115
    /*
1116
      TODO: all operations creating/deleting the index file or a log, should
1117
      call my_sync_dir() or my_sync_dir_by_file() to be durable.
1118
      TODO: file creation should be done with my_create() not my_open().
1119
    */
1120
    if (index_file_nr >= 0)
1121
      my_close(index_file_nr,MYF(0));
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1122
    return true;
1 by brian
clean slate
1123
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1124
  return false;
1 by brian
clean slate
1125
}
1126
1127
1128
/**
1129
  Open a (new) binlog file.
1130
1131
  - Open the log file and the index file. Register the new
1132
  file name in it
1133
  - When calling this when the file is in use, you must have a locks
1134
  on LOCK_log and LOCK_index.
1135
1136
  @retval
1137
    0	ok
1138
  @retval
1139
    1	error
1140
*/
1141
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1142
bool DRIZZLE_BIN_LOG::open(const char *log_name,
1 by brian
clean slate
1143
                         enum_log_type log_type_arg,
1144
                         const char *new_name,
1145
                         enum cache_type io_cache_type_arg,
1146
                         bool no_auto_events_arg,
1147
                         ulong max_size_arg,
1148
                         bool null_created_arg)
1149
{
1150
  File file= -1;
1151
1152
  write_error=0;
1153
1154
  /* open the main log file */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1155
  if (DRIZZLE_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg))
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1156
    return(1);                            /* all warnings issued */
1 by brian
clean slate
1157
1158
  init(no_auto_events_arg, max_size_arg);
1159
1160
  open_count++;
1161
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1162
  assert(log_type == LOG_BIN);
1 by brian
clean slate
1163
1164
  {
1165
    bool write_file_name_to_index_file=0;
1166
1167
    if (!my_b_filelength(&log_file))
1168
    {
1169
      /*
1170
	The binary log file was empty (probably newly created)
1171
	This is the normal case and happens when the user doesn't specify
1172
	an extension for the binary log files.
1173
	In this case we write a standard header to it.
1174
      */
481 by Brian Aker
Remove all of uchar.
1175
      if (my_b_safe_write(&log_file, (unsigned char*) BINLOG_MAGIC,
1 by brian
clean slate
1176
			  BIN_LOG_HEADER_SIZE))
1177
        goto err;
1178
      bytes_written+= BIN_LOG_HEADER_SIZE;
1179
      write_file_name_to_index_file= 1;
1180
    }
1181
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1182
    assert(my_b_inited(&index_file) != 0);
1 by brian
clean slate
1183
    reinit_io_cache(&index_file, WRITE_CACHE,
1184
                    my_b_filelength(&index_file), 0, 0);
1185
    if (need_start_event && !no_auto_events)
1186
    {
1187
      /*
1188
        In 4.x we set need_start_event=0 here, but in 5.0 we want a Start event
1189
        even if this is not the very first binlog.
1190
      */
1191
      Format_description_log_event s(BINLOG_VERSION);
1192
      /*
1193
        don't set LOG_EVENT_BINLOG_IN_USE_F for SEQ_READ_APPEND io_cache
1194
        as we won't be able to reset it later
1195
      */
1196
      if (io_cache_type == WRITE_CACHE)
1197
        s.flags|= LOG_EVENT_BINLOG_IN_USE_F;
1198
      if (!s.is_valid())
1199
        goto err;
1200
      s.dont_set_created= null_created_arg;
1201
      if (s.write(&log_file))
1202
        goto err;
1203
      bytes_written+= s.data_written;
1204
    }
1205
    if (description_event_for_queue &&
1206
        description_event_for_queue->binlog_version>=4)
1207
    {
1208
      /*
1209
        This is a relay log written to by the I/O slave thread.
1210
        Write the event so that others can later know the format of this relay
1211
        log.
1212
        Note that this event is very close to the original event from the
1213
        master (it has binlog version of the master, event types of the
1214
        master), so this is suitable to parse the next relay log's event. It
1215
        has been produced by
1216
        Format_description_log_event::Format_description_log_event(char* buf,).
1217
        Why don't we want to write the description_event_for_queue if this
1218
        event is for format<4 (3.23 or 4.x): this is because in that case, the
1219
        description_event_for_queue describes the data received from the
1220
        master, but not the data written to the relay log (*conversion*),
1221
        which is in format 4 (slave's).
1222
      */
1223
      /*
1224
        Set 'created' to 0, so that in next relay logs this event does not
1225
        trigger cleaning actions on the slave in
1226
        Format_description_log_event::apply_event_impl().
1227
      */
1228
      description_event_for_queue->created= 0;
1229
      /* Don't set log_pos in event header */
1230
      description_event_for_queue->artificial_event=1;
1231
1232
      if (description_event_for_queue->write(&log_file))
1233
        goto err;
1234
      bytes_written+= description_event_for_queue->data_written;
1235
    }
1236
    if (flush_io_cache(&log_file) ||
1237
        my_sync(log_file.file, MYF(MY_WME)))
1238
      goto err;
1239
1240
    if (write_file_name_to_index_file)
1241
    {
1242
      /*
1243
        As this is a new log file, we write the file name to the index
1244
        file. As every time we write to the index file, we sync it.
1245
      */
481 by Brian Aker
Remove all of uchar.
1246
      if (my_b_write(&index_file, (unsigned char*) log_file_name,
1 by brian
clean slate
1247
		     strlen(log_file_name)) ||
481 by Brian Aker
Remove all of uchar.
1248
	  my_b_write(&index_file, (unsigned char*) "\n", 1) ||
1 by brian
clean slate
1249
	  flush_io_cache(&index_file) ||
1250
          my_sync(index_file.file, MYF(MY_WME)))
1251
	goto err;
1252
    }
1253
  }
1254
  log_state= LOG_OPENED;
1255
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1256
  return(0);
1 by brian
clean slate
1257
1258
err:
338 by Monty Taylor
Tagged more strings.
1259
  sql_print_error(_("Could not use %s for logging (error %d). "
1260
                    "Turning logging off for the whole duration of the "
1261
                    "Drizzle server process. "
1262
                    "To turn it on again: fix the cause, "
342 by Monty Taylor
Fixed syntax error.
1263
                    "shutdown the Drizzle server and restart it."),
338 by Monty Taylor
Tagged more strings.
1264
                    name, errno);
1 by brian
clean slate
1265
  if (file >= 0)
1266
    my_close(file,MYF(0));
1267
  end_io_cache(&log_file);
1268
  end_io_cache(&index_file);
462 by Monty Taylor
Removed safeFree.
1269
  if (name)
1270
  {
1271
    free(name);
1272
    name= NULL;
1273
  }
1 by brian
clean slate
1274
  log_state= LOG_CLOSED;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1275
  return(1);
1 by brian
clean slate
1276
}
1277
1278
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1279
int DRIZZLE_BIN_LOG::get_current_log(LOG_INFO* linfo)
1 by brian
clean slate
1280
{
1281
  pthread_mutex_lock(&LOCK_log);
1282
  int ret = raw_get_current_log(linfo);
1283
  pthread_mutex_unlock(&LOCK_log);
1284
  return ret;
1285
}
1286
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1287
int DRIZZLE_BIN_LOG::raw_get_current_log(LOG_INFO* linfo)
1 by brian
clean slate
1288
{
1289
  strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
1290
  linfo->pos = my_b_tell(&log_file);
1291
  return 0;
1292
}
1293
1294
/**
1295
  Move all data up in a file in an filename index file.
1296
1297
    We do the copy outside of the IO_CACHE as the cache buffers would just
1298
    make things slower and more complicated.
1299
    In most cases the copy loop should only do one read.
1300
1301
  @param index_file			File to move
1302
  @param offset			Move everything from here to beginning
1303
1304
  @note
1305
    File will be truncated to be 'offset' shorter or filled up with newlines
1306
1307
  @retval
1308
    0	ok
1309
*/
1310
1311
static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
1312
{
1313
  int bytes_read;
1314
  my_off_t init_offset= offset;
1315
  File file= index_file->file;
481 by Brian Aker
Remove all of uchar.
1316
  unsigned char io_buf[IO_SIZE*2];
1 by brian
clean slate
1317
1318
  for (;; offset+= bytes_read)
1319
  {
1320
    (void) my_seek(file, offset, MY_SEEK_SET, MYF(0));
1321
    if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME)))
1322
	< 0)
1323
      goto err;
1324
    if (!bytes_read)
1325
      break;					// end of file
1326
    (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
1327
    if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
1328
      goto err;
1329
  }
1330
  /* The following will either truncate the file or fill the end with \n' */
30 by Brian Aker
Large file and ftruncate() support
1331
  if (ftruncate(file, offset - init_offset) || my_sync(file, MYF(MY_WME)))
1 by brian
clean slate
1332
    goto err;
1333
1334
  /* Reset data in old index cache */
1335
  reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 1);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1336
  return(0);
1 by brian
clean slate
1337
1338
err:
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1339
  return(1);
1 by brian
clean slate
1340
}
1341
1342
/**
1343
  Find the position in the log-index-file for the given log name.
1344
1345
  @param linfo		Store here the found log file name and position to
1346
                       the NEXT log file name in the index file.
1347
  @param log_name	Filename to find in the index file.
1348
                       Is a null pointer if we want to read the first entry
1349
  @param need_lock	Set this to 1 if the parent doesn't already have a
1350
                       lock on LOCK_index
1351
1352
  @note
1353
    On systems without the truncate function the file will end with one or
1354
    more empty lines.  These will be ignored when reading the file.
1355
1356
  @retval
1357
    0			ok
1358
  @retval
1359
    LOG_INFO_EOF	        End of log-index-file found
1360
  @retval
1361
    LOG_INFO_IO		Got IO error while reading file
1362
*/
1363
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1364
int DRIZZLE_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
1 by brian
clean slate
1365
			    bool need_lock)
1366
{
1367
  int error= 0;
1368
  char *fname= linfo->log_file_name;
482 by Brian Aker
Remove uint.
1369
  uint32_t log_name_len= log_name ? (uint) strlen(log_name) : 0;
1 by brian
clean slate
1370
1371
  /*
1372
    Mutex needed because we need to make sure the file pointer does not
1373
    move from under our feet
1374
  */
1375
  if (need_lock)
1376
    pthread_mutex_lock(&LOCK_index);
1377
  safe_mutex_assert_owner(&LOCK_index);
1378
1379
  /* As the file is flushed, we can't get an error here */
1380
  (void) reinit_io_cache(&index_file, READ_CACHE, (my_off_t) 0, 0, 0);
1381
1382
  for (;;)
1383
  {
482 by Brian Aker
Remove uint.
1384
    uint32_t length;
1 by brian
clean slate
1385
    my_off_t offset= my_b_tell(&index_file);
1386
    /* If we get 0 or 1 characters, this is the end of the file */
1387
1388
    if ((length= my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
1389
    {
1390
      /* Did not find the given entry; Return not found or error */
1391
      error= !index_file.error ? LOG_INFO_EOF : LOG_INFO_IO;
1392
      break;
1393
    }
1394
1395
    // if the log entry matches, null string matching anything
1396
    if (!log_name ||
1397
	(log_name_len == length-1 && fname[log_name_len] == '\n' &&
1398
	 !memcmp(fname, log_name, log_name_len)))
1399
    {
1400
      fname[length-1]=0;			// remove last \n
1401
      linfo->index_file_start_offset= offset;
1402
      linfo->index_file_offset = my_b_tell(&index_file);
1403
      break;
1404
    }
1405
  }
1406
1407
  if (need_lock)
1408
    pthread_mutex_unlock(&LOCK_index);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1409
  return(error);
1 by brian
clean slate
1410
}
1411
1412
1413
/**
1414
  Find the position in the log-index-file for the given log name.
1415
1416
  @param
1417
    linfo		Store here the next log file name and position to
1418
			the file name after that.
1419
  @param
1420
    need_lock		Set this to 1 if the parent doesn't already have a
1421
			lock on LOCK_index
1422
1423
  @note
1424
    - Before calling this function, one has to call find_log_pos()
1425
    to set up 'linfo'
1426
    - Mutex needed because we need to make sure the file pointer does not move
1427
    from under our feet
1428
1429
  @retval
1430
    0			ok
1431
  @retval
1432
    LOG_INFO_EOF	        End of log-index-file found
1433
  @retval
1434
    LOG_INFO_IO		Got IO error while reading file
1435
*/
1436
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1437
int DRIZZLE_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
1 by brian
clean slate
1438
{
1439
  int error= 0;
482 by Brian Aker
Remove uint.
1440
  uint32_t length;
1 by brian
clean slate
1441
  char *fname= linfo->log_file_name;
1442
1443
  if (need_lock)
1444
    pthread_mutex_lock(&LOCK_index);
1445
  safe_mutex_assert_owner(&LOCK_index);
1446
1447
  /* As the file is flushed, we can't get an error here */
1448
  (void) reinit_io_cache(&index_file, READ_CACHE, linfo->index_file_offset, 0,
1449
			 0);
1450
1451
  linfo->index_file_start_offset= linfo->index_file_offset;
1452
  if ((length=my_b_gets(&index_file, fname, FN_REFLEN)) <= 1)
1453
  {
1454
    error = !index_file.error ? LOG_INFO_EOF : LOG_INFO_IO;
1455
    goto err;
1456
  }
1457
  fname[length-1]=0;				// kill \n
1458
  linfo->index_file_offset = my_b_tell(&index_file);
1459
1460
err:
1461
  if (need_lock)
1462
    pthread_mutex_unlock(&LOCK_index);
1463
  return error;
1464
}
1465
1466
1467
/**
1468
  Delete all logs refered to in the index file.
1469
  Start writing to a new log file.
1470
1471
  The new index file will only contain this file.
1472
520.1.22 by Brian Aker
Second pass of thd cleanup
1473
  @param session		Thread
1 by brian
clean slate
1474
1475
  @note
1476
    If not called from slave thread, write start event to new log
1477
1478
  @retval
1479
    0	ok
1480
  @retval
1481
    1   error
1482
*/
1483
520.1.22 by Brian Aker
Second pass of thd cleanup
1484
bool DRIZZLE_BIN_LOG::reset_logs(Session* session)
1 by brian
clean slate
1485
{
1486
  LOG_INFO linfo;
1487
  bool error=0;
1488
  const char* save_name;
1489
1490
  /*
1491
    We need to get both locks to be sure that no one is trying to
1492
    write to the index log file.
1493
  */
1494
  pthread_mutex_lock(&LOCK_log);
1495
  pthread_mutex_lock(&LOCK_index);
1496
1497
  /*
1498
    The following mutex is needed to ensure that no threads call
520.1.22 by Brian Aker
Second pass of thd cleanup
1499
    'delete session' as we would then risk missing a 'rollback' from this
1 by brian
clean slate
1500
    thread. If the transaction involved MyISAM tables, it should go
1501
    into binlog even on rollback.
1502
  */
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1503
  pthread_mutex_lock(&LOCK_thread_count);
1 by brian
clean slate
1504
1505
  /* Save variables so that we can reopen the log */
1506
  save_name=name;
1507
  name=0;					// Protect against free
1508
  close(LOG_CLOSE_TO_BE_OPENED);
1509
1510
  /* First delete all old log files */
1511
461 by Monty Taylor
Removed NullS. bu-bye.
1512
  if (find_log_pos(&linfo, NULL, 0))
1 by brian
clean slate
1513
  {
1514
    error=1;
1515
    goto err;
1516
  }
1517
1518
  for (;;)
1519
  {
1520
    if ((error= my_delete_allow_opened(linfo.log_file_name, MYF(0))) != 0)
1521
    {
1522
      if (my_errno == ENOENT) 
1523
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
1524
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1525
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1526
                            linfo.log_file_name);
338 by Monty Taylor
Tagged more strings.
1527
        sql_print_information(_("Failed to delete file '%s'"),
1 by brian
clean slate
1528
                              linfo.log_file_name);
1529
        my_errno= 0;
1530
        error= 0;
1531
      }
1532
      else
1533
      {
520.1.22 by Brian Aker
Second pass of thd cleanup
1534
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1535
                            ER_BINLOG_PURGE_FATAL_ERR,
338 by Monty Taylor
Tagged more strings.
1536
                            _("a problem with deleting %s; "
1 by brian
clean slate
1537
                            "consider examining correspondence "
1538
                            "of your binlog index file "
338 by Monty Taylor
Tagged more strings.
1539
                            "to the actual binlog files"),
1 by brian
clean slate
1540
                            linfo.log_file_name);
1541
        error= 1;
1542
        goto err;
1543
      }
1544
    }
1545
    if (find_next_log(&linfo, 0))
1546
      break;
1547
  }
1548
1549
  /* Start logging with a new file */
1550
  close(LOG_CLOSE_INDEX);
1551
  if ((error= my_delete_allow_opened(index_file_name, MYF(0))))	// Reset (open will update)
1552
  {
1553
    if (my_errno == ENOENT) 
1554
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
1555
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1556
                          ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1557
                          index_file_name);
338 by Monty Taylor
Tagged more strings.
1558
      sql_print_information(_("Failed to delete file '%s'"),
1 by brian
clean slate
1559
                            index_file_name);
1560
      my_errno= 0;
1561
      error= 0;
1562
    }
1563
    else
1564
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
1565
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1566
                          ER_BINLOG_PURGE_FATAL_ERR,
1567
                          "a problem with deleting %s; "
1568
                          "consider examining correspondence "
1569
                          "of your binlog index file "
1570
                          "to the actual binlog files",
1571
                          index_file_name);
1572
      error= 1;
1573
      goto err;
1574
    }
1575
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
1576
  if (!session->slave_thread)
1 by brian
clean slate
1577
    need_start_event=1;
1578
  if (!open_index_file(index_file_name, 0))
1579
    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0);
481 by Brian Aker
Remove all of uchar.
1580
  free((unsigned char*) save_name);
1 by brian
clean slate
1581
1582
err:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
1583
  pthread_mutex_unlock(&LOCK_thread_count);
1 by brian
clean slate
1584
  pthread_mutex_unlock(&LOCK_index);
1585
  pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1586
  return(error);
1 by brian
clean slate
1587
}
1588
1589
1590
/**
1591
  Delete relay log files prior to rli->group_relay_log_name
1592
  (i.e. all logs which are not involved in a non-finished group
1593
  (transaction)), remove them from the index file and start on next
1594
  relay log.
1595
1596
  IMPLEMENTATION
1597
  - Protects index file with LOCK_index
1598
  - Delete relevant relay log files
1599
  - Copy all file names after these ones to the front of the index file
1600
  - If the OS has truncate, truncate the file, else fill it with \n'
1601
  - Read the next file name from the index file and store in rli->linfo
1602
1603
  @param rli	       Relay log information
1604
  @param included     If false, all relay logs that are strictly before
1605
                      rli->group_relay_log_name are deleted ; if true, the
1606
                      latter is deleted too (i.e. all relay logs
1607
                      read by the SQL slave thread are deleted).
1608
1609
  @note
1610
    - This is only called from the slave-execute thread when it has read
1611
    all commands from a relay log and want to switch to a new relay log.
1612
    - When this happens, we can be in an active transaction as
1613
    a transaction can span over two relay logs
1614
    (although it is always written as a single block to the master's binary
1615
    log, hence cannot span over two master's binary logs).
1616
1617
  @retval
1618
    0			ok
1619
  @retval
1620
    LOG_INFO_EOF	        End of log-index-file found
1621
  @retval
1622
    LOG_INFO_SEEK	Could not allocate IO cache
1623
  @retval
1624
    LOG_INFO_IO		Got IO error while reading file
1625
*/
1626
1627
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1628
int DRIZZLE_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
1 by brian
clean slate
1629
{
1630
  int error;
1631
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1632
  assert(is_open());
1633
  assert(rli->slave_running == 1);
490 by Brian Aker
More effort around master.info (and relay.info)
1634
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name.c_str()));
1 by brian
clean slate
1635
1636
  pthread_mutex_lock(&LOCK_index);
1637
  pthread_mutex_lock(&rli->log_space_lock);
490 by Brian Aker
More effort around master.info (and relay.info)
1638
  rli->relay_log.purge_logs(rli->group_relay_log_name.c_str(), included,
1 by brian
clean slate
1639
                            0, 0, &rli->log_space_total);
1640
  // Tell the I/O thread to take the relay_log_space_limit into account
1641
  rli->ignore_log_space_limit= 0;
1642
  pthread_mutex_unlock(&rli->log_space_lock);
1643
1644
  /*
1645
    Ok to broadcast after the critical region as there is no risk of
1646
    the mutex being destroyed by this thread later - this helps save
1647
    context switches
1648
  */
1649
  pthread_cond_broadcast(&rli->log_space_cond);
1650
  
1651
  /*
1652
    Read the next log file name from the index file and pass it back to
1653
    the caller
1654
    If included is true, we want the first relay log;
1655
    otherwise we want the one after event_relay_log_name.
1656
  */
461 by Monty Taylor
Removed NullS. bu-bye.
1657
  if ((included && (error=find_log_pos(&rli->linfo, NULL, 0))) ||
1 by brian
clean slate
1658
      (!included &&
490 by Brian Aker
More effort around master.info (and relay.info)
1659
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name.c_str(), 0)) ||
1 by brian
clean slate
1660
        (error=find_next_log(&rli->linfo, 0)))))
1661
  {
1662
    char buff[22];
338 by Monty Taylor
Tagged more strings.
1663
    sql_print_error(_("next log error: %d  offset: %s  log: %s included: %d"),
1 by brian
clean slate
1664
                    error,
1665
                    llstr(rli->linfo.index_file_offset,buff),
490 by Brian Aker
More effort around master.info (and relay.info)
1666
                    rli->group_relay_log_name.c_str(),
1 by brian
clean slate
1667
                    included);
1668
    goto err;
1669
  }
1670
1671
  /*
1672
    Reset rli's coordinates to the current log.
1673
  */
1674
  rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
490 by Brian Aker
More effort around master.info (and relay.info)
1675
  rli->event_relay_log_name.assign(rli->linfo.log_file_name);
1 by brian
clean slate
1676
1677
  /*
1678
    If we removed the rli->group_relay_log_name file,
1679
    we must update the rli->group* coordinates, otherwise do not touch it as the
1680
    group's execution is not finished (e.g. COMMIT not executed)
1681
  */
1682
  if (included)
1683
  {
1684
    rli->group_relay_log_pos = BIN_LOG_HEADER_SIZE;
490 by Brian Aker
More effort around master.info (and relay.info)
1685
    rli->group_relay_log_name.assign(rli->linfo.log_file_name);
1 by brian
clean slate
1686
    rli->notify_group_relay_log_name_update();
1687
  }
1688
1689
  /* Store where we are in the new file for the execution thread */
1690
  flush_relay_log_info(rli);
1691
1692
err:
1693
  pthread_mutex_unlock(&LOCK_index);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1694
  return(error);
1 by brian
clean slate
1695
}
1696
1697
/**
1698
  Update log index_file.
1699
*/
1700
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1701
int DRIZZLE_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
1 by brian
clean slate
1702
{
1703
  if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset))
1704
    return LOG_INFO_IO;
1705
1706
  // now update offsets in index file for running threads
1707
  if (need_update_threads)
1708
    adjust_linfo_offsets(log_info->index_file_start_offset);
1709
  return 0;
1710
}
1711
1712
/**
1713
  Remove all logs before the given log from disk and from the index file.
1714
1715
  @param to_log	      Delete all log file name before this file.
1716
  @param included            If true, to_log is deleted too.
1717
  @param need_mutex
1718
  @param need_update_threads If we want to update the log coordinates of
1719
                             all threads. False for relay logs, true otherwise.
1720
  @param freed_log_space     If not null, decrement this variable of
1721
                             the amount of log space freed
1722
1723
  @note
1724
    If any of the logs before the deleted one is in use,
1725
    only purge logs up to this one.
1726
1727
  @retval
1728
    0			ok
1729
  @retval
1730
    LOG_INFO_EOF		to_log not found
1731
    LOG_INFO_EMFILE             too many files opened
1732
    LOG_INFO_FATAL              if any other than ENOENT error from
15 by brian
Fix for stat, NETWARE removal
1733
                                stat() or my_delete()
1 by brian
clean slate
1734
*/
1735
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1736
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log, 
1 by brian
clean slate
1737
                          bool included,
1738
                          bool need_mutex, 
1739
                          bool need_update_threads, 
151 by Brian Aker
Ulonglong to uint64_t
1740
                          uint64_t *decrease_log_space)
1 by brian
clean slate
1741
{
1742
  int error;
1743
  int ret = 0;
1744
  bool exit_loop= 0;
1745
  LOG_INFO log_info;
1746
1747
  if (need_mutex)
1748
    pthread_mutex_lock(&LOCK_index);
1749
  if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
1750
    goto err;
1751
1752
  /*
1753
    File name exists in index file; delete until we find this file
1754
    or a file that is used.
1755
  */
461 by Monty Taylor
Removed NullS. bu-bye.
1756
  if ((error=find_log_pos(&log_info, NULL, 0 /*no mutex*/)))
1 by brian
clean slate
1757
    goto err;
1758
  while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
1759
         !log_in_use(log_info.log_file_name))
1760
  {
15 by brian
Fix for stat, NETWARE removal
1761
    struct stat s;
1762
    if (stat(log_info.log_file_name, &s))
1 by brian
clean slate
1763
    {
15 by brian
Fix for stat, NETWARE removal
1764
      if (errno == ENOENT) 
1 by brian
clean slate
1765
      {
1766
        /*
1767
          It's not fatal if we can't stat a log file that does not exist;
1768
          If we could not stat, we won't delete.
1769
        */     
520.1.22 by Brian Aker
Second pass of thd cleanup
1770
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1771
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1772
                            log_info.log_file_name);
338 by Monty Taylor
Tagged more strings.
1773
        sql_print_information(_("Failed to execute stat() on file '%s'"),
1 by brian
clean slate
1774
			      log_info.log_file_name);
1775
        my_errno= 0;
1776
      }
1777
      else
1778
      {
1779
        /*
1780
          Other than ENOENT are fatal
1781
        */
520.1.22 by Brian Aker
Second pass of thd cleanup
1782
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1783
                            ER_BINLOG_PURGE_FATAL_ERR,
338 by Monty Taylor
Tagged more strings.
1784
                            _("a problem with getting info on being purged %s; "
1 by brian
clean slate
1785
                            "consider examining correspondence "
1786
                            "of your binlog index file "
338 by Monty Taylor
Tagged more strings.
1787
                            "to the actual binlog files"),
1 by brian
clean slate
1788
                            log_info.log_file_name);
1789
        error= LOG_INFO_FATAL;
1790
        goto err;
1791
      }
1792
    }
1793
    else
1794
    {
1795
      if (!my_delete(log_info.log_file_name, MYF(0)))
1796
      {
1797
        if (decrease_log_space)
1798
          *decrease_log_space-= s.st_size;
1799
      }
1800
      else
1801
      {
1802
        if (my_errno == ENOENT) 
1803
        {
520.1.22 by Brian Aker
Second pass of thd cleanup
1804
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1805
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1806
                              log_info.log_file_name);
338 by Monty Taylor
Tagged more strings.
1807
          sql_print_information(_("Failed to delete file '%s'"),
1 by brian
clean slate
1808
                                log_info.log_file_name);
1809
          my_errno= 0;
1810
        }
1811
        else
1812
        {
520.1.22 by Brian Aker
Second pass of thd cleanup
1813
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1814
                              ER_BINLOG_PURGE_FATAL_ERR,
338 by Monty Taylor
Tagged more strings.
1815
                              _("a problem with deleting %s; "
1 by brian
clean slate
1816
                              "consider examining correspondence "
1817
                              "of your binlog index file "
338 by Monty Taylor
Tagged more strings.
1818
                              "to the actual binlog files"),
1 by brian
clean slate
1819
                              log_info.log_file_name);
1820
          if (my_errno == EMFILE)
1821
          {
1822
            error= LOG_INFO_EMFILE;
1823
          }
1824
          error= LOG_INFO_FATAL;
1825
          goto err;
1826
        }
1827
      }
1828
    }
1829
1830
    if (find_next_log(&log_info, 0) || exit_loop)
1831
      break;
1832
  }
1833
  
1834
  /*
1835
    If we get killed -9 here, the sysadmin would have to edit
1836
    the log index file after restart - otherwise, this should be safe
1837
  */
1838
  error= update_log_index(&log_info, need_update_threads);
1839
  if (error == 0) {
1840
    error = ret;
1841
  }
1842
1843
err:
1844
  if (need_mutex)
1845
    pthread_mutex_unlock(&LOCK_index);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1846
  return(error);
1 by brian
clean slate
1847
}
1848
1849
/**
1850
  Remove all logs before the given file date from disk and from the
1851
  index file.
1852
520.1.22 by Brian Aker
Second pass of thd cleanup
1853
  @param session		Thread pointer
1 by brian
clean slate
1854
  @param before_date	Delete all log files before given date.
1855
1856
  @note
1857
    If any of the logs before the deleted one is in use,
1858
    only purge logs up to this one.
1859
1860
  @retval
1861
    0				ok
1862
  @retval
1863
    LOG_INFO_PURGE_NO_ROTATE	Binary file that can't be rotated
1864
    LOG_INFO_FATAL              if any other than ENOENT error from
15 by brian
Fix for stat, NETWARE removal
1865
                                stat() or my_delete()
1 by brian
clean slate
1866
*/
1867
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1868
int DRIZZLE_BIN_LOG::purge_logs_before_date(time_t purge_time)
1 by brian
clean slate
1869
{
1870
  int error;
1871
  LOG_INFO log_info;
15 by brian
Fix for stat, NETWARE removal
1872
  struct stat stat_area;
1 by brian
clean slate
1873
1874
  pthread_mutex_lock(&LOCK_index);
1875
1876
  /*
1877
    Delete until we find curren file
1878
    or a file that is used or a file
1879
    that is older than purge_time.
1880
  */
461 by Monty Taylor
Removed NullS. bu-bye.
1881
  if ((error=find_log_pos(&log_info, NULL, 0 /*no mutex*/)))
1 by brian
clean slate
1882
    goto err;
1883
1884
  while (strcmp(log_file_name, log_info.log_file_name) &&
1885
	 !log_in_use(log_info.log_file_name))
1886
  {
15 by brian
Fix for stat, NETWARE removal
1887
    if (stat(log_info.log_file_name, &stat_area))
1 by brian
clean slate
1888
    {
15 by brian
Fix for stat, NETWARE removal
1889
      if (errno == ENOENT) 
1 by brian
clean slate
1890
      {
1891
        /*
1892
          It's not fatal if we can't stat a log file that does not exist.
1893
        */     
520.1.22 by Brian Aker
Second pass of thd cleanup
1894
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1895
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1896
                            log_info.log_file_name);
338 by Monty Taylor
Tagged more strings.
1897
	sql_print_information(_("Failed to execute stat() on file '%s'"),
1 by brian
clean slate
1898
			      log_info.log_file_name);
1899
        my_errno= 0;
1900
      }
1901
      else
1902
      {
1903
        /*
1904
          Other than ENOENT are fatal
1905
        */
520.1.22 by Brian Aker
Second pass of thd cleanup
1906
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1907
                            ER_BINLOG_PURGE_FATAL_ERR,
338 by Monty Taylor
Tagged more strings.
1908
                            _("a problem with getting info on being purged %s; "
1 by brian
clean slate
1909
                            "consider examining correspondence "
1910
                            "of your binlog index file "
338 by Monty Taylor
Tagged more strings.
1911
                            "to the actual binlog files"),
1 by brian
clean slate
1912
                            log_info.log_file_name);
1913
        error= LOG_INFO_FATAL;
1914
        goto err;
1915
      }
1916
    }
1917
    else
1918
    {
1919
      if (stat_area.st_mtime >= purge_time)
1920
        break;
1921
      if (my_delete(log_info.log_file_name, MYF(0)))
1922
      {
1923
        if (my_errno == ENOENT) 
1924
        {
1925
          /* It's not fatal even if we can't delete a log file */
520.1.22 by Brian Aker
Second pass of thd cleanup
1926
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1 by brian
clean slate
1927
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1928
                              log_info.log_file_name);
338 by Monty Taylor
Tagged more strings.
1929
          sql_print_information(_("Failed to delete file '%s'"),
1 by brian
clean slate
1930
                                log_info.log_file_name);
1931
          my_errno= 0;
1932
        }
1933
        else
1934
        {
520.1.22 by Brian Aker
Second pass of thd cleanup
1935
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1 by brian
clean slate
1936
                              ER_BINLOG_PURGE_FATAL_ERR,
338 by Monty Taylor
Tagged more strings.
1937
                              _("a problem with deleting %s; "
1 by brian
clean slate
1938
                              "consider examining correspondence "
1939
                              "of your binlog index file "
338 by Monty Taylor
Tagged more strings.
1940
                              "to the actual binlog files"),
1 by brian
clean slate
1941
                              log_info.log_file_name);
1942
          error= LOG_INFO_FATAL;
1943
          goto err;
1944
        }
1945
      }
1946
    }
1947
    if (find_next_log(&log_info, 0))
1948
      break;
1949
  }
1950
1951
  /*
1952
    If we get killed -9 here, the sysadmin would have to edit
1953
    the log index file after restart - otherwise, this should be safe
1954
  */
1955
  error= update_log_index(&log_info, 1);
1956
1957
err:
1958
  pthread_mutex_unlock(&LOCK_index);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
1959
  return(error);
1 by brian
clean slate
1960
}
1961
1962
1963
/**
1964
  Create a new log file name.
1965
1966
  @param buf		buf of at least FN_REFLEN where new name is stored
1967
1968
  @note
1969
    If file name will be longer then FN_REFLEN it will be truncated
1970
*/
1971
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1972
void DRIZZLE_BIN_LOG::make_log_name(char* buf, const char* log_ident)
1 by brian
clean slate
1973
{
482 by Brian Aker
Remove uint.
1974
  uint32_t dir_len = dirname_length(log_file_name); 
1 by brian
clean slate
1975
  if (dir_len >= FN_REFLEN)
1976
    dir_len=FN_REFLEN-1;
411.1.1 by Brian Aker
Work on removing GNU specific calls.
1977
  my_stpncpy(buf, log_file_name, dir_len);
1 by brian
clean slate
1978
  strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
1979
}
1980
1981
1982
/**
1983
  Check if we are writing/reading to the given log file.
1984
*/
1985
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
1986
bool DRIZZLE_BIN_LOG::is_active(const char *log_file_name_arg)
1 by brian
clean slate
1987
{
1988
  return !strcmp(log_file_name, log_file_name_arg);
1989
}
1990
1991
1992
/*
1993
  Wrappers around new_file_impl to avoid using argument
1994
  to control locking. The argument 1) less readable 2) breaks
1995
  incapsulation 3) allows external access to the class without
1996
  a lock (which is not possible with private new_file_without_locking
1997
  method).
1998
*/
1999
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2000
void DRIZZLE_BIN_LOG::new_file()
1 by brian
clean slate
2001
{
2002
  new_file_impl(1);
2003
}
2004
2005
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2006
void DRIZZLE_BIN_LOG::new_file_without_locking()
1 by brian
clean slate
2007
{
2008
  new_file_impl(0);
2009
}
2010
2011
2012
/**
2013
  Start writing to a new log file or reopen the old file.
2014
2015
  @param need_lock		Set to 1 if caller has not locked LOCK_log
2016
2017
  @note
2018
    The new file name is stored last in the index file
2019
*/
2020
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2021
void DRIZZLE_BIN_LOG::new_file_impl(bool need_lock)
1 by brian
clean slate
2022
{
2023
  char new_name[FN_REFLEN], *new_name_ptr, *old_name;
2024
2025
  if (!is_open())
2026
  {
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2027
    return;
1 by brian
clean slate
2028
  }
2029
2030
  if (need_lock)
2031
    pthread_mutex_lock(&LOCK_log);
2032
  pthread_mutex_lock(&LOCK_index);
2033
2034
  safe_mutex_assert_owner(&LOCK_log);
2035
  safe_mutex_assert_owner(&LOCK_index);
2036
2037
  /*
2038
    if binlog is used as tc log, be sure all xids are "unlogged",
2039
    so that on recover we only need to scan one - latest - binlog file
2040
    for prepared xids. As this is expected to be a rare event,
2041
    simple wait strategy is enough. We're locking LOCK_log to be sure no
2042
    new Xid_log_event's are added to the log (and prepared_xids is not
2043
    increased), and waiting on COND_prep_xids for late threads to
2044
    catch up.
2045
  */
2046
  if (prepared_xids)
2047
  {
2048
    tc_log_page_waits++;
2049
    pthread_mutex_lock(&LOCK_prep_xids);
2050
    while (prepared_xids) {
2051
      pthread_cond_wait(&COND_prep_xids, &LOCK_prep_xids);
2052
    }
2053
    pthread_mutex_unlock(&LOCK_prep_xids);
2054
  }
2055
2056
  /* Reuse old name if not binlog and not update log */
2057
  new_name_ptr= name;
2058
2059
  /*
2060
    If user hasn't specified an extension, generate a new log name
2061
    We have to do this here and not in open as we want to store the
2062
    new file name in the current binary log file.
2063
  */
2064
  if (generate_new_name(new_name, name))
2065
    goto end;
2066
  new_name_ptr=new_name;
2067
2068
  if (log_type == LOG_BIN)
2069
  {
2070
    if (!no_auto_events)
2071
    {
2072
      /*
2073
        We log the whole file name for log file as the user may decide
2074
        to change base names at some point.
2075
      */
2076
      Rotate_log_event r(new_name+dirname_length(new_name),
2077
                         0, LOG_EVENT_OFFSET, 0);
2078
      r.write(&log_file);
2079
      bytes_written += r.data_written;
2080
    }
2081
    /*
2082
      Update needs to be signalled even if there is no rotate event
2083
      log rotation should give the waiting thread a signal to
2084
      discover EOF and move on to the next log.
2085
    */
2086
    signal_update();
2087
  }
2088
  old_name=name;
2089
  name=0;				// Don't free name
2090
  close(LOG_CLOSE_TO_BE_OPENED);
2091
2092
  /*
2093
     Note that at this point, log_state != LOG_CLOSED (important for is_open()).
2094
  */
2095
2096
  /*
2097
     new_file() is only used for rotation (in FLUSH LOGS or because size >
2098
     max_binlog_size or max_relay_log_size).
2099
     If this is a binary log, the Format_description_log_event at the beginning of
2100
     the new file should have created=0 (to distinguish with the
2101
     Format_description_log_event written at server startup, which should
2102
     trigger temp tables deletion on slaves.
2103
  */
2104
2105
  open(old_name, log_type, new_name_ptr,
2106
       io_cache_type, no_auto_events, max_size, 1);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
2107
  free(old_name);
1 by brian
clean slate
2108
2109
end:
2110
  if (need_lock)
2111
    pthread_mutex_unlock(&LOCK_log);
2112
  pthread_mutex_unlock(&LOCK_index);
2113
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2114
  return;
1 by brian
clean slate
2115
}
2116
2117
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2118
bool DRIZZLE_BIN_LOG::append(Log_event* ev)
1 by brian
clean slate
2119
{
2120
  bool error = 0;
2121
  pthread_mutex_lock(&LOCK_log);
2122
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2123
  assert(log_file.type == SEQ_READ_APPEND);
1 by brian
clean slate
2124
  /*
2125
    Log_event::write() is smart enough to use my_b_write() or
2126
    my_b_append() depending on the kind of cache we have.
2127
  */
2128
  if (ev->write(&log_file))
2129
  {
2130
    error=1;
2131
    goto err;
2132
  }
2133
  bytes_written+= ev->data_written;
2134
  if ((uint) my_b_append_tell(&log_file) > max_size)
2135
    new_file_without_locking();
2136
2137
err:
2138
  pthread_mutex_unlock(&LOCK_log);
2139
  signal_update();				// Safe as we don't call close
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2140
  return(error);
1 by brian
clean slate
2141
}
2142
2143
482 by Brian Aker
Remove uint.
2144
bool DRIZZLE_BIN_LOG::appendv(const char* buf, uint32_t len,...)
1 by brian
clean slate
2145
{
2146
  bool error= 0;
2147
  va_list(args);
2148
  va_start(args,len);
2149
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2150
  assert(log_file.type == SEQ_READ_APPEND);
1 by brian
clean slate
2151
2152
  safe_mutex_assert_owner(&LOCK_log);
2153
  do
2154
  {
481 by Brian Aker
Remove all of uchar.
2155
    if (my_b_append(&log_file,(unsigned char*) buf,len))
1 by brian
clean slate
2156
    {
2157
      error= 1;
2158
      goto err;
2159
    }
2160
    bytes_written += len;
2161
  } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
2162
  if ((uint) my_b_append_tell(&log_file) > max_size)
2163
    new_file_without_locking();
2164
2165
err:
2166
  if (!error)
2167
    signal_update();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2168
  return(error);
1 by brian
clean slate
2169
}
2170
2171
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2172
bool DRIZZLE_BIN_LOG::flush_and_sync()
1 by brian
clean slate
2173
{
2174
  int err=0, fd=log_file.file;
2175
  safe_mutex_assert_owner(&LOCK_log);
2176
  if (flush_io_cache(&log_file))
2177
    return 1;
2178
  if (++sync_binlog_counter >= sync_binlog_period && sync_binlog_period)
2179
  {
2180
    sync_binlog_counter= 0;
2181
    err=my_sync(fd, MYF(MY_WME));
2182
  }
2183
  return err;
2184
}
2185
520.1.22 by Brian Aker
Second pass of thd cleanup
2186
void DRIZZLE_BIN_LOG::start_union_events(Session *session, query_id_t query_id_param)
2187
{
2188
  assert(!session->binlog_evt_union.do_union);
2189
  session->binlog_evt_union.do_union= true;
2190
  session->binlog_evt_union.unioned_events= false;
2191
  session->binlog_evt_union.unioned_events_trans= false;
2192
  session->binlog_evt_union.first_query_id= query_id_param;
2193
}
2194
2195
void DRIZZLE_BIN_LOG::stop_union_events(Session *session)
2196
{
2197
  assert(session->binlog_evt_union.do_union);
2198
  session->binlog_evt_union.do_union= false;
2199
}
2200
2201
bool DRIZZLE_BIN_LOG::is_query_in_union(Session *session, query_id_t query_id_param)
2202
{
2203
  return (session->binlog_evt_union.do_union && 
2204
          query_id_param >= session->binlog_evt_union.first_query_id);
1 by brian
clean slate
2205
}
2206
2207
2208
/*
2209
  These functions are placed in this file since they need access to
2210
  binlog_hton, which has internal linkage.
2211
*/
2212
520.1.21 by Brian Aker
THD -> Session rename
2213
int Session::binlog_setup_trx_data()
1 by brian
clean slate
2214
{
2215
  binlog_trx_data *trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2216
    (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2217
2218
  if (trx_data)
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2219
    return(0);                             // Already set up
1 by brian
clean slate
2220
2221
  trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
2222
  if (!trx_data ||
575.4.3 by ysano
Rename mysql to drizzle.
2223
      open_cached_file(&trx_data->trans_log, drizzle_tmpdir,
1 by brian
clean slate
2224
                       LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
2225
  {
481 by Brian Aker
Remove all of uchar.
2226
    free((unsigned char*)trx_data);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2227
    return(1);                      // Didn't manage to set it up
1 by brian
clean slate
2228
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
2229
  session_set_ha_data(this, binlog_hton, trx_data);
1 by brian
clean slate
2230
520.1.22 by Brian Aker
Second pass of thd cleanup
2231
  trx_data= new (session_get_ha_data(this, binlog_hton)) binlog_trx_data;
1 by brian
clean slate
2232
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2233
  return(0);
1 by brian
clean slate
2234
}
2235
2236
/*
2237
  Function to start a statement and optionally a transaction for the
2238
  binary log.
2239
2240
  SYNOPSIS
2241
    binlog_start_trans_and_stmt()
2242
2243
  DESCRIPTION
2244
2245
    This function does three things:
2246
    - Start a transaction if not in autocommit mode or if a BEGIN
2247
      statement has been seen.
2248
2249
    - Start a statement transaction to allow us to truncate the binary
2250
      log.
2251
2252
    - Save the currrent binlog position so that we can roll back the
2253
      statement by truncating the transaction log.
2254
2255
      We only update the saved position if the old one was undefined,
2256
      the reason is that there are some cases (e.g., for CREATE-SELECT)
2257
      where the position is saved twice (e.g., both in
520.1.21 by Brian Aker
THD -> Session rename
2258
      select_create::prepare() and Session::binlog_write_table_map()) , but
1 by brian
clean slate
2259
      we should use the first. This means that calls to this function
2260
      can be used to start the statement before the first table map
2261
      event, to include some extra events.
2262
 */
2263
2264
void
520.1.21 by Brian Aker
THD -> Session rename
2265
Session::binlog_start_trans_and_stmt()
1 by brian
clean slate
2266
{
520.1.22 by Brian Aker
Second pass of thd cleanup
2267
  binlog_trx_data *trx_data= (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2268
2269
  if (trx_data == NULL ||
2270
      trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
2271
  {
2272
    this->binlog_set_stmt_begin();
2273
    if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2274
      trans_register_ha(this, true, binlog_hton);
2275
    trans_register_ha(this, false, binlog_hton);
1 by brian
clean slate
2276
    /*
2277
      Mark statement transaction as read/write. We never start
2278
      a binary log transaction and keep it read-only,
2279
      therefore it's best to mark the transaction read/write just
2280
      at the same time we start it.
2281
      Not necessary to mark the normal transaction read/write
2282
      since the statement-level flag will be propagated automatically
2283
      inside ha_commit_trans.
2284
    */
2285
    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
2286
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2287
  return;
1 by brian
clean slate
2288
}
2289
520.1.21 by Brian Aker
THD -> Session rename
2290
void Session::binlog_set_stmt_begin() {
1 by brian
clean slate
2291
  binlog_trx_data *trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2292
    (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2293
2294
  /*
2295
    The call to binlog_trans_log_savepos() might create the trx_data
2296
    structure, if it didn't exist before, so we save the position
2297
    into an auto variable and then write it into the transaction
2298
    data for the binary log (i.e., trx_data).
2299
  */
2300
  my_off_t pos= 0;
2301
  binlog_trans_log_savepos(this, &pos);
520.1.22 by Brian Aker
Second pass of thd cleanup
2302
  trx_data= (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2303
  trx_data->before_stmt_pos= pos;
2304
}
2305
2306
2307
/*
2308
  Write a table map to the binary log.
2309
 */
2310
520.1.21 by Brian Aker
THD -> Session rename
2311
int Session::binlog_write_table_map(Table *table, bool is_trans)
1 by brian
clean slate
2312
{
2313
  int error;
2314
2315
  /* Pre-conditions */
365.2.4 by Monty Taylor
Updated some Long refs to use stdint constants.
2316
  assert(table->s->table_map_id != UINT32_MAX);
1 by brian
clean slate
2317
2318
  Table_map_log_event::flag_set const
2319
    flags= Table_map_log_event::TM_NO_FLAGS;
2320
2321
  Table_map_log_event
2322
    the_event(this, table, table->s->table_map_id, is_trans, flags);
2323
2324
  if (is_trans && binlog_table_maps == 0)
2325
    binlog_start_trans_and_stmt();
2326
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
2327
  if ((error= drizzle_bin_log.write(&the_event)))
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2328
    return(error);
1 by brian
clean slate
2329
2330
  binlog_table_maps++;
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
2331
  table->s->table_map_version= drizzle_bin_log.table_map_version();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2332
  return(0);
1 by brian
clean slate
2333
}
2334
2335
Rows_log_event*
520.1.21 by Brian Aker
THD -> Session rename
2336
Session::binlog_get_pending_rows_event() const
1 by brian
clean slate
2337
{
2338
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2339
    (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2340
  /*
2341
    This is less than ideal, but here's the story: If there is no
2342
    trx_data, prepare_pending_rows_event() has never been called
2343
    (since the trx_data is set up there). In that case, we just return
2344
    NULL.
2345
   */
2346
  return trx_data ? trx_data->pending() : NULL;
2347
}
2348
2349
void
520.1.21 by Brian Aker
THD -> Session rename
2350
Session::binlog_set_pending_rows_event(Rows_log_event* ev)
1 by brian
clean slate
2351
{
520.1.22 by Brian Aker
Second pass of thd cleanup
2352
  if (session_get_ha_data(this, binlog_hton) == NULL)
1 by brian
clean slate
2353
    binlog_setup_trx_data();
2354
2355
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2356
    (binlog_trx_data*) session_get_ha_data(this, binlog_hton);
1 by brian
clean slate
2357
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2358
  assert(trx_data);
1 by brian
clean slate
2359
  trx_data->set_pending(ev);
2360
}
2361
2362
2363
/*
2364
  Moves the last bunch of rows from the pending Rows event to the binlog
2365
  (either cached binlog if transaction, or disk binlog). Sets a new pending
2366
  event.
2367
*/
2368
int
520.1.22 by Brian Aker
Second pass of thd cleanup
2369
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(Session *session,
1 by brian
clean slate
2370
                                                Rows_log_event* event)
2371
{
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
2372
  assert(drizzle_bin_log.is_open());
1 by brian
clean slate
2373
2374
  int error= 0;
2375
2376
  binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2377
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
2378
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2379
  assert(trx_data);
1 by brian
clean slate
2380
2381
  if (Rows_log_event* pending= trx_data->pending())
2382
  {
2383
    IO_CACHE *file= &log_file;
2384
2385
    /*
2386
      Decide if we should write to the log file directly or to the
2387
      transaction log.
2388
    */
2389
    if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log))
2390
      file= &trx_data->trans_log;
2391
2392
    /*
2393
      If we are writing to the log file directly, we could avoid
2394
      locking the log. This does not work since we need to step the
2395
      m_table_map_version below, and that change has to be protected
2396
      by the LOCK_log mutex.
2397
    */
2398
    pthread_mutex_lock(&LOCK_log);
2399
2400
    /*
2401
      Write pending event to log file or transaction cache
2402
    */
2403
    if (pending->write(file))
2404
    {
2405
      pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2406
      return(1);
1 by brian
clean slate
2407
    }
2408
2409
    /*
2410
      We step the table map version if we are writing an event
2411
      representing the end of a statement.  We do this regardless of
2412
      wheather we write to the transaction cache or to directly to the
2413
      file.
2414
2415
      In an ideal world, we could avoid stepping the table map version
2416
      if we were writing to a transaction cache, since we could then
2417
      reuse the table map that was written earlier in the transaction
2418
      cache.  This does not work since STMT_END_F implies closing all
2419
      table mappings on the slave side.
2420
2421
      TODO: Find a solution so that table maps does not have to be
2422
      written several times within a transaction.
2423
     */
2424
    if (pending->get_flags(Rows_log_event::STMT_END_F))
2425
      ++m_table_map_version;
2426
2427
    delete pending;
2428
2429
    if (file == &log_file)
2430
    {
2431
      error= flush_and_sync();
2432
      if (!error)
2433
      {
2434
        signal_update();
2435
        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2436
      }
2437
    }
2438
2439
    pthread_mutex_unlock(&LOCK_log);
2440
  }
2441
520.1.22 by Brian Aker
Second pass of thd cleanup
2442
  session->binlog_set_pending_rows_event(event);
1 by brian
clean slate
2443
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2444
  return(error);
1 by brian
clean slate
2445
}
2446
2447
/**
2448
  Write an event to the binary log.
2449
*/
2450
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2451
bool DRIZZLE_BIN_LOG::write(Log_event *event_info)
1 by brian
clean slate
2452
{
520.1.22 by Brian Aker
Second pass of thd cleanup
2453
  Session *session= event_info->session;
1 by brian
clean slate
2454
  bool error= 1;
2455
520.1.22 by Brian Aker
Second pass of thd cleanup
2456
  if (session->binlog_evt_union.do_union)
1 by brian
clean slate
2457
  {
2458
    /*
2459
      In Stored function; Remember that function call caused an update.
2460
      We will log the function call to the binary log on function exit
2461
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
2462
    session->binlog_evt_union.unioned_events= true;
2463
    session->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2464
    return(0);
1 by brian
clean slate
2465
  }
2466
2467
  /*
2468
    Flush the pending rows event to the transaction cache or to the
2469
    log file.  Since this function potentially aquire the LOCK_log
2470
    mutex, we do this before aquiring the LOCK_log mutex in this
2471
    function.
2472
2473
    We only end the statement if we are in a top-level statement.  If
2474
    we are inside a stored function, we do not end the statement since
2475
    this will close all tables on the slave.
2476
  */
2477
  bool const end_stmt= false;
520.1.22 by Brian Aker
Second pass of thd cleanup
2478
  session->binlog_flush_pending_rows_event(end_stmt);
1 by brian
clean slate
2479
2480
  pthread_mutex_lock(&LOCK_log);
2481
2482
  /*
2483
     In most cases this is only called if 'is_open()' is true; in fact this is
2484
     mostly called if is_open() *was* true a few instructions before, but it
2485
     could have changed since.
2486
  */
2487
  if (likely(is_open()))
2488
  {
2489
    IO_CACHE *file= &log_file;
2490
    /*
2491
      In the future we need to add to the following if tests like
2492
      "do the involved tables match (to be implemented)
2493
      binlog_[wild_]{do|ignore}_table?" (WL#1049)"
2494
    */
614 by Brian Aker
Remove filtering (wrong layer, belongs in plugin).
2495
    if (session && !(session->options & OPTION_BIN_LOG))
1 by brian
clean slate
2496
    {
398.1.10 by Monty Taylor
Actually removed VOID() this time.
2497
      pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2498
      return(0);
1 by brian
clean slate
2499
    }
2500
2501
    /*
2502
      Should we write to the binlog cache or to the binlog on disk?
2503
      Write to the binlog cache if:
2504
      - it is already not empty (meaning we're in a transaction; note that the
2505
     present event could be about a non-transactional table, but still we need
2506
     to write to the binlog cache in that case to handle updates to mixed
2507
     trans/non-trans table types the best possible in binlogging)
2508
      - or if the event asks for it (cache_stmt == TRUE).
2509
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
2510
    if (opt_using_transactions && session)
1 by brian
clean slate
2511
    {
520.1.22 by Brian Aker
Second pass of thd cleanup
2512
      if (session->binlog_setup_trx_data())
1 by brian
clean slate
2513
        goto err;
2514
2515
      binlog_trx_data *const trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
2516
        (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
2517
      IO_CACHE *trans_log= &trx_data->trans_log;
2518
      my_off_t trans_log_pos= my_b_tell(trans_log);
2519
      if (event_info->get_cache_stmt() || trans_log_pos != 0)
2520
      {
2521
        if (trans_log_pos == 0)
520.1.22 by Brian Aker
Second pass of thd cleanup
2522
          session->binlog_start_trans_and_stmt();
1 by brian
clean slate
2523
        file= trans_log;
2524
      }
2525
      /*
2526
        TODO as Mats suggested, for all the cases above where we write to
2527
        trans_log, it sounds unnecessary to lock LOCK_log. We should rather
2528
        test first if we want to write to trans_log, and if not, lock
2529
        LOCK_log.
2530
      */
2531
    }
2532
2533
    /*
2534
       Write the SQL command
2535
     */
2536
2537
    if (event_info->write(file))
2538
      goto err;
2539
2540
    if (file == &log_file) // we are writing to the real log (disk)
2541
    {
2542
      if (flush_and_sync())
2543
	goto err;
2544
      signal_update();
2545
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2546
    }
2547
    error=0;
2548
2549
err:
2550
    if (error)
2551
    {
2552
      if (my_errno == EFBIG)
2553
	my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(0));
2554
      else
2555
	my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno);
2556
      write_error=1;
2557
    }
2558
  }
2559
2560
  if (event_info->flags & LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F)
2561
    ++m_table_map_version;
2562
2563
  pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2564
  return(error);
1 by brian
clean slate
2565
}
2566
2567
2568
int error_log_print(enum loglevel level, const char *format,
2569
                    va_list args)
2570
{
2571
  return logger.error_log_print(level, format, args);
2572
}
2573
482 by Brian Aker
Remove uint.
2574
void DRIZZLE_BIN_LOG::rotate_and_purge(uint32_t flags)
1 by brian
clean slate
2575
{
2576
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2577
    pthread_mutex_lock(&LOCK_log);
2578
  if ((flags & RP_FORCE_ROTATE) ||
2579
      (my_b_tell(&log_file) >= (my_off_t) max_size))
2580
  {
2581
    new_file_without_locking();
2582
    if (expire_logs_days)
2583
    {
2584
      time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
2585
      if (purge_time >= 0)
2586
        purge_logs_before_date(purge_time);
2587
    }
2588
  }
2589
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2590
    pthread_mutex_unlock(&LOCK_log);
2591
}
2592
482 by Brian Aker
Remove uint.
2593
uint32_t DRIZZLE_BIN_LOG::next_file_id()
1 by brian
clean slate
2594
{
482 by Brian Aker
Remove uint.
2595
  uint32_t res;
1 by brian
clean slate
2596
  pthread_mutex_lock(&LOCK_log);
2597
  res = file_id++;
2598
  pthread_mutex_unlock(&LOCK_log);
2599
  return res;
2600
}
2601
2602
2603
/*
2604
  Write the contents of a cache to the binary log.
2605
2606
  SYNOPSIS
2607
    write_cache()
2608
    cache    Cache to write to the binary log
2609
    lock_log True if the LOCK_log mutex should be aquired, false otherwise
2610
    sync_log True if the log should be flushed and sync:ed
2611
2612
  DESCRIPTION
2613
    Write the contents of the cache to the binary log. The cache will
2614
    be reset as a READ_CACHE to be able to read the contents from it.
2615
 */
2616
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2617
int DRIZZLE_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
1 by brian
clean slate
2618
{
2619
  Mutex_sentry sentry(lock_log ? &LOCK_log : NULL);
2620
2621
  if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
2622
    return ER_ERROR_ON_WRITE;
482 by Brian Aker
Remove uint.
2623
  uint32_t length= my_b_bytes_in_cache(cache), group, carry, hdr_offs;
1 by brian
clean slate
2624
  long val;
481 by Brian Aker
Remove all of uchar.
2625
  unsigned char header[LOG_EVENT_HEADER_LEN];
1 by brian
clean slate
2626
2627
  /*
2628
    The events in the buffer have incorrect end_log_pos data
2629
    (relative to beginning of group rather than absolute),
2630
    so we'll recalculate them in situ so the binlog is always
2631
    correct, even in the middle of a group. This is possible
2632
    because we now know the start position of the group (the
2633
    offset of this cache in the log, if you will); all we need
2634
    to do is to find all event-headers, and add the position of
2635
    the group to the end_log_pos of each event.  This is pretty
2636
    straight forward, except that we read the cache in segments,
2637
    so an event-header might end up on the cache-border and get
2638
    split.
2639
  */
2640
2641
  group= (uint)my_b_tell(&log_file);
2642
  hdr_offs= carry= 0;
2643
2644
  do
2645
  {
2646
2647
    /*
2648
      if we only got a partial header in the last iteration,
2649
      get the other half now and process a full header.
2650
    */
2651
    if (unlikely(carry > 0))
2652
    {
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2653
      assert(carry < LOG_EVENT_HEADER_LEN);
1 by brian
clean slate
2654
2655
      /* assemble both halves */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2656
      memcpy(&header[carry], cache->read_pos, LOG_EVENT_HEADER_LEN - carry);
1 by brian
clean slate
2657
2658
      /* fix end_log_pos */
2659
      val= uint4korr(&header[LOG_POS_OFFSET]) + group;
2660
      int4store(&header[LOG_POS_OFFSET], val);
2661
2662
      /* write the first half of the split header */
2663
      if (my_b_write(&log_file, header, carry))
2664
        return ER_ERROR_ON_WRITE;
2665
2666
      /*
2667
        copy fixed second half of header to cache so the correct
2668
        version will be written later.
2669
      */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2670
      memcpy(cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry);
1 by brian
clean slate
2671
2672
      /* next event header at ... */
2673
      hdr_offs = uint4korr(&header[EVENT_LEN_OFFSET]) - carry;
2674
2675
      carry= 0;
2676
    }
2677
2678
    /* if there is anything to write, process it. */
2679
2680
    if (likely(length > 0))
2681
    {
2682
      /*
2683
        process all event-headers in this (partial) cache.
2684
        if next header is beyond current read-buffer,
2685
        we'll get it later (though not necessarily in the
2686
        very next iteration, just "eventually").
2687
      */
2688
2689
      while (hdr_offs < length)
2690
      {
2691
        /*
2692
          partial header only? save what we can get, process once
2693
          we get the rest.
2694
        */
2695
2696
        if (hdr_offs + LOG_EVENT_HEADER_LEN > length)
2697
        {
2698
          carry= length - hdr_offs;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
2699
          memcpy(header, cache->read_pos + hdr_offs, carry);
1 by brian
clean slate
2700
          length= hdr_offs;
2701
        }
2702
        else
2703
        {
2704
          /* we've got a full event-header, and it came in one piece */
2705
481 by Brian Aker
Remove all of uchar.
2706
          unsigned char *log_pos= (unsigned char *)cache->read_pos + hdr_offs + LOG_POS_OFFSET;
1 by brian
clean slate
2707
2708
          /* fix end_log_pos */
2709
          val= uint4korr(log_pos) + group;
2710
          int4store(log_pos, val);
2711
2712
          /* next event header at ... */
481 by Brian Aker
Remove all of uchar.
2713
          log_pos= (unsigned char *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET;
1 by brian
clean slate
2714
          hdr_offs += uint4korr(log_pos);
2715
2716
        }
2717
      }
2718
2719
      /*
2720
        Adjust hdr_offs. Note that it may still point beyond the segment
2721
        read in the next iteration; if the current event is very long,
2722
        it may take a couple of read-iterations (and subsequent adjustments
2723
        of hdr_offs) for it to point into the then-current segment.
2724
        If we have a split header (!carry), hdr_offs will be set at the
2725
        beginning of the next iteration, overwriting the value we set here:
2726
      */
2727
      hdr_offs -= length;
2728
    }
2729
2730
    /* Write data to the binary log file */
2731
    if (my_b_write(&log_file, cache->read_pos, length))
2732
      return ER_ERROR_ON_WRITE;
2733
    cache->read_pos=cache->read_end;		// Mark buffer used up
2734
  } while ((length= my_b_fill(cache)));
2735
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2736
  assert(carry == 0);
1 by brian
clean slate
2737
2738
  if (sync_log)
2739
    flush_and_sync();
2740
2741
  return 0;                                     // All OK
2742
}
2743
2744
/**
2745
  Write a cached log entry to the binary log.
2746
  - To support transaction over replication, we wrap the transaction
2747
  with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
2748
  We want to write a BEGIN/ROLLBACK block when a non-transactional table
2749
  was updated in a transaction which was rolled back. This is to ensure
2750
  that the same updates are run on the slave.
2751
520.1.22 by Brian Aker
Second pass of thd cleanup
2752
  @param session
1 by brian
clean slate
2753
  @param cache		The cache to copy to the binlog
2754
  @param commit_event   The commit event to print after writing the
2755
                        contents of the cache.
2756
2757
  @note
2758
    We only come here if there is something in the cache.
2759
  @note
2760
    The thing in the cache is always a complete transaction.
2761
  @note
2762
    'cache' needs to be reinitialized after this functions returns.
2763
*/
2764
520.1.22 by Brian Aker
Second pass of thd cleanup
2765
bool DRIZZLE_BIN_LOG::write(Session *session, IO_CACHE *cache, Log_event *commit_event)
1 by brian
clean slate
2766
{
398.1.10 by Monty Taylor
Actually removed VOID() this time.
2767
  pthread_mutex_lock(&LOCK_log);
1 by brian
clean slate
2768
2769
  /* NULL would represent nothing to replicate after ROLLBACK */
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2770
  assert(commit_event != NULL);
1 by brian
clean slate
2771
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2772
  assert(is_open());
1 by brian
clean slate
2773
  if (likely(is_open()))                       // Should always be true
2774
  {
2775
    /*
2776
      We only bother to write to the binary log if there is anything
2777
      to write.
2778
     */
2779
    if (my_b_tell(cache) > 0)
2780
    {
2781
      /*
2782
        Log "BEGIN" at the beginning of every transaction.  Here, a
2783
        transaction is either a BEGIN..COMMIT block or a single
2784
        statement in autocommit mode.
2785
      */
520.1.22 by Brian Aker
Second pass of thd cleanup
2786
      Query_log_event qinfo(session, STRING_WITH_LEN("BEGIN"), true, false);
1 by brian
clean slate
2787
      /*
2788
        Imagine this is rollback due to net timeout, after all
2789
        statements of the transaction succeeded. Then we want a
2790
        zero-error code in BEGIN.  In other words, if there was a
2791
        really serious error code it's already in the statement's
2792
        events, there is no need to put it also in this internally
2793
        generated event, and as this event is generated late it would
2794
        lead to false alarms.
2795
520.1.22 by Brian Aker
Second pass of thd cleanup
2796
        This is safer than session->clear_error() against kills at shutdown.
1 by brian
clean slate
2797
      */
2798
      qinfo.error_code= 0;
2799
      /*
2800
        Now this Query_log_event has artificial log_pos 0. It must be
2801
        adjusted to reflect the real position in the log. Not doing it
2802
        would confuse the slave: it would prevent this one from
2803
        knowing where he is in the master's binlog, which would result
2804
        in wrong positions being shown to the user, MASTER_POS_WAIT
2805
        undue waiting etc.
2806
      */
2807
      if (qinfo.write(&log_file))
2808
        goto err;
2809
2810
      if ((write_error= write_cache(cache, false, false)))
2811
        goto err;
2812
2813
      if (commit_event && commit_event->write(&log_file))
2814
        goto err;
2815
      if (flush_and_sync())
2816
        goto err;
2817
      if (cache->error)				// Error on read
2818
      {
2819
        sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
2820
        write_error=1;				// Don't give more errors
2821
        goto err;
2822
      }
2823
      signal_update();
2824
    }
2825
2826
    /*
2827
      if commit_event is Xid_log_event, increase the number of
2828
      prepared_xids (it's decreasd in ::unlog()). Binlog cannot be rotated
2829
      if there're prepared xids in it - see the comment in new_file() for
2830
      an explanation.
2831
      If the commit_event is not Xid_log_event (then it's a Query_log_event)
2832
      rotate binlog, if necessary.
2833
    */
2834
    if (commit_event && commit_event->get_type_code() == XID_EVENT)
2835
    {
2836
      pthread_mutex_lock(&LOCK_prep_xids);
2837
      prepared_xids++;
2838
      pthread_mutex_unlock(&LOCK_prep_xids);
2839
    }
2840
    else
2841
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2842
  }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
2843
  pthread_mutex_unlock(&LOCK_log);
1 by brian
clean slate
2844
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2845
  return(0);
1 by brian
clean slate
2846
2847
err:
2848
  if (!write_error)
2849
  {
2850
    write_error= 1;
2851
    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
2852
  }
398.1.10 by Monty Taylor
Actually removed VOID() this time.
2853
  pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2854
  return(1);
1 by brian
clean slate
2855
}
2856
2857
2858
/**
2859
  Wait until we get a signal that the relay log has been updated
2860
520.1.22 by Brian Aker
Second pass of thd cleanup
2861
  @param[in] session   a Session struct
1 by brian
clean slate
2862
  @note
2863
    LOCK_log must be taken before calling this function.
2864
    It will be released at the end of the function.
2865
*/
2866
520.1.22 by Brian Aker
Second pass of thd cleanup
2867
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(Session* session)
1 by brian
clean slate
2868
{
2869
  const char *old_msg;
520.1.22 by Brian Aker
Second pass of thd cleanup
2870
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
1 by brian
clean slate
2871
                           "Slave has read all relay log; " 
2872
                           "waiting for the slave I/O "
2873
                           "thread to update it" );
2874
  pthread_cond_wait(&update_cond, &LOCK_log);
520.1.22 by Brian Aker
Second pass of thd cleanup
2875
  session->exit_cond(old_msg);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2876
  return;
1 by brian
clean slate
2877
}
2878
2879
2880
/**
2881
  Wait until we get a signal that the binary log has been updated.
2882
  Applies to master only.
2883
     
2884
  NOTES
520.1.22 by Brian Aker
Second pass of thd cleanup
2885
  @param[in] session        a Session struct
1 by brian
clean slate
2886
  @param[in] timeout    a pointer to a timespec;
2887
                        NULL means to wait w/o timeout.
2888
  @retval    0          if got signalled on update
2889
  @retval    non-0      if wait timeout elapsed
2890
  @note
2891
    LOCK_log must be taken before calling this function.
2892
    LOCK_log is being released while the thread is waiting.
2893
    LOCK_log is released by the caller.
2894
*/
2895
520.1.22 by Brian Aker
Second pass of thd cleanup
2896
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(Session* session,
1 by brian
clean slate
2897
                                           const struct timespec *timeout)
2898
{
2899
  int ret= 0;
520.1.22 by Brian Aker
Second pass of thd cleanup
2900
  const char* old_msg = session->get_proc_info();
2901
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
1 by brian
clean slate
2902
                           "Master has sent all binlog to slave; "
2903
                           "waiting for binlog to be updated");
2904
  if (!timeout)
2905
    pthread_cond_wait(&update_cond, &LOCK_log);
2906
  else
2907
    ret= pthread_cond_timedwait(&update_cond, &LOCK_log,
2908
                                const_cast<struct timespec *>(timeout));
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2909
  return(ret);
1 by brian
clean slate
2910
}
2911
2912
2913
/**
2914
  Close the log file.
2915
2916
  @param exiting     Bitmask for one or more of the following bits:
2917
          - LOG_CLOSE_INDEX : if we should close the index file
2918
          - LOG_CLOSE_TO_BE_OPENED : if we intend to call open
2919
                                     at once after close.
2920
          - LOG_CLOSE_STOP_EVENT : write a 'stop' event to the log
2921
2922
  @note
2923
    One can do an open on the object at once after doing a close.
2924
    The internal structures are not freed until cleanup() is called
2925
*/
2926
482 by Brian Aker
Remove uint.
2927
void DRIZZLE_BIN_LOG::close(uint32_t exiting)
1 by brian
clean slate
2928
{					// One can't set log_type here!
2929
  if (log_state == LOG_OPENED)
2930
  {
2931
    if (log_type == LOG_BIN && !no_auto_events &&
2932
	(exiting & LOG_CLOSE_STOP_EVENT))
2933
    {
2934
      Stop_log_event s;
2935
      s.write(&log_file);
2936
      bytes_written+= s.data_written;
2937
      signal_update();
2938
    }
2939
2940
    /* don't pwrite in a file opened with O_APPEND - it doesn't work */
2941
    if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
2942
    {
2943
      my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
481 by Brian Aker
Remove all of uchar.
2944
      unsigned char flags= 0;            // clearing LOG_EVENT_BINLOG_IN_USE_F
512.1.15 by Stewart Smith
log.cc:3030: error: ignoring return value of ssize_t pwrite(int, const void*, size_t, __off_t), declared with attribute warn_unused_result
2945
      assert(pwrite(log_file.file, &flags, 1, offset)==1);
1 by brian
clean slate
2946
    }
2947
2948
    /* this will cleanup IO_CACHE, sync and close the file */
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2949
    DRIZZLE_LOG::close(exiting);
1 by brian
clean slate
2950
  }
2951
2952
  /*
2953
    The following test is needed even if is_open() is not set, as we may have
2954
    called a not complete close earlier and the index file is still open.
2955
  */
2956
2957
  if ((exiting & LOG_CLOSE_INDEX) && my_b_inited(&index_file))
2958
  {
2959
    end_io_cache(&index_file);
2960
    if (my_close(index_file.file, MYF(0)) < 0 && ! write_error)
2961
    {
2962
      write_error= 1;
2963
      sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno);
2964
    }
2965
  }
2966
  log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
462 by Monty Taylor
Removed safeFree.
2967
  if (name)
2968
  {
2969
    free(name);
2970
    name= NULL;
2971
  }
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2972
  return;
1 by brian
clean slate
2973
}
2974
2975
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
2976
void DRIZZLE_BIN_LOG::set_max_size(ulong max_size_arg)
1 by brian
clean slate
2977
{
2978
  /*
2979
    We need to take locks, otherwise this may happen:
2980
    new_file() is called, calls open(old_max_size), then before open() starts,
2981
    set_max_size() sets max_size to max_size_arg, then open() starts and
2982
    uses the old_max_size argument, so max_size_arg has been overwritten and
2983
    it's like if the SET command was never run.
2984
  */
2985
  pthread_mutex_lock(&LOCK_log);
2986
  if (is_open())
2987
    max_size= max_size_arg;
2988
  pthread_mutex_unlock(&LOCK_log);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
2989
  return;
1 by brian
clean slate
2990
}
2991
2992
2993
/**
2994
  Check if a string is a valid number.
2995
2996
  @param str			String to test
2997
  @param res			Store value here
2998
  @param allow_wildcards	Set to 1 if we should ignore '%' and '_'
2999
3000
  @note
3001
    For the moment the allow_wildcards argument is not used
3002
    Should be move to some other file.
3003
3004
  @retval
3005
    1	String is a number
3006
  @retval
3007
    0	Error
3008
*/
3009
3010
static bool test_if_number(register const char *str,
3011
			   long *res, bool allow_wildcards)
3012
{
3013
  register int flag;
3014
  const char *start;
3015
3016
  flag= 0; 
3017
  start= str;
3018
  while (*str++ == ' ') ;
3019
  if (*--str == '-' || *str == '+')
3020
    str++;
3021
  while (my_isdigit(files_charset_info,*str) ||
3022
	 (allow_wildcards && (*str == wild_many || *str == wild_one)))
3023
  {
3024
    flag=1;
3025
    str++;
3026
  }
3027
  if (*str == '.')
3028
  {
3029
    for (str++ ;
3030
	 my_isdigit(files_charset_info,*str) ||
3031
	   (allow_wildcards && (*str == wild_many || *str == wild_one)) ;
3032
	 str++, flag=1) ;
3033
  }
3034
  if (*str != 0 || flag == 0)
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3035
    return(0);
1 by brian
clean slate
3036
  if (res)
3037
    *res=atol(start);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3038
  return(1);			/* Number ok */
1 by brian
clean slate
3039
} /* test_if_number */
3040
3041
3042
void sql_perror(const char *message)
3043
{
3044
  sql_print_error("%s: %s",message, strerror(errno));
3045
}
3046
3047
3048
bool flush_error_log()
3049
{
3050
  bool result=0;
3051
  if (opt_error_log)
3052
  {
3053
    char err_renamed[FN_REFLEN], *end;
3054
    end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
411.1.1 by Brian Aker
Work on removing GNU specific calls.
3055
    my_stpcpy(end, "-old");
398.1.10 by Monty Taylor
Actually removed VOID() this time.
3056
    pthread_mutex_lock(&LOCK_error_log);
1 by brian
clean slate
3057
    char err_temp[FN_REFLEN+4];
3058
    /*
3059
     On Windows is necessary a temporary file for to rename
3060
     the current error file.
3061
    */
461 by Monty Taylor
Removed NullS. bu-bye.
3062
    strxmov(err_temp, err_renamed,"-tmp",NULL);
1 by brian
clean slate
3063
    (void) my_delete(err_temp, MYF(0)); 
3064
    if (freopen(err_temp,"a+",stdout))
3065
    {
3066
      int fd;
3067
      size_t bytes;
481 by Brian Aker
Remove all of uchar.
3068
      unsigned char buf[IO_SIZE];
1 by brian
clean slate
3069
512.1.16 by Stewart Smith
log.cc: In function bool flush_error_log():
3070
      if(freopen(err_temp,"a+",stderr)==NULL)
3071
        return 1;
1 by brian
clean slate
3072
      (void) my_delete(err_renamed, MYF(0));
3073
      my_rename(log_error_file,err_renamed,MYF(0));
512.1.16 by Stewart Smith
log.cc: In function bool flush_error_log():
3074
      if (freopen(log_error_file,"a+",stdout)==NULL)
3075
        return 1;
3076
      else
3077
        if(freopen(log_error_file,"a+",stderr)==NULL)
3078
          return 1;
1 by brian
clean slate
3079
3080
      if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
3081
      {
3082
        while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
3083
               bytes != MY_FILE_ERROR)
3084
          my_fwrite(stderr, buf, bytes, MYF(0));
3085
        my_close(fd, MYF(0));
3086
      }
3087
      (void) my_delete(err_temp, MYF(0)); 
3088
    }
3089
    else
3090
     result= 1;
398.1.10 by Monty Taylor
Actually removed VOID() this time.
3091
    pthread_mutex_unlock(&LOCK_error_log);
1 by brian
clean slate
3092
  }
3093
   return result;
3094
}
3095
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3096
void DRIZZLE_BIN_LOG::signal_update()
1 by brian
clean slate
3097
{
3098
  pthread_cond_broadcast(&update_cond);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3099
  return;
1 by brian
clean slate
3100
}
3101
3102
void sql_print_error(const char *format, ...) 
3103
{
3104
  va_list args;
3105
3106
  va_start(args, format);
602.1.1 by Mark Atwood
hook up the errmsg plugin to the sql_print_error function
3107
  errmsg_vprintf (current_session, ERROR_LEVEL, format, args);
1 by brian
clean slate
3108
  va_end(args);
3109
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3110
  return;
1 by brian
clean slate
3111
}
3112
3113
3114
void sql_print_warning(const char *format, ...) 
3115
{
3116
  va_list args;
3117
3118
  va_start(args, format);
602.1.1 by Mark Atwood
hook up the errmsg plugin to the sql_print_error function
3119
  errmsg_vprintf (current_session, WARNING_LEVEL, format, args);
1 by brian
clean slate
3120
  va_end(args);
3121
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3122
  return;
1 by brian
clean slate
3123
}
3124
3125
3126
void sql_print_information(const char *format, ...) 
3127
{
3128
  va_list args;
3129
3130
  va_start(args, format);
602.1.1 by Mark Atwood
hook up the errmsg plugin to the sql_print_error function
3131
  errmsg_vprintf (current_session, INFORMATION_LEVEL, format, args);
1 by brian
clean slate
3132
  va_end(args);
3133
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3134
  return;
1 by brian
clean slate
3135
}
3136
3137
3138
/********* transaction coordinator log for 2pc - mmap() based solution *******/
3139
3140
/*
3141
  the log consists of a file, mmapped to a memory.
3142
  file is divided on pages of tc_log_page_size size.
3143
  (usable size of the first page is smaller because of log header)
3144
  there's PAGE control structure for each page
3145
  each page (or rather PAGE control structure) can be in one of three
3146
  states - active, syncing, pool.
3147
  there could be only one page in active or syncing states,
3148
  but many in pool - pool is fifo queue.
3149
  usual lifecycle of a page is pool->active->syncing->pool
3150
  "active" page - is a page where new xid's are logged.
3151
  the page stays active as long as syncing slot is taken.
3152
  "syncing" page is being synced to disk. no new xid can be added to it.
3153
  when the sync is done the page is moved to a pool and an active page
3154
  becomes "syncing".
3155
3156
  the result of such an architecture is a natural "commit grouping" -
3157
  If commits are coming faster than the system can sync, they do not
3158
  stall. Instead, all commit that came since the last sync are
3159
  logged to the same page, and they all are synced with the next -
3160
  one - sync. Thus, thought individual commits are delayed, throughput
3161
  is not decreasing.
3162
3163
  when a xid is added to an active page, the thread of this xid waits
3164
  for a page's condition until the page is synced. when syncing slot
3165
  becomes vacant one of these waiters is awaken to take care of syncing.
3166
  it syncs the page and signals all waiters that the page is synced.
3167
  PAGE::waiters is used to count these waiters, and a page may never
3168
  become active again until waiters==0 (that is all waiters from the
3169
  previous sync have noticed the sync was completed)
3170
3171
  note, that the page becomes "dirty" and has to be synced only when a
3172
  new xid is added into it. Removing a xid from a page does not make it
3173
  dirty - we don't sync removals to disk.
3174
*/
3175
3176
ulong tc_log_page_waits= 0;
3177
3178
#ifdef HAVE_MMAP
3179
3180
#define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
3181
3182
static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
3183
3184
ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
3185
ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
3186
3187
int TC_LOG_MMAP::open(const char *opt_name)
3188
{
482 by Brian Aker
Remove uint.
3189
  uint32_t i;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3190
  bool crashed= false;
1 by brian
clean slate
3191
  PAGE *pg;
3192
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3193
  assert(total_ha_2pc > 1);
3194
  assert(opt_name && opt_name[0]);
1 by brian
clean slate
3195
236.1.53 by Monty Taylor
Made getpagesize an automake compat LIBOBJ.
3196
  tc_log_page_size= getpagesize();
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3197
  assert(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
1 by brian
clean slate
3198
575.4.1 by ysano
Rename mysql to drizzle.
3199
  fn_format(logname,opt_name,drizzle_data_home,"",MY_UNPACK_FILENAME);
1 by brian
clean slate
3200
  if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
3201
  {
3202
    if (my_errno != ENOENT)
3203
      goto err;
3204
    if (using_heuristic_recover())
3205
      return 1;
3206
    if ((fd= my_create(logname, CREATE_MODE, O_RDWR, MYF(MY_WME))) < 0)
3207
      goto err;
3208
    inited=1;
3209
    file_length= opt_tc_log_size;
30 by Brian Aker
Large file and ftruncate() support
3210
    if (ftruncate(fd, file_length))
1 by brian
clean slate
3211
      goto err;
3212
  }
3213
  else
3214
  {
3215
    inited= 1;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3216
    crashed= true;
338 by Monty Taylor
Tagged more strings.
3217
    sql_print_information(_("Recovering after a crash using %s"), opt_name);
1 by brian
clean slate
3218
    if (tc_heuristic_recover)
3219
    {
338 by Monty Taylor
Tagged more strings.
3220
      sql_print_error(_("Cannot perform automatic crash recovery when "
3221
                      "--tc-heuristic-recover is used"));
1 by brian
clean slate
3222
      goto err;
3223
    }
3224
    file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
3225
    if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
3226
      goto err;
3227
  }
3228
481 by Brian Aker
Remove all of uchar.
3229
  data= (unsigned char *)my_mmap(0, (size_t)file_length, PROT_READ|PROT_WRITE,
1 by brian
clean slate
3230
                        MAP_NOSYNC|MAP_SHARED, fd, 0);
3231
  if (data == MAP_FAILED)
3232
  {
3233
    my_errno=errno;
3234
    goto err;
3235
  }
3236
  inited=2;
3237
3238
  npages=(uint)file_length/tc_log_page_size;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3239
  assert(npages >= 3);             // to guarantee non-empty pool
1 by brian
clean slate
3240
  if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
3241
    goto err;
3242
  inited=3;
3243
  for (pg=pages, i=0; i < npages; i++, pg++)
3244
  {
3245
    pg->next=pg+1;
3246
    pg->waiters=0;
3247
    pg->state=POOL;
3248
    pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST);
3249
    pthread_cond_init (&pg->cond, 0);
3250
    pg->start=(my_xid *)(data + i*tc_log_page_size);
3251
    pg->ptr=pg->start;
3252
    pg->end=(my_xid *)(pg->start + tc_log_page_size);
3253
    pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
3254
  }
3255
  pages[0].size=pages[0].free=
3256
                (tc_log_page_size-TC_LOG_HEADER_SIZE)/sizeof(my_xid);
3257
  pages[0].start=pages[0].end-pages[0].size;
3258
  pages[npages-1].next=0;
3259
  inited=4;
3260
3261
  if (crashed && recover())
3262
      goto err;
3263
3264
  memcpy(data, tc_log_magic, sizeof(tc_log_magic));
481 by Brian Aker
Remove all of uchar.
3265
  data[sizeof(tc_log_magic)]= (unsigned char)total_ha_2pc;
520.9.3 by mordred
zomg. Solaris actually builds all the way!!!
3266
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
3267
  //   so the cast should be fine. 
3268
  msync((char *)data, tc_log_page_size, MS_SYNC);
15 by brian
Fix for stat, NETWARE removal
3269
  my_sync(fd, MYF(0));
1 by brian
clean slate
3270
  inited=5;
3271
3272
  pthread_mutex_init(&LOCK_sync,    MY_MUTEX_INIT_FAST);
3273
  pthread_mutex_init(&LOCK_active,  MY_MUTEX_INIT_FAST);
3274
  pthread_mutex_init(&LOCK_pool,    MY_MUTEX_INIT_FAST);
3275
  pthread_cond_init(&COND_active, 0);
3276
  pthread_cond_init(&COND_pool, 0);
3277
3278
  inited=6;
3279
3280
  syncing= 0;
3281
  active=pages;
3282
  pool=pages+1;
3283
  pool_last=pages+npages-1;
3284
3285
  return 0;
3286
3287
err:
3288
  close();
3289
  return 1;
3290
}
3291
3292
/**
3293
  there is no active page, let's got one from the pool.
3294
3295
  Two strategies here:
3296
    -# take the first from the pool
3297
    -# if there're waiters - take the one with the most free space.
3298
3299
  @todo
3300
    TODO page merging. try to allocate adjacent page first,
3301
    so that they can be flushed both in one sync
3302
*/
3303
3304
void TC_LOG_MMAP::get_active_from_pool()
3305
{
3306
  PAGE **p, **best_p=0;
3307
  int best_free;
3308
3309
  if (syncing)
3310
    pthread_mutex_lock(&LOCK_pool);
3311
3312
  do
3313
  {
3314
    best_p= p= &pool;
3315
    if ((*p)->waiters == 0) // can the first page be used ?
3316
      break;                // yes - take it.
3317
3318
    best_free=0;            // no - trying second strategy
3319
    for (p=&(*p)->next; *p; p=&(*p)->next)
3320
    {
3321
      if ((*p)->waiters == 0 && (*p)->free > best_free)
3322
      {
3323
        best_free=(*p)->free;
3324
        best_p=p;
3325
      }
3326
    }
3327
  }
3328
  while ((*best_p == 0 || best_free == 0) && overflow());
3329
3330
  active=*best_p;
3331
  if (active->free == active->size) // we've chosen an empty page
3332
  {
3333
    tc_log_cur_pages_used++;
3334
    set_if_bigger(tc_log_max_pages_used, tc_log_cur_pages_used);
3335
  }
3336
3337
  if ((*best_p)->next)              // unlink the page from the pool
3338
    *best_p=(*best_p)->next;
3339
  else
3340
    pool_last=*best_p;
3341
3342
  if (syncing)
3343
    pthread_mutex_unlock(&LOCK_pool);
3344
}
3345
3346
/**
3347
  @todo
3348
  perhaps, increase log size ?
3349
*/
3350
int TC_LOG_MMAP::overflow()
3351
{
3352
  /*
3353
    simple overflow handling - just wait
3354
    TODO perhaps, increase log size ?
3355
    let's check the behaviour of tc_log_page_waits first
3356
  */
3357
  tc_log_page_waits++;
3358
  pthread_cond_wait(&COND_pool, &LOCK_pool);
3359
  return 1; // always return 1
3360
}
3361
3362
/**
3363
  Record that transaction XID is committed on the persistent storage.
3364
3365
    This function is called in the middle of two-phase commit:
3366
    First all resources prepare the transaction, then tc_log->log() is called,
3367
    then all resources commit the transaction, then tc_log->unlog() is called.
3368
3369
    All access to active page is serialized but it's not a problem, as
3370
    we're assuming that fsync() will be a main bottleneck.
3371
    That is, parallelizing writes to log pages we'll decrease number of
3372
    threads waiting for a page, but then all these threads will be waiting
3373
    for a fsync() anyway
3374
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3375
   If tc_log == DRIZZLE_LOG then tc_log writes transaction to binlog and
1 by brian
clean slate
3376
   records XID in a special Xid_log_event.
3377
   If tc_log = TC_LOG_MMAP then xid is written in a special memory-mapped
3378
   log.
3379
3380
  @retval
3381
    0  - error
3382
  @retval
3383
    \# - otherwise, "cookie", a number that will be passed as an argument
3384
    to unlog() call. tc_log can define it any way it wants,
3385
    and use for whatever purposes. TC_LOG_MMAP sets it
3386
    to the position in memory where xid was logged to.
3387
*/
3388
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
3389
int TC_LOG_MMAP::log_xid(Session *, my_xid xid)
1 by brian
clean slate
3390
{
3391
  int err;
3392
  PAGE *p;
3393
  ulong cookie;
3394
3395
  pthread_mutex_lock(&LOCK_active);
3396
3397
  /*
3398
    if active page is full - just wait...
3399
    frankly speaking, active->free here accessed outside of mutex
3400
    protection, but it's safe, because it only means we may miss an
3401
    unlog() for the active page, and we're not waiting for it here -
3402
    unlog() does not signal COND_active.
3403
  */
3404
  while (unlikely(active && active->free == 0))
3405
    pthread_cond_wait(&COND_active, &LOCK_active);
3406
3407
  /* no active page ? take one from the pool */
3408
  if (active == 0)
3409
    get_active_from_pool();
3410
3411
  p=active;
3412
  pthread_mutex_lock(&p->lock);
3413
3414
  /* searching for an empty slot */
3415
  while (*p->ptr)
3416
  {
3417
    p->ptr++;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3418
    assert(p->ptr < p->end);               // because p->free > 0
1 by brian
clean slate
3419
  }
3420
3421
  /* found! store xid there and mark the page dirty */
481 by Brian Aker
Remove all of uchar.
3422
  cookie= (ulong)((unsigned char *)p->ptr - data);      // can never be zero
1 by brian
clean slate
3423
  *p->ptr++= xid;
3424
  p->free--;
3425
  p->state= DIRTY;
3426
3427
  /* to sync or not to sync - this is the question */
3428
  pthread_mutex_unlock(&LOCK_active);
3429
  pthread_mutex_lock(&LOCK_sync);
3430
  pthread_mutex_unlock(&p->lock);
3431
3432
  if (syncing)
3433
  {                                          // somebody's syncing. let's wait
3434
    p->waiters++;
3435
    /*
3436
      note - it must be while (), not do ... while () here
3437
      as p->state may be not DIRTY when we come here
3438
    */
3439
    while (p->state == DIRTY && syncing)
3440
      pthread_cond_wait(&p->cond, &LOCK_sync);
3441
    p->waiters--;
3442
    err= p->state == ERROR;
3443
    if (p->state != DIRTY)                   // page was synced
3444
    {
3445
      if (p->waiters == 0)
3446
        pthread_cond_signal(&COND_pool);     // in case somebody's waiting
3447
      pthread_mutex_unlock(&LOCK_sync);
3448
      goto done;                             // we're done
3449
    }
3450
  }                                          // page was not synced! do it now
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3451
  assert(active == p && syncing == 0);
1 by brian
clean slate
3452
  pthread_mutex_lock(&LOCK_active);
3453
  syncing=p;                                 // place is vacant - take it
3454
  active=0;                                  // page is not active anymore
3455
  pthread_cond_broadcast(&COND_active);      // in case somebody's waiting
3456
  pthread_mutex_unlock(&LOCK_active);
3457
  pthread_mutex_unlock(&LOCK_sync);
3458
  err= sync();
3459
3460
done:
3461
  return err ? 0 : cookie;
3462
}
3463
3464
int TC_LOG_MMAP::sync()
3465
{
3466
  int err;
3467
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3468
  assert(syncing != active);
1 by brian
clean slate
3469
3470
  /*
3471
    sit down and relax - this can take a while...
3472
    note - no locks are held at this point
3473
  */
520.9.3 by mordred
zomg. Solaris actually builds all the way!!!
3474
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
3475
  //   so the cast should be fine. 
3476
  err= msync((char *)syncing->start, 1, MS_SYNC);
15 by brian
Fix for stat, NETWARE removal
3477
  if(err==0)
3478
    err= my_sync(fd, MYF(0));
1 by brian
clean slate
3479
3480
  /* page is synced. let's move it to the pool */
3481
  pthread_mutex_lock(&LOCK_pool);
3482
  pool_last->next=syncing;
3483
  pool_last=syncing;
3484
  syncing->next=0;
3485
  syncing->state= err ? ERROR : POOL;
3486
  pthread_cond_broadcast(&syncing->cond);    // signal "sync done"
3487
  pthread_cond_signal(&COND_pool);           // in case somebody's waiting
3488
  pthread_mutex_unlock(&LOCK_pool);
3489
3490
  /* marking 'syncing' slot free */
3491
  pthread_mutex_lock(&LOCK_sync);
3492
  syncing=0;
3493
  pthread_cond_signal(&active->cond);        // wake up a new syncer
3494
  pthread_mutex_unlock(&LOCK_sync);
3495
  return err;
3496
}
3497
3498
/**
3499
  erase xid from the page, update page free space counters/pointers.
3500
  cookie points directly to the memory where xid was logged.
3501
*/
3502
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
3503
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
1 by brian
clean slate
3504
{
3505
  PAGE *p=pages+(cookie/tc_log_page_size);
3506
  my_xid *x=(my_xid *)(data+cookie);
3507
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3508
  assert(*x == xid);
3509
  assert(x >= p->start && x < p->end);
1 by brian
clean slate
3510
  *x=0;
3511
3512
  pthread_mutex_lock(&p->lock);
3513
  p->free++;
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3514
  assert(p->free <= p->size);
1 by brian
clean slate
3515
  set_if_smaller(p->ptr, x);
3516
  if (p->free == p->size)               // the page is completely empty
3517
    statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
3518
  if (p->waiters == 0)                 // the page is in pool and ready to rock
3519
    pthread_cond_signal(&COND_pool);   // ping ... for overflow()
3520
  pthread_mutex_unlock(&p->lock);
3521
}
3522
3523
void TC_LOG_MMAP::close()
3524
{
482 by Brian Aker
Remove uint.
3525
  uint32_t i;
1 by brian
clean slate
3526
  switch (inited) {
3527
  case 6:
3528
    pthread_mutex_destroy(&LOCK_sync);
3529
    pthread_mutex_destroy(&LOCK_active);
3530
    pthread_mutex_destroy(&LOCK_pool);
3531
    pthread_cond_destroy(&COND_pool);
3532
  case 5:
3533
    data[0]='A'; // garble the first (signature) byte, in case my_delete fails
3534
  case 4:
3535
    for (i=0; i < npages; i++)
3536
    {
3537
      if (pages[i].ptr == 0)
3538
        break;
3539
      pthread_mutex_destroy(&pages[i].lock);
3540
      pthread_cond_destroy(&pages[i].cond);
3541
    }
3542
  case 3:
481 by Brian Aker
Remove all of uchar.
3543
    free((unsigned char*)pages);
1 by brian
clean slate
3544
  case 2:
3545
    my_munmap((char*)data, (size_t)file_length);
3546
  case 1:
3547
    my_close(fd, MYF(0));
3548
  }
3549
  if (inited>=5) // cannot do in the switch because of Windows
3550
    my_delete(logname, MYF(MY_WME));
3551
  inited=0;
3552
}
3553
3554
int TC_LOG_MMAP::recover()
3555
{
3556
  HASH xids;
3557
  PAGE *p=pages, *end_p=pages+npages;
3558
3559
  if (memcmp(data, tc_log_magic, sizeof(tc_log_magic)))
3560
  {
338 by Monty Taylor
Tagged more strings.
3561
    sql_print_error(_("Bad magic header in tc log"));
1 by brian
clean slate
3562
    goto err1;
3563
  }
3564
3565
  /*
3566
    the first byte after magic signature is set to current
3567
    number of storage engines on startup
3568
  */
3569
  if (data[sizeof(tc_log_magic)] != total_ha_2pc)
3570
  {
338 by Monty Taylor
Tagged more strings.
3571
    sql_print_error(_("Recovery failed! You must enable "
1 by brian
clean slate
3572
                    "exactly %d storage engines that support "
338 by Monty Taylor
Tagged more strings.
3573
                    "two-phase commit protocol"),
1 by brian
clean slate
3574
                    data[sizeof(tc_log_magic)]);
3575
    goto err1;
3576
  }
3577
3578
  if (hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
3579
                sizeof(my_xid), 0, 0, MYF(0)))
3580
    goto err1;
3581
3582
  for ( ; p < end_p ; p++)
3583
  {
3584
    for (my_xid *x=p->start; x < p->end; x++)
481 by Brian Aker
Remove all of uchar.
3585
      if (*x && my_hash_insert(&xids, (unsigned char *)x))
1 by brian
clean slate
3586
        goto err2; // OOM
3587
  }
3588
3589
  if (ha_recover(&xids))
3590
    goto err2;
3591
3592
  hash_free(&xids);
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
3593
  memset(data, 0, (size_t)file_length);
1 by brian
clean slate
3594
  return 0;
3595
3596
err2:
3597
  hash_free(&xids);
3598
err1:
338 by Monty Taylor
Tagged more strings.
3599
  sql_print_error(_("Crash recovery failed. Either correct the problem "
1 by brian
clean slate
3600
                  "(if it's, for example, out of memory error) and restart, "
338 by Monty Taylor
Tagged more strings.
3601
                  "or delete tc log and start drizzled with "
3602
                  "--tc-heuristic-recover={commit|rollback}"));
1 by brian
clean slate
3603
  return 1;
3604
}
3605
#endif
3606
3607
TC_LOG *tc_log;
3608
TC_LOG_DUMMY tc_log_dummy;
3609
TC_LOG_MMAP  tc_log_mmap;
3610
3611
/**
3612
  Perform heuristic recovery, if --tc-heuristic-recover was used.
3613
3614
  @note
3615
    no matter whether heuristic recovery was successful or not
3616
    mysqld must exit. So, return value is the same in both cases.
3617
3618
  @retval
3619
    0	no heuristic recovery was requested
3620
  @retval
3621
    1   heuristic recovery was performed
3622
*/
3623
3624
int TC_LOG::using_heuristic_recover()
3625
{
3626
  if (!tc_heuristic_recover)
3627
    return 0;
3628
338 by Monty Taylor
Tagged more strings.
3629
  sql_print_information(_("Heuristic crash recovery mode"));
1 by brian
clean slate
3630
  if (ha_recover(0))
338 by Monty Taylor
Tagged more strings.
3631
    sql_print_error(_("Heuristic crash recovery failed"));
3632
  sql_print_information(_("Please restart mysqld without --tc-heuristic-recover"));
1 by brian
clean slate
3633
  return 1;
3634
}
3635
3636
/****** transaction coordinator log for 2pc - binlog() based solution ******/
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3637
#define TC_LOG_BINLOG DRIZZLE_BIN_LOG
1 by brian
clean slate
3638
3639
/**
3640
  @todo
3641
  keep in-memory list of prepared transactions
3642
  (add to list in log(), remove on unlog())
3643
  and copy it to the new binlog if rotated
3644
  but let's check the behaviour of tc_log_page_waits first!
3645
*/
3646
3647
int TC_LOG_BINLOG::open(const char *opt_name)
3648
{
3649
  LOG_INFO log_info;
3650
  int      error= 1;
3651
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3652
  assert(total_ha_2pc > 1);
3653
  assert(opt_name && opt_name[0]);
1 by brian
clean slate
3654
3655
  pthread_mutex_init(&LOCK_prep_xids, MY_MUTEX_INIT_FAST);
3656
  pthread_cond_init (&COND_prep_xids, 0);
3657
3658
  if (!my_b_inited(&index_file))
3659
  {
3660
    /* There was a failure to open the index file, can't open the binlog */
3661
    cleanup();
3662
    return 1;
3663
  }
3664
3665
  if (using_heuristic_recover())
3666
  {
3667
    /* generate a new binlog to mask a corrupted one */
3668
    open(opt_name, LOG_BIN, 0, WRITE_CACHE, 0, max_binlog_size, 0);
3669
    cleanup();
3670
    return 1;
3671
  }
3672
461 by Monty Taylor
Removed NullS. bu-bye.
3673
  if ((error= find_log_pos(&log_info, NULL, 1)))
1 by brian
clean slate
3674
  {
3675
    if (error != LOG_INFO_EOF)
338 by Monty Taylor
Tagged more strings.
3676
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
1 by brian
clean slate
3677
    else
3678
      error= 0;
3679
    goto err;
3680
  }
3681
3682
  {
3683
    const char *errmsg;
3684
    IO_CACHE    log;
3685
    File        file;
3686
    Log_event  *ev=0;
3687
    Format_description_log_event fdle(BINLOG_VERSION);
3688
    char        log_name[FN_REFLEN];
3689
3690
    if (! fdle.is_valid())
3691
      goto err;
3692
3693
    do
3694
    {
3695
      strmake(log_name, log_info.log_file_name, sizeof(log_name)-1);
3696
    } while (!(error= find_next_log(&log_info, 1)));
3697
3698
    if (error !=  LOG_INFO_EOF)
3699
    {
338 by Monty Taylor
Tagged more strings.
3700
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
1 by brian
clean slate
3701
      goto err;
3702
    }
3703
3704
    if ((file= open_binlog(&log, log_name, &errmsg)) < 0)
3705
    {
3706
      sql_print_error("%s", errmsg);
3707
      goto err;
3708
    }
3709
3710
    if ((ev= Log_event::read_log_event(&log, 0, &fdle)) &&
3711
        ev->get_type_code() == FORMAT_DESCRIPTION_EVENT &&
3712
        ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
3713
    {
338 by Monty Taylor
Tagged more strings.
3714
      sql_print_information(_("Recovering after a crash using %s"), opt_name);
1 by brian
clean slate
3715
      error= recover(&log, (Format_description_log_event *)ev);
3716
    }
3717
    else
3718
      error=0;
3719
3720
    delete ev;
3721
    end_io_cache(&log);
3722
    my_close(file, MYF(MY_WME));
3723
3724
    if (error)
3725
      goto err;
3726
  }
3727
3728
err:
3729
  return error;
3730
}
3731
3732
/** This is called on shutdown, after ha_panic. */
3733
void TC_LOG_BINLOG::close()
3734
{
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3735
  assert(prepared_xids==0);
1 by brian
clean slate
3736
  pthread_mutex_destroy(&LOCK_prep_xids);
3737
  pthread_cond_destroy (&COND_prep_xids);
3738
}
3739
3740
/**
3741
  @todo
3742
  group commit
3743
3744
  @retval
3745
    0    error
3746
  @retval
3747
    1    success
3748
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
3749
int TC_LOG_BINLOG::log_xid(Session *session, my_xid xid)
1 by brian
clean slate
3750
{
520.1.22 by Brian Aker
Second pass of thd cleanup
3751
  Xid_log_event xle(session, xid);
1 by brian
clean slate
3752
  binlog_trx_data *trx_data=
520.1.22 by Brian Aker
Second pass of thd cleanup
3753
    (binlog_trx_data*) session_get_ha_data(session, binlog_hton);
1 by brian
clean slate
3754
  /*
3755
    We always commit the entire transaction when writing an XID. Also
3756
    note that the return value is inverted.
3757
   */
520.1.22 by Brian Aker
Second pass of thd cleanup
3758
  return(!binlog_end_trans(session, trx_data, &xle, true));
1 by brian
clean slate
3759
}
3760
575.1.2 by Monty Taylor
Changed a bunch of __attribute__((unused)) to removing the parameter name instead.
3761
void TC_LOG_BINLOG::unlog(ulong, my_xid)
1 by brian
clean slate
3762
{
3763
  pthread_mutex_lock(&LOCK_prep_xids);
51.1.29 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
3764
  assert(prepared_xids > 0);
1 by brian
clean slate
3765
  if (--prepared_xids == 0) {
3766
    pthread_cond_signal(&COND_prep_xids);
3767
  }
3768
  pthread_mutex_unlock(&LOCK_prep_xids);
3769
  rotate_and_purge(0);     // as ::write() did not rotate
3770
}
3771
3772
int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)
3773
{
3774
  Log_event  *ev;
3775
  HASH xids;
3776
  MEM_ROOT mem_root;
3777
3778
  if (! fdle->is_valid() ||
3779
      hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
3780
                sizeof(my_xid), 0, 0, MYF(0)))
3781
    goto err1;
3782
3783
  init_alloc_root(&mem_root, TC_LOG_PAGE_SIZE, TC_LOG_PAGE_SIZE);
3784
3785
  fdle->flags&= ~LOG_EVENT_BINLOG_IN_USE_F; // abort on the first error
3786
3787
  while ((ev= Log_event::read_log_event(log,0,fdle)) && ev->is_valid())
3788
  {
3789
    if (ev->get_type_code() == XID_EVENT)
3790
    {
3791
      Xid_log_event *xev=(Xid_log_event *)ev;
481 by Brian Aker
Remove all of uchar.
3792
      unsigned char *x= (unsigned char *) memdup_root(&mem_root, (unsigned char*) &xev->xid,
1 by brian
clean slate
3793
                                      sizeof(xev->xid));
3794
      if (! x)
3795
        goto err2;
3796
      my_hash_insert(&xids, x);
3797
    }
3798
    delete ev;
3799
  }
3800
3801
  if (ha_recover(&xids))
3802
    goto err2;
3803
3804
  free_root(&mem_root, MYF(0));
3805
  hash_free(&xids);
3806
  return 0;
3807
3808
err2:
3809
  free_root(&mem_root, MYF(0));
3810
  hash_free(&xids);
3811
err1:
338 by Monty Taylor
Tagged more strings.
3812
  sql_print_error(_("Crash recovery failed. Either correct the problem "
1 by brian
clean slate
3813
                  "(if it's, for example, out of memory error) and restart, "
3814
                  "or delete (or rename) binary log and start mysqld with "
338 by Monty Taylor
Tagged more strings.
3815
                  "--tc-heuristic-recover={commit|rollback}"));
1 by brian
clean slate
3816
  return 1;
3817
}
3818
3819
584.1.13 by Monty Taylor
Split out a little more code. Removed table_list.h from common_includes.
3820
bool DRIZZLE_BIN_LOG::is_table_mapped(Table *table) const
3821
{
3822
  return table->s->table_map_version == table_map_version();
3823
}
3824
3825
1 by brian
clean slate
3826
#ifdef INNODB_COMPATIBILITY_HOOKS
3827
/**
3828
  Get the file name of the MySQL binlog.
3829
  @return the name of the binlog file
3830
*/
3831
extern "C"
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
3832
const char* drizzle_bin_log_file_name(void)
1 by brian
clean slate
3833
{
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
3834
  return drizzle_bin_log.get_log_fname();
1 by brian
clean slate
3835
}
3836
/**
3837
  Get the current position of the MySQL binlog.
3838
  @return byte offset from the beginning of the binlog
3839
*/
3840
extern "C"
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
3841
uint64_t drizzle_bin_log_file_pos(void)
1 by brian
clean slate
3842
{
586.1.1 by Yoshinori Sano
Rename mysql to drizzle, specifically mysql_bin_log to drizzle_bin_log.
3843
  return (uint64_t) drizzle_bin_log.get_log_file()->pos_in_file;
1 by brian
clean slate
3844
}
3845
#endif /* INNODB_COMPATIBILITY_HOOKS */
3846
3847
3848
mysql_declare_plugin(binlog)
3849
{
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
3850
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1 by brian
clean slate
3851
  "binlog",
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
3852
  "1.0",
1 by brian
clean slate
3853
  "MySQL AB",
3854
  "This is a pseudo storage engine to represent the binlog in a transaction",
3855
  PLUGIN_LICENSE_GPL,
3856
  binlog_init, /* Plugin Init */
3857
  NULL, /* Plugin Deinit */
3858
  NULL,                       /* status variables                */
3859
  NULL,                       /* system variables                */
3860
  NULL                        /* config options                  */
3861
}
3862
mysql_declare_plugin_end;