~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/log.cc

  • Committer: Mark Atwood
  • Date: 2009-01-05 04:37:22 UTC
  • mto: (758.1.1 devel)
  • mto: This revision was merged to the branch mainline in revision 759.
  • Revision ID: me@mark.atwood.name-20090105043722-03l4mzcxi4yjjjih
replace sql_print_error etc with errmsg_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
*/
26
26
 
27
27
#include <drizzled/server_includes.h>
28
 
#include "sql_repl.h"
29
 
#include "rpl_filter.h"
30
 
#include "rpl_rli.h"
 
28
#include <drizzled/replication/replication.h>
 
29
#include <libdrizzle/libdrizzle.h>
 
30
#include <drizzled/replicator.h>
 
31
#include <mysys/hash.h>
 
32
#include <drizzled/replication/rli.h>
31
33
 
32
34
#include <mysys/my_dir.h>
33
35
#include <stdarg.h>
34
36
 
35
37
#include <drizzled/plugin.h>
36
 
#include <drizzled/drizzled_error_messages.h>
37
 
#include <libdrizzle/gettext.h>
 
38
#include <drizzled/error.h>
 
39
#include <drizzled/errmsg_print.h>
 
40
#include <drizzled/gettext.h>
 
41
#include <drizzled/data_home.h>
 
42
#include <drizzled/log_event.h>
38
43
 
39
44
/* max size of the log message */
40
 
#define MAX_LOG_BUFFER_SIZE 1024
41
 
#define MAX_USER_HOST_SIZE 512
42
 
#define MAX_TIME_SIZE 32
43
45
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
44
46
 
45
 
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
46
 
 
47
 
LOGGER logger;
48
 
 
49
 
DRIZZLE_BIN_LOG mysql_bin_log;
50
 
ulong sync_binlog_counter= 0;
 
47
DRIZZLE_BIN_LOG drizzle_bin_log;
 
48
uint64_t sync_binlog_counter= 0; /* We should rationalize the largest possible counters for binlog sync */
51
49
 
52
50
static bool test_if_number(const char *str,
53
 
                           long *res, bool allow_wildcards);
 
51
                           long *res, bool allow_wildcards);
54
52
static int binlog_init(void *p);
55
 
static int binlog_close_connection(handlerton *hton, THD *thd);
56
 
static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv);
57
 
static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv);
58
 
static int binlog_commit(handlerton *hton, THD *thd, bool all);
59
 
static int binlog_rollback(handlerton *hton, THD *thd, bool all);
60
 
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
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);
74
 
  return fn_format(buff, buff, mysql_data_home, log_ext,
 
53
static int binlog_close_connection(handlerton *hton, Session *session);
 
54
static int binlog_savepoint_set(handlerton *hton, Session *session, void *sv);
 
55
static int binlog_savepoint_rollback(handlerton *hton, Session *session, void *sv);
 
56
static int binlog_commit(handlerton *hton, Session *session, bool all);
 
57
static int binlog_rollback(handlerton *hton, Session *session, bool all);
 
58
static int binlog_prepare(handlerton *hton, Session *session, bool all);
 
59
 
 
60
 
 
61
char *make_default_log_name(char *buff,const char *log_ext)
 
62
{
 
63
  strncpy(buff, pidfile_name, FN_REFLEN-5);
 
64
  return fn_format(buff, buff, drizzle_data_home, log_ext,
75
65
                   MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
76
66
}
77
67
 
108
98
  void operator=(Mutex_sentry const&);
109
99
};
110
100
 
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
 
  {
124
 
    assert(pending() == NULL);
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
101
handlerton *binlog_hton;
204
102
 
205
103
 
206
 
/* Check if a given table is opened log table */
207
 
int check_if_log_table(uint32_t db_len __attribute__((unused)),
208
 
                       const char *db __attribute__((unused)),
209
 
                       uint32_t table_name_len __attribute__((unused)),
210
 
                       const char *table_name __attribute__((unused)),
211
 
                       uint32_t check_if_opened __attribute__((unused)))
212
 
{
213
 
  return 0;
214
 
}
215
 
 
216
 
/*
217
 
  Log error with all enabled log event handlers
218
 
 
219
 
  SYNOPSIS
220
 
    error_log_print()
221
 
 
222
 
    level             The level of the error significance: NOTE,
223
 
                      WARNING or ERROR.
224
 
    format            format string for the error message
225
 
    args              list of arguments for the format string
226
 
 
227
 
  RETURN
228
 
    FALSE - OK
229
 
    TRUE - error occured
230
 
*/
231
 
 
232
 
bool LOGGER::error_log_print(enum loglevel level, const char *format,
233
 
                             va_list args)
234
 
{
235
 
  bool error= false;
236
 
  Log_event_handler **current_handler;
237
 
 
238
 
  /* currently we don't need locking here as there is no error_log table */
239
 
  for (current_handler= error_log_handler_list ; *current_handler ;)
240
 
    error= (*current_handler++)->log_error(level, format, args) || error;
241
 
 
242
 
  return error;
243
 
}
244
 
 
245
 
 
246
 
void LOGGER::cleanup_base()
247
 
{
248
 
  assert(inited == 1);
249
 
  rwlock_destroy(&LOCK_logger);
250
 
}
251
 
 
252
 
 
253
 
void LOGGER::cleanup_end()
254
 
{
255
 
  assert(inited == 1);
256
 
}
257
 
 
258
 
 
259
 
/**
260
 
  Perform basic log initialization: create file-based log handler and
261
 
  init error log.
262
 
*/
263
 
void LOGGER::init_base()
264
 
{
265
 
  assert(inited == 0);
266
 
  inited= 1;
267
 
 
268
 
  /* by default we use traditional error log */
269
 
  init_error_log(LOG_FILE);
270
 
 
271
 
  my_rwlock_init(&LOCK_logger, NULL);
272
 
}
273
 
 
274
 
 
275
 
bool LOGGER::flush_logs(THD *thd __attribute__((unused)))
276
 
{
277
 
  int rc= 0;
278
 
 
279
 
  /*
280
 
    Now we lock logger, as nobody should be able to use logging routines while
281
 
    log tables are closed
282
 
  */
283
 
  logger.lock_exclusive();
284
 
 
285
 
  /* end of log flush */
286
 
  logger.unlock();
287
 
  return rc;
288
 
}
289
 
 
290
 
void LOGGER::init_error_log(uint32_t error_log_printer)
291
 
{
292
 
  if (error_log_printer & LOG_NONE)
293
 
  {
294
 
    error_log_handler_list[0]= 0;
295
 
    return;
296
 
  }
297
 
 
298
 
}
299
 
 
300
 
int LOGGER::set_handlers(uint32_t error_log_printer)
301
 
{
302
 
  /* error log table is not supported yet */
303
 
  lock_exclusive();
304
 
 
305
 
  init_error_log(error_log_printer);
306
 
  unlock();
307
 
 
308
 
  return 0;
309
 
}
310
 
 
311
 
 
312
104
 /*
313
105
  Save position of binary log transaction cache.
314
106
 
315
107
  SYNPOSIS
316
108
    binlog_trans_log_savepos()
317
109
 
318
 
    thd      The thread to take the binlog data from
 
110
    session      The thread to take the binlog data from
319
111
    pos      Pointer to variable where the position will be stored
320
112
 
321
113
  DESCRIPTION
325
117
 */
326
118
 
327
119
static void
328
 
binlog_trans_log_savepos(THD *thd, my_off_t *pos)
 
120
binlog_trans_log_savepos(Session *, my_off_t *pos)
329
121
{
330
122
  assert(pos != NULL);
331
 
  if (thd_get_ha_data(thd, binlog_hton) == NULL)
332
 
    thd->binlog_setup_trx_data();
333
 
  binlog_trx_data *const trx_data=
334
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
335
 
  assert(mysql_bin_log.is_open());
336
 
  *pos= trx_data->position();
337
 
  return;
338
 
}
339
 
 
340
 
 
341
 
/*
342
 
  Truncate the binary log transaction cache.
343
 
 
344
 
  SYNPOSIS
345
 
    binlog_trans_log_truncate()
346
 
 
347
 
    thd      The thread to take the binlog data from
348
 
    pos      Position to truncate to
349
 
 
350
 
  DESCRIPTION
351
 
 
352
 
    Truncate the binary log to the given position. Will not change
353
 
    anything else.
354
 
 
355
 
 */
356
 
static void
357
 
binlog_trans_log_truncate(THD *thd, my_off_t pos)
358
 
{
359
 
  assert(thd_get_ha_data(thd, binlog_hton) != NULL);
360
 
  /* Only true if binlog_trans_log_savepos() wasn't called before */
361
 
  assert(pos != ~(my_off_t) 0);
362
 
 
363
 
  binlog_trx_data *const trx_data=
364
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
365
 
  trx_data->truncate(pos);
 
123
 
366
124
  return;
367
125
}
368
126
 
389
147
  return 0;
390
148
}
391
149
 
392
 
static int binlog_close_connection(handlerton *hton __attribute__((unused)),
393
 
                                   THD *thd)
 
150
static int binlog_close_connection(handlerton *, Session *)
394
151
{
395
 
  binlog_trx_data *const trx_data=
396
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
397
 
  assert(trx_data->empty());
398
 
  thd_set_ha_data(thd, binlog_hton, NULL);
399
 
  trx_data->~binlog_trx_data();
400
 
  free((unsigned char*)trx_data);
 
152
 
401
153
  return 0;
402
154
}
403
155
 
404
 
/*
405
 
  End a transaction.
406
 
 
407
 
  SYNOPSIS
408
 
    binlog_end_trans()
409
 
 
410
 
    thd      The thread whose transaction should be ended
411
 
    trx_data Pointer to the transaction data to use
412
 
    end_ev   The end event to use, or NULL
413
 
    all      True if the entire transaction should be ended, false if
414
 
             only the statement transaction should be ended.
415
 
 
416
 
  DESCRIPTION
417
 
 
418
 
    End the currently open transaction. The transaction can be either
419
 
    a real transaction (if 'all' is true) or a statement transaction
420
 
    (if 'all' is false).
421
 
 
422
 
    If 'end_ev' is NULL, the transaction is a rollback of only
423
 
    transactional tables, so the transaction cache will be truncated
424
 
    to either just before the last opened statement transaction (if
425
 
    'all' is false), or reset completely (if 'all' is true).
426
 
 */
427
 
static int
428
 
binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
429
 
                 Log_event *end_ev, bool all)
430
 
{
431
 
  int error=0;
432
 
  IO_CACHE *trans_log= &trx_data->trans_log;
433
 
 
434
 
  /*
435
 
    NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
436
 
    only transactional tables.  If the transaction contain changes to
437
 
    any non-transactiona tables, we need write the transaction and log
438
 
    a ROLLBACK last.
439
 
  */
440
 
  if (end_ev != NULL)
441
 
  {
442
 
    /*
443
 
      Doing a commit or a rollback including non-transactional tables,
444
 
      i.e., ending a transaction where we might write the transaction
445
 
      cache to the binary log.
446
 
 
447
 
      We can always end the statement when ending a transaction since
448
 
      transactions are not allowed inside stored functions.  If they
449
 
      were, we would have to ensure that we're not ending a statement
450
 
      inside a stored function.
451
 
     */
452
 
    thd->binlog_flush_pending_rows_event(true);
453
 
 
454
 
    error= mysql_bin_log.write(thd, &trx_data->trans_log, end_ev);
455
 
    trx_data->reset();
456
 
 
457
 
    /*
458
 
      We need to step the table map version after writing the
459
 
      transaction cache to disk.
460
 
    */
461
 
    mysql_bin_log.update_table_map_version();
462
 
    statistic_increment(binlog_cache_use, &LOCK_status);
463
 
    if (trans_log->disk_writes != 0)
464
 
    {
465
 
      statistic_increment(binlog_cache_disk_use, &LOCK_status);
466
 
      trans_log->disk_writes= 0;
467
 
    }
468
 
  }
469
 
  else
470
 
  {
471
 
    /*
472
 
      If rolling back an entire transaction or a single statement not
473
 
      inside a transaction, we reset the transaction cache.
474
 
 
475
 
      If rolling back a statement in a transaction, we truncate the
476
 
      transaction cache to remove the statement.
477
 
     */
478
 
    if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
479
 
    {
480
 
      trx_data->reset();
481
 
 
482
 
      assert(!thd->binlog_get_pending_rows_event());
483
 
      thd->clear_binlog_table_maps();
484
 
    }
485
 
    else                                        // ...statement
486
 
      trx_data->truncate(trx_data->before_stmt_pos);
487
 
 
488
 
    /*
489
 
      We need to step the table map version on a rollback to ensure
490
 
      that a new table map event is generated instead of the one that
491
 
      was written to the thrown-away transaction cache.
492
 
    */
493
 
    mysql_bin_log.update_table_map_version();
494
 
  }
495
 
 
496
 
  return(error);
497
 
}
498
 
 
499
 
static int binlog_prepare(handlerton *hton __attribute__((unused)),
500
 
                          THD *thd __attribute__((unused)),
501
 
                          bool all __attribute__((unused)))
 
156
static int binlog_prepare(handlerton *, Session *session, bool)
502
157
{
503
158
  /*
504
159
    do nothing.
506
161
    switch to 1pc.
507
162
    real work will be done in DRIZZLE_BIN_LOG::log_xid()
508
163
  */
 
164
 
 
165
  (void)replicator_prepare(session);
 
166
 
509
167
  return 0;
510
168
}
511
169
 
512
 
#define YESNO(X) ((X) ? "yes" : "no")
513
 
 
514
170
/**
515
171
  This function is called once after each statement.
516
172
 
518
174
  binlog file on commits.
519
175
 
520
176
  @param hton  The binlog handlerton.
521
 
  @param thd   The client thread that executes the transaction.
 
177
  @param session   The client thread that executes the transaction.
522
178
  @param all   This is @c true if this is a real transaction commit, and
523
179
               @false otherwise.
524
180
 
525
181
  @see handlerton::commit
526
182
*/
527
 
static int binlog_commit(handlerton *hton __attribute__((unused)),
528
 
                         THD *thd, bool all)
 
183
static int binlog_commit(handlerton *, Session *session, bool all)
529
184
{
530
 
  binlog_trx_data *const trx_data=
531
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
532
 
 
533
 
  if (trx_data->empty())
534
 
  {
535
 
    // we're here because trans_log was flushed in DRIZZLE_BIN_LOG::log_xid()
536
 
    trx_data->reset();
537
 
    return(0);
538
 
  }
539
 
 
540
185
  /*
541
186
    Decision table for committing a transaction. The top part, the
542
187
    *conditions* represent different cases that can occur, and hte
595
240
 
596
241
    Otherwise, we accumulate the statement
597
242
  */
598
 
  uint64_t const in_transaction=
599
 
    thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
600
 
  if ((in_transaction && (all || (!trx_data->at_least_one_stmt && thd->transaction.stmt.modified_non_trans_table))) || (!in_transaction && !all))
 
243
 
 
244
  if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) 
601
245
  {
602
 
    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), true, false);
603
 
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(THD, IO_CACHE)
604
 
    int error= binlog_end_trans(thd, trx_data, &qev, all);
605
 
    return(error);
 
246
    return replicator_end_transaction(session, all, true);
606
247
  }
 
248
 
607
249
  return(0);
608
250
}
609
251
 
616
258
  non-transactional tables, nothing needs to be logged.
617
259
 
618
260
  @param hton  The binlog handlerton.
619
 
  @param thd   The client thread that executes the transaction.
 
261
  @param session   The client thread that executes the transaction.
620
262
  @param all   This is @c true if this is a real transaction rollback, and
621
263
               @false otherwise.
622
264
 
623
265
  @see handlerton::rollback
624
266
*/
625
 
static int binlog_rollback(handlerton *hton __attribute__((unused)),
626
 
                           THD *thd, bool all)
 
267
static int binlog_rollback(handlerton *, Session *session, bool all)
627
268
{
628
269
  int error=0;
629
 
  binlog_trx_data *const trx_data=
630
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
631
 
 
632
 
  if (trx_data->empty()) {
633
 
    trx_data->reset();
634
 
    return(0);
635
 
  }
636
 
 
637
 
  if ((all && thd->transaction.all.modified_non_trans_table) ||
638
 
      (!all && thd->transaction.stmt.modified_non_trans_table) ||
639
 
      (thd->options & OPTION_KEEP_LOG))
640
 
  {
641
 
    /*
642
 
      We write the transaction cache with a rollback last if we have
643
 
      modified any non-transactional table. We do this even if we are
644
 
      committing a single statement that has modified a
645
 
      non-transactional table since it can have modified a
646
 
      transactional table in that statement as well, which needs to be
647
 
      rolled back on the slave.
648
 
    */
649
 
    Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), true, false);
650
 
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(THD, IO_CACHE)
651
 
    error= binlog_end_trans(thd, trx_data, &qev, all);
652
 
  }
653
 
  else if ((all && !thd->transaction.all.modified_non_trans_table) ||
654
 
           (!all && !thd->transaction.stmt.modified_non_trans_table))
655
 
  {
656
 
    /*
657
 
      If we have modified only transactional tables, we can truncate
658
 
      the transaction cache without writing anything to the binary
659
 
      log.
660
 
     */
661
 
    error= binlog_end_trans(thd, trx_data, 0, all);
662
 
  }
 
270
 
 
271
  /* TODO: Fix return type */
 
272
  (void)replicator_end_transaction(session, all, false);
 
273
 
663
274
  return(error);
664
275
}
665
276
 
687
298
  that case there is no need to have it in the binlog).
688
299
*/
689
300
 
690
 
static int binlog_savepoint_set(handlerton *hton __attribute__((unused)),
691
 
                                THD *thd, void *sv)
 
301
static int binlog_savepoint_set(handlerton *, Session *session, void *sv)
692
302
{
693
 
  binlog_trans_log_savepos(thd, (my_off_t*) sv);
 
303
  bool error;
 
304
  binlog_trans_log_savepos(session, (my_off_t*) sv);
694
305
  /* Write it to the binary log */
695
 
  
696
 
  int const error=
697
 
    thd->binlog_query(THD::STMT_QUERY_TYPE,
698
 
                      thd->query, thd->query_length, true, false);
 
306
 
 
307
  error= replicator_statement(session, session->query, session->query_length);
 
308
 
699
309
  return(error);
700
310
}
701
311
 
702
 
static int binlog_savepoint_rollback(handlerton *hton __attribute__((unused)),
703
 
                                     THD *thd, void *sv)
 
312
static int binlog_savepoint_rollback(handlerton *, Session *session, void *)
704
313
{
705
 
  /*
706
 
    Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
707
 
    non-transactional table. Otherwise, truncate the binlog cache starting
708
 
    from the SAVEPOINT command.
709
 
  */
710
 
  if (unlikely(thd->transaction.all.modified_non_trans_table || 
711
 
               (thd->options & OPTION_KEEP_LOG)))
712
 
  {
713
 
    int error=
714
 
      thd->binlog_query(THD::STMT_QUERY_TYPE,
715
 
                        thd->query, thd->query_length, true, false);
716
 
    return(error);
717
 
  }
718
 
  binlog_trans_log_truncate(thd, *(my_off_t*)sv);
719
 
  return(0);
 
314
  bool error;
 
315
 
 
316
  error= replicator_statement(session, session->query, session->query_length);
 
317
 
 
318
  return error;
720
319
}
721
320
 
722
321
 
728
327
  if (my_b_read(log, (unsigned char*) magic, sizeof(magic)))
729
328
  {
730
329
    *errmsg = _("I/O error reading the header from the binary log");
731
 
    sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
 
330
    errmsg_printf(ERRMSG_LVL_ERROR, "%s, errno=%d, io cache code=%d", *errmsg, my_errno,
732
331
                    log->error);
733
332
    return 1;
734
333
  }
746
345
{
747
346
  File file;
748
347
 
749
 
  if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE, 
 
348
  if ((file = my_open(log_file_name, O_RDONLY,
750
349
                      MYF(MY_WME))) < 0)
751
350
  {
752
 
    sql_print_error(_("Failed to open log (file '%s', errno %d)"),
 
351
    errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to open log (file '%s', errno %d)"),
753
352
                    log_file_name, my_errno);
754
353
    *errmsg = _("Could not open log file");
755
354
    goto err;
757
356
  if (init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
758
357
                    MYF(MY_WME|MY_DONT_CHECK_FILESIZE)))
759
358
  {
760
 
    sql_print_error(_("Failed to create a cache on log (file '%s')"),
 
359
    errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to create a cache on log (file '%s')"),
761
360
                    log_file_name);
762
361
    *errmsg = _("Could not open log file");
763
362
    goto err;
805
404
 
806
405
  if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
807
406
  {                                             // This shouldn't happen
808
 
    my_stpcpy(end,".1");                                // use name+1
 
407
    strcpy(end,".1");                           // use name+1
809
408
    return(0);
810
409
  }
811
410
  file_info= dir_info->dir_entry;
860
459
{
861
460
  char buff[FN_REFLEN];
862
461
  File file= -1;
863
 
  int open_flags= O_CREAT | O_BINARY;
 
462
  int open_flags= O_CREAT;
864
463
 
865
464
  write_error= 0;
866
465
 
867
466
  init(log_type_arg, io_cache_type_arg);
868
467
 
869
 
  if (!(name= my_strdup(log_name, MYF(MY_WME))))
 
468
  if (!(name= strdup(log_name)))
870
469
  {
871
470
    name= (char *)log_name; // for the error message
872
471
    goto err;
873
472
  }
874
473
 
875
474
  if (new_name)
876
 
    my_stpcpy(log_file_name, new_name);
 
475
    strcpy(log_file_name, new_name);
877
476
  else if (generate_new_name(log_file_name, name))
878
477
    goto err;
879
478
 
887
486
  if ((file= my_open(log_file_name, open_flags,
888
487
                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
889
488
      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
890
 
                    my_tell(file, MYF(MY_WME)), 0,
 
489
                    lseek(file, 0, SEEK_CUR), 0,
891
490
                    MYF(MY_WME | MY_NABP |
892
491
                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
893
492
    goto err;
894
493
 
895
494
  if (log_type == LOG_NORMAL)
896
495
  {
897
 
    char *end;
898
 
    int len=snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
899
 
                     "started with:\nTCP Port: %d, Named Pipe: %s\n",
900
 
                     my_progname, server_version, DRIZZLE_COMPILATION_COMMENT,
901
 
                     mysqld_port, ""
902
 
                     );
903
 
    end= my_stpncpy(buff + len, "Time                 Id Command    Argument\n",
904
 
                 sizeof(buff) - len);
905
 
    if (my_b_write(&log_file, (unsigned char*) buff, (uint) (end-buff)) ||
906
 
        flush_io_cache(&log_file))
 
496
    int len= snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
 
497
                      "started with:\nTCP Port: %d, Named Pipe: %s\n",
 
498
                      my_progname, server_version, COMPILATION_COMMENT,
 
499
                      drizzled_port, "");
 
500
    len+= sprintf(buff+len, "Time                 Id Command    Argument\n");
 
501
 
 
502
    if (my_b_write(&log_file, (unsigned char*) buff, len) ||
 
503
        flush_io_cache(&log_file))
907
504
      goto err;
908
505
  }
909
506
 
911
508
  return(0);
912
509
 
913
510
err:
914
 
  sql_print_error(_("Could not use %s for logging (error %d). "
 
511
  errmsg_printf(ERRMSG_LVL_ERROR, _("Could not use %s for logging (error %d). "
915
512
                    "Turning logging off for the whole duration of the "
916
513
                    "Drizzle server process. "
917
514
                    "To turn it on again: fix the cause, "
972
569
    if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error)
973
570
    {
974
571
      write_error= 1;
975
 
      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
 
572
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_ERROR_ON_WRITE), name, errno);
976
573
    }
977
574
 
978
575
    if (my_close(log_file.file, MYF(MY_WME)) && ! write_error)
979
576
    {
980
577
      write_error= 1;
981
 
      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
 
578
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_ERROR_ON_WRITE), name, errno);
982
579
    }
983
580
  }
984
581
 
1007
604
 
1008
605
int DRIZZLE_LOG::generate_new_name(char *new_name, const char *log_name)
1009
606
{
1010
 
  fn_format(new_name, log_name, mysql_data_home, "", 4);
 
607
  fn_format(new_name, log_name, drizzle_data_home, "", 4);
1011
608
  if (log_type == LOG_BIN)
1012
609
  {
1013
610
    if (!fn_ext(log_name)[0])
1014
611
    {
1015
612
      if (find_uniq_filename(new_name))
1016
613
      {
1017
 
        sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
 
614
        errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_NO_UNIQUE_LOGFILE), log_name);
1018
615
        return 1;
1019
616
      }
1020
617
    }
1034
631
{
1035
632
  if (!log_name || !log_name[0])
1036
633
  {
1037
 
    strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
 
634
    strncpy(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
1038
635
    return (const char *)
1039
636
      fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR));
1040
637
  }
1042
639
  if (strip_ext)
1043
640
  {
1044
641
    char *p= fn_ext(log_name);
1045
 
    uint32_t length= (uint) (p - log_name);
1046
 
    strmake(buff, log_name, cmin(length, (uint)FN_REFLEN));
 
642
    uint32_t length= cmin((uint32_t)(p - log_name), FN_REFLEN);
 
643
    strncpy(buff, log_name, length);
 
644
    buff[length]= '\0';
1047
645
    return (const char*)buff;
1048
646
  }
1049
647
  return log_name;
1120
718
    index_file_name_arg= log_name;    // Use same basename for index file
1121
719
    opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
1122
720
  }
1123
 
  fn_format(index_file_name, index_file_name_arg, mysql_data_home,
 
721
  fn_format(index_file_name, index_file_name_arg, drizzle_data_home,
1124
722
            ".index", opt);
1125
723
  if ((index_file_nr= my_open(index_file_name,
1126
 
                              O_RDWR | O_CREAT | O_BINARY ,
 
724
                              O_RDWR | O_CREAT,
1127
725
                              MYF(MY_WME))) < 0 ||
1128
726
       my_sync(index_file_nr, MYF(MY_WME)) ||
1129
727
       init_io_cache(&index_file, index_file_nr,
1130
728
                     IO_SIZE, WRITE_CACHE,
1131
 
                     my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
 
729
                     lseek(index_file_nr,0,SEEK_END),
1132
730
                        0, MYF(MY_WME | MY_WAIT_IF_FULL)))
1133
731
  {
1134
732
    /*
1275
873
  return(0);
1276
874
 
1277
875
err:
1278
 
  sql_print_error(_("Could not use %s for logging (error %d). "
 
876
  errmsg_printf(ERRMSG_LVL_ERROR, _("Could not use %s for logging (error %d). "
1279
877
                    "Turning logging off for the whole duration of the "
1280
878
                    "Drizzle server process. "
1281
879
                    "To turn it on again: fix the cause, "
1305
903
 
1306
904
int DRIZZLE_BIN_LOG::raw_get_current_log(LOG_INFO* linfo)
1307
905
{
1308
 
  strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
 
906
  strncpy(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
1309
907
  linfo->pos = my_b_tell(&log_file);
1310
908
  return 0;
1311
909
}
1336
934
 
1337
935
  for (;; offset+= bytes_read)
1338
936
  {
1339
 
    (void) my_seek(file, offset, MY_SEEK_SET, MYF(0));
 
937
    (void) lseek(file, offset, SEEK_SET);
1340
938
    if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME)))
1341
939
        < 0)
1342
940
      goto err;
1343
941
    if (!bytes_read)
1344
942
      break;                                    // end of file
1345
 
    (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
 
943
    (void) lseek(file, offset-init_offset, SEEK_SET);
1346
944
    if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
1347
945
      goto err;
1348
946
  }
1489
1087
 
1490
1088
  The new index file will only contain this file.
1491
1089
 
1492
 
  @param thd            Thread
 
1090
  @param session                Thread
1493
1091
 
1494
1092
  @note
1495
1093
    If not called from slave thread, write start event to new log
1500
1098
    1   error
1501
1099
*/
1502
1100
 
1503
 
bool DRIZZLE_BIN_LOG::reset_logs(THD* thd)
 
1101
bool DRIZZLE_BIN_LOG::reset_logs(Session* session)
1504
1102
{
1505
1103
  LOG_INFO linfo;
1506
1104
  bool error=0;
1515
1113
 
1516
1114
  /*
1517
1115
    The following mutex is needed to ensure that no threads call
1518
 
    'delete thd' as we would then risk missing a 'rollback' from this
 
1116
    'delete session' as we would then risk missing a 'rollback' from this
1519
1117
    thread. If the transaction involved MyISAM tables, it should go
1520
1118
    into binlog even on rollback.
1521
1119
  */
1538
1136
  {
1539
1137
    if ((error= my_delete_allow_opened(linfo.log_file_name, MYF(0))) != 0)
1540
1138
    {
1541
 
      if (my_errno == ENOENT) 
 
1139
      if (my_errno == ENOENT)
1542
1140
      {
1543
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1141
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1544
1142
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1545
1143
                            linfo.log_file_name);
1546
 
        sql_print_information(_("Failed to delete file '%s'"),
 
1144
        errmsg_printf(ERRMSG_LVL_INFO, _("Failed to delete file '%s'"),
1547
1145
                              linfo.log_file_name);
1548
1146
        my_errno= 0;
1549
1147
        error= 0;
1550
1148
      }
1551
1149
      else
1552
1150
      {
1553
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1151
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1554
1152
                            ER_BINLOG_PURGE_FATAL_ERR,
1555
1153
                            _("a problem with deleting %s; "
1556
1154
                            "consider examining correspondence "
1569
1167
  close(LOG_CLOSE_INDEX);
1570
1168
  if ((error= my_delete_allow_opened(index_file_name, MYF(0)))) // Reset (open will update)
1571
1169
  {
1572
 
    if (my_errno == ENOENT) 
 
1170
    if (my_errno == ENOENT)
1573
1171
    {
1574
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1172
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1575
1173
                          ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1576
1174
                          index_file_name);
1577
 
      sql_print_information(_("Failed to delete file '%s'"),
 
1175
      errmsg_printf(ERRMSG_LVL_INFO, _("Failed to delete file '%s'"),
1578
1176
                            index_file_name);
1579
1177
      my_errno= 0;
1580
1178
      error= 0;
1581
1179
    }
1582
1180
    else
1583
1181
    {
1584
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1182
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1585
1183
                          ER_BINLOG_PURGE_FATAL_ERR,
1586
1184
                          "a problem with deleting %s; "
1587
1185
                          "consider examining correspondence "
1592
1190
      goto err;
1593
1191
    }
1594
1192
  }
1595
 
  if (!thd->slave_thread)
 
1193
  if (!session->slave_thread)
1596
1194
    need_start_event=1;
1597
1195
  if (!open_index_file(index_file_name, 0))
1598
1196
    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0);
1650
1248
 
1651
1249
  assert(is_open());
1652
1250
  assert(rli->slave_running == 1);
1653
 
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
 
1251
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name.c_str()));
1654
1252
 
1655
1253
  pthread_mutex_lock(&LOCK_index);
1656
1254
  pthread_mutex_lock(&rli->log_space_lock);
1657
 
  rli->relay_log.purge_logs(rli->group_relay_log_name, included,
 
1255
  rli->relay_log.purge_logs(rli->group_relay_log_name.c_str(), included,
1658
1256
                            0, 0, &rli->log_space_total);
1659
1257
  // Tell the I/O thread to take the relay_log_space_limit into account
1660
1258
  rli->ignore_log_space_limit= 0;
1666
1264
    context switches
1667
1265
  */
1668
1266
  pthread_cond_broadcast(&rli->log_space_cond);
1669
 
  
 
1267
 
1670
1268
  /*
1671
1269
    Read the next log file name from the index file and pass it back to
1672
1270
    the caller
1675
1273
  */
1676
1274
  if ((included && (error=find_log_pos(&rli->linfo, NULL, 0))) ||
1677
1275
      (!included &&
1678
 
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
 
1276
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name.c_str(), 0)) ||
1679
1277
        (error=find_next_log(&rli->linfo, 0)))))
1680
1278
  {
1681
1279
    char buff[22];
1682
 
    sql_print_error(_("next log error: %d  offset: %s  log: %s included: %d"),
 
1280
    errmsg_printf(ERRMSG_LVL_ERROR, _("next log error: %d  offset: %s  log: %s included: %d"),
1683
1281
                    error,
1684
1282
                    llstr(rli->linfo.index_file_offset,buff),
1685
 
                    rli->group_relay_log_name,
 
1283
                    rli->group_relay_log_name.c_str(),
1686
1284
                    included);
1687
1285
    goto err;
1688
1286
  }
1691
1289
    Reset rli's coordinates to the current log.
1692
1290
  */
1693
1291
  rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
1694
 
  strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
1695
 
          sizeof(rli->event_relay_log_name)-1);
 
1292
  rli->event_relay_log_name.assign(rli->linfo.log_file_name);
1696
1293
 
1697
1294
  /*
1698
1295
    If we removed the rli->group_relay_log_name file,
1702
1299
  if (included)
1703
1300
  {
1704
1301
    rli->group_relay_log_pos = BIN_LOG_HEADER_SIZE;
1705
 
    strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
1706
 
            sizeof(rli->group_relay_log_name)-1);
 
1302
    rli->group_relay_log_name.assign(rli->linfo.log_file_name);
1707
1303
    rli->notify_group_relay_log_name_update();
1708
1304
  }
1709
1305
 
1754
1350
                                stat() or my_delete()
1755
1351
*/
1756
1352
 
1757
 
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log, 
 
1353
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log,
1758
1354
                          bool included,
1759
 
                          bool need_mutex, 
1760
 
                          bool need_update_threads, 
 
1355
                          bool need_mutex,
 
1356
                          bool need_update_threads,
1761
1357
                          uint64_t *decrease_log_space)
1762
1358
{
1763
1359
  int error;
1782
1378
    struct stat s;
1783
1379
    if (stat(log_info.log_file_name, &s))
1784
1380
    {
1785
 
      if (errno == ENOENT) 
 
1381
      if (errno == ENOENT)
1786
1382
      {
1787
1383
        /*
1788
1384
          It's not fatal if we can't stat a log file that does not exist;
1789
1385
          If we could not stat, we won't delete.
1790
 
        */     
1791
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1386
        */
 
1387
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1792
1388
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1793
1389
                            log_info.log_file_name);
1794
 
        sql_print_information(_("Failed to execute stat() on file '%s'"),
 
1390
        errmsg_printf(ERRMSG_LVL_INFO, _("Failed to execute stat() on file '%s'"),
1795
1391
                              log_info.log_file_name);
1796
1392
        my_errno= 0;
1797
1393
      }
1800
1396
        /*
1801
1397
          Other than ENOENT are fatal
1802
1398
        */
1803
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1399
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1804
1400
                            ER_BINLOG_PURGE_FATAL_ERR,
1805
1401
                            _("a problem with getting info on being purged %s; "
1806
1402
                            "consider examining correspondence "
1820
1416
      }
1821
1417
      else
1822
1418
      {
1823
 
        if (my_errno == ENOENT) 
 
1419
        if (my_errno == ENOENT)
1824
1420
        {
1825
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1421
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1826
1422
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1827
1423
                              log_info.log_file_name);
1828
 
          sql_print_information(_("Failed to delete file '%s'"),
 
1424
          errmsg_printf(ERRMSG_LVL_INFO, _("Failed to delete file '%s'"),
1829
1425
                                log_info.log_file_name);
1830
1426
          my_errno= 0;
1831
1427
        }
1832
1428
        else
1833
1429
        {
1834
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1430
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1835
1431
                              ER_BINLOG_PURGE_FATAL_ERR,
1836
1432
                              _("a problem with deleting %s; "
1837
1433
                              "consider examining correspondence "
1851
1447
    if (find_next_log(&log_info, 0) || exit_loop)
1852
1448
      break;
1853
1449
  }
1854
 
  
 
1450
 
1855
1451
  /*
1856
1452
    If we get killed -9 here, the sysadmin would have to edit
1857
1453
    the log index file after restart - otherwise, this should be safe
1871
1467
  Remove all logs before the given file date from disk and from the
1872
1468
  index file.
1873
1469
 
1874
 
  @param thd            Thread pointer
 
1470
  @param session                Thread pointer
1875
1471
  @param before_date    Delete all log files before given date.
1876
1472
 
1877
1473
  @note
1907
1503
  {
1908
1504
    if (stat(log_info.log_file_name, &stat_area))
1909
1505
    {
1910
 
      if (errno == ENOENT) 
 
1506
      if (errno == ENOENT)
1911
1507
      {
1912
1508
        /*
1913
1509
          It's not fatal if we can't stat a log file that does not exist.
1914
 
        */     
1915
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1510
        */
 
1511
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1916
1512
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1917
1513
                            log_info.log_file_name);
1918
 
        sql_print_information(_("Failed to execute stat() on file '%s'"),
 
1514
        errmsg_printf(ERRMSG_LVL_INFO, _("Failed to execute stat() on file '%s'"),
1919
1515
                              log_info.log_file_name);
1920
1516
        my_errno= 0;
1921
1517
      }
1924
1520
        /*
1925
1521
          Other than ENOENT are fatal
1926
1522
        */
1927
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1523
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1928
1524
                            ER_BINLOG_PURGE_FATAL_ERR,
1929
1525
                            _("a problem with getting info on being purged %s; "
1930
1526
                            "consider examining correspondence "
1941
1537
        break;
1942
1538
      if (my_delete(log_info.log_file_name, MYF(0)))
1943
1539
      {
1944
 
        if (my_errno == ENOENT) 
 
1540
        if (my_errno == ENOENT)
1945
1541
        {
1946
1542
          /* It's not fatal even if we can't delete a log file */
1947
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1543
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1948
1544
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1949
1545
                              log_info.log_file_name);
1950
 
          sql_print_information(_("Failed to delete file '%s'"),
 
1546
          errmsg_printf(ERRMSG_LVL_INFO, _("Failed to delete file '%s'"),
1951
1547
                                log_info.log_file_name);
1952
1548
          my_errno= 0;
1953
1549
        }
1954
1550
        else
1955
1551
        {
1956
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1552
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1957
1553
                              ER_BINLOG_PURGE_FATAL_ERR,
1958
1554
                              _("a problem with deleting %s; "
1959
1555
                              "consider examining correspondence "
1992
1588
 
1993
1589
void DRIZZLE_BIN_LOG::make_log_name(char* buf, const char* log_ident)
1994
1590
{
1995
 
  uint32_t dir_len = dirname_length(log_file_name); 
 
1591
  uint32_t dir_len = dirname_length(log_file_name);
1996
1592
  if (dir_len >= FN_REFLEN)
1997
1593
    dir_len=FN_REFLEN-1;
1998
 
  my_stpncpy(buf, log_file_name, dir_len);
1999
 
  strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
 
1594
  strncpy(buf, log_file_name, dir_len);
 
1595
  strncpy(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
2000
1596
}
2001
1597
 
2002
1598
 
2204
1800
  return err;
2205
1801
}
2206
1802
 
2207
 
void DRIZZLE_BIN_LOG::start_union_events(THD *thd, query_id_t query_id_param)
2208
 
{
2209
 
  assert(!thd->binlog_evt_union.do_union);
2210
 
  thd->binlog_evt_union.do_union= true;
2211
 
  thd->binlog_evt_union.unioned_events= false;
2212
 
  thd->binlog_evt_union.unioned_events_trans= false;
2213
 
  thd->binlog_evt_union.first_query_id= query_id_param;
2214
 
}
2215
 
 
2216
 
void DRIZZLE_BIN_LOG::stop_union_events(THD *thd)
2217
 
{
2218
 
  assert(thd->binlog_evt_union.do_union);
2219
 
  thd->binlog_evt_union.do_union= false;
2220
 
}
2221
 
 
2222
 
bool DRIZZLE_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
2223
 
{
2224
 
  return (thd->binlog_evt_union.do_union && 
2225
 
          query_id_param >= thd->binlog_evt_union.first_query_id);
2226
 
}
2227
 
 
2228
 
 
2229
 
/*
2230
 
  These functions are placed in this file since they need access to
2231
 
  binlog_hton, which has internal linkage.
2232
 
*/
2233
 
 
2234
 
int THD::binlog_setup_trx_data()
2235
 
{
2236
 
  binlog_trx_data *trx_data=
2237
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2238
 
 
2239
 
  if (trx_data)
2240
 
    return(0);                             // Already set up
2241
 
 
2242
 
  trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
2243
 
  if (!trx_data ||
2244
 
      open_cached_file(&trx_data->trans_log, mysql_tmpdir,
2245
 
                       LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
2246
 
  {
2247
 
    free((unsigned char*)trx_data);
2248
 
    return(1);                      // Didn't manage to set it up
2249
 
  }
2250
 
  thd_set_ha_data(this, binlog_hton, trx_data);
2251
 
 
2252
 
  trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data;
2253
 
 
2254
 
  return(0);
2255
 
}
2256
 
 
2257
 
/*
2258
 
  Function to start a statement and optionally a transaction for the
2259
 
  binary log.
2260
 
 
2261
 
  SYNOPSIS
2262
 
    binlog_start_trans_and_stmt()
2263
 
 
2264
 
  DESCRIPTION
2265
 
 
2266
 
    This function does three things:
2267
 
    - Start a transaction if not in autocommit mode or if a BEGIN
2268
 
      statement has been seen.
2269
 
 
2270
 
    - Start a statement transaction to allow us to truncate the binary
2271
 
      log.
2272
 
 
2273
 
    - Save the currrent binlog position so that we can roll back the
2274
 
      statement by truncating the transaction log.
2275
 
 
2276
 
      We only update the saved position if the old one was undefined,
2277
 
      the reason is that there are some cases (e.g., for CREATE-SELECT)
2278
 
      where the position is saved twice (e.g., both in
2279
 
      select_create::prepare() and THD::binlog_write_table_map()) , but
2280
 
      we should use the first. This means that calls to this function
2281
 
      can be used to start the statement before the first table map
2282
 
      event, to include some extra events.
2283
 
 */
2284
 
 
2285
 
void
2286
 
THD::binlog_start_trans_and_stmt()
2287
 
{
2288
 
  binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2289
 
 
2290
 
  if (trx_data == NULL ||
2291
 
      trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
2292
 
  {
2293
 
    this->binlog_set_stmt_begin();
2294
 
    if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2295
 
      trans_register_ha(this, true, binlog_hton);
2296
 
    trans_register_ha(this, false, binlog_hton);
2297
 
    /*
2298
 
      Mark statement transaction as read/write. We never start
2299
 
      a binary log transaction and keep it read-only,
2300
 
      therefore it's best to mark the transaction read/write just
2301
 
      at the same time we start it.
2302
 
      Not necessary to mark the normal transaction read/write
2303
 
      since the statement-level flag will be propagated automatically
2304
 
      inside ha_commit_trans.
2305
 
    */
2306
 
    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
2307
 
  }
2308
 
  return;
2309
 
}
2310
 
 
2311
 
void THD::binlog_set_stmt_begin() {
2312
 
  binlog_trx_data *trx_data=
2313
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2314
 
 
2315
 
  /*
2316
 
    The call to binlog_trans_log_savepos() might create the trx_data
2317
 
    structure, if it didn't exist before, so we save the position
2318
 
    into an auto variable and then write it into the transaction
2319
 
    data for the binary log (i.e., trx_data).
2320
 
  */
2321
 
  my_off_t pos= 0;
2322
 
  binlog_trans_log_savepos(this, &pos);
2323
 
  trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2324
 
  trx_data->before_stmt_pos= pos;
2325
 
}
2326
 
 
2327
 
 
2328
 
/*
2329
 
  Write a table map to the binary log.
2330
 
 */
2331
 
 
2332
 
int THD::binlog_write_table_map(Table *table, bool is_trans)
2333
 
{
2334
 
  int error;
2335
 
 
2336
 
  /* Pre-conditions */
2337
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2338
 
  assert(table->s->table_map_id != UINT32_MAX);
2339
 
 
2340
 
  Table_map_log_event::flag_set const
2341
 
    flags= Table_map_log_event::TM_NO_FLAGS;
2342
 
 
2343
 
  Table_map_log_event
2344
 
    the_event(this, table, table->s->table_map_id, is_trans, flags);
2345
 
 
2346
 
  if (is_trans && binlog_table_maps == 0)
2347
 
    binlog_start_trans_and_stmt();
2348
 
 
2349
 
  if ((error= mysql_bin_log.write(&the_event)))
2350
 
    return(error);
2351
 
 
2352
 
  binlog_table_maps++;
2353
 
  table->s->table_map_version= mysql_bin_log.table_map_version();
2354
 
  return(0);
2355
 
}
2356
 
 
2357
 
Rows_log_event*
2358
 
THD::binlog_get_pending_rows_event() const
2359
 
{
2360
 
  binlog_trx_data *const trx_data=
2361
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2362
 
  /*
2363
 
    This is less than ideal, but here's the story: If there is no
2364
 
    trx_data, prepare_pending_rows_event() has never been called
2365
 
    (since the trx_data is set up there). In that case, we just return
2366
 
    NULL.
2367
 
   */
2368
 
  return trx_data ? trx_data->pending() : NULL;
2369
 
}
2370
 
 
2371
 
void
2372
 
THD::binlog_set_pending_rows_event(Rows_log_event* ev)
2373
 
{
2374
 
  if (thd_get_ha_data(this, binlog_hton) == NULL)
2375
 
    binlog_setup_trx_data();
2376
 
 
2377
 
  binlog_trx_data *const trx_data=
2378
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2379
 
 
2380
 
  assert(trx_data);
2381
 
  trx_data->set_pending(ev);
2382
 
}
2383
 
 
 
1803
void DRIZZLE_BIN_LOG::start_union_events(Session *session, query_id_t query_id_param)
 
1804
{
 
1805
  assert(!session->binlog_evt_union.do_union);
 
1806
  session->binlog_evt_union.do_union= true;
 
1807
  session->binlog_evt_union.unioned_events= false;
 
1808
  session->binlog_evt_union.unioned_events_trans= false;
 
1809
  session->binlog_evt_union.first_query_id= query_id_param;
 
1810
}
 
1811
 
 
1812
void DRIZZLE_BIN_LOG::stop_union_events(Session *session)
 
1813
{
 
1814
  assert(session->binlog_evt_union.do_union);
 
1815
  session->binlog_evt_union.do_union= false;
 
1816
}
 
1817
 
 
1818
bool DRIZZLE_BIN_LOG::is_query_in_union(Session *session, query_id_t query_id_param)
 
1819
{
 
1820
  return (session->binlog_evt_union.do_union &&
 
1821
          query_id_param >= session->binlog_evt_union.first_query_id);
 
1822
}
2384
1823
 
2385
1824
/*
2386
1825
  Moves the last bunch of rows from the pending Rows event to the binlog
2388
1827
  event.
2389
1828
*/
2390
1829
int
2391
 
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
2392
 
                                                Rows_log_event* event)
 
1830
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(Session *, Rows_log_event*)
2393
1831
{
2394
 
  assert(mysql_bin_log.is_open());
2395
 
 
2396
 
  int error= 0;
2397
 
 
2398
 
  binlog_trx_data *const trx_data=
2399
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
2400
 
 
2401
 
  assert(trx_data);
2402
 
 
2403
 
  if (Rows_log_event* pending= trx_data->pending())
2404
 
  {
2405
 
    IO_CACHE *file= &log_file;
2406
 
 
2407
 
    /*
2408
 
      Decide if we should write to the log file directly or to the
2409
 
      transaction log.
2410
 
    */
2411
 
    if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log))
2412
 
      file= &trx_data->trans_log;
2413
 
 
2414
 
    /*
2415
 
      If we are writing to the log file directly, we could avoid
2416
 
      locking the log. This does not work since we need to step the
2417
 
      m_table_map_version below, and that change has to be protected
2418
 
      by the LOCK_log mutex.
2419
 
    */
2420
 
    pthread_mutex_lock(&LOCK_log);
2421
 
 
2422
 
    /*
2423
 
      Write pending event to log file or transaction cache
2424
 
    */
2425
 
    if (pending->write(file))
2426
 
    {
2427
 
      pthread_mutex_unlock(&LOCK_log);
2428
 
      return(1);
2429
 
    }
2430
 
 
2431
 
    /*
2432
 
      We step the table map version if we are writing an event
2433
 
      representing the end of a statement.  We do this regardless of
2434
 
      wheather we write to the transaction cache or to directly to the
2435
 
      file.
2436
 
 
2437
 
      In an ideal world, we could avoid stepping the table map version
2438
 
      if we were writing to a transaction cache, since we could then
2439
 
      reuse the table map that was written earlier in the transaction
2440
 
      cache.  This does not work since STMT_END_F implies closing all
2441
 
      table mappings on the slave side.
2442
 
 
2443
 
      TODO: Find a solution so that table maps does not have to be
2444
 
      written several times within a transaction.
2445
 
     */
2446
 
    if (pending->get_flags(Rows_log_event::STMT_END_F))
2447
 
      ++m_table_map_version;
2448
 
 
2449
 
    delete pending;
2450
 
 
2451
 
    if (file == &log_file)
2452
 
    {
2453
 
      error= flush_and_sync();
2454
 
      if (!error)
2455
 
      {
2456
 
        signal_update();
2457
 
        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2458
 
      }
2459
 
    }
2460
 
 
2461
 
    pthread_mutex_unlock(&LOCK_log);
2462
 
  }
2463
 
 
2464
 
  thd->binlog_set_pending_rows_event(event);
2465
 
 
2466
 
  return(error);
 
1832
  assert(drizzle_bin_log.is_open());
 
1833
 
 
1834
  return false;
2467
1835
}
2468
1836
 
2469
1837
/**
2472
1840
 
2473
1841
bool DRIZZLE_BIN_LOG::write(Log_event *event_info)
2474
1842
{
2475
 
  THD *thd= event_info->thd;
 
1843
  Session *session= event_info->session;
2476
1844
  bool error= 1;
2477
1845
 
2478
 
  if (thd->binlog_evt_union.do_union)
 
1846
  if (session->binlog_evt_union.do_union)
2479
1847
  {
2480
1848
    /*
2481
1849
      In Stored function; Remember that function call caused an update.
2482
1850
      We will log the function call to the binary log on function exit
2483
1851
    */
2484
 
    thd->binlog_evt_union.unioned_events= true;
2485
 
    thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
 
1852
    session->binlog_evt_union.unioned_events= true;
 
1853
    session->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
2486
1854
    return(0);
2487
1855
  }
2488
1856
 
2496
1864
    we are inside a stored function, we do not end the statement since
2497
1865
    this will close all tables on the slave.
2498
1866
  */
2499
 
  bool const end_stmt= false;
2500
 
  thd->binlog_flush_pending_rows_event(end_stmt);
2501
1867
 
2502
1868
  pthread_mutex_lock(&LOCK_log);
2503
1869
 
2514
1880
      "do the involved tables match (to be implemented)
2515
1881
      binlog_[wild_]{do|ignore}_table?" (WL#1049)"
2516
1882
    */
2517
 
    const char *local_db= event_info->get_db();
2518
 
    if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
2519
 
        (!binlog_filter->db_ok(local_db)))
 
1883
    if (session && !(session->options & OPTION_BIN_LOG))
2520
1884
    {
2521
1885
      pthread_mutex_unlock(&LOCK_log);
2522
1886
      return(0);
2523
1887
    }
2524
1888
 
2525
1889
    /*
2526
 
      Should we write to the binlog cache or to the binlog on disk?
2527
 
      Write to the binlog cache if:
2528
 
      - it is already not empty (meaning we're in a transaction; note that the
2529
 
     present event could be about a non-transactional table, but still we need
2530
 
     to write to the binlog cache in that case to handle updates to mixed
2531
 
     trans/non-trans table types the best possible in binlogging)
2532
 
      - or if the event asks for it (cache_stmt == TRUE).
2533
 
    */
2534
 
    if (opt_using_transactions && thd)
2535
 
    {
2536
 
      if (thd->binlog_setup_trx_data())
2537
 
        goto err;
2538
 
 
2539
 
      binlog_trx_data *const trx_data=
2540
 
        (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
2541
 
      IO_CACHE *trans_log= &trx_data->trans_log;
2542
 
      my_off_t trans_log_pos= my_b_tell(trans_log);
2543
 
      if (event_info->get_cache_stmt() || trans_log_pos != 0)
2544
 
      {
2545
 
        if (trans_log_pos == 0)
2546
 
          thd->binlog_start_trans_and_stmt();
2547
 
        file= trans_log;
2548
 
      }
2549
 
      /*
2550
 
        TODO as Mats suggested, for all the cases above where we write to
2551
 
        trans_log, it sounds unnecessary to lock LOCK_log. We should rather
2552
 
        test first if we want to write to trans_log, and if not, lock
2553
 
        LOCK_log.
2554
 
      */
2555
 
    }
2556
 
 
2557
 
    /*
2558
 
      No check for auto events flag here - this write method should
2559
 
      never be called if auto-events are enabled
2560
 
    */
2561
 
 
2562
 
    /*
2563
 
      1. Write first log events which describe the 'run environment'
2564
 
      of the SQL command
2565
 
    */
2566
 
 
2567
 
    /*
2568
 
      If row-based binlogging, Insert_id, Rand and other kind of "setting
2569
 
      context" events are not needed.
2570
 
    */
2571
 
    if (thd)
2572
 
    {
2573
 
      if (!thd->current_stmt_binlog_row_based)
2574
 
      {
2575
 
        if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
2576
 
        {
2577
 
          Intvar_log_event e(thd,(unsigned char) LAST_INSERT_ID_EVENT,
2578
 
                             thd->first_successful_insert_id_in_prev_stmt_for_binlog);
2579
 
          if (e.write(file))
2580
 
            goto err;
2581
 
        }
2582
 
        if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
2583
 
        {
2584
 
          /*
2585
 
            If the auto_increment was second in a table's index (possible with
2586
 
            MyISAM or BDB) (table->next_number_keypart != 0), such event is
2587
 
            in fact not necessary. We could avoid logging it.
2588
 
          */
2589
 
          Intvar_log_event e(thd, (unsigned char) INSERT_ID_EVENT,
2590
 
                             thd->auto_inc_intervals_in_cur_stmt_for_binlog.
2591
 
                             minimum());
2592
 
          if (e.write(file))
2593
 
            goto err;
2594
 
        }
2595
 
        if (thd->rand_used)
2596
 
        {
2597
 
          Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
2598
 
          if (e.write(file))
2599
 
            goto err;
2600
 
        }
2601
 
        if (thd->user_var_events.elements)
2602
 
        {
2603
 
          for (uint32_t i= 0; i < thd->user_var_events.elements; i++)
2604
 
          {
2605
 
            BINLOG_USER_VAR_EVENT *user_var_event;
2606
 
            get_dynamic(&thd->user_var_events,(unsigned char*) &user_var_event, i);
2607
 
            User_var_log_event e(thd, user_var_event->user_var_event->name.str,
2608
 
                                 user_var_event->user_var_event->name.length,
2609
 
                                 user_var_event->value,
2610
 
                                 user_var_event->length,
2611
 
                                 user_var_event->type,
2612
 
                                 user_var_event->charset_number);
2613
 
            if (e.write(file))
2614
 
              goto err;
2615
 
          }
2616
 
        }
2617
 
      }
2618
 
    }
2619
 
 
2620
 
    /*
2621
1890
       Write the SQL command
2622
1891
     */
2623
1892
 
2651
1920
  return(error);
2652
1921
}
2653
1922
 
2654
 
 
2655
 
int error_log_print(enum loglevel level, const char *format,
2656
 
                    va_list args)
2657
 
{
2658
 
  return logger.error_log_print(level, format, args);
2659
 
}
2660
 
 
2661
1923
void DRIZZLE_BIN_LOG::rotate_and_purge(uint32_t flags)
2662
1924
{
2663
1925
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2668
1930
    new_file_without_locking();
2669
1931
    if (expire_logs_days)
2670
1932
    {
2671
 
      time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
 
1933
      time_t purge_time= time(0) - expire_logs_days*24*60*60;
2672
1934
      if (purge_time >= 0)
2673
1935
        purge_logs_before_date(purge_time);
2674
1936
    }
2836
2098
  was updated in a transaction which was rolled back. This is to ensure
2837
2099
  that the same updates are run on the slave.
2838
2100
 
2839
 
  @param thd
 
2101
  @param session
2840
2102
  @param cache          The cache to copy to the binlog
2841
2103
  @param commit_event   The commit event to print after writing the
2842
2104
                        contents of the cache.
2849
2111
    'cache' needs to be reinitialized after this functions returns.
2850
2112
*/
2851
2113
 
2852
 
bool DRIZZLE_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
 
2114
bool DRIZZLE_BIN_LOG::write(Session *session, IO_CACHE *cache, Log_event *commit_event)
2853
2115
{
2854
2116
  pthread_mutex_lock(&LOCK_log);
2855
2117
 
2870
2132
        transaction is either a BEGIN..COMMIT block or a single
2871
2133
        statement in autocommit mode.
2872
2134
      */
2873
 
      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), true, false);
 
2135
      Query_log_event qinfo(session, STRING_WITH_LEN("BEGIN"), true, false);
2874
2136
      /*
2875
2137
        Imagine this is rollback due to net timeout, after all
2876
2138
        statements of the transaction succeeded. Then we want a
2880
2142
        generated event, and as this event is generated late it would
2881
2143
        lead to false alarms.
2882
2144
 
2883
 
        This is safer than thd->clear_error() against kills at shutdown.
 
2145
        This is safer than session->clear_error() against kills at shutdown.
2884
2146
      */
2885
2147
      qinfo.error_code= 0;
2886
2148
      /*
2903
2165
        goto err;
2904
2166
      if (cache->error)                         // Error on read
2905
2167
      {
2906
 
        sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
 
2168
        errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_ERROR_ON_READ), cache->file_name, errno);
2907
2169
        write_error=1;                          // Don't give more errors
2908
2170
        goto err;
2909
2171
      }
2935
2197
  if (!write_error)
2936
2198
  {
2937
2199
    write_error= 1;
2938
 
    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
 
2200
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_ERROR_ON_WRITE), name, errno);
2939
2201
  }
2940
2202
  pthread_mutex_unlock(&LOCK_log);
2941
2203
  return(1);
2945
2207
/**
2946
2208
  Wait until we get a signal that the relay log has been updated
2947
2209
 
2948
 
  @param[in] thd   a THD struct
 
2210
  @param[in] session   a Session struct
2949
2211
  @note
2950
2212
    LOCK_log must be taken before calling this function.
2951
2213
    It will be released at the end of the function.
2952
2214
*/
2953
2215
 
2954
 
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(THD* thd)
 
2216
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(Session* session)
2955
2217
{
2956
2218
  const char *old_msg;
2957
 
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
2958
 
                           "Slave has read all relay log; " 
 
2219
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
 
2220
                           "Slave has read all relay log; "
2959
2221
                           "waiting for the slave I/O "
2960
2222
                           "thread to update it" );
2961
2223
  pthread_cond_wait(&update_cond, &LOCK_log);
2962
 
  thd->exit_cond(old_msg);
 
2224
  session->exit_cond(old_msg);
2963
2225
  return;
2964
2226
}
2965
2227
 
2967
2229
/**
2968
2230
  Wait until we get a signal that the binary log has been updated.
2969
2231
  Applies to master only.
2970
 
     
 
2232
 
2971
2233
  NOTES
2972
 
  @param[in] thd        a THD struct
 
2234
  @param[in] session        a Session struct
2973
2235
  @param[in] timeout    a pointer to a timespec;
2974
2236
                        NULL means to wait w/o timeout.
2975
2237
  @retval    0          if got signalled on update
2980
2242
    LOCK_log is released by the caller.
2981
2243
*/
2982
2244
 
2983
 
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(THD* thd,
 
2245
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(Session* session,
2984
2246
                                           const struct timespec *timeout)
2985
2247
{
2986
2248
  int ret= 0;
2987
 
  const char* old_msg = thd->get_proc_info();
2988
 
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
 
2249
  const char* old_msg = session->get_proc_info();
 
2250
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
2989
2251
                           "Master has sent all binlog to slave; "
2990
2252
                           "waiting for binlog to be updated");
2991
2253
  if (!timeout)
3029
2291
    {
3030
2292
      my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
3031
2293
      unsigned char flags= 0;            // clearing LOG_EVENT_BINLOG_IN_USE_F
3032
 
      pwrite(log_file.file, &flags, 1, offset);
 
2294
      assert(pwrite(log_file.file, &flags, 1, offset)==1);
3033
2295
    }
3034
2296
 
3035
2297
    /* this will cleanup IO_CACHE, sync and close the file */
3047
2309
    if (my_close(index_file.file, MYF(0)) < 0 && ! write_error)
3048
2310
    {
3049
2311
      write_error= 1;
3050
 
      sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno);
 
2312
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_ERROR_ON_WRITE), index_file_name, errno);
3051
2313
    }
3052
2314
  }
3053
2315
  log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
3100
2362
  register int flag;
3101
2363
  const char *start;
3102
2364
 
3103
 
  flag= 0; 
 
2365
  flag= 0;
3104
2366
  start= str;
3105
2367
  while (*str++ == ' ') ;
3106
2368
  if (*--str == '-' || *str == '+')
3125
2387
  return(1);                    /* Number ok */
3126
2388
} /* test_if_number */
3127
2389
 
3128
 
 
3129
 
void sql_perror(const char *message)
3130
 
{
3131
 
  sql_print_error("%s: %s",message, strerror(errno));
3132
 
}
3133
 
 
3134
 
 
3135
 
bool flush_error_log()
3136
 
{
3137
 
  bool result=0;
3138
 
  if (opt_error_log)
3139
 
  {
3140
 
    char err_renamed[FN_REFLEN], *end;
3141
 
    end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
3142
 
    my_stpcpy(end, "-old");
3143
 
    pthread_mutex_lock(&LOCK_error_log);
3144
 
    char err_temp[FN_REFLEN+4];
3145
 
    /*
3146
 
     On Windows is necessary a temporary file for to rename
3147
 
     the current error file.
3148
 
    */
3149
 
    strxmov(err_temp, err_renamed,"-tmp",NULL);
3150
 
    (void) my_delete(err_temp, MYF(0)); 
3151
 
    if (freopen(err_temp,"a+",stdout))
3152
 
    {
3153
 
      int fd;
3154
 
      size_t bytes;
3155
 
      unsigned char buf[IO_SIZE];
3156
 
 
3157
 
      freopen(err_temp,"a+",stderr);
3158
 
      (void) my_delete(err_renamed, MYF(0));
3159
 
      my_rename(log_error_file,err_renamed,MYF(0));
3160
 
      if (freopen(log_error_file,"a+",stdout))
3161
 
        freopen(log_error_file,"a+",stderr);
3162
 
 
3163
 
      if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
3164
 
      {
3165
 
        while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
3166
 
               bytes != MY_FILE_ERROR)
3167
 
          my_fwrite(stderr, buf, bytes, MYF(0));
3168
 
        my_close(fd, MYF(0));
3169
 
      }
3170
 
      (void) my_delete(err_temp, MYF(0)); 
3171
 
    }
3172
 
    else
3173
 
     result= 1;
3174
 
    pthread_mutex_unlock(&LOCK_error_log);
3175
 
  }
3176
 
   return result;
3177
 
}
3178
 
 
3179
2390
void DRIZZLE_BIN_LOG::signal_update()
3180
2391
{
3181
2392
  pthread_cond_broadcast(&update_cond);
3182
2393
  return;
3183
2394
}
3184
2395
 
3185
 
/**
3186
 
  Prints a printf style message to the error log and, under NT, to the
3187
 
  Windows event log.
3188
 
 
3189
 
  This function prints the message into a buffer and then sends that buffer
3190
 
  to other functions to write that message to other logging sources.
3191
 
 
3192
 
  @param event_type          Type of event to write (Error, Warning, or Info)
3193
 
  @param format              Printf style format of message
3194
 
  @param args                va_list list of arguments for the message
3195
 
 
3196
 
  @returns
3197
 
    The function always returns 0. The return value is present in the
3198
 
    signature to be compatible with other logging routines, which could
3199
 
    return an error (e.g. logging to the log tables)
3200
 
*/
3201
 
static void print_buffer_to_file(enum loglevel level,
3202
 
                                 int error_code __attribute__((unused)),
3203
 
                                 const char *buffer,
3204
 
                                 size_t buffer_length __attribute__((unused)))
3205
 
{
3206
 
  time_t skr;
3207
 
  struct tm tm_tmp;
3208
 
  struct tm *start;
3209
 
 
3210
 
  pthread_mutex_lock(&LOCK_error_log);
3211
 
 
3212
 
  skr= my_time(0);
3213
 
  localtime_r(&skr, &tm_tmp);
3214
 
  start=&tm_tmp;
3215
 
 
3216
 
  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
3217
 
          start->tm_year % 100,
3218
 
          start->tm_mon+1,
3219
 
          start->tm_mday,
3220
 
          start->tm_hour,
3221
 
          start->tm_min,
3222
 
          start->tm_sec,
3223
 
          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
3224
 
           "Warning" : "Note"),
3225
 
          buffer);
3226
 
 
3227
 
  fflush(stderr);
3228
 
 
3229
 
  pthread_mutex_unlock(&LOCK_error_log);
3230
 
  return;
3231
 
}
3232
 
 
3233
 
 
3234
 
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
3235
 
{
3236
 
  char   buff[1024];
3237
 
  size_t length;
3238
 
  int error_code= errno;
3239
 
 
3240
 
  length= vsnprintf(buff, sizeof(buff), format, args);
3241
 
 
3242
 
  print_buffer_to_file(level, error_code, buff, length);
3243
 
 
3244
 
  return(0);
3245
 
}
3246
 
 
3247
 
 
3248
 
void sql_print_error(const char *format, ...) 
3249
 
{
3250
 
  va_list args;
3251
 
 
3252
 
  va_start(args, format);
3253
 
  error_log_print(ERROR_LEVEL, format, args);
3254
 
  va_end(args);
3255
 
 
3256
 
  return;
3257
 
}
3258
 
 
3259
 
 
3260
 
void sql_print_warning(const char *format, ...) 
3261
 
{
3262
 
  va_list args;
3263
 
 
3264
 
  va_start(args, format);
3265
 
  error_log_print(WARNING_LEVEL, format, args);
3266
 
  va_end(args);
3267
 
 
3268
 
  return;
3269
 
}
3270
 
 
3271
 
 
3272
 
void sql_print_information(const char *format, ...) 
3273
 
{
3274
 
  va_list args;
3275
 
 
3276
 
  va_start(args, format);
3277
 
  error_log_print(INFORMATION_LEVEL, format, args);
3278
 
  va_end(args);
3279
 
 
3280
 
  return;
3281
 
}
3282
 
 
3283
 
 
3284
2396
/********* transaction coordinator log for 2pc - mmap() based solution *******/
3285
2397
 
3286
2398
/*
3319
2431
  dirty - we don't sync removals to disk.
3320
2432
*/
3321
2433
 
3322
 
ulong tc_log_page_waits= 0;
 
2434
uint64_t tc_log_page_waits= 0;
3323
2435
 
3324
2436
#ifdef HAVE_MMAP
3325
2437
 
3327
2439
 
3328
2440
static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
3329
2441
 
3330
 
ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
3331
 
ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
 
2442
uint64_t opt_tc_log_size= TC_LOG_MIN_SIZE;
 
2443
uint64_t tc_log_max_pages_used= 0;
 
2444
uint64_t tc_log_page_size= 0;
 
2445
uint64_t tc_log_cur_pages_used= 0;
3332
2446
 
3333
2447
int TC_LOG_MMAP::open(const char *opt_name)
3334
2448
{
3342
2456
  tc_log_page_size= getpagesize();
3343
2457
  assert(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
3344
2458
 
3345
 
  fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
 
2459
  fn_format(logname,opt_name,drizzle_data_home,"",MY_UNPACK_FILENAME);
3346
2460
  if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
3347
2461
  {
3348
2462
    if (my_errno != ENOENT)
3360
2474
  {
3361
2475
    inited= 1;
3362
2476
    crashed= true;
3363
 
    sql_print_information(_("Recovering after a crash using %s"), opt_name);
 
2477
    errmsg_printf(ERRMSG_LVL_INFO, _("Recovering after a crash using %s"), opt_name);
3364
2478
    if (tc_heuristic_recover)
3365
2479
    {
3366
 
      sql_print_error(_("Cannot perform automatic crash recovery when "
 
2480
      errmsg_printf(ERRMSG_LVL_ERROR, _("Cannot perform automatic crash recovery when "
3367
2481
                      "--tc-heuristic-recover is used"));
3368
2482
      goto err;
3369
2483
    }
3370
 
    file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
3371
 
    if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
 
2484
    file_length= lseek(fd, 0, SEEK_END);
 
2485
    if (file_length == OFF_T_MAX || file_length % tc_log_page_size)
3372
2486
      goto err;
3373
2487
  }
3374
2488
 
3383
2497
 
3384
2498
  npages=(uint)file_length/tc_log_page_size;
3385
2499
  assert(npages >= 3);             // to guarantee non-empty pool
3386
 
  if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
 
2500
  if (!(pages=(PAGE *)malloc(npages*sizeof(PAGE))))
3387
2501
    goto err;
 
2502
  memset(pages, 0, npages*sizeof(PAGE));
3388
2503
  inited=3;
3389
2504
  for (pg=pages, i=0; i < npages; i++, pg++)
3390
2505
  {
3409
2524
 
3410
2525
  memcpy(data, tc_log_magic, sizeof(tc_log_magic));
3411
2526
  data[sizeof(tc_log_magic)]= (unsigned char)total_ha_2pc;
3412
 
  msync(data, tc_log_page_size, MS_SYNC);
 
2527
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
 
2528
  //   so the cast should be fine.
 
2529
  msync((char *)data, tc_log_page_size, MS_SYNC);
3413
2530
  my_sync(fd, MYF(0));
3414
2531
  inited=5;
3415
2532
 
3530
2647
    to the position in memory where xid was logged to.
3531
2648
*/
3532
2649
 
3533
 
int TC_LOG_MMAP::log_xid(THD *thd __attribute__((unused)), my_xid xid)
 
2650
int TC_LOG_MMAP::log_xid(Session *, my_xid xid)
3534
2651
{
3535
2652
  int err;
3536
2653
  PAGE *p;
3615
2732
    sit down and relax - this can take a while...
3616
2733
    note - no locks are held at this point
3617
2734
  */
3618
 
  err= msync(syncing->start, 1, MS_SYNC);
 
2735
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
 
2736
  //   so the cast should be fine.
 
2737
  err= msync((char *)syncing->start, 1, MS_SYNC);
3619
2738
  if(err==0)
3620
2739
    err= my_sync(fd, MYF(0));
3621
2740
 
3642
2761
  cookie points directly to the memory where xid was logged.
3643
2762
*/
3644
2763
 
3645
 
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid __attribute__((unused)))
 
2764
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
3646
2765
{
3647
2766
  PAGE *p=pages+(cookie/tc_log_page_size);
3648
2767
  my_xid *x=(my_xid *)(data+cookie);
3700
2819
 
3701
2820
  if (memcmp(data, tc_log_magic, sizeof(tc_log_magic)))
3702
2821
  {
3703
 
    sql_print_error(_("Bad magic header in tc log"));
 
2822
    errmsg_printf(ERRMSG_LVL_ERROR, _("Bad magic header in tc log"));
3704
2823
    goto err1;
3705
2824
  }
3706
2825
 
3710
2829
  */
3711
2830
  if (data[sizeof(tc_log_magic)] != total_ha_2pc)
3712
2831
  {
3713
 
    sql_print_error(_("Recovery failed! You must enable "
 
2832
    errmsg_printf(ERRMSG_LVL_ERROR, _("Recovery failed! You must enable "
3714
2833
                    "exactly %d storage engines that support "
3715
2834
                    "two-phase commit protocol"),
3716
2835
                    data[sizeof(tc_log_magic)]);
3738
2857
err2:
3739
2858
  hash_free(&xids);
3740
2859
err1:
3741
 
  sql_print_error(_("Crash recovery failed. Either correct the problem "
 
2860
  errmsg_printf(ERRMSG_LVL_ERROR, _("Crash recovery failed. Either correct the problem "
3742
2861
                  "(if it's, for example, out of memory error) and restart, "
3743
2862
                  "or delete tc log and start drizzled with "
3744
2863
                  "--tc-heuristic-recover={commit|rollback}"));
3768
2887
  if (!tc_heuristic_recover)
3769
2888
    return 0;
3770
2889
 
3771
 
  sql_print_information(_("Heuristic crash recovery mode"));
 
2890
  errmsg_printf(ERRMSG_LVL_INFO, _("Heuristic crash recovery mode"));
3772
2891
  if (ha_recover(0))
3773
 
    sql_print_error(_("Heuristic crash recovery failed"));
3774
 
  sql_print_information(_("Please restart mysqld without --tc-heuristic-recover"));
 
2892
    errmsg_printf(ERRMSG_LVL_ERROR, _("Heuristic crash recovery failed"));
 
2893
  errmsg_printf(ERRMSG_LVL_INFO, _("Please restart mysqld without --tc-heuristic-recover"));
3775
2894
  return 1;
3776
2895
}
3777
2896
 
3815
2934
  if ((error= find_log_pos(&log_info, NULL, 1)))
3816
2935
  {
3817
2936
    if (error != LOG_INFO_EOF)
3818
 
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
 
2937
      errmsg_printf(ERRMSG_LVL_ERROR, _("find_log_pos() failed (error: %d)"), error);
3819
2938
    else
3820
2939
      error= 0;
3821
2940
    goto err;
3834
2953
 
3835
2954
    do
3836
2955
    {
3837
 
      strmake(log_name, log_info.log_file_name, sizeof(log_name)-1);
 
2956
      strncpy(log_name, log_info.log_file_name, sizeof(log_name)-1);
3838
2957
    } while (!(error= find_next_log(&log_info, 1)));
3839
2958
 
3840
2959
    if (error !=  LOG_INFO_EOF)
3841
2960
    {
3842
 
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
 
2961
      errmsg_printf(ERRMSG_LVL_ERROR, _("find_log_pos() failed (error: %d)"), error);
3843
2962
      goto err;
3844
2963
    }
3845
2964
 
3846
2965
    if ((file= open_binlog(&log, log_name, &errmsg)) < 0)
3847
2966
    {
3848
 
      sql_print_error("%s", errmsg);
 
2967
      errmsg_printf(ERRMSG_LVL_ERROR, "%s", errmsg);
3849
2968
      goto err;
3850
2969
    }
3851
2970
 
3853
2972
        ev->get_type_code() == FORMAT_DESCRIPTION_EVENT &&
3854
2973
        ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
3855
2974
    {
3856
 
      sql_print_information(_("Recovering after a crash using %s"), opt_name);
 
2975
      errmsg_printf(ERRMSG_LVL_INFO, _("Recovering after a crash using %s"), opt_name);
3857
2976
      error= recover(&log, (Format_description_log_event *)ev);
3858
2977
    }
3859
2978
    else
3888
3007
  @retval
3889
3008
    1    success
3890
3009
*/
3891
 
int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
 
3010
int TC_LOG_BINLOG::log_xid(Session *session, my_xid xid)
3892
3011
{
3893
 
  Xid_log_event xle(thd, xid);
3894
 
  binlog_trx_data *trx_data=
3895
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
 
3012
  Xid_log_event xle(session, xid);
 
3013
  /* TODO: Fix return type */
3896
3014
  /*
3897
3015
    We always commit the entire transaction when writing an XID. Also
3898
3016
    note that the return value is inverted.
 
3017
 
 
3018
    TODO: fix backasswards logic on this method
3899
3019
   */
3900
 
  return(!binlog_end_trans(thd, trx_data, &xle, true));
 
3020
 
 
3021
  return replicator_end_transaction(session, true, true) ? false : true;
3901
3022
}
3902
3023
 
3903
 
void TC_LOG_BINLOG::unlog(ulong cookie __attribute__((unused)),
3904
 
                          my_xid xid __attribute__((unused)))
 
3024
void TC_LOG_BINLOG::unlog(ulong, my_xid)
3905
3025
{
3906
3026
  pthread_mutex_lock(&LOCK_prep_xids);
3907
3027
  assert(prepared_xids > 0);
3952
3072
  free_root(&mem_root, MYF(0));
3953
3073
  hash_free(&xids);
3954
3074
err1:
3955
 
  sql_print_error(_("Crash recovery failed. Either correct the problem "
 
3075
  errmsg_printf(ERRMSG_LVL_ERROR, 
 
3076
                _("Crash recovery failed. Either correct the problem "
3956
3077
                  "(if it's, for example, out of memory error) and restart, "
3957
3078
                  "or delete (or rename) binary log and start mysqld with "
3958
3079
                  "--tc-heuristic-recover={commit|rollback}"));
3960
3081
}
3961
3082
 
3962
3083
 
3963
 
#ifdef INNODB_COMPATIBILITY_HOOKS
 
3084
bool DRIZZLE_BIN_LOG::is_table_mapped(Table *table) const
 
3085
{
 
3086
  return table->s->table_map_version == table_map_version();
 
3087
}
 
3088
 
3964
3089
/**
3965
3090
  Get the file name of the MySQL binlog.
3966
3091
  @return the name of the binlog file
3967
3092
*/
3968
3093
extern "C"
3969
 
const char* mysql_bin_log_file_name(void)
 
3094
const char* drizzle_bin_log_file_name(void)
3970
3095
{
3971
 
  return mysql_bin_log.get_log_fname();
 
3096
  return drizzle_bin_log.get_log_fname();
3972
3097
}
 
3098
 
 
3099
 
3973
3100
/**
3974
3101
  Get the current position of the MySQL binlog.
3975
3102
  @return byte offset from the beginning of the binlog
3976
3103
*/
3977
3104
extern "C"
3978
 
uint64_t mysql_bin_log_file_pos(void)
 
3105
uint64_t drizzle_bin_log_file_pos(void)
3979
3106
{
3980
 
  return (uint64_t) mysql_bin_log.get_log_file()->pos_in_file;
 
3107
  return (uint64_t) drizzle_bin_log.get_log_file()->pos_in_file;
3981
3108
}
3982
 
#endif /* INNODB_COMPATIBILITY_HOOKS */
3983
3109
 
3984
3110
 
3985
3111
mysql_declare_plugin(binlog)