~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/log.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 11:20:18 UTC
  • mto: This revision was merged to the branch mainline in revision 62.
  • Revision ID: monty@inaugust.com-20080705112018-fr12kkmgphtu7m29
Changes so that removal of duplicate curr_dir from my_sys.h work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
    Abort logging when we get an error in reading or writing log files
25
25
*/
26
26
 
27
 
#include <drizzled/server_includes.h>
 
27
#include "mysql_priv.h"
28
28
#include "sql_repl.h"
29
29
#include "rpl_filter.h"
30
30
#include "rpl_rli.h"
31
31
 
32
 
#include <mysys/my_dir.h>
 
32
#include <my_dir.h>
33
33
#include <stdarg.h>
 
34
#include <m_ctype.h>                            // For test_if_number
34
35
 
35
 
#include <drizzled/plugin.h>
36
 
#include <drizzled/drizzled_error_messages.h>
37
 
#include <libdrizzle/gettext.h>
 
36
#include <mysql/plugin.h>
38
37
 
39
38
/* max size of the log message */
40
39
#define MAX_LOG_BUFFER_SIZE 1024
46
45
 
47
46
LOGGER logger;
48
47
 
49
 
DRIZZLE_BIN_LOG mysql_bin_log;
 
48
MYSQL_BIN_LOG mysql_bin_log;
50
49
ulong sync_binlog_counter= 0;
51
50
 
52
51
static bool test_if_number(const char *str,
59
58
static int binlog_rollback(handlerton *hton, THD *thd, bool all);
60
59
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
61
60
 
 
61
/**
 
62
  Silence all errors and warnings reported when performing a write
 
63
  to a log table.
 
64
  Errors and warnings are not reported to the client or SQL exception
 
65
  handlers, so that the presence of logging does not interfere and affect
 
66
  the logic of an application.
 
67
*/
 
68
class Silence_log_table_errors : public Internal_error_handler
 
69
{
 
70
  char m_message[MYSQL_ERRMSG_SIZE];
 
71
public:
 
72
  Silence_log_table_errors()
 
73
  {
 
74
    m_message[0]= '\0';
 
75
  }
 
76
 
 
77
  virtual ~Silence_log_table_errors() {}
 
78
 
 
79
  virtual bool handle_error(uint sql_errno, const char *message,
 
80
                            MYSQL_ERROR::enum_warning_level level,
 
81
                            THD *thd);
 
82
  const char *message() const { return m_message; }
 
83
};
 
84
 
 
85
bool
 
86
Silence_log_table_errors::handle_error(uint /* sql_errno */,
 
87
                                       const char *message_arg,
 
88
                                       MYSQL_ERROR::enum_warning_level /* level */,
 
89
                                       THD * /* thd */)
 
90
{
 
91
  strmake(m_message, message_arg, sizeof(m_message)-1);
 
92
  return TRUE;
 
93
}
 
94
 
62
95
 
63
96
sql_print_message_func sql_print_message_handlers[3] =
64
97
{
97
130
  {
98
131
    if (m_mutex)
99
132
      pthread_mutex_unlock(m_mutex);
 
133
#ifndef DBUG_OFF
100
134
    m_mutex= 0;
 
135
#endif
101
136
  }
102
137
 
103
138
private:
121
156
 
122
157
  ~binlog_trx_data()
123
158
  {
124
 
    assert(pending() == NULL);
 
159
    DBUG_ASSERT(pending() == NULL);
125
160
    close_cached_file(&trans_log);
126
161
  }
127
162
 
140
175
   */
141
176
  void truncate(my_off_t pos)
142
177
  {
 
178
    DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
 
179
    DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos));
143
180
    delete pending();
144
181
    set_pending(0);
145
182
    reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
204
241
 
205
242
 
206
243
/* 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)))
 
244
int check_if_log_table(uint db_len, const char *db, uint table_name_len,
 
245
                       const char *table_name, uint check_if_opened)
212
246
{
213
247
  return 0;
214
248
}
215
249
 
 
250
/* log event handlers */
 
251
 
 
252
bool Log_to_file_event_handler::
 
253
  log_error(enum loglevel level, const char *format,
 
254
            va_list args)
 
255
{
 
256
  return vprint_msg_to_log(level, format, args);
 
257
}
 
258
 
 
259
void Log_to_file_event_handler::init_pthread_objects()
 
260
{
 
261
  mysql_log.init_pthread_objects();
 
262
  mysql_slow_log.init_pthread_objects();
 
263
}
 
264
 
 
265
 
 
266
/** Wrapper around MYSQL_LOG::write() for slow log. */
 
267
 
 
268
bool Log_to_file_event_handler::
 
269
  log_slow(THD *thd, time_t current_time, time_t query_start_arg,
 
270
           const char *user_host, uint user_host_len,
 
271
           ulonglong query_utime, ulonglong lock_utime, bool is_command,
 
272
           const char *sql_text, uint sql_text_len)
 
273
{
 
274
  return mysql_slow_log.write(thd, current_time, query_start_arg,
 
275
                              user_host, user_host_len,
 
276
                              query_utime, lock_utime, is_command,
 
277
                              sql_text, sql_text_len);
 
278
}
 
279
 
 
280
 
 
281
/**
 
282
   Wrapper around MYSQL_LOG::write() for general log. We need it since we
 
283
   want all log event handlers to have the same signature.
 
284
*/
 
285
 
 
286
bool Log_to_file_event_handler::
 
287
  log_general(THD *thd, time_t event_time, const char *user_host,
 
288
              uint user_host_len, int thread_id,
 
289
              const char *command_type, uint command_type_len,
 
290
              const char *sql_text, uint sql_text_len,
 
291
              CHARSET_INFO *client_cs)
 
292
{
 
293
  return mysql_log.write(event_time, user_host, user_host_len,
 
294
                         thread_id, command_type, command_type_len,
 
295
                         sql_text, sql_text_len);
 
296
}
 
297
 
 
298
 
 
299
bool Log_to_file_event_handler::init()
 
300
{
 
301
  if (!is_initialized)
 
302
  {
 
303
    if (opt_slow_log)
 
304
      mysql_slow_log.open_slow_log(sys_var_slow_log_path.value);
 
305
 
 
306
    if (opt_log)
 
307
      mysql_log.open_query_log(sys_var_general_log_path.value);
 
308
 
 
309
    is_initialized= TRUE;
 
310
  }
 
311
 
 
312
  return FALSE;
 
313
}
 
314
 
 
315
 
 
316
void Log_to_file_event_handler::cleanup()
 
317
{
 
318
  mysql_log.cleanup();
 
319
  mysql_slow_log.cleanup();
 
320
}
 
321
 
 
322
void Log_to_file_event_handler::flush()
 
323
{
 
324
  /* reopen log files */
 
325
  if (opt_log)
 
326
    mysql_log.reopen_file();
 
327
  if (opt_slow_log)
 
328
    mysql_slow_log.reopen_file();
 
329
}
 
330
 
216
331
/*
217
332
  Log error with all enabled log event handlers
218
333
 
232
347
bool LOGGER::error_log_print(enum loglevel level, const char *format,
233
348
                             va_list args)
234
349
{
235
 
  bool error= false;
 
350
  bool error= FALSE;
236
351
  Log_event_handler **current_handler;
237
352
 
238
353
  /* currently we don't need locking here as there is no error_log table */
245
360
 
246
361
void LOGGER::cleanup_base()
247
362
{
248
 
  assert(inited == 1);
 
363
  DBUG_ASSERT(inited == 1);
249
364
  rwlock_destroy(&LOCK_logger);
 
365
  if (file_log_handler)
 
366
    file_log_handler->cleanup();
250
367
}
251
368
 
252
369
 
253
370
void LOGGER::cleanup_end()
254
371
{
255
 
  assert(inited == 1);
 
372
  DBUG_ASSERT(inited == 1);
 
373
  if (file_log_handler)
 
374
    delete file_log_handler;
256
375
}
257
376
 
258
377
 
262
381
*/
263
382
void LOGGER::init_base()
264
383
{
265
 
  assert(inited == 0);
 
384
  DBUG_ASSERT(inited == 0);
266
385
  inited= 1;
267
386
 
 
387
  /*
 
388
    Here we create file log handler. We don't do it for the table log handler
 
389
    here as it cannot be created so early. The reason is THD initialization,
 
390
    which depends on the system variables (parsed later).
 
391
  */
 
392
  if (!file_log_handler)
 
393
    file_log_handler= new Log_to_file_event_handler;
 
394
 
268
395
  /* by default we use traditional error log */
269
396
  init_error_log(LOG_FILE);
270
397
 
 
398
  file_log_handler->init_pthread_objects();
271
399
  my_rwlock_init(&LOCK_logger, NULL);
272
400
}
273
401
 
274
402
 
275
 
bool LOGGER::flush_logs(THD *thd __attribute__((unused)))
 
403
bool LOGGER::flush_logs(THD *thd)
276
404
{
277
405
  int rc= 0;
278
406
 
282
410
  */
283
411
  logger.lock_exclusive();
284
412
 
 
413
  /* reopen log files */
 
414
  file_log_handler->flush();
 
415
 
285
416
  /* end of log flush */
286
417
  logger.unlock();
287
418
  return rc;
288
419
}
289
420
 
290
 
void LOGGER::init_error_log(uint32_t error_log_printer)
 
421
 
 
422
/*
 
423
  Log slow query with all enabled log event handlers
 
424
 
 
425
  SYNOPSIS
 
426
    slow_log_print()
 
427
 
 
428
    thd                 THD of the query being logged
 
429
    query               The query being logged
 
430
    query_length        The length of the query string
 
431
    current_utime       Current time in microseconds (from undefined start)
 
432
 
 
433
  RETURN
 
434
    FALSE   OK
 
435
    TRUE    error occured
 
436
*/
 
437
 
 
438
bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
 
439
                            ulonglong current_utime)
 
440
 
 
441
{
 
442
  bool error= FALSE;
 
443
  Log_event_handler **current_handler;
 
444
  bool is_command= FALSE;
 
445
  char user_host_buff[MAX_USER_HOST_SIZE];
 
446
  Security_context *sctx= thd->security_ctx;
 
447
  uint user_host_len= 0;
 
448
  ulonglong query_utime, lock_utime;
 
449
 
 
450
  /*
 
451
    Print the message to the buffer if we have slow log enabled
 
452
  */
 
453
 
 
454
  if (*slow_log_handler_list)
 
455
  {
 
456
    time_t current_time;
 
457
 
 
458
    /* do not log slow queries from replication threads */
 
459
    if (thd->slave_thread && !opt_log_slow_slave_statements)
 
460
      return 0;
 
461
 
 
462
    lock_shared();
 
463
    if (!opt_slow_log)
 
464
    {
 
465
      unlock();
 
466
      return 0;
 
467
    }
 
468
 
 
469
    /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
 
470
    user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
 
471
                             sctx->priv_user ? sctx->priv_user : "", "[",
 
472
                             sctx->user ? sctx->user : "", "] @ ",
 
473
                             sctx->host ? sctx->host : "", " [",
 
474
                             sctx->ip ? sctx->ip : "", "]", NullS) -
 
475
                    user_host_buff);
 
476
 
 
477
    current_time= my_time_possible_from_micro(current_utime);
 
478
    if (thd->start_utime)
 
479
    {
 
480
      query_utime= (current_utime - thd->start_utime);
 
481
      lock_utime=  (thd->utime_after_lock - thd->start_utime);
 
482
    }
 
483
    else
 
484
    {
 
485
      query_utime= lock_utime= 0;
 
486
    }
 
487
 
 
488
    if (!query)
 
489
    {
 
490
      is_command= TRUE;
 
491
      query= command_name[thd->command].str;
 
492
      query_length= command_name[thd->command].length;
 
493
    }
 
494
 
 
495
    for (current_handler= slow_log_handler_list; *current_handler ;)
 
496
      error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
 
497
                                            user_host_buff, user_host_len,
 
498
                                            query_utime, lock_utime, is_command,
 
499
                                            query, query_length) || error;
 
500
 
 
501
    unlock();
 
502
  }
 
503
  return error;
 
504
}
 
505
 
 
506
bool LOGGER::general_log_write(THD *thd, enum enum_server_command command,
 
507
                               const char *query, uint query_length)
 
508
{
 
509
  bool error= FALSE;
 
510
  Log_event_handler **current_handler= general_log_handler_list;
 
511
  char user_host_buff[MAX_USER_HOST_SIZE];
 
512
  Security_context *sctx= thd->security_ctx;
 
513
  ulong id;
 
514
  uint user_host_len= 0;
 
515
  time_t current_time;
 
516
 
 
517
  if (thd)
 
518
    id= thd->thread_id;                 /* Normal thread */
 
519
  else
 
520
    id= 0;                              /* Log from connect handler */
 
521
 
 
522
  lock_shared();
 
523
  if (!opt_log)
 
524
  {
 
525
    unlock();
 
526
    return 0;
 
527
  }
 
528
  user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
 
529
                          sctx->priv_user ? sctx->priv_user : "", "[",
 
530
                          sctx->user ? sctx->user : "", "] @ ",
 
531
                          sctx->host ? sctx->host : "", " [",
 
532
                          sctx->ip ? sctx->ip : "", "]", NullS) -
 
533
                                                          user_host_buff;
 
534
 
 
535
  current_time= my_time(0);
 
536
 
 
537
  while (*current_handler)
 
538
    error|= (*current_handler++)->
 
539
      log_general(thd, current_time, user_host_buff,
 
540
                  user_host_len, id,
 
541
                  command_name[(uint) command].str,
 
542
                  command_name[(uint) command].length,
 
543
                  query, query_length,
 
544
                  thd->variables.character_set_client) || error;
 
545
  unlock();
 
546
 
 
547
  return error;
 
548
}
 
549
 
 
550
bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
 
551
                               const char *format, va_list args)
 
552
{
 
553
  uint message_buff_len= 0;
 
554
  char message_buff[MAX_LOG_BUFFER_SIZE];
 
555
 
 
556
  /* prepare message */
 
557
  if (format)
 
558
    message_buff_len= my_vsnprintf(message_buff, sizeof(message_buff),
 
559
                                   format, args);
 
560
  else
 
561
    message_buff[0]= '\0';
 
562
 
 
563
  return general_log_write(thd, command, message_buff, message_buff_len);
 
564
}
 
565
 
 
566
void LOGGER::init_error_log(uint error_log_printer)
291
567
{
292
568
  if (error_log_printer & LOG_NONE)
293
569
  {
295
571
    return;
296
572
  }
297
573
 
298
 
}
299
 
 
300
 
int LOGGER::set_handlers(uint32_t error_log_printer)
 
574
  switch (error_log_printer) {
 
575
  case LOG_FILE:
 
576
    error_log_handler_list[0]= file_log_handler;
 
577
    error_log_handler_list[1]= 0;
 
578
    break;
 
579
    /* these two are disabled for now */
 
580
  case LOG_TABLE:
 
581
    DBUG_ASSERT(0);
 
582
    break;
 
583
  case LOG_TABLE|LOG_FILE:
 
584
    DBUG_ASSERT(0);
 
585
    break;
 
586
  }
 
587
}
 
588
 
 
589
void LOGGER::init_slow_log(uint slow_log_printer)
 
590
{
 
591
  if (slow_log_printer & LOG_NONE)
 
592
  {
 
593
    slow_log_handler_list[0]= 0;
 
594
    return;
 
595
  }
 
596
 
 
597
  slow_log_handler_list[0]= file_log_handler;
 
598
  slow_log_handler_list[1]= 0;
 
599
}
 
600
 
 
601
void LOGGER::init_general_log(uint general_log_printer)
 
602
{
 
603
  if (general_log_printer & LOG_NONE)
 
604
  {
 
605
    general_log_handler_list[0]= 0;
 
606
    return;
 
607
  }
 
608
 
 
609
  general_log_handler_list[0]= file_log_handler;
 
610
  general_log_handler_list[1]= 0;
 
611
}
 
612
 
 
613
 
 
614
bool LOGGER::activate_log_handler(THD* thd, uint log_type)
 
615
{
 
616
  MYSQL_QUERY_LOG *file_log;
 
617
  bool res= FALSE;
 
618
  lock_exclusive();
 
619
  switch (log_type) {
 
620
  case QUERY_LOG_SLOW:
 
621
    if (!opt_slow_log)
 
622
    {
 
623
      file_log= file_log_handler->get_mysql_slow_log();
 
624
 
 
625
      file_log->open_slow_log(sys_var_slow_log_path.value);
 
626
      init_slow_log(log_output_options);
 
627
      opt_slow_log= TRUE;
 
628
    }
 
629
    break;
 
630
  case QUERY_LOG_GENERAL:
 
631
    if (!opt_log)
 
632
    {
 
633
      file_log= file_log_handler->get_mysql_log();
 
634
 
 
635
      file_log->open_query_log(sys_var_general_log_path.value);
 
636
      init_general_log(log_output_options);
 
637
      opt_log= TRUE;
 
638
    }
 
639
    break;
 
640
  default:
 
641
    DBUG_ASSERT(0);
 
642
  }
 
643
  unlock();
 
644
  return res;
 
645
}
 
646
 
 
647
 
 
648
void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
 
649
{
 
650
  my_bool *tmp_opt= 0;
 
651
  MYSQL_LOG *file_log;
 
652
 
 
653
  switch (log_type) {
 
654
  case QUERY_LOG_SLOW:
 
655
    tmp_opt= &opt_slow_log;
 
656
    file_log= file_log_handler->get_mysql_slow_log();
 
657
    break;
 
658
  case QUERY_LOG_GENERAL:
 
659
    tmp_opt= &opt_log;
 
660
    file_log= file_log_handler->get_mysql_log();
 
661
    break;
 
662
  default:
 
663
    assert(0);                                  // Impossible
 
664
  }
 
665
 
 
666
  if (!(*tmp_opt))
 
667
    return;
 
668
 
 
669
  lock_exclusive();
 
670
  file_log->close(0);
 
671
  *tmp_opt= FALSE;
 
672
  unlock();
 
673
}
 
674
 
 
675
int LOGGER::set_handlers(uint error_log_printer,
 
676
                         uint slow_log_printer,
 
677
                         uint general_log_printer)
301
678
{
302
679
  /* error log table is not supported yet */
 
680
  DBUG_ASSERT(error_log_printer < LOG_TABLE);
 
681
 
303
682
  lock_exclusive();
304
683
 
305
684
  init_error_log(error_log_printer);
 
685
  init_slow_log(slow_log_printer);
 
686
  init_general_log(general_log_printer);
 
687
 
306
688
  unlock();
307
689
 
308
690
  return 0;
327
709
static void
328
710
binlog_trans_log_savepos(THD *thd, my_off_t *pos)
329
711
{
330
 
  assert(pos != NULL);
 
712
  DBUG_ENTER("binlog_trans_log_savepos");
 
713
  DBUG_ASSERT(pos != NULL);
331
714
  if (thd_get_ha_data(thd, binlog_hton) == NULL)
332
715
    thd->binlog_setup_trx_data();
333
716
  binlog_trx_data *const trx_data=
334
717
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
335
 
  assert(mysql_bin_log.is_open());
 
718
  DBUG_ASSERT(mysql_bin_log.is_open());
336
719
  *pos= trx_data->position();
337
 
  return;
 
720
  DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
 
721
  DBUG_VOID_RETURN;
338
722
}
339
723
 
340
724
 
356
740
static void
357
741
binlog_trans_log_truncate(THD *thd, my_off_t pos)
358
742
{
359
 
  assert(thd_get_ha_data(thd, binlog_hton) != NULL);
 
743
  DBUG_ENTER("binlog_trans_log_truncate");
 
744
  DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
 
745
 
 
746
  DBUG_ASSERT(thd_get_ha_data(thd, binlog_hton) != NULL);
360
747
  /* Only true if binlog_trans_log_savepos() wasn't called before */
361
 
  assert(pos != ~(my_off_t) 0);
 
748
  DBUG_ASSERT(pos != ~(my_off_t) 0);
362
749
 
363
750
  binlog_trx_data *const trx_data=
364
751
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
365
752
  trx_data->truncate(pos);
366
 
  return;
 
753
  DBUG_VOID_RETURN;
367
754
}
368
755
 
369
756
 
370
757
/*
371
758
  this function is mostly a placeholder.
372
 
  conceptually, binlog initialization (now mostly done in DRIZZLE_BIN_LOG::open)
 
759
  conceptually, binlog initialization (now mostly done in MYSQL_BIN_LOG::open)
373
760
  should be moved here.
374
761
*/
375
762
 
377
764
{
378
765
  binlog_hton= (handlerton *)p;
379
766
  binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO;
 
767
  binlog_hton->db_type=DB_TYPE_BINLOG;
380
768
  binlog_hton->savepoint_offset= sizeof(my_off_t);
381
769
  binlog_hton->close_connection= binlog_close_connection;
382
770
  binlog_hton->savepoint_set= binlog_savepoint_set;
385
773
  binlog_hton->rollback= binlog_rollback;
386
774
  binlog_hton->prepare= binlog_prepare;
387
775
  binlog_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN;
388
 
 
389
776
  return 0;
390
777
}
391
778
 
392
 
static int binlog_close_connection(handlerton *hton __attribute__((unused)),
393
 
                                   THD *thd)
 
779
static int binlog_close_connection(handlerton *hton, THD *thd)
394
780
{
395
781
  binlog_trx_data *const trx_data=
396
782
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
397
 
  assert(trx_data->empty());
 
783
  DBUG_ASSERT(trx_data->empty());
398
784
  thd_set_ha_data(thd, binlog_hton, NULL);
399
785
  trx_data->~binlog_trx_data();
400
 
  free((unsigned char*)trx_data);
 
786
  my_free((uchar*)trx_data, MYF(0));
401
787
  return 0;
402
788
}
403
789
 
428
814
binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
429
815
                 Log_event *end_ev, bool all)
430
816
{
 
817
  DBUG_ENTER("binlog_end_trans");
431
818
  int error=0;
432
819
  IO_CACHE *trans_log= &trx_data->trans_log;
 
820
  DBUG_PRINT("enter", ("transaction: %s  end_ev: 0x%lx",
 
821
                       all ? "all" : "stmt", (long) end_ev));
 
822
  DBUG_PRINT("info", ("thd->options={ %s%s}",
 
823
                      FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
 
824
                      FLAGSTR(thd->options, OPTION_BEGIN)));
433
825
 
434
826
  /*
435
827
    NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
449
841
      were, we would have to ensure that we're not ending a statement
450
842
      inside a stored function.
451
843
     */
452
 
    thd->binlog_flush_pending_rows_event(true);
 
844
    thd->binlog_flush_pending_rows_event(TRUE);
453
845
 
454
846
    error= mysql_bin_log.write(thd, &trx_data->trans_log, end_ev);
455
847
    trx_data->reset();
479
871
    {
480
872
      trx_data->reset();
481
873
 
482
 
      assert(!thd->binlog_get_pending_rows_event());
 
874
      DBUG_ASSERT(!thd->binlog_get_pending_rows_event());
483
875
      thd->clear_binlog_table_maps();
484
876
    }
485
877
    else                                        // ...statement
493
885
    mysql_bin_log.update_table_map_version();
494
886
  }
495
887
 
496
 
  return(error);
 
888
  DBUG_RETURN(error);
497
889
}
498
890
 
499
 
static int binlog_prepare(handlerton *hton __attribute__((unused)),
500
 
                          THD *thd __attribute__((unused)),
501
 
                          bool all __attribute__((unused)))
 
891
static int binlog_prepare(handlerton *hton, THD *thd, bool all)
502
892
{
503
893
  /*
504
894
    do nothing.
505
895
    just pretend we can do 2pc, so that MySQL won't
506
896
    switch to 1pc.
507
 
    real work will be done in DRIZZLE_BIN_LOG::log_xid()
 
897
    real work will be done in MYSQL_BIN_LOG::log_xid()
508
898
  */
509
899
  return 0;
510
900
}
524
914
 
525
915
  @see handlerton::commit
526
916
*/
527
 
static int binlog_commit(handlerton *hton __attribute__((unused)),
528
 
                         THD *thd, bool all)
 
917
static int binlog_commit(handlerton *hton, THD *thd, bool all)
529
918
{
 
919
  DBUG_ENTER("binlog_commit");
530
920
  binlog_trx_data *const trx_data=
531
921
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
532
922
 
533
923
  if (trx_data->empty())
534
924
  {
535
 
    // we're here because trans_log was flushed in DRIZZLE_BIN_LOG::log_xid()
 
925
    // we're here because trans_log was flushed in MYSQL_BIN_LOG::log_xid()
536
926
    trx_data->reset();
537
 
    return(0);
 
927
    DBUG_RETURN(0);
538
928
  }
539
929
 
540
930
  /*
595
985
 
596
986
    Otherwise, we accumulate the statement
597
987
  */
598
 
  uint64_t const in_transaction=
 
988
  ulonglong const in_transaction=
599
989
    thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
 
990
  DBUG_PRINT("debug",
 
991
             ("all: %d, empty: %s, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
 
992
              all,
 
993
              YESNO(trx_data->empty()),
 
994
              YESNO(in_transaction),
 
995
              YESNO(thd->transaction.all.modified_non_trans_table),
 
996
              YESNO(thd->transaction.stmt.modified_non_trans_table)));
600
997
  if ((in_transaction && (all || (!trx_data->at_least_one_stmt && thd->transaction.stmt.modified_non_trans_table))) || (!in_transaction && !all))
601
998
  {
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)
 
999
    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
 
1000
    qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
604
1001
    int error= binlog_end_trans(thd, trx_data, &qev, all);
605
 
    return(error);
 
1002
    DBUG_RETURN(error);
606
1003
  }
607
 
  return(0);
 
1004
  DBUG_RETURN(0);
608
1005
}
609
1006
 
610
1007
/**
622
1019
 
623
1020
  @see handlerton::rollback
624
1021
*/
625
 
static int binlog_rollback(handlerton *hton __attribute__((unused)),
626
 
                           THD *thd, bool all)
 
1022
static int binlog_rollback(handlerton *hton, THD *thd, bool all)
627
1023
{
 
1024
  DBUG_ENTER("binlog_rollback");
628
1025
  int error=0;
629
1026
  binlog_trx_data *const trx_data=
630
1027
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
631
1028
 
632
1029
  if (trx_data->empty()) {
633
1030
    trx_data->reset();
634
 
    return(0);
 
1031
    DBUG_RETURN(0);
635
1032
  }
636
1033
 
 
1034
  DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
 
1035
                       YESNO(all),
 
1036
                       YESNO(thd->transaction.all.modified_non_trans_table),
 
1037
                       YESNO(thd->transaction.stmt.modified_non_trans_table)));
637
1038
  if ((all && thd->transaction.all.modified_non_trans_table) ||
638
1039
      (!all && thd->transaction.stmt.modified_non_trans_table) ||
639
1040
      (thd->options & OPTION_KEEP_LOG))
646
1047
      transactional table in that statement as well, which needs to be
647
1048
      rolled back on the slave.
648
1049
    */
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)
 
1050
    Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
 
1051
    qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
651
1052
    error= binlog_end_trans(thd, trx_data, &qev, all);
652
1053
  }
653
1054
  else if ((all && !thd->transaction.all.modified_non_trans_table) ||
660
1061
     */
661
1062
    error= binlog_end_trans(thd, trx_data, 0, all);
662
1063
  }
663
 
  return(error);
 
1064
  DBUG_RETURN(error);
664
1065
}
665
1066
 
666
1067
/**
687
1088
  that case there is no need to have it in the binlog).
688
1089
*/
689
1090
 
690
 
static int binlog_savepoint_set(handlerton *hton __attribute__((unused)),
691
 
                                THD *thd, void *sv)
 
1091
static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
692
1092
{
 
1093
  DBUG_ENTER("binlog_savepoint_set");
 
1094
 
693
1095
  binlog_trans_log_savepos(thd, (my_off_t*) sv);
694
1096
  /* Write it to the binary log */
695
1097
  
696
1098
  int const error=
697
1099
    thd->binlog_query(THD::STMT_QUERY_TYPE,
698
 
                      thd->query, thd->query_length, true, false);
699
 
  return(error);
 
1100
                      thd->query, thd->query_length, TRUE, FALSE);
 
1101
  DBUG_RETURN(error);
700
1102
}
701
1103
 
702
 
static int binlog_savepoint_rollback(handlerton *hton __attribute__((unused)),
703
 
                                     THD *thd, void *sv)
 
1104
static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
704
1105
{
 
1106
  DBUG_ENTER("binlog_savepoint_rollback");
 
1107
 
705
1108
  /*
706
1109
    Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
707
1110
    non-transactional table. Otherwise, truncate the binlog cache starting
712
1115
  {
713
1116
    int error=
714
1117
      thd->binlog_query(THD::STMT_QUERY_TYPE,
715
 
                        thd->query, thd->query_length, true, false);
716
 
    return(error);
 
1118
                        thd->query, thd->query_length, TRUE, FALSE);
 
1119
    DBUG_RETURN(error);
717
1120
  }
718
1121
  binlog_trans_log_truncate(thd, *(my_off_t*)sv);
719
 
  return(0);
 
1122
  DBUG_RETURN(0);
720
1123
}
721
1124
 
722
1125
 
723
1126
int check_binlog_magic(IO_CACHE* log, const char** errmsg)
724
1127
{
725
1128
  char magic[4];
726
 
  assert(my_b_tell(log) == 0);
 
1129
  DBUG_ASSERT(my_b_tell(log) == 0);
727
1130
 
728
 
  if (my_b_read(log, (unsigned char*) magic, sizeof(magic)))
 
1131
  if (my_b_read(log, (uchar*) magic, sizeof(magic)))
729
1132
  {
730
 
    *errmsg = _("I/O error reading the header from the binary log");
 
1133
    *errmsg = "I/O error reading the header from the binary log";
731
1134
    sql_print_error("%s, errno=%d, io cache code=%d", *errmsg, my_errno,
732
1135
                    log->error);
733
1136
    return 1;
734
1137
  }
735
1138
  if (memcmp(magic, BINLOG_MAGIC, sizeof(magic)))
736
1139
  {
737
 
    *errmsg = _("Binlog has bad magic number;  It's not a binary log file "
738
 
                "that can be used by this version of Drizzle");
 
1140
    *errmsg = "Binlog has bad magic number;  It's not a binary log file that can be used by this version of MySQL";
739
1141
    return 1;
740
1142
  }
741
1143
  return 0;
745
1147
File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
746
1148
{
747
1149
  File file;
 
1150
  DBUG_ENTER("open_binlog");
748
1151
 
749
1152
  if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE, 
750
1153
                      MYF(MY_WME))) < 0)
751
1154
  {
752
 
    sql_print_error(_("Failed to open log (file '%s', errno %d)"),
 
1155
    sql_print_error("Failed to open log (file '%s', errno %d)",
753
1156
                    log_file_name, my_errno);
754
 
    *errmsg = _("Could not open log file");
 
1157
    *errmsg = "Could not open log file";
755
1158
    goto err;
756
1159
  }
757
1160
  if (init_io_cache(log, file, IO_SIZE*2, READ_CACHE, 0, 0,
758
1161
                    MYF(MY_WME|MY_DONT_CHECK_FILESIZE)))
759
1162
  {
760
 
    sql_print_error(_("Failed to create a cache on log (file '%s')"),
 
1163
    sql_print_error("Failed to create a cache on log (file '%s')",
761
1164
                    log_file_name);
762
 
    *errmsg = _("Could not open log file");
 
1165
    *errmsg = "Could not open log file";
763
1166
    goto err;
764
1167
  }
765
1168
  if (check_binlog_magic(log,errmsg))
766
1169
    goto err;
767
 
  return(file);
 
1170
  DBUG_RETURN(file);
768
1171
 
769
1172
err:
770
1173
  if (file >= 0)
772
1175
    my_close(file,MYF(0));
773
1176
    end_io_cache(log);
774
1177
  }
775
 
  return(-1);
 
1178
  DBUG_RETURN(-1);
776
1179
}
777
1180
 
778
1181
 
788
1191
static int find_uniq_filename(char *name)
789
1192
{
790
1193
  long                  number;
791
 
  uint32_t                  i;
 
1194
  uint                  i;
792
1195
  char                  buff[FN_REFLEN];
793
1196
  struct st_my_dir     *dir_info;
794
1197
  register struct fileinfo *file_info;
795
1198
  ulong                 max_found=0;
796
1199
  size_t                buf_length, length;
797
1200
  char                  *start, *end;
 
1201
  DBUG_ENTER("find_uniq_filename");
798
1202
 
799
1203
  length= dirname_part(buff, name, &buf_length);
800
1204
  start=  name + length;
801
 
  end= strchr(start, '\0');
 
1205
  end=    strend(start);
802
1206
 
803
1207
  *end='.';
804
1208
  length= (size_t) (end-start+1);
805
1209
 
806
1210
  if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
807
1211
  {                                             // This shouldn't happen
808
 
    my_stpcpy(end,".1");                                // use name+1
809
 
    return(0);
 
1212
    strmov(end,".1");                           // use name+1
 
1213
    DBUG_RETURN(0);
810
1214
  }
811
1215
  file_info= dir_info->dir_entry;
812
1216
  for (i=dir_info->number_off_files ; i-- ; file_info++)
813
1217
  {
814
 
    if (memcmp(file_info->name, start, length) == 0 &&
 
1218
    if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 &&
815
1219
        test_if_number(file_info->name+length, &number,0))
816
1220
    {
817
1221
      set_if_bigger(max_found,(ulong) number);
821
1225
 
822
1226
  *end++='.';
823
1227
  sprintf(end,"%06ld",max_found+1);
824
 
  return(0);
 
1228
  DBUG_RETURN(0);
825
1229
}
826
1230
 
827
1231
 
828
 
void DRIZZLE_LOG::init(enum_log_type log_type_arg,
 
1232
void MYSQL_LOG::init(enum_log_type log_type_arg,
829
1233
                     enum cache_type io_cache_type_arg)
830
1234
{
 
1235
  DBUG_ENTER("MYSQL_LOG::init");
831
1236
  log_type= log_type_arg;
832
1237
  io_cache_type= io_cache_type_arg;
833
 
  return;
 
1238
  DBUG_PRINT("info",("log_type: %d", log_type));
 
1239
  DBUG_VOID_RETURN;
834
1240
}
835
1241
 
836
1242
 
855
1261
    1   error
856
1262
*/
857
1263
 
858
 
bool DRIZZLE_LOG::open(const char *log_name, enum_log_type log_type_arg,
 
1264
bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
859
1265
                     const char *new_name, enum cache_type io_cache_type_arg)
860
1266
{
861
1267
  char buff[FN_REFLEN];
862
1268
  File file= -1;
863
1269
  int open_flags= O_CREAT | O_BINARY;
 
1270
  DBUG_ENTER("MYSQL_LOG::open");
 
1271
  DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
864
1272
 
865
1273
  write_error= 0;
866
1274
 
873
1281
  }
874
1282
 
875
1283
  if (new_name)
876
 
    my_stpcpy(log_file_name, new_name);
 
1284
    strmov(log_file_name, new_name);
877
1285
  else if (generate_new_name(log_file_name, name))
878
1286
    goto err;
879
1287
 
895
1303
  if (log_type == LOG_NORMAL)
896
1304
  {
897
1305
    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",
 
1306
    int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
 
1307
                        "started with:\nTCP Port: %d, Named Pipe: %s\n",
 
1308
                        my_progname, server_version, MYSQL_COMPILATION_COMMENT,
 
1309
                        mysqld_port, ""
 
1310
                       );
 
1311
    end= strnmov(buff + len, "Time                 Id Command    Argument\n",
904
1312
                 sizeof(buff) - len);
905
 
    if (my_b_write(&log_file, (unsigned char*) buff, (uint) (end-buff)) ||
 
1313
    if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) ||
906
1314
        flush_io_cache(&log_file))
907
1315
      goto err;
908
1316
  }
909
1317
 
910
1318
  log_state= LOG_OPENED;
911
 
  return(0);
 
1319
  DBUG_RETURN(0);
912
1320
 
913
1321
err:
914
 
  sql_print_error(_("Could not use %s for logging (error %d). "
915
 
                    "Turning logging off for the whole duration of the "
916
 
                    "Drizzle server process. "
917
 
                    "To turn it on again: fix the cause, "
918
 
                    "shutdown the Drizzle server and restart it."),
919
 
                    name, errno);
 
1322
  sql_print_error("Could not use %s for logging (error %d). \
 
1323
Turning logging off for the whole duration of the MySQL server process. \
 
1324
To turn it on again: fix the cause, \
 
1325
shutdown the MySQL server and restart it.", name, errno);
920
1326
  if (file >= 0)
921
1327
    my_close(file, MYF(0));
922
1328
  end_io_cache(&log_file);
923
 
  if (name)
924
 
  {
925
 
    free(name);
926
 
    name= NULL;
927
 
  }
 
1329
  safeFree(name);
928
1330
  log_state= LOG_CLOSED;
929
 
  return(1);
 
1331
  DBUG_RETURN(1);
930
1332
}
931
1333
 
932
 
DRIZZLE_LOG::DRIZZLE_LOG()
933
 
  : name(0), write_error(false), inited(false), log_type(LOG_UNKNOWN),
 
1334
MYSQL_LOG::MYSQL_LOG()
 
1335
  : name(0), write_error(FALSE), inited(FALSE), log_type(LOG_UNKNOWN),
934
1336
    log_state(LOG_CLOSED)
935
1337
{
936
1338
  /*
939
1341
    called only in main(). Doing initialization here would make it happen
940
1342
    before main().
941
1343
  */
942
 
  memset(&log_file, 0, sizeof(log_file));
 
1344
  bzero((char*) &log_file, sizeof(log_file));
943
1345
}
944
1346
 
945
 
void DRIZZLE_LOG::init_pthread_objects()
 
1347
void MYSQL_LOG::init_pthread_objects()
946
1348
{
947
 
  assert(inited == 0);
 
1349
  DBUG_ASSERT(inited == 0);
948
1350
  inited= 1;
949
1351
  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
950
1352
}
963
1365
    The internal structures are not freed until cleanup() is called
964
1366
*/
965
1367
 
966
 
void DRIZZLE_LOG::close(uint32_t exiting)
 
1368
void MYSQL_LOG::close(uint exiting)
967
1369
{                                       // One can't set log_type here!
 
1370
  DBUG_ENTER("MYSQL_LOG::close");
 
1371
  DBUG_PRINT("enter",("exiting: %d", (int) exiting));
968
1372
  if (log_state == LOG_OPENED)
969
1373
  {
970
1374
    end_io_cache(&log_file);
983
1387
  }
984
1388
 
985
1389
  log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
986
 
  if (name)
987
 
  {
988
 
    free(name);
989
 
    name= NULL;
990
 
  }
991
 
  return;
 
1390
  safeFree(name);
 
1391
  DBUG_VOID_RETURN;
992
1392
}
993
1393
 
994
1394
/** This is called only once. */
995
1395
 
996
 
void DRIZZLE_LOG::cleanup()
 
1396
void MYSQL_LOG::cleanup()
997
1397
{
 
1398
  DBUG_ENTER("cleanup");
998
1399
  if (inited)
999
1400
  {
1000
1401
    inited= 0;
1001
1402
    (void) pthread_mutex_destroy(&LOCK_log);
1002
1403
    close(0);
1003
1404
  }
1004
 
  return;
 
1405
  DBUG_VOID_RETURN;
1005
1406
}
1006
1407
 
1007
1408
 
1008
 
int DRIZZLE_LOG::generate_new_name(char *new_name, const char *log_name)
 
1409
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
1009
1410
{
1010
1411
  fn_format(new_name, log_name, mysql_data_home, "", 4);
1011
1412
  if (log_type == LOG_BIN)
1023
1424
}
1024
1425
 
1025
1426
 
 
1427
/*
 
1428
  Reopen the log file
 
1429
 
 
1430
  SYNOPSIS
 
1431
    reopen_file()
 
1432
 
 
1433
  DESCRIPTION
 
1434
    Reopen the log file. The method is used during FLUSH LOGS
 
1435
    and locks LOCK_log mutex
 
1436
*/
 
1437
 
 
1438
 
 
1439
void MYSQL_QUERY_LOG::reopen_file()
 
1440
{
 
1441
  char *save_name;
 
1442
 
 
1443
  DBUG_ENTER("MYSQL_LOG::reopen_file");
 
1444
  if (!is_open())
 
1445
  {
 
1446
    DBUG_PRINT("info",("log is closed"));
 
1447
    DBUG_VOID_RETURN;
 
1448
  }
 
1449
 
 
1450
  pthread_mutex_lock(&LOCK_log);
 
1451
 
 
1452
  save_name= name;
 
1453
  name= 0;                              // Don't free name
 
1454
  close(LOG_CLOSE_TO_BE_OPENED);
 
1455
 
 
1456
  /*
 
1457
     Note that at this point, log_state != LOG_CLOSED (important for is_open()).
 
1458
  */
 
1459
 
 
1460
  open(save_name, log_type, 0, io_cache_type);
 
1461
  my_free(save_name, MYF(0));
 
1462
 
 
1463
  pthread_mutex_unlock(&LOCK_log);
 
1464
 
 
1465
  DBUG_VOID_RETURN;
 
1466
}
 
1467
 
 
1468
 
 
1469
/*
 
1470
  Write a command to traditional general log file
 
1471
 
 
1472
  SYNOPSIS
 
1473
    write()
 
1474
 
 
1475
    event_time        command start timestamp
 
1476
    user_host         the pointer to the string with user@host info
 
1477
    user_host_len     length of the user_host string. this is computed once
 
1478
                      and passed to all general log  event handlers
 
1479
    thread_id         Id of the thread, issued a query
 
1480
    command_type      the type of the command being logged
 
1481
    command_type_len  the length of the string above
 
1482
    sql_text          the very text of the query being executed
 
1483
    sql_text_len      the length of sql_text string
 
1484
 
 
1485
  DESCRIPTION
 
1486
 
 
1487
   Log given command to to normal (not rotable) log file
 
1488
 
 
1489
  RETURN
 
1490
    FASE - OK
 
1491
    TRUE - error occured
 
1492
*/
 
1493
 
 
1494
bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host,
 
1495
                            uint user_host_len, int thread_id,
 
1496
                            const char *command_type, uint command_type_len,
 
1497
                            const char *sql_text, uint sql_text_len)
 
1498
{
 
1499
  char buff[32];
 
1500
  uint length= 0;
 
1501
  char local_time_buff[MAX_TIME_SIZE];
 
1502
  struct tm start;
 
1503
  uint time_buff_len= 0;
 
1504
 
 
1505
  (void) pthread_mutex_lock(&LOCK_log);
 
1506
 
 
1507
  /* Test if someone closed between the is_open test and lock */
 
1508
  if (is_open())
 
1509
  {
 
1510
    /* Note that my_b_write() assumes it knows the length for this */
 
1511
      if (event_time != last_time)
 
1512
      {
 
1513
        last_time= event_time;
 
1514
 
 
1515
        localtime_r(&event_time, &start);
 
1516
 
 
1517
        time_buff_len= my_snprintf(local_time_buff, MAX_TIME_SIZE,
 
1518
                                   "%02d%02d%02d %2d:%02d:%02d",
 
1519
                                   start.tm_year % 100, start.tm_mon + 1,
 
1520
                                   start.tm_mday, start.tm_hour,
 
1521
                                   start.tm_min, start.tm_sec);
 
1522
 
 
1523
        if (my_b_write(&log_file, (uchar*) local_time_buff, time_buff_len))
 
1524
          goto err;
 
1525
      }
 
1526
      else
 
1527
        if (my_b_write(&log_file, (uchar*) "\t\t" ,2) < 0)
 
1528
          goto err;
 
1529
 
 
1530
      /* command_type, thread_id */
 
1531
      length= my_snprintf(buff, 32, "%5ld ", (long) thread_id);
 
1532
 
 
1533
    if (my_b_write(&log_file, (uchar*) buff, length))
 
1534
      goto err;
 
1535
 
 
1536
    if (my_b_write(&log_file, (uchar*) command_type, command_type_len))
 
1537
      goto err;
 
1538
 
 
1539
    if (my_b_write(&log_file, (uchar*) "\t", 1))
 
1540
      goto err;
 
1541
 
 
1542
    /* sql_text */
 
1543
    if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len))
 
1544
      goto err;
 
1545
 
 
1546
    if (my_b_write(&log_file, (uchar*) "\n", 1) ||
 
1547
        flush_io_cache(&log_file))
 
1548
      goto err;
 
1549
  }
 
1550
 
 
1551
  (void) pthread_mutex_unlock(&LOCK_log);
 
1552
  return FALSE;
 
1553
err:
 
1554
 
 
1555
  if (!write_error)
 
1556
  {
 
1557
    write_error= 1;
 
1558
    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
 
1559
  }
 
1560
  (void) pthread_mutex_unlock(&LOCK_log);
 
1561
  return TRUE;
 
1562
}
 
1563
 
 
1564
 
 
1565
/*
 
1566
  Log a query to the traditional slow log file
 
1567
 
 
1568
  SYNOPSIS
 
1569
    write()
 
1570
 
 
1571
    thd               THD of the query
 
1572
    current_time      current timestamp
 
1573
    query_start_arg   command start timestamp
 
1574
    user_host         the pointer to the string with user@host info
 
1575
    user_host_len     length of the user_host string. this is computed once
 
1576
                      and passed to all general log event handlers
 
1577
    query_utime       Amount of time the query took to execute (in microseconds)
 
1578
    lock_utime        Amount of time the query was locked (in microseconds)
 
1579
    is_command        The flag, which determines, whether the sql_text is a
 
1580
                      query or an administrator command.
 
1581
    sql_text          the very text of the query or administrator command
 
1582
                      processed
 
1583
    sql_text_len      the length of sql_text string
 
1584
 
 
1585
  DESCRIPTION
 
1586
 
 
1587
   Log a query to the slow log file.
 
1588
 
 
1589
  RETURN
 
1590
    FALSE - OK
 
1591
    TRUE - error occured
 
1592
*/
 
1593
 
 
1594
bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
 
1595
                            time_t query_start_arg, const char *user_host,
 
1596
                            uint user_host_len, ulonglong query_utime,
 
1597
                            ulonglong lock_utime, bool is_command,
 
1598
                            const char *sql_text, uint sql_text_len)
 
1599
{
 
1600
  bool error= 0;
 
1601
  DBUG_ENTER("MYSQL_QUERY_LOG::write");
 
1602
 
 
1603
  (void) pthread_mutex_lock(&LOCK_log);
 
1604
 
 
1605
  if (!is_open())
 
1606
  {
 
1607
    (void) pthread_mutex_unlock(&LOCK_log);
 
1608
    DBUG_RETURN(0);
 
1609
  }
 
1610
 
 
1611
  if (is_open())
 
1612
  {                                             // Safety agains reopen
 
1613
    int tmp_errno= 0;
 
1614
    char buff[80], *end;
 
1615
    char query_time_buff[22+7], lock_time_buff[22+7];
 
1616
    uint buff_len;
 
1617
    end= buff;
 
1618
 
 
1619
    if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
 
1620
    {
 
1621
      if (current_time != last_time)
 
1622
      {
 
1623
        last_time= current_time;
 
1624
        struct tm start;
 
1625
        localtime_r(&current_time, &start);
 
1626
 
 
1627
        buff_len= my_snprintf(buff, sizeof buff,
 
1628
                              "# Time: %02d%02d%02d %2d:%02d:%02d\n",
 
1629
                              start.tm_year % 100, start.tm_mon + 1,
 
1630
                              start.tm_mday, start.tm_hour,
 
1631
                              start.tm_min, start.tm_sec);
 
1632
 
 
1633
        /* Note that my_b_write() assumes it knows the length for this */
 
1634
        if (my_b_write(&log_file, (uchar*) buff, buff_len))
 
1635
          tmp_errno= errno;
 
1636
      }
 
1637
      const uchar uh[]= "# User@Host: ";
 
1638
      if (my_b_write(&log_file, uh, sizeof(uh) - 1))
 
1639
        tmp_errno= errno;
 
1640
      if (my_b_write(&log_file, (uchar*) user_host, user_host_len))
 
1641
        tmp_errno= errno;
 
1642
      if (my_b_write(&log_file, (uchar*) "\n", 1))
 
1643
        tmp_errno= errno;
 
1644
    }
 
1645
    /* For slow query log */
 
1646
    sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0);
 
1647
    sprintf(lock_time_buff,  "%.6f", ulonglong2double(lock_utime)/1000000.0);
 
1648
    if (my_b_printf(&log_file,
 
1649
                    "# Query_time: %s  Lock_time: %s"
 
1650
                    " Rows_sent: %lu  Rows_examined: %lu\n",
 
1651
                    query_time_buff, lock_time_buff,
 
1652
                    (ulong) thd->sent_row_count,
 
1653
                    (ulong) thd->examined_row_count) == (uint) -1)
 
1654
      tmp_errno= errno;
 
1655
    if (thd->db && strcmp(thd->db, db))
 
1656
    {                                           // Database changed
 
1657
      if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
 
1658
        tmp_errno= errno;
 
1659
      strmov(db,thd->db);
 
1660
    }
 
1661
    if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
 
1662
    {
 
1663
      end=strmov(end, ",last_insert_id=");
 
1664
      end=longlong10_to_str((longlong)
 
1665
                            thd->first_successful_insert_id_in_prev_stmt_for_binlog,
 
1666
                            end, -10);
 
1667
    }
 
1668
    // Save value if we do an insert.
 
1669
    if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
 
1670
    {
 
1671
      if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
 
1672
      {
 
1673
        end=strmov(end,",insert_id=");
 
1674
        end=longlong10_to_str((longlong)
 
1675
                              thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(),
 
1676
                              end, -10);
 
1677
      }
 
1678
    }
 
1679
 
 
1680
    /*
 
1681
      This info used to show up randomly, depending on whether the query
 
1682
      checked the query start time or not. now we always write current
 
1683
      timestamp to the slow log
 
1684
    */
 
1685
    end= strmov(end, ",timestamp=");
 
1686
    end= int10_to_str((long) current_time, end, 10);
 
1687
 
 
1688
    if (end != buff)
 
1689
    {
 
1690
      *end++=';';
 
1691
      *end='\n';
 
1692
      if (my_b_write(&log_file, (uchar*) "SET ", 4) ||
 
1693
          my_b_write(&log_file, (uchar*) buff + 1, (uint) (end-buff)))
 
1694
        tmp_errno= errno;
 
1695
    }
 
1696
    if (is_command)
 
1697
    {
 
1698
      end= strxmov(buff, "# administrator command: ", NullS);
 
1699
      buff_len= (ulong) (end - buff);
 
1700
      my_b_write(&log_file, (uchar*) buff, buff_len);
 
1701
    }
 
1702
    if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len) ||
 
1703
        my_b_write(&log_file, (uchar*) ";\n",2) ||
 
1704
        flush_io_cache(&log_file))
 
1705
      tmp_errno= errno;
 
1706
    if (tmp_errno)
 
1707
    {
 
1708
      error= 1;
 
1709
      if (! write_error)
 
1710
      {
 
1711
        write_error= 1;
 
1712
        sql_print_error(ER(ER_ERROR_ON_WRITE), name, error);
 
1713
      }
 
1714
    }
 
1715
  }
 
1716
  (void) pthread_mutex_unlock(&LOCK_log);
 
1717
  DBUG_RETURN(error);
 
1718
}
 
1719
 
 
1720
 
1026
1721
/**
1027
1722
  @todo
1028
1723
  The following should be using fn_format();  We just need to
1029
1724
  first change fn_format() to cut the file name if it's too long.
1030
1725
*/
1031
 
const char *DRIZZLE_LOG::generate_name(const char *log_name,
 
1726
const char *MYSQL_LOG::generate_name(const char *log_name,
1032
1727
                                      const char *suffix,
1033
1728
                                      bool strip_ext, char *buff)
1034
1729
{
1042
1737
  if (strip_ext)
1043
1738
  {
1044
1739
    char *p= fn_ext(log_name);
1045
 
    uint32_t length= (uint) (p - log_name);
1046
 
    strmake(buff, log_name, cmin(length, (uint)FN_REFLEN));
 
1740
    uint length= (uint) (p - log_name);
 
1741
    strmake(buff, log_name, min(length, FN_REFLEN));
1047
1742
    return (const char*)buff;
1048
1743
  }
1049
1744
  return log_name;
1051
1746
 
1052
1747
 
1053
1748
 
1054
 
DRIZZLE_BIN_LOG::DRIZZLE_BIN_LOG()
 
1749
MYSQL_BIN_LOG::MYSQL_BIN_LOG()
1055
1750
  :bytes_written(0), prepared_xids(0), file_id(1), open_count(1),
1056
 
   need_start_event(true), m_table_map_version(0),
 
1751
   need_start_event(TRUE), m_table_map_version(0),
1057
1752
   description_event_for_exec(0), description_event_for_queue(0)
1058
1753
{
1059
1754
  /*
1063
1758
    before main().
1064
1759
  */
1065
1760
  index_file_name[0] = 0;
1066
 
  memset(&index_file, 0, sizeof(index_file));
 
1761
  bzero((char*) &index_file, sizeof(index_file));
1067
1762
}
1068
1763
 
1069
1764
/* this is called only once */
1070
1765
 
1071
 
void DRIZZLE_BIN_LOG::cleanup()
 
1766
void MYSQL_BIN_LOG::cleanup()
1072
1767
{
 
1768
  DBUG_ENTER("cleanup");
1073
1769
  if (inited)
1074
1770
  {
1075
1771
    inited= 0;
1080
1776
    (void) pthread_mutex_destroy(&LOCK_index);
1081
1777
    (void) pthread_cond_destroy(&update_cond);
1082
1778
  }
1083
 
  return;
 
1779
  DBUG_VOID_RETURN;
1084
1780
}
1085
1781
 
1086
1782
 
1087
1783
/* Init binlog-specific vars */
1088
 
void DRIZZLE_BIN_LOG::init(bool no_auto_events_arg, ulong max_size_arg)
 
1784
void MYSQL_BIN_LOG::init(bool no_auto_events_arg, ulong max_size_arg)
1089
1785
{
 
1786
  DBUG_ENTER("MYSQL_BIN_LOG::init");
1090
1787
  no_auto_events= no_auto_events_arg;
1091
1788
  max_size= max_size_arg;
1092
 
  return;
 
1789
  DBUG_PRINT("info",("max_size: %lu", max_size));
 
1790
  DBUG_VOID_RETURN;
1093
1791
}
1094
1792
 
1095
1793
 
1096
 
void DRIZZLE_BIN_LOG::init_pthread_objects()
 
1794
void MYSQL_BIN_LOG::init_pthread_objects()
1097
1795
{
1098
 
  assert(inited == 0);
 
1796
  DBUG_ASSERT(inited == 0);
1099
1797
  inited= 1;
1100
1798
  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
1101
1799
  (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
1103
1801
}
1104
1802
 
1105
1803
 
1106
 
bool DRIZZLE_BIN_LOG::open_index_file(const char *index_file_name_arg,
 
1804
bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
1107
1805
                                const char *log_name)
1108
1806
{
1109
1807
  File index_file_nr= -1;
1110
 
  assert(!my_b_inited(&index_file));
 
1808
  DBUG_ASSERT(!my_b_inited(&index_file));
1111
1809
 
1112
1810
  /*
1113
1811
    First open of this class instance
1138
1836
    */
1139
1837
    if (index_file_nr >= 0)
1140
1838
      my_close(index_file_nr,MYF(0));
1141
 
    return true;
 
1839
    return TRUE;
1142
1840
  }
1143
 
  return false;
 
1841
  return FALSE;
1144
1842
}
1145
1843
 
1146
1844
 
1158
1856
    1   error
1159
1857
*/
1160
1858
 
1161
 
bool DRIZZLE_BIN_LOG::open(const char *log_name,
 
1859
bool MYSQL_BIN_LOG::open(const char *log_name,
1162
1860
                         enum_log_type log_type_arg,
1163
1861
                         const char *new_name,
1164
1862
                         enum cache_type io_cache_type_arg,
1167
1865
                         bool null_created_arg)
1168
1866
{
1169
1867
  File file= -1;
 
1868
  DBUG_ENTER("MYSQL_BIN_LOG::open");
 
1869
  DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
1170
1870
 
1171
1871
  write_error=0;
1172
1872
 
1173
1873
  /* open the main log file */
1174
 
  if (DRIZZLE_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg))
1175
 
    return(1);                            /* all warnings issued */
 
1874
  if (MYSQL_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg))
 
1875
    DBUG_RETURN(1);                            /* all warnings issued */
1176
1876
 
1177
1877
  init(no_auto_events_arg, max_size_arg);
1178
1878
 
1179
1879
  open_count++;
1180
1880
 
1181
 
  assert(log_type == LOG_BIN);
 
1881
  DBUG_ASSERT(log_type == LOG_BIN);
1182
1882
 
1183
1883
  {
1184
1884
    bool write_file_name_to_index_file=0;
1191
1891
        an extension for the binary log files.
1192
1892
        In this case we write a standard header to it.
1193
1893
      */
1194
 
      if (my_b_safe_write(&log_file, (unsigned char*) BINLOG_MAGIC,
 
1894
      if (my_b_safe_write(&log_file, (uchar*) BINLOG_MAGIC,
1195
1895
                          BIN_LOG_HEADER_SIZE))
1196
1896
        goto err;
1197
1897
      bytes_written+= BIN_LOG_HEADER_SIZE;
1198
1898
      write_file_name_to_index_file= 1;
1199
1899
    }
1200
1900
 
1201
 
    assert(my_b_inited(&index_file) != 0);
 
1901
    DBUG_ASSERT(my_b_inited(&index_file) != 0);
1202
1902
    reinit_io_cache(&index_file, WRITE_CACHE,
1203
1903
                    my_b_filelength(&index_file), 0, 0);
1204
1904
    if (need_start_event && !no_auto_events)
1262
1962
        As this is a new log file, we write the file name to the index
1263
1963
        file. As every time we write to the index file, we sync it.
1264
1964
      */
1265
 
      if (my_b_write(&index_file, (unsigned char*) log_file_name,
 
1965
      if (my_b_write(&index_file, (uchar*) log_file_name,
1266
1966
                     strlen(log_file_name)) ||
1267
 
          my_b_write(&index_file, (unsigned char*) "\n", 1) ||
 
1967
          my_b_write(&index_file, (uchar*) "\n", 1) ||
1268
1968
          flush_io_cache(&index_file) ||
1269
1969
          my_sync(index_file.file, MYF(MY_WME)))
1270
1970
        goto err;
1272
1972
  }
1273
1973
  log_state= LOG_OPENED;
1274
1974
 
1275
 
  return(0);
 
1975
  DBUG_RETURN(0);
1276
1976
 
1277
1977
err:
1278
 
  sql_print_error(_("Could not use %s for logging (error %d). "
1279
 
                    "Turning logging off for the whole duration of the "
1280
 
                    "Drizzle server process. "
1281
 
                    "To turn it on again: fix the cause, "
1282
 
                    "shutdown the Drizzle server and restart it."),
1283
 
                    name, errno);
 
1978
  sql_print_error("Could not use %s for logging (error %d). \
 
1979
Turning logging off for the whole duration of the MySQL server process. \
 
1980
To turn it on again: fix the cause, \
 
1981
shutdown the MySQL server and restart it.", name, errno);
1284
1982
  if (file >= 0)
1285
1983
    my_close(file,MYF(0));
1286
1984
  end_io_cache(&log_file);
1287
1985
  end_io_cache(&index_file);
1288
 
  if (name)
1289
 
  {
1290
 
    free(name);
1291
 
    name= NULL;
1292
 
  }
 
1986
  safeFree(name);
1293
1987
  log_state= LOG_CLOSED;
1294
 
  return(1);
 
1988
  DBUG_RETURN(1);
1295
1989
}
1296
1990
 
1297
1991
 
1298
 
int DRIZZLE_BIN_LOG::get_current_log(LOG_INFO* linfo)
 
1992
int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo)
1299
1993
{
1300
1994
  pthread_mutex_lock(&LOCK_log);
1301
1995
  int ret = raw_get_current_log(linfo);
1303
1997
  return ret;
1304
1998
}
1305
1999
 
1306
 
int DRIZZLE_BIN_LOG::raw_get_current_log(LOG_INFO* linfo)
 
2000
int MYSQL_BIN_LOG::raw_get_current_log(LOG_INFO* linfo)
1307
2001
{
1308
2002
  strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
1309
2003
  linfo->pos = my_b_tell(&log_file);
1327
2021
    0   ok
1328
2022
*/
1329
2023
 
 
2024
#ifdef HAVE_REPLICATION
 
2025
 
1330
2026
static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
1331
2027
{
1332
2028
  int bytes_read;
1333
2029
  my_off_t init_offset= offset;
1334
2030
  File file= index_file->file;
1335
 
  unsigned char io_buf[IO_SIZE*2];
 
2031
  uchar io_buf[IO_SIZE*2];
 
2032
  DBUG_ENTER("copy_up_file_and_fill");
1336
2033
 
1337
2034
  for (;; offset+= bytes_read)
1338
2035
  {
1352
2049
 
1353
2050
  /* Reset data in old index cache */
1354
2051
  reinit_io_cache(index_file, READ_CACHE, (my_off_t) 0, 0, 1);
1355
 
  return(0);
 
2052
  DBUG_RETURN(0);
1356
2053
 
1357
2054
err:
1358
 
  return(1);
 
2055
  DBUG_RETURN(1);
1359
2056
}
1360
2057
 
 
2058
#endif /* HAVE_REPLICATION */
 
2059
 
1361
2060
/**
1362
2061
  Find the position in the log-index-file for the given log name.
1363
2062
 
1380
2079
    LOG_INFO_IO         Got IO error while reading file
1381
2080
*/
1382
2081
 
1383
 
int DRIZZLE_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
 
2082
int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
1384
2083
                            bool need_lock)
1385
2084
{
1386
2085
  int error= 0;
1387
2086
  char *fname= linfo->log_file_name;
1388
 
  uint32_t log_name_len= log_name ? (uint) strlen(log_name) : 0;
 
2087
  uint log_name_len= log_name ? (uint) strlen(log_name) : 0;
 
2088
  DBUG_ENTER("find_log_pos");
 
2089
  DBUG_PRINT("enter",("log_name: %s", log_name ? log_name : "NULL"));
1389
2090
 
1390
2091
  /*
1391
2092
    Mutex needed because we need to make sure the file pointer does not
1400
2101
 
1401
2102
  for (;;)
1402
2103
  {
1403
 
    uint32_t length;
 
2104
    uint length;
1404
2105
    my_off_t offset= my_b_tell(&index_file);
1405
2106
    /* If we get 0 or 1 characters, this is the end of the file */
1406
2107
 
1416
2117
        (log_name_len == length-1 && fname[log_name_len] == '\n' &&
1417
2118
         !memcmp(fname, log_name, log_name_len)))
1418
2119
    {
 
2120
      DBUG_PRINT("info",("Found log file entry"));
1419
2121
      fname[length-1]=0;                        // remove last \n
1420
2122
      linfo->index_file_start_offset= offset;
1421
2123
      linfo->index_file_offset = my_b_tell(&index_file);
1425
2127
 
1426
2128
  if (need_lock)
1427
2129
    pthread_mutex_unlock(&LOCK_index);
1428
 
  return(error);
 
2130
  DBUG_RETURN(error);
1429
2131
}
1430
2132
 
1431
2133
 
1453
2155
    LOG_INFO_IO         Got IO error while reading file
1454
2156
*/
1455
2157
 
1456
 
int DRIZZLE_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
 
2158
int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
1457
2159
{
1458
2160
  int error= 0;
1459
 
  uint32_t length;
 
2161
  uint length;
1460
2162
  char *fname= linfo->log_file_name;
1461
2163
 
1462
2164
  if (need_lock)
1500
2202
    1   error
1501
2203
*/
1502
2204
 
1503
 
bool DRIZZLE_BIN_LOG::reset_logs(THD* thd)
 
2205
bool MYSQL_BIN_LOG::reset_logs(THD* thd)
1504
2206
{
1505
2207
  LOG_INFO linfo;
1506
2208
  bool error=0;
1507
2209
  const char* save_name;
 
2210
  DBUG_ENTER("reset_logs");
1508
2211
 
 
2212
  ha_reset_logs(thd);
1509
2213
  /*
1510
2214
    We need to get both locks to be sure that no one is trying to
1511
2215
    write to the index log file.
1519
2223
    thread. If the transaction involved MyISAM tables, it should go
1520
2224
    into binlog even on rollback.
1521
2225
  */
1522
 
  pthread_mutex_lock(&LOCK_thread_count);
 
2226
  VOID(pthread_mutex_lock(&LOCK_thread_count));
1523
2227
 
1524
2228
  /* Save variables so that we can reopen the log */
1525
2229
  save_name=name;
1528
2232
 
1529
2233
  /* First delete all old log files */
1530
2234
 
1531
 
  if (find_log_pos(&linfo, NULL, 0))
 
2235
  if (find_log_pos(&linfo, NullS, 0))
1532
2236
  {
1533
2237
    error=1;
1534
2238
    goto err;
1540
2244
    {
1541
2245
      if (my_errno == ENOENT) 
1542
2246
      {
1543
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2247
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1544
2248
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1545
2249
                            linfo.log_file_name);
1546
 
        sql_print_information(_("Failed to delete file '%s'"),
 
2250
        sql_print_information("Failed to delete file '%s'",
1547
2251
                              linfo.log_file_name);
1548
2252
        my_errno= 0;
1549
2253
        error= 0;
1550
2254
      }
1551
2255
      else
1552
2256
      {
1553
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2257
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1554
2258
                            ER_BINLOG_PURGE_FATAL_ERR,
1555
 
                            _("a problem with deleting %s; "
 
2259
                            "a problem with deleting %s; "
1556
2260
                            "consider examining correspondence "
1557
2261
                            "of your binlog index file "
1558
 
                            "to the actual binlog files"),
 
2262
                            "to the actual binlog files",
1559
2263
                            linfo.log_file_name);
1560
2264
        error= 1;
1561
2265
        goto err;
1571
2275
  {
1572
2276
    if (my_errno == ENOENT) 
1573
2277
    {
1574
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2278
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1575
2279
                          ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1576
2280
                          index_file_name);
1577
 
      sql_print_information(_("Failed to delete file '%s'"),
 
2281
      sql_print_information("Failed to delete file '%s'",
1578
2282
                            index_file_name);
1579
2283
      my_errno= 0;
1580
2284
      error= 0;
1581
2285
    }
1582
2286
    else
1583
2287
    {
1584
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2288
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1585
2289
                          ER_BINLOG_PURGE_FATAL_ERR,
1586
2290
                          "a problem with deleting %s; "
1587
2291
                          "consider examining correspondence "
1596
2300
    need_start_event=1;
1597
2301
  if (!open_index_file(index_file_name, 0))
1598
2302
    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0);
1599
 
  free((unsigned char*) save_name);
 
2303
  my_free((uchar*) save_name, MYF(0));
1600
2304
 
1601
2305
err:
1602
 
  pthread_mutex_unlock(&LOCK_thread_count);
 
2306
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
1603
2307
  pthread_mutex_unlock(&LOCK_index);
1604
2308
  pthread_mutex_unlock(&LOCK_log);
1605
 
  return(error);
 
2309
  DBUG_RETURN(error);
1606
2310
}
1607
2311
 
1608
2312
 
1643
2347
    LOG_INFO_IO         Got IO error while reading file
1644
2348
*/
1645
2349
 
 
2350
#ifdef HAVE_REPLICATION
1646
2351
 
1647
 
int DRIZZLE_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
 
2352
int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
1648
2353
{
1649
2354
  int error;
 
2355
  DBUG_ENTER("purge_first_log");
1650
2356
 
1651
 
  assert(is_open());
1652
 
  assert(rli->slave_running == 1);
1653
 
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
 
2357
  DBUG_ASSERT(is_open());
 
2358
  DBUG_ASSERT(rli->slave_running == 1);
 
2359
  DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
1654
2360
 
1655
2361
  pthread_mutex_lock(&LOCK_index);
1656
2362
  pthread_mutex_lock(&rli->log_space_lock);
1673
2379
    If included is true, we want the first relay log;
1674
2380
    otherwise we want the one after event_relay_log_name.
1675
2381
  */
1676
 
  if ((included && (error=find_log_pos(&rli->linfo, NULL, 0))) ||
 
2382
  if ((included && (error=find_log_pos(&rli->linfo, NullS, 0))) ||
1677
2383
      (!included &&
1678
2384
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
1679
2385
        (error=find_next_log(&rli->linfo, 0)))))
1680
2386
  {
1681
2387
    char buff[22];
1682
 
    sql_print_error(_("next log error: %d  offset: %s  log: %s included: %d"),
 
2388
    sql_print_error("next log error: %d  offset: %s  log: %s included: %d",
1683
2389
                    error,
1684
2390
                    llstr(rli->linfo.index_file_offset,buff),
1685
2391
                    rli->group_relay_log_name,
1712
2418
 
1713
2419
err:
1714
2420
  pthread_mutex_unlock(&LOCK_index);
1715
 
  return(error);
 
2421
  DBUG_RETURN(error);
1716
2422
}
1717
2423
 
1718
2424
/**
1719
2425
  Update log index_file.
1720
2426
*/
1721
2427
 
1722
 
int DRIZZLE_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
 
2428
int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
1723
2429
{
1724
2430
  if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset))
1725
2431
    return LOG_INFO_IO;
1754
2460
                                stat() or my_delete()
1755
2461
*/
1756
2462
 
1757
 
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log, 
 
2463
int MYSQL_BIN_LOG::purge_logs(const char *to_log, 
1758
2464
                          bool included,
1759
2465
                          bool need_mutex, 
1760
2466
                          bool need_update_threads, 
1761
 
                          uint64_t *decrease_log_space)
 
2467
                          ulonglong *decrease_log_space)
1762
2468
{
1763
2469
  int error;
1764
2470
  int ret = 0;
1765
2471
  bool exit_loop= 0;
1766
2472
  LOG_INFO log_info;
 
2473
  DBUG_ENTER("purge_logs");
 
2474
  DBUG_PRINT("info",("to_log= %s",to_log));
1767
2475
 
1768
2476
  if (need_mutex)
1769
2477
    pthread_mutex_lock(&LOCK_index);
1774
2482
    File name exists in index file; delete until we find this file
1775
2483
    or a file that is used.
1776
2484
  */
1777
 
  if ((error=find_log_pos(&log_info, NULL, 0 /*no mutex*/)))
 
2485
  if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
1778
2486
    goto err;
1779
2487
  while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
1780
2488
         !log_in_use(log_info.log_file_name))
1788
2496
          It's not fatal if we can't stat a log file that does not exist;
1789
2497
          If we could not stat, we won't delete.
1790
2498
        */     
1791
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2499
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1792
2500
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1793
2501
                            log_info.log_file_name);
1794
 
        sql_print_information(_("Failed to execute stat() on file '%s'"),
 
2502
        sql_print_information("Failed to execute stat on file '%s'",
1795
2503
                              log_info.log_file_name);
1796
2504
        my_errno= 0;
1797
2505
      }
1800
2508
        /*
1801
2509
          Other than ENOENT are fatal
1802
2510
        */
1803
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2511
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1804
2512
                            ER_BINLOG_PURGE_FATAL_ERR,
1805
 
                            _("a problem with getting info on being purged %s; "
 
2513
                            "a problem with getting info on being purged %s; "
1806
2514
                            "consider examining correspondence "
1807
2515
                            "of your binlog index file "
1808
 
                            "to the actual binlog files"),
 
2516
                            "to the actual binlog files",
1809
2517
                            log_info.log_file_name);
1810
2518
        error= LOG_INFO_FATAL;
1811
2519
        goto err;
1813
2521
    }
1814
2522
    else
1815
2523
    {
 
2524
      DBUG_PRINT("info",("purging %s",log_info.log_file_name));
1816
2525
      if (!my_delete(log_info.log_file_name, MYF(0)))
1817
2526
      {
1818
2527
        if (decrease_log_space)
1822
2531
      {
1823
2532
        if (my_errno == ENOENT) 
1824
2533
        {
1825
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2534
          push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1826
2535
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1827
2536
                              log_info.log_file_name);
1828
 
          sql_print_information(_("Failed to delete file '%s'"),
 
2537
          sql_print_information("Failed to delete file '%s'",
1829
2538
                                log_info.log_file_name);
1830
2539
          my_errno= 0;
1831
2540
        }
1832
2541
        else
1833
2542
        {
1834
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2543
          push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1835
2544
                              ER_BINLOG_PURGE_FATAL_ERR,
1836
 
                              _("a problem with deleting %s; "
 
2545
                              "a problem with deleting %s; "
1837
2546
                              "consider examining correspondence "
1838
2547
                              "of your binlog index file "
1839
 
                              "to the actual binlog files"),
 
2548
                              "to the actual binlog files",
1840
2549
                              log_info.log_file_name);
1841
2550
          if (my_errno == EMFILE)
1842
2551
          {
 
2552
            DBUG_PRINT("info",
 
2553
                       ("my_errno: %d, set ret = LOG_INFO_EMFILE", my_errno));
1843
2554
            error= LOG_INFO_EMFILE;
1844
2555
          }
1845
2556
          error= LOG_INFO_FATAL;
1848
2559
      }
1849
2560
    }
1850
2561
 
 
2562
    ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
 
2563
 
1851
2564
    if (find_next_log(&log_info, 0) || exit_loop)
1852
2565
      break;
1853
2566
  }
1864
2577
err:
1865
2578
  if (need_mutex)
1866
2579
    pthread_mutex_unlock(&LOCK_index);
1867
 
  return(error);
 
2580
  DBUG_RETURN(error);
1868
2581
}
1869
2582
 
1870
2583
/**
1886
2599
                                stat() or my_delete()
1887
2600
*/
1888
2601
 
1889
 
int DRIZZLE_BIN_LOG::purge_logs_before_date(time_t purge_time)
 
2602
int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
1890
2603
{
1891
2604
  int error;
1892
2605
  LOG_INFO log_info;
1893
2606
  struct stat stat_area;
1894
2607
 
 
2608
  DBUG_ENTER("purge_logs_before_date");
 
2609
 
1895
2610
  pthread_mutex_lock(&LOCK_index);
1896
2611
 
1897
2612
  /*
1899
2614
    or a file that is used or a file
1900
2615
    that is older than purge_time.
1901
2616
  */
1902
 
  if ((error=find_log_pos(&log_info, NULL, 0 /*no mutex*/)))
 
2617
  if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
1903
2618
    goto err;
1904
2619
 
1905
2620
  while (strcmp(log_file_name, log_info.log_file_name) &&
1912
2627
        /*
1913
2628
          It's not fatal if we can't stat a log file that does not exist.
1914
2629
        */     
1915
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2630
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1916
2631
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1917
2632
                            log_info.log_file_name);
1918
 
        sql_print_information(_("Failed to execute stat() on file '%s'"),
 
2633
        sql_print_information("Failed to execute stat on file '%s'",
1919
2634
                              log_info.log_file_name);
1920
2635
        my_errno= 0;
1921
2636
      }
1924
2639
        /*
1925
2640
          Other than ENOENT are fatal
1926
2641
        */
1927
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2642
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1928
2643
                            ER_BINLOG_PURGE_FATAL_ERR,
1929
 
                            _("a problem with getting info on being purged %s; "
 
2644
                            "a problem with getting info on being purged %s; "
1930
2645
                            "consider examining correspondence "
1931
2646
                            "of your binlog index file "
1932
 
                            "to the actual binlog files"),
 
2647
                            "to the actual binlog files",
1933
2648
                            log_info.log_file_name);
1934
2649
        error= LOG_INFO_FATAL;
1935
2650
        goto err;
1944
2659
        if (my_errno == ENOENT) 
1945
2660
        {
1946
2661
          /* It's not fatal even if we can't delete a log file */
1947
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2662
          push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1948
2663
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1949
2664
                              log_info.log_file_name);
1950
 
          sql_print_information(_("Failed to delete file '%s'"),
 
2665
          sql_print_information("Failed to delete file '%s'",
1951
2666
                                log_info.log_file_name);
1952
2667
          my_errno= 0;
1953
2668
        }
1954
2669
        else
1955
2670
        {
1956
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
2671
          push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
1957
2672
                              ER_BINLOG_PURGE_FATAL_ERR,
1958
 
                              _("a problem with deleting %s; "
 
2673
                              "a problem with deleting %s; "
1959
2674
                              "consider examining correspondence "
1960
2675
                              "of your binlog index file "
1961
 
                              "to the actual binlog files"),
 
2676
                              "to the actual binlog files",
1962
2677
                              log_info.log_file_name);
1963
2678
          error= LOG_INFO_FATAL;
1964
2679
          goto err;
1965
2680
        }
1966
2681
      }
 
2682
      ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
1967
2683
    }
1968
2684
    if (find_next_log(&log_info, 0))
1969
2685
      break;
1977
2693
 
1978
2694
err:
1979
2695
  pthread_mutex_unlock(&LOCK_index);
1980
 
  return(error);
 
2696
  DBUG_RETURN(error);
1981
2697
}
 
2698
#endif /* HAVE_REPLICATION */
1982
2699
 
1983
2700
 
1984
2701
/**
1990
2707
    If file name will be longer then FN_REFLEN it will be truncated
1991
2708
*/
1992
2709
 
1993
 
void DRIZZLE_BIN_LOG::make_log_name(char* buf, const char* log_ident)
 
2710
void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident)
1994
2711
{
1995
 
  uint32_t dir_len = dirname_length(log_file_name); 
 
2712
  uint dir_len = dirname_length(log_file_name); 
1996
2713
  if (dir_len >= FN_REFLEN)
1997
2714
    dir_len=FN_REFLEN-1;
1998
 
  my_stpncpy(buf, log_file_name, dir_len);
 
2715
  strnmov(buf, log_file_name, dir_len);
1999
2716
  strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
2000
2717
}
2001
2718
 
2004
2721
  Check if we are writing/reading to the given log file.
2005
2722
*/
2006
2723
 
2007
 
bool DRIZZLE_BIN_LOG::is_active(const char *log_file_name_arg)
 
2724
bool MYSQL_BIN_LOG::is_active(const char *log_file_name_arg)
2008
2725
{
2009
2726
  return !strcmp(log_file_name, log_file_name_arg);
2010
2727
}
2018
2735
  method).
2019
2736
*/
2020
2737
 
2021
 
void DRIZZLE_BIN_LOG::new_file()
 
2738
void MYSQL_BIN_LOG::new_file()
2022
2739
{
2023
2740
  new_file_impl(1);
2024
2741
}
2025
2742
 
2026
2743
 
2027
 
void DRIZZLE_BIN_LOG::new_file_without_locking()
 
2744
void MYSQL_BIN_LOG::new_file_without_locking()
2028
2745
{
2029
2746
  new_file_impl(0);
2030
2747
}
2039
2756
    The new file name is stored last in the index file
2040
2757
*/
2041
2758
 
2042
 
void DRIZZLE_BIN_LOG::new_file_impl(bool need_lock)
 
2759
void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
2043
2760
{
2044
2761
  char new_name[FN_REFLEN], *new_name_ptr, *old_name;
2045
2762
 
 
2763
  DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
2046
2764
  if (!is_open())
2047
2765
  {
2048
 
    return;
 
2766
    DBUG_PRINT("info",("log is closed"));
 
2767
    DBUG_VOID_RETURN;
2049
2768
  }
2050
2769
 
2051
2770
  if (need_lock)
2069
2788
    tc_log_page_waits++;
2070
2789
    pthread_mutex_lock(&LOCK_prep_xids);
2071
2790
    while (prepared_xids) {
 
2791
      DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
2072
2792
      pthread_cond_wait(&COND_prep_xids, &LOCK_prep_xids);
2073
2793
    }
2074
2794
    pthread_mutex_unlock(&LOCK_prep_xids);
2125
2845
 
2126
2846
  open(old_name, log_type, new_name_ptr,
2127
2847
       io_cache_type, no_auto_events, max_size, 1);
2128
 
  free(old_name);
 
2848
  my_free(old_name,MYF(0));
2129
2849
 
2130
2850
end:
2131
2851
  if (need_lock)
2132
2852
    pthread_mutex_unlock(&LOCK_log);
2133
2853
  pthread_mutex_unlock(&LOCK_index);
2134
2854
 
2135
 
  return;
 
2855
  DBUG_VOID_RETURN;
2136
2856
}
2137
2857
 
2138
2858
 
2139
 
bool DRIZZLE_BIN_LOG::append(Log_event* ev)
 
2859
bool MYSQL_BIN_LOG::append(Log_event* ev)
2140
2860
{
2141
2861
  bool error = 0;
2142
2862
  pthread_mutex_lock(&LOCK_log);
 
2863
  DBUG_ENTER("MYSQL_BIN_LOG::append");
2143
2864
 
2144
 
  assert(log_file.type == SEQ_READ_APPEND);
 
2865
  DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
2145
2866
  /*
2146
2867
    Log_event::write() is smart enough to use my_b_write() or
2147
2868
    my_b_append() depending on the kind of cache we have.
2152
2873
    goto err;
2153
2874
  }
2154
2875
  bytes_written+= ev->data_written;
 
2876
  DBUG_PRINT("info",("max_size: %lu",max_size));
2155
2877
  if ((uint) my_b_append_tell(&log_file) > max_size)
2156
2878
    new_file_without_locking();
2157
2879
 
2158
2880
err:
2159
2881
  pthread_mutex_unlock(&LOCK_log);
2160
2882
  signal_update();                              // Safe as we don't call close
2161
 
  return(error);
 
2883
  DBUG_RETURN(error);
2162
2884
}
2163
2885
 
2164
2886
 
2165
 
bool DRIZZLE_BIN_LOG::appendv(const char* buf, uint32_t len,...)
 
2887
bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...)
2166
2888
{
2167
2889
  bool error= 0;
 
2890
  DBUG_ENTER("MYSQL_BIN_LOG::appendv");
2168
2891
  va_list(args);
2169
2892
  va_start(args,len);
2170
2893
 
2171
 
  assert(log_file.type == SEQ_READ_APPEND);
 
2894
  DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
2172
2895
 
2173
2896
  safe_mutex_assert_owner(&LOCK_log);
2174
2897
  do
2175
2898
  {
2176
 
    if (my_b_append(&log_file,(unsigned char*) buf,len))
 
2899
    if (my_b_append(&log_file,(uchar*) buf,len))
2177
2900
    {
2178
2901
      error= 1;
2179
2902
      goto err;
2180
2903
    }
2181
2904
    bytes_written += len;
2182
2905
  } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
 
2906
  DBUG_PRINT("info",("max_size: %lu",max_size));
2183
2907
  if ((uint) my_b_append_tell(&log_file) > max_size)
2184
2908
    new_file_without_locking();
2185
2909
 
2186
2910
err:
2187
2911
  if (!error)
2188
2912
    signal_update();
2189
 
  return(error);
 
2913
  DBUG_RETURN(error);
2190
2914
}
2191
2915
 
2192
2916
 
2193
 
bool DRIZZLE_BIN_LOG::flush_and_sync()
 
2917
bool MYSQL_BIN_LOG::flush_and_sync()
2194
2918
{
2195
2919
  int err=0, fd=log_file.file;
2196
2920
  safe_mutex_assert_owner(&LOCK_log);
2204
2928
  return err;
2205
2929
}
2206
2930
 
2207
 
void DRIZZLE_BIN_LOG::start_union_events(THD *thd, query_id_t query_id_param)
 
2931
void MYSQL_BIN_LOG::start_union_events(THD *thd, query_id_t query_id_param)
2208
2932
{
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;
 
2933
  DBUG_ASSERT(!thd->binlog_evt_union.do_union);
 
2934
  thd->binlog_evt_union.do_union= TRUE;
 
2935
  thd->binlog_evt_union.unioned_events= FALSE;
 
2936
  thd->binlog_evt_union.unioned_events_trans= FALSE;
2213
2937
  thd->binlog_evt_union.first_query_id= query_id_param;
2214
2938
}
2215
2939
 
2216
 
void DRIZZLE_BIN_LOG::stop_union_events(THD *thd)
 
2940
void MYSQL_BIN_LOG::stop_union_events(THD *thd)
2217
2941
{
2218
 
  assert(thd->binlog_evt_union.do_union);
2219
 
  thd->binlog_evt_union.do_union= false;
 
2942
  DBUG_ASSERT(thd->binlog_evt_union.do_union);
 
2943
  thd->binlog_evt_union.do_union= FALSE;
2220
2944
}
2221
2945
 
2222
 
bool DRIZZLE_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
 
2946
bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
2223
2947
{
2224
2948
  return (thd->binlog_evt_union.do_union && 
2225
2949
          query_id_param >= thd->binlog_evt_union.first_query_id);
2233
2957
 
2234
2958
int THD::binlog_setup_trx_data()
2235
2959
{
 
2960
  DBUG_ENTER("THD::binlog_setup_trx_data");
2236
2961
  binlog_trx_data *trx_data=
2237
2962
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2238
2963
 
2239
2964
  if (trx_data)
2240
 
    return(0);                             // Already set up
 
2965
    DBUG_RETURN(0);                             // Already set up
2241
2966
 
2242
2967
  trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
2243
2968
  if (!trx_data ||
2244
2969
      open_cached_file(&trx_data->trans_log, mysql_tmpdir,
2245
2970
                       LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
2246
2971
  {
2247
 
    free((unsigned char*)trx_data);
2248
 
    return(1);                      // Didn't manage to set it up
 
2972
    my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR));
 
2973
    DBUG_RETURN(1);                      // Didn't manage to set it up
2249
2974
  }
2250
2975
  thd_set_ha_data(this, binlog_hton, trx_data);
2251
2976
 
2252
2977
  trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data;
2253
2978
 
2254
 
  return(0);
 
2979
  DBUG_RETURN(0);
2255
2980
}
2256
2981
 
2257
2982
/*
2286
3011
THD::binlog_start_trans_and_stmt()
2287
3012
{
2288
3013
  binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
 
3014
  DBUG_ENTER("binlog_start_trans_and_stmt");
 
3015
  DBUG_PRINT("enter", ("trx_data: 0x%lx  trx_data->before_stmt_pos: %lu",
 
3016
                       (long) trx_data,
 
3017
                       (trx_data ? (ulong) trx_data->before_stmt_pos :
 
3018
                        (ulong) 0)));
2289
3019
 
2290
3020
  if (trx_data == NULL ||
2291
3021
      trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
2292
3022
  {
2293
3023
    this->binlog_set_stmt_begin();
2294
3024
    if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2295
 
      trans_register_ha(this, true, binlog_hton);
2296
 
    trans_register_ha(this, false, binlog_hton);
 
3025
      trans_register_ha(this, TRUE, binlog_hton);
 
3026
    trans_register_ha(this, FALSE, binlog_hton);
2297
3027
    /*
2298
3028
      Mark statement transaction as read/write. We never start
2299
3029
      a binary log transaction and keep it read-only,
2305
3035
    */
2306
3036
    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
2307
3037
  }
2308
 
  return;
 
3038
  DBUG_VOID_RETURN;
2309
3039
}
2310
3040
 
2311
3041
void THD::binlog_set_stmt_begin() {
2329
3059
  Write a table map to the binary log.
2330
3060
 */
2331
3061
 
2332
 
int THD::binlog_write_table_map(Table *table, bool is_trans)
 
3062
int THD::binlog_write_table_map(TABLE *table, bool is_trans)
2333
3063
{
2334
3064
  int error;
 
3065
  DBUG_ENTER("THD::binlog_write_table_map");
 
3066
  DBUG_PRINT("enter", ("table: 0x%lx  (%s: #%lu)",
 
3067
                       (long) table, table->s->table_name.str,
 
3068
                       table->s->table_map_id));
2335
3069
 
2336
3070
  /* Pre-conditions */
2337
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2338
 
  assert(table->s->table_map_id != UINT32_MAX);
 
3071
  DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
 
3072
  DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
2339
3073
 
2340
3074
  Table_map_log_event::flag_set const
2341
3075
    flags= Table_map_log_event::TM_NO_FLAGS;
2347
3081
    binlog_start_trans_and_stmt();
2348
3082
 
2349
3083
  if ((error= mysql_bin_log.write(&the_event)))
2350
 
    return(error);
 
3084
    DBUG_RETURN(error);
2351
3085
 
2352
3086
  binlog_table_maps++;
2353
3087
  table->s->table_map_version= mysql_bin_log.table_map_version();
2354
 
  return(0);
 
3088
  DBUG_RETURN(0);
2355
3089
}
2356
3090
 
2357
3091
Rows_log_event*
2377
3111
  binlog_trx_data *const trx_data=
2378
3112
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2379
3113
 
2380
 
  assert(trx_data);
 
3114
  DBUG_ASSERT(trx_data);
2381
3115
  trx_data->set_pending(ev);
2382
3116
}
2383
3117
 
2388
3122
  event.
2389
3123
*/
2390
3124
int
2391
 
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
 
3125
MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
2392
3126
                                                Rows_log_event* event)
2393
3127
{
2394
 
  assert(mysql_bin_log.is_open());
 
3128
  DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
 
3129
  DBUG_ASSERT(mysql_bin_log.is_open());
 
3130
  DBUG_PRINT("enter", ("event: 0x%lx", (long) event));
2395
3131
 
2396
3132
  int error= 0;
2397
3133
 
2398
3134
  binlog_trx_data *const trx_data=
2399
3135
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
2400
3136
 
2401
 
  assert(trx_data);
 
3137
  DBUG_ASSERT(trx_data);
 
3138
 
 
3139
  DBUG_PRINT("info", ("trx_data->pending(): 0x%lx", (long) trx_data->pending()));
2402
3140
 
2403
3141
  if (Rows_log_event* pending= trx_data->pending())
2404
3142
  {
2425
3163
    if (pending->write(file))
2426
3164
    {
2427
3165
      pthread_mutex_unlock(&LOCK_log);
2428
 
      return(1);
 
3166
      DBUG_RETURN(1);
2429
3167
    }
2430
3168
 
2431
3169
    /*
2463
3201
 
2464
3202
  thd->binlog_set_pending_rows_event(event);
2465
3203
 
2466
 
  return(error);
 
3204
  DBUG_RETURN(error);
2467
3205
}
2468
3206
 
2469
3207
/**
2470
3208
  Write an event to the binary log.
2471
3209
*/
2472
3210
 
2473
 
bool DRIZZLE_BIN_LOG::write(Log_event *event_info)
 
3211
bool MYSQL_BIN_LOG::write(Log_event *event_info)
2474
3212
{
2475
3213
  THD *thd= event_info->thd;
2476
3214
  bool error= 1;
 
3215
  DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)");
2477
3216
 
2478
3217
  if (thd->binlog_evt_union.do_union)
2479
3218
  {
2481
3220
      In Stored function; Remember that function call caused an update.
2482
3221
      We will log the function call to the binary log on function exit
2483
3222
    */
2484
 
    thd->binlog_evt_union.unioned_events= true;
 
3223
    thd->binlog_evt_union.unioned_events= TRUE;
2485
3224
    thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
2486
 
    return(0);
 
3225
    DBUG_RETURN(0);
2487
3226
  }
2488
3227
 
2489
3228
  /*
2518
3257
    if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
2519
3258
        (!binlog_filter->db_ok(local_db)))
2520
3259
    {
2521
 
      pthread_mutex_unlock(&LOCK_log);
2522
 
      return(0);
 
3260
      VOID(pthread_mutex_unlock(&LOCK_log));
 
3261
      DBUG_RETURN(0);
2523
3262
    }
2524
3263
 
2525
3264
    /*
2542
3281
      my_off_t trans_log_pos= my_b_tell(trans_log);
2543
3282
      if (event_info->get_cache_stmt() || trans_log_pos != 0)
2544
3283
      {
 
3284
        DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
 
3285
                            event_info->get_cache_stmt(),
 
3286
                            (ulong) trans_log_pos));
2545
3287
        if (trans_log_pos == 0)
2546
3288
          thd->binlog_start_trans_and_stmt();
2547
3289
        file= trans_log;
2553
3295
        LOCK_log.
2554
3296
      */
2555
3297
    }
 
3298
    DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
2556
3299
 
2557
3300
    /*
2558
3301
      No check for auto events flag here - this write method should
2574
3317
      {
2575
3318
        if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
2576
3319
        {
2577
 
          Intvar_log_event e(thd,(unsigned char) LAST_INSERT_ID_EVENT,
 
3320
          Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
2578
3321
                             thd->first_successful_insert_id_in_prev_stmt_for_binlog);
2579
3322
          if (e.write(file))
2580
3323
            goto err;
2581
3324
        }
2582
3325
        if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
2583
3326
        {
 
3327
          DBUG_PRINT("info",("number of auto_inc intervals: %u",
 
3328
                             thd->auto_inc_intervals_in_cur_stmt_for_binlog.
 
3329
                             nb_elements()));
2584
3330
          /*
2585
3331
            If the auto_increment was second in a table's index (possible with
2586
3332
            MyISAM or BDB) (table->next_number_keypart != 0), such event is
2587
3333
            in fact not necessary. We could avoid logging it.
2588
3334
          */
2589
 
          Intvar_log_event e(thd, (unsigned char) INSERT_ID_EVENT,
 
3335
          Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
2590
3336
                             thd->auto_inc_intervals_in_cur_stmt_for_binlog.
2591
3337
                             minimum());
2592
3338
          if (e.write(file))
2600
3346
        }
2601
3347
        if (thd->user_var_events.elements)
2602
3348
        {
2603
 
          for (uint32_t i= 0; i < thd->user_var_events.elements; i++)
 
3349
          for (uint i= 0; i < thd->user_var_events.elements; i++)
2604
3350
          {
2605
3351
            BINLOG_USER_VAR_EVENT *user_var_event;
2606
 
            get_dynamic(&thd->user_var_events,(unsigned char*) &user_var_event, i);
 
3352
            get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i);
2607
3353
            User_var_log_event e(thd, user_var_event->user_var_event->name.str,
2608
3354
                                 user_var_event->user_var_event->name.length,
2609
3355
                                 user_var_event->value,
2648
3394
    ++m_table_map_version;
2649
3395
 
2650
3396
  pthread_mutex_unlock(&LOCK_log);
2651
 
  return(error);
 
3397
  DBUG_RETURN(error);
2652
3398
}
2653
3399
 
2654
3400
 
2658
3404
  return logger.error_log_print(level, format, args);
2659
3405
}
2660
3406
 
2661
 
void DRIZZLE_BIN_LOG::rotate_and_purge(uint32_t flags)
 
3407
 
 
3408
bool slow_log_print(THD *thd, const char *query, uint query_length,
 
3409
                    ulonglong current_utime)
 
3410
{
 
3411
  return logger.slow_log_print(thd, query, query_length, current_utime);
 
3412
}
 
3413
 
 
3414
 
 
3415
bool LOGGER::log_command(THD *thd, enum enum_server_command command)
 
3416
{
 
3417
  /*
 
3418
    Log command if we have at least one log event handler enabled and want
 
3419
    to log this king of commands
 
3420
  */
 
3421
  if (*general_log_handler_list && (what_to_log & (1L << (uint) command)))
 
3422
  {
 
3423
    if (thd->options & OPTION_LOG_OFF)
 
3424
    {
 
3425
      /* No logging */
 
3426
      return FALSE;
 
3427
    }
 
3428
 
 
3429
    return TRUE;
 
3430
  }
 
3431
 
 
3432
  return FALSE;
 
3433
}
 
3434
 
 
3435
 
 
3436
bool general_log_print(THD *thd, enum enum_server_command command,
 
3437
                       const char *format, ...)
 
3438
{
 
3439
  va_list args;
 
3440
  uint error= 0;
 
3441
 
 
3442
  /* Print the message to the buffer if we want to log this king of commands */
 
3443
  if (! logger.log_command(thd, command))
 
3444
    return FALSE;
 
3445
 
 
3446
  va_start(args, format);
 
3447
  error= logger.general_log_print(thd, command, format, args);
 
3448
  va_end(args);
 
3449
 
 
3450
  return error;
 
3451
}
 
3452
 
 
3453
bool general_log_write(THD *thd, enum enum_server_command command,
 
3454
                       const char *query, uint query_length)
 
3455
{
 
3456
  /* Write the message to the log if we want to log this king of commands */
 
3457
  if (logger.log_command(thd, command))
 
3458
    return logger.general_log_write(thd, command, query, query_length);
 
3459
 
 
3460
  return FALSE;
 
3461
}
 
3462
 
 
3463
void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
2662
3464
{
2663
3465
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2664
3466
    pthread_mutex_lock(&LOCK_log);
2666
3468
      (my_b_tell(&log_file) >= (my_off_t) max_size))
2667
3469
  {
2668
3470
    new_file_without_locking();
 
3471
#ifdef HAVE_REPLICATION
2669
3472
    if (expire_logs_days)
2670
3473
    {
2671
3474
      time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
2672
3475
      if (purge_time >= 0)
2673
3476
        purge_logs_before_date(purge_time);
2674
3477
    }
 
3478
#endif
2675
3479
  }
2676
3480
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2677
3481
    pthread_mutex_unlock(&LOCK_log);
2678
3482
}
2679
3483
 
2680
 
uint32_t DRIZZLE_BIN_LOG::next_file_id()
 
3484
uint MYSQL_BIN_LOG::next_file_id()
2681
3485
{
2682
 
  uint32_t res;
 
3486
  uint res;
2683
3487
  pthread_mutex_lock(&LOCK_log);
2684
3488
  res = file_id++;
2685
3489
  pthread_mutex_unlock(&LOCK_log);
2701
3505
    be reset as a READ_CACHE to be able to read the contents from it.
2702
3506
 */
2703
3507
 
2704
 
int DRIZZLE_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
 
3508
int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log)
2705
3509
{
2706
3510
  Mutex_sentry sentry(lock_log ? &LOCK_log : NULL);
2707
3511
 
2708
3512
  if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
2709
3513
    return ER_ERROR_ON_WRITE;
2710
 
  uint32_t length= my_b_bytes_in_cache(cache), group, carry, hdr_offs;
 
3514
  uint length= my_b_bytes_in_cache(cache), group, carry, hdr_offs;
2711
3515
  long val;
2712
 
  unsigned char header[LOG_EVENT_HEADER_LEN];
 
3516
  uchar header[LOG_EVENT_HEADER_LEN];
2713
3517
 
2714
3518
  /*
2715
3519
    The events in the buffer have incorrect end_log_pos data
2737
3541
    */
2738
3542
    if (unlikely(carry > 0))
2739
3543
    {
2740
 
      assert(carry < LOG_EVENT_HEADER_LEN);
 
3544
      DBUG_ASSERT(carry < LOG_EVENT_HEADER_LEN);
2741
3545
 
2742
3546
      /* assemble both halves */
2743
 
      memcpy(&header[carry], cache->read_pos, LOG_EVENT_HEADER_LEN - carry);
 
3547
      memcpy(&header[carry], (char *)cache->read_pos, LOG_EVENT_HEADER_LEN - carry);
2744
3548
 
2745
3549
      /* fix end_log_pos */
2746
3550
      val= uint4korr(&header[LOG_POS_OFFSET]) + group;
2754
3558
        copy fixed second half of header to cache so the correct
2755
3559
        version will be written later.
2756
3560
      */
2757
 
      memcpy(cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry);
 
3561
      memcpy((char *)cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry);
2758
3562
 
2759
3563
      /* next event header at ... */
2760
3564
      hdr_offs = uint4korr(&header[EVENT_LEN_OFFSET]) - carry;
2783
3587
        if (hdr_offs + LOG_EVENT_HEADER_LEN > length)
2784
3588
        {
2785
3589
          carry= length - hdr_offs;
2786
 
          memcpy(header, cache->read_pos + hdr_offs, carry);
 
3590
          memcpy(header, (char *)cache->read_pos + hdr_offs, carry);
2787
3591
          length= hdr_offs;
2788
3592
        }
2789
3593
        else
2790
3594
        {
2791
3595
          /* we've got a full event-header, and it came in one piece */
2792
3596
 
2793
 
          unsigned char *log_pos= (unsigned char *)cache->read_pos + hdr_offs + LOG_POS_OFFSET;
 
3597
          uchar *log_pos= (uchar *)cache->read_pos + hdr_offs + LOG_POS_OFFSET;
2794
3598
 
2795
3599
          /* fix end_log_pos */
2796
3600
          val= uint4korr(log_pos) + group;
2797
3601
          int4store(log_pos, val);
2798
3602
 
2799
3603
          /* next event header at ... */
2800
 
          log_pos= (unsigned char *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET;
 
3604
          log_pos= (uchar *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET;
2801
3605
          hdr_offs += uint4korr(log_pos);
2802
3606
 
2803
3607
        }
2820
3624
    cache->read_pos=cache->read_end;            // Mark buffer used up
2821
3625
  } while ((length= my_b_fill(cache)));
2822
3626
 
2823
 
  assert(carry == 0);
 
3627
  DBUG_ASSERT(carry == 0);
2824
3628
 
2825
3629
  if (sync_log)
2826
3630
    flush_and_sync();
2849
3653
    'cache' needs to be reinitialized after this functions returns.
2850
3654
*/
2851
3655
 
2852
 
bool DRIZZLE_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
 
3656
bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
2853
3657
{
2854
 
  pthread_mutex_lock(&LOCK_log);
 
3658
  DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
 
3659
  VOID(pthread_mutex_lock(&LOCK_log));
2855
3660
 
2856
3661
  /* NULL would represent nothing to replicate after ROLLBACK */
2857
 
  assert(commit_event != NULL);
 
3662
  DBUG_ASSERT(commit_event != NULL);
2858
3663
 
2859
 
  assert(is_open());
 
3664
  DBUG_ASSERT(is_open());
2860
3665
  if (likely(is_open()))                       // Should always be true
2861
3666
  {
2862
3667
    /*
2870
3675
        transaction is either a BEGIN..COMMIT block or a single
2871
3676
        statement in autocommit mode.
2872
3677
      */
2873
 
      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), true, false);
 
3678
      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE);
2874
3679
      /*
2875
3680
        Imagine this is rollback due to net timeout, after all
2876
3681
        statements of the transaction succeeded. Then we want a
2894
3699
      if (qinfo.write(&log_file))
2895
3700
        goto err;
2896
3701
 
 
3702
      DBUG_EXECUTE_IF("crash_before_writing_xid",
 
3703
                      {
 
3704
                        if ((write_error= write_cache(cache, false, true)))
 
3705
                          DBUG_PRINT("info", ("error writing binlog cache: %d",
 
3706
                                               write_error));
 
3707
                        DBUG_PRINT("info", ("crashing before writing xid"));
 
3708
                        abort();
 
3709
                      });
 
3710
 
2897
3711
      if ((write_error= write_cache(cache, false, false)))
2898
3712
        goto err;
2899
3713
 
2901
3715
        goto err;
2902
3716
      if (flush_and_sync())
2903
3717
        goto err;
 
3718
      DBUG_EXECUTE_IF("half_binlogged_transaction", abort(););
2904
3719
      if (cache->error)                         // Error on read
2905
3720
      {
2906
3721
        sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
2927
3742
    else
2928
3743
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2929
3744
  }
2930
 
  pthread_mutex_unlock(&LOCK_log);
 
3745
  VOID(pthread_mutex_unlock(&LOCK_log));
2931
3746
 
2932
 
  return(0);
 
3747
  DBUG_RETURN(0);
2933
3748
 
2934
3749
err:
2935
3750
  if (!write_error)
2937
3752
    write_error= 1;
2938
3753
    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
2939
3754
  }
2940
 
  pthread_mutex_unlock(&LOCK_log);
2941
 
  return(1);
 
3755
  VOID(pthread_mutex_unlock(&LOCK_log));
 
3756
  DBUG_RETURN(1);
2942
3757
}
2943
3758
 
2944
3759
 
2951
3766
    It will be released at the end of the function.
2952
3767
*/
2953
3768
 
2954
 
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(THD* thd)
 
3769
void MYSQL_BIN_LOG::wait_for_update_relay_log(THD* thd)
2955
3770
{
2956
3771
  const char *old_msg;
 
3772
  DBUG_ENTER("wait_for_update_relay_log");
2957
3773
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
2958
3774
                           "Slave has read all relay log; " 
2959
3775
                           "waiting for the slave I/O "
2960
3776
                           "thread to update it" );
2961
3777
  pthread_cond_wait(&update_cond, &LOCK_log);
2962
3778
  thd->exit_cond(old_msg);
2963
 
  return;
 
3779
  DBUG_VOID_RETURN;
2964
3780
}
2965
3781
 
2966
3782
 
2980
3796
    LOCK_log is released by the caller.
2981
3797
*/
2982
3798
 
2983
 
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(THD* thd,
 
3799
int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd,
2984
3800
                                           const struct timespec *timeout)
2985
3801
{
2986
3802
  int ret= 0;
2987
 
  const char* old_msg = thd->get_proc_info();
 
3803
  const char* old_msg = thd->proc_info;
 
3804
  DBUG_ENTER("wait_for_update_bin_log");
2988
3805
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
2989
3806
                           "Master has sent all binlog to slave; "
2990
3807
                           "waiting for binlog to be updated");
2993
3810
  else
2994
3811
    ret= pthread_cond_timedwait(&update_cond, &LOCK_log,
2995
3812
                                const_cast<struct timespec *>(timeout));
2996
 
  return(ret);
 
3813
  DBUG_RETURN(ret);
2997
3814
}
2998
3815
 
2999
3816
 
3011
3828
    The internal structures are not freed until cleanup() is called
3012
3829
*/
3013
3830
 
3014
 
void DRIZZLE_BIN_LOG::close(uint32_t exiting)
 
3831
void MYSQL_BIN_LOG::close(uint exiting)
3015
3832
{                                       // One can't set log_type here!
 
3833
  DBUG_ENTER("MYSQL_BIN_LOG::close");
 
3834
  DBUG_PRINT("enter",("exiting: %d", (int) exiting));
3016
3835
  if (log_state == LOG_OPENED)
3017
3836
  {
 
3837
#ifdef HAVE_REPLICATION
3018
3838
    if (log_type == LOG_BIN && !no_auto_events &&
3019
3839
        (exiting & LOG_CLOSE_STOP_EVENT))
3020
3840
    {
3023
3843
      bytes_written+= s.data_written;
3024
3844
      signal_update();
3025
3845
    }
 
3846
#endif /* HAVE_REPLICATION */
3026
3847
 
3027
3848
    /* don't pwrite in a file opened with O_APPEND - it doesn't work */
3028
3849
    if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
3029
3850
    {
3030
3851
      my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
3031
 
      unsigned char flags= 0;            // clearing LOG_EVENT_BINLOG_IN_USE_F
 
3852
      my_off_t org_position= my_tell(log_file.file, MYF(0));
 
3853
      uchar flags= 0;            // clearing LOG_EVENT_BINLOG_IN_USE_F
3032
3854
      pwrite(log_file.file, &flags, 1, offset);
3033
3855
    }
3034
3856
 
3035
3857
    /* this will cleanup IO_CACHE, sync and close the file */
3036
 
    DRIZZLE_LOG::close(exiting);
 
3858
    MYSQL_LOG::close(exiting);
3037
3859
  }
3038
3860
 
3039
3861
  /*
3051
3873
    }
3052
3874
  }
3053
3875
  log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
3054
 
  if (name)
3055
 
  {
3056
 
    free(name);
3057
 
    name= NULL;
3058
 
  }
3059
 
  return;
 
3876
  safeFree(name);
 
3877
  DBUG_VOID_RETURN;
3060
3878
}
3061
3879
 
3062
3880
 
3063
 
void DRIZZLE_BIN_LOG::set_max_size(ulong max_size_arg)
 
3881
void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg)
3064
3882
{
3065
3883
  /*
3066
3884
    We need to take locks, otherwise this may happen:
3069
3887
    uses the old_max_size argument, so max_size_arg has been overwritten and
3070
3888
    it's like if the SET command was never run.
3071
3889
  */
 
3890
  DBUG_ENTER("MYSQL_BIN_LOG::set_max_size");
3072
3891
  pthread_mutex_lock(&LOCK_log);
3073
3892
  if (is_open())
3074
3893
    max_size= max_size_arg;
3075
3894
  pthread_mutex_unlock(&LOCK_log);
3076
 
  return;
 
3895
  DBUG_VOID_RETURN;
3077
3896
}
3078
3897
 
3079
3898
 
3099
3918
{
3100
3919
  register int flag;
3101
3920
  const char *start;
 
3921
  DBUG_ENTER("test_if_number");
3102
3922
 
3103
3923
  flag= 0; 
3104
3924
  start= str;
3119
3939
         str++, flag=1) ;
3120
3940
  }
3121
3941
  if (*str != 0 || flag == 0)
3122
 
    return(0);
 
3942
    DBUG_RETURN(0);
3123
3943
  if (res)
3124
3944
    *res=atol(start);
3125
 
  return(1);                    /* Number ok */
 
3945
  DBUG_RETURN(1);                       /* Number ok */
3126
3946
} /* test_if_number */
3127
3947
 
3128
3948
 
3129
3949
void sql_perror(const char *message)
3130
3950
{
 
3951
#ifdef HAVE_STRERROR
3131
3952
  sql_print_error("%s: %s",message, strerror(errno));
 
3953
#else
 
3954
  perror(message);
 
3955
#endif
3132
3956
}
3133
3957
 
3134
3958
 
3139
3963
  {
3140
3964
    char err_renamed[FN_REFLEN], *end;
3141
3965
    end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
3142
 
    my_stpcpy(end, "-old");
3143
 
    pthread_mutex_lock(&LOCK_error_log);
 
3966
    strmov(end, "-old");
 
3967
    VOID(pthread_mutex_lock(&LOCK_error_log));
3144
3968
    char err_temp[FN_REFLEN+4];
3145
3969
    /*
3146
3970
     On Windows is necessary a temporary file for to rename
3147
3971
     the current error file.
3148
3972
    */
3149
 
    strxmov(err_temp, err_renamed,"-tmp",NULL);
 
3973
    strxmov(err_temp, err_renamed,"-tmp",NullS);
3150
3974
    (void) my_delete(err_temp, MYF(0)); 
3151
3975
    if (freopen(err_temp,"a+",stdout))
3152
3976
    {
3153
3977
      int fd;
3154
3978
      size_t bytes;
3155
 
      unsigned char buf[IO_SIZE];
 
3979
      uchar buf[IO_SIZE];
3156
3980
 
3157
3981
      freopen(err_temp,"a+",stderr);
3158
3982
      (void) my_delete(err_renamed, MYF(0));
3171
3995
    }
3172
3996
    else
3173
3997
     result= 1;
3174
 
    pthread_mutex_unlock(&LOCK_error_log);
 
3998
    VOID(pthread_mutex_unlock(&LOCK_error_log));
3175
3999
  }
3176
4000
   return result;
3177
4001
}
3178
4002
 
3179
 
void DRIZZLE_BIN_LOG::signal_update()
 
4003
void MYSQL_BIN_LOG::signal_update()
3180
4004
{
 
4005
  DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
3181
4006
  pthread_cond_broadcast(&update_cond);
3182
 
  return;
 
4007
  DBUG_VOID_RETURN;
3183
4008
}
3184
4009
 
3185
4010
/**
3198
4023
    signature to be compatible with other logging routines, which could
3199
4024
    return an error (e.g. logging to the log tables)
3200
4025
*/
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)))
 
4026
static void print_buffer_to_file(enum loglevel level, int error_code,
 
4027
                                 const char *buffer, size_t buffer_length)
3205
4028
{
3206
4029
  time_t skr;
3207
4030
  struct tm tm_tmp;
3208
4031
  struct tm *start;
 
4032
  DBUG_ENTER("print_buffer_to_file");
 
4033
  DBUG_PRINT("enter",("buffer: %s", buffer));
3209
4034
 
3210
 
  pthread_mutex_lock(&LOCK_error_log);
 
4035
  VOID(pthread_mutex_lock(&LOCK_error_log));
3211
4036
 
3212
4037
  skr= my_time(0);
3213
4038
  localtime_r(&skr, &tm_tmp);
3226
4051
 
3227
4052
  fflush(stderr);
3228
4053
 
3229
 
  pthread_mutex_unlock(&LOCK_error_log);
3230
 
  return;
 
4054
  VOID(pthread_mutex_unlock(&LOCK_error_log));
 
4055
  DBUG_VOID_RETURN;
3231
4056
}
3232
4057
 
3233
4058
 
3236
4061
  char   buff[1024];
3237
4062
  size_t length;
3238
4063
  int error_code= errno;
 
4064
  DBUG_ENTER("vprint_msg_to_log");
3239
4065
 
3240
 
  length= vsnprintf(buff, sizeof(buff), format, args);
 
4066
  length= my_vsnprintf(buff, sizeof(buff), format, args);
3241
4067
 
3242
4068
  print_buffer_to_file(level, error_code, buff, length);
3243
4069
 
3244
 
  return(0);
 
4070
  DBUG_RETURN(0);
3245
4071
}
3246
4072
 
3247
4073
 
3248
4074
void sql_print_error(const char *format, ...) 
3249
4075
{
3250
4076
  va_list args;
 
4077
  DBUG_ENTER("sql_print_error");
3251
4078
 
3252
4079
  va_start(args, format);
3253
4080
  error_log_print(ERROR_LEVEL, format, args);
3254
4081
  va_end(args);
3255
4082
 
3256
 
  return;
 
4083
  DBUG_VOID_RETURN;
3257
4084
}
3258
4085
 
3259
4086
 
3260
4087
void sql_print_warning(const char *format, ...) 
3261
4088
{
3262
4089
  va_list args;
 
4090
  DBUG_ENTER("sql_print_warning");
3263
4091
 
3264
4092
  va_start(args, format);
3265
4093
  error_log_print(WARNING_LEVEL, format, args);
3266
4094
  va_end(args);
3267
4095
 
3268
 
  return;
 
4096
  DBUG_VOID_RETURN;
3269
4097
}
3270
4098
 
3271
4099
 
3272
4100
void sql_print_information(const char *format, ...) 
3273
4101
{
3274
4102
  va_list args;
 
4103
  DBUG_ENTER("sql_print_information");
3275
4104
 
3276
4105
  va_start(args, format);
3277
4106
  error_log_print(INFORMATION_LEVEL, format, args);
3278
4107
  va_end(args);
3279
4108
 
3280
 
  return;
 
4109
  DBUG_VOID_RETURN;
3281
4110
}
3282
4111
 
3283
4112
 
3332
4161
 
3333
4162
int TC_LOG_MMAP::open(const char *opt_name)
3334
4163
{
3335
 
  uint32_t i;
3336
 
  bool crashed= false;
 
4164
  uint i;
 
4165
  bool crashed=FALSE;
3337
4166
  PAGE *pg;
3338
4167
 
3339
 
  assert(total_ha_2pc > 1);
3340
 
  assert(opt_name && opt_name[0]);
 
4168
  DBUG_ASSERT(total_ha_2pc > 1);
 
4169
  DBUG_ASSERT(opt_name && opt_name[0]);
3341
4170
 
3342
 
  tc_log_page_size= getpagesize();
3343
 
  assert(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
 
4171
  tc_log_page_size= my_getpagesize();
 
4172
  DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
3344
4173
 
3345
4174
  fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
3346
4175
  if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
3359
4188
  else
3360
4189
  {
3361
4190
    inited= 1;
3362
 
    crashed= true;
3363
 
    sql_print_information(_("Recovering after a crash using %s"), opt_name);
 
4191
    crashed= TRUE;
 
4192
    sql_print_information("Recovering after a crash using %s", opt_name);
3364
4193
    if (tc_heuristic_recover)
3365
4194
    {
3366
 
      sql_print_error(_("Cannot perform automatic crash recovery when "
3367
 
                      "--tc-heuristic-recover is used"));
 
4195
      sql_print_error("Cannot perform automatic crash recovery when "
 
4196
                      "--tc-heuristic-recover is used");
3368
4197
      goto err;
3369
4198
    }
3370
4199
    file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
3372
4201
      goto err;
3373
4202
  }
3374
4203
 
3375
 
  data= (unsigned char *)my_mmap(0, (size_t)file_length, PROT_READ|PROT_WRITE,
 
4204
  data= (uchar *)my_mmap(0, (size_t)file_length, PROT_READ|PROT_WRITE,
3376
4205
                        MAP_NOSYNC|MAP_SHARED, fd, 0);
3377
4206
  if (data == MAP_FAILED)
3378
4207
  {
3382
4211
  inited=2;
3383
4212
 
3384
4213
  npages=(uint)file_length/tc_log_page_size;
3385
 
  assert(npages >= 3);             // to guarantee non-empty pool
 
4214
  DBUG_ASSERT(npages >= 3);             // to guarantee non-empty pool
3386
4215
  if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
3387
4216
    goto err;
3388
4217
  inited=3;
3408
4237
      goto err;
3409
4238
 
3410
4239
  memcpy(data, tc_log_magic, sizeof(tc_log_magic));
3411
 
  data[sizeof(tc_log_magic)]= (unsigned char)total_ha_2pc;
 
4240
  data[sizeof(tc_log_magic)]= (uchar)total_ha_2pc;
3412
4241
  msync(data, tc_log_page_size, MS_SYNC);
3413
4242
  my_sync(fd, MYF(0));
3414
4243
  inited=5;
3516
4345
    threads waiting for a page, but then all these threads will be waiting
3517
4346
    for a fsync() anyway
3518
4347
 
3519
 
   If tc_log == DRIZZLE_LOG then tc_log writes transaction to binlog and
 
4348
   If tc_log == MYSQL_LOG then tc_log writes transaction to binlog and
3520
4349
   records XID in a special Xid_log_event.
3521
4350
   If tc_log = TC_LOG_MMAP then xid is written in a special memory-mapped
3522
4351
   log.
3530
4359
    to the position in memory where xid was logged to.
3531
4360
*/
3532
4361
 
3533
 
int TC_LOG_MMAP::log_xid(THD *thd __attribute__((unused)), my_xid xid)
 
4362
int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
3534
4363
{
3535
4364
  int err;
3536
4365
  PAGE *p;
3559
4388
  while (*p->ptr)
3560
4389
  {
3561
4390
    p->ptr++;
3562
 
    assert(p->ptr < p->end);               // because p->free > 0
 
4391
    DBUG_ASSERT(p->ptr < p->end);               // because p->free > 0
3563
4392
  }
3564
4393
 
3565
4394
  /* found! store xid there and mark the page dirty */
3566
 
  cookie= (ulong)((unsigned char *)p->ptr - data);      // can never be zero
 
4395
  cookie= (ulong)((uchar *)p->ptr - data);      // can never be zero
3567
4396
  *p->ptr++= xid;
3568
4397
  p->free--;
3569
4398
  p->state= DIRTY;
3592
4421
      goto done;                             // we're done
3593
4422
    }
3594
4423
  }                                          // page was not synced! do it now
3595
 
  assert(active == p && syncing == 0);
 
4424
  DBUG_ASSERT(active == p && syncing == 0);
3596
4425
  pthread_mutex_lock(&LOCK_active);
3597
4426
  syncing=p;                                 // place is vacant - take it
3598
4427
  active=0;                                  // page is not active anymore
3609
4438
{
3610
4439
  int err;
3611
4440
 
3612
 
  assert(syncing != active);
 
4441
  DBUG_ASSERT(syncing != active);
3613
4442
 
3614
4443
  /*
3615
4444
    sit down and relax - this can take a while...
3642
4471
  cookie points directly to the memory where xid was logged.
3643
4472
*/
3644
4473
 
3645
 
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid __attribute__((unused)))
 
4474
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
3646
4475
{
3647
4476
  PAGE *p=pages+(cookie/tc_log_page_size);
3648
4477
  my_xid *x=(my_xid *)(data+cookie);
3649
4478
 
3650
 
  assert(*x == xid);
3651
 
  assert(x >= p->start && x < p->end);
 
4479
  DBUG_ASSERT(*x == xid);
 
4480
  DBUG_ASSERT(x >= p->start && x < p->end);
3652
4481
  *x=0;
3653
4482
 
3654
4483
  pthread_mutex_lock(&p->lock);
3655
4484
  p->free++;
3656
 
  assert(p->free <= p->size);
 
4485
  DBUG_ASSERT(p->free <= p->size);
3657
4486
  set_if_smaller(p->ptr, x);
3658
4487
  if (p->free == p->size)               // the page is completely empty
3659
4488
    statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
3664
4493
 
3665
4494
void TC_LOG_MMAP::close()
3666
4495
{
3667
 
  uint32_t i;
 
4496
  uint i;
3668
4497
  switch (inited) {
3669
4498
  case 6:
3670
4499
    pthread_mutex_destroy(&LOCK_sync);
3682
4511
      pthread_cond_destroy(&pages[i].cond);
3683
4512
    }
3684
4513
  case 3:
3685
 
    free((unsigned char*)pages);
 
4514
    my_free((uchar*)pages, MYF(0));
3686
4515
  case 2:
3687
4516
    my_munmap((char*)data, (size_t)file_length);
3688
4517
  case 1:
3700
4529
 
3701
4530
  if (memcmp(data, tc_log_magic, sizeof(tc_log_magic)))
3702
4531
  {
3703
 
    sql_print_error(_("Bad magic header in tc log"));
 
4532
    sql_print_error("Bad magic header in tc log");
3704
4533
    goto err1;
3705
4534
  }
3706
4535
 
3710
4539
  */
3711
4540
  if (data[sizeof(tc_log_magic)] != total_ha_2pc)
3712
4541
  {
3713
 
    sql_print_error(_("Recovery failed! You must enable "
 
4542
    sql_print_error("Recovery failed! You must enable "
3714
4543
                    "exactly %d storage engines that support "
3715
 
                    "two-phase commit protocol"),
 
4544
                    "two-phase commit protocol",
3716
4545
                    data[sizeof(tc_log_magic)]);
3717
4546
    goto err1;
3718
4547
  }
3724
4553
  for ( ; p < end_p ; p++)
3725
4554
  {
3726
4555
    for (my_xid *x=p->start; x < p->end; x++)
3727
 
      if (*x && my_hash_insert(&xids, (unsigned char *)x))
 
4556
      if (*x && my_hash_insert(&xids, (uchar *)x))
3728
4557
        goto err2; // OOM
3729
4558
  }
3730
4559
 
3732
4561
    goto err2;
3733
4562
 
3734
4563
  hash_free(&xids);
3735
 
  memset(data, 0, (size_t)file_length);
 
4564
  bzero(data, (size_t)file_length);
3736
4565
  return 0;
3737
4566
 
3738
4567
err2:
3739
4568
  hash_free(&xids);
3740
4569
err1:
3741
 
  sql_print_error(_("Crash recovery failed. Either correct the problem "
 
4570
  sql_print_error("Crash recovery failed. Either correct the problem "
3742
4571
                  "(if it's, for example, out of memory error) and restart, "
3743
 
                  "or delete tc log and start drizzled with "
3744
 
                  "--tc-heuristic-recover={commit|rollback}"));
 
4572
                  "or delete tc log and start mysqld with "
 
4573
                  "--tc-heuristic-recover={commit|rollback}");
3745
4574
  return 1;
3746
4575
}
3747
4576
#endif
3768
4597
  if (!tc_heuristic_recover)
3769
4598
    return 0;
3770
4599
 
3771
 
  sql_print_information(_("Heuristic crash recovery mode"));
 
4600
  sql_print_information("Heuristic crash recovery mode");
3772
4601
  if (ha_recover(0))
3773
 
    sql_print_error(_("Heuristic crash recovery failed"));
3774
 
  sql_print_information(_("Please restart mysqld without --tc-heuristic-recover"));
 
4602
    sql_print_error("Heuristic crash recovery failed");
 
4603
  sql_print_information("Please restart mysqld without --tc-heuristic-recover");
3775
4604
  return 1;
3776
4605
}
3777
4606
 
3778
4607
/****** transaction coordinator log for 2pc - binlog() based solution ******/
3779
 
#define TC_LOG_BINLOG DRIZZLE_BIN_LOG
 
4608
#define TC_LOG_BINLOG MYSQL_BIN_LOG
3780
4609
 
3781
4610
/**
3782
4611
  @todo
3791
4620
  LOG_INFO log_info;
3792
4621
  int      error= 1;
3793
4622
 
3794
 
  assert(total_ha_2pc > 1);
3795
 
  assert(opt_name && opt_name[0]);
 
4623
  DBUG_ASSERT(total_ha_2pc > 1);
 
4624
  DBUG_ASSERT(opt_name && opt_name[0]);
3796
4625
 
3797
4626
  pthread_mutex_init(&LOCK_prep_xids, MY_MUTEX_INIT_FAST);
3798
4627
  pthread_cond_init (&COND_prep_xids, 0);
3812
4641
    return 1;
3813
4642
  }
3814
4643
 
3815
 
  if ((error= find_log_pos(&log_info, NULL, 1)))
 
4644
  if ((error= find_log_pos(&log_info, NullS, 1)))
3816
4645
  {
3817
4646
    if (error != LOG_INFO_EOF)
3818
 
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
 
4647
      sql_print_error("find_log_pos() failed (error: %d)", error);
3819
4648
    else
3820
4649
      error= 0;
3821
4650
    goto err;
3839
4668
 
3840
4669
    if (error !=  LOG_INFO_EOF)
3841
4670
    {
3842
 
      sql_print_error(_("find_log_pos() failed (error: %d)"), error);
 
4671
      sql_print_error("find_log_pos() failed (error: %d)", error);
3843
4672
      goto err;
3844
4673
    }
3845
4674
 
3853
4682
        ev->get_type_code() == FORMAT_DESCRIPTION_EVENT &&
3854
4683
        ev->flags & LOG_EVENT_BINLOG_IN_USE_F)
3855
4684
    {
3856
 
      sql_print_information(_("Recovering after a crash using %s"), opt_name);
 
4685
      sql_print_information("Recovering after a crash using %s", opt_name);
3857
4686
      error= recover(&log, (Format_description_log_event *)ev);
3858
4687
    }
3859
4688
    else
3874
4703
/** This is called on shutdown, after ha_panic. */
3875
4704
void TC_LOG_BINLOG::close()
3876
4705
{
3877
 
  assert(prepared_xids==0);
 
4706
  DBUG_ASSERT(prepared_xids==0);
3878
4707
  pthread_mutex_destroy(&LOCK_prep_xids);
3879
4708
  pthread_cond_destroy (&COND_prep_xids);
3880
4709
}
3890
4719
*/
3891
4720
int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
3892
4721
{
 
4722
  DBUG_ENTER("TC_LOG_BINLOG::log");
3893
4723
  Xid_log_event xle(thd, xid);
3894
4724
  binlog_trx_data *trx_data=
3895
4725
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
3897
4727
    We always commit the entire transaction when writing an XID. Also
3898
4728
    note that the return value is inverted.
3899
4729
   */
3900
 
  return(!binlog_end_trans(thd, trx_data, &xle, true));
 
4730
  DBUG_RETURN(!binlog_end_trans(thd, trx_data, &xle, TRUE));
3901
4731
}
3902
4732
 
3903
 
void TC_LOG_BINLOG::unlog(ulong cookie __attribute__((unused)),
3904
 
                          my_xid xid __attribute__((unused)))
 
4733
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
3905
4734
{
3906
4735
  pthread_mutex_lock(&LOCK_prep_xids);
3907
 
  assert(prepared_xids > 0);
 
4736
  DBUG_ASSERT(prepared_xids > 0);
3908
4737
  if (--prepared_xids == 0) {
 
4738
    DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
3909
4739
    pthread_cond_signal(&COND_prep_xids);
3910
4740
  }
3911
4741
  pthread_mutex_unlock(&LOCK_prep_xids);
3932
4762
    if (ev->get_type_code() == XID_EVENT)
3933
4763
    {
3934
4764
      Xid_log_event *xev=(Xid_log_event *)ev;
3935
 
      unsigned char *x= (unsigned char *) memdup_root(&mem_root, (unsigned char*) &xev->xid,
 
4765
      uchar *x= (uchar *) memdup_root(&mem_root, (uchar*) &xev->xid,
3936
4766
                                      sizeof(xev->xid));
3937
4767
      if (! x)
3938
4768
        goto err2;
3952
4782
  free_root(&mem_root, MYF(0));
3953
4783
  hash_free(&xids);
3954
4784
err1:
3955
 
  sql_print_error(_("Crash recovery failed. Either correct the problem "
 
4785
  sql_print_error("Crash recovery failed. Either correct the problem "
3956
4786
                  "(if it's, for example, out of memory error) and restart, "
3957
4787
                  "or delete (or rename) binary log and start mysqld with "
3958
 
                  "--tc-heuristic-recover={commit|rollback}"));
 
4788
                  "--tc-heuristic-recover={commit|rollback}");
3959
4789
  return 1;
3960
4790
}
3961
4791
 
3975
4805
  @return byte offset from the beginning of the binlog
3976
4806
*/
3977
4807
extern "C"
3978
 
uint64_t mysql_bin_log_file_pos(void)
 
4808
ulonglong mysql_bin_log_file_pos(void)
3979
4809
{
3980
 
  return (uint64_t) mysql_bin_log.get_log_file()->pos_in_file;
 
4810
  return (ulonglong) mysql_bin_log.get_log_file()->pos_in_file;
3981
4811
}
3982
4812
#endif /* INNODB_COMPATIBILITY_HOOKS */
3983
4813
 
3984
4814
 
 
4815
struct st_mysql_storage_engine binlog_storage_engine=
 
4816
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
4817
 
3985
4818
mysql_declare_plugin(binlog)
3986
4819
{
3987
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
4820
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
4821
  &binlog_storage_engine,
3988
4822
  "binlog",
3989
 
  "1.0",
3990
4823
  "MySQL AB",
3991
4824
  "This is a pseudo storage engine to represent the binlog in a transaction",
3992
4825
  PLUGIN_LICENSE_GPL,
3993
4826
  binlog_init, /* Plugin Init */
3994
4827
  NULL, /* Plugin Deinit */
 
4828
  0x0100 /* 1.0 */,
3995
4829
  NULL,                       /* status variables                */
3996
4830
  NULL,                       /* system variables                */
3997
4831
  NULL                        /* config options                  */