~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/log.cc

  • Committer: jay
  • Date: 2008-12-23 00:18:10 UTC
  • Revision ID: jay@piggy.tangent.org-20081223001810-026ibij22q2842k1
Had a --regex-replace by accident. Should have been --replace_column call.  Only showed up in make test, not running single test, because InnoDB key numbers were different with multiple test running.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
*/
26
26
 
27
27
#include <drizzled/server_includes.h>
28
 
#include "sql_repl.h"
29
 
#include "rpl_filter.h"
30
 
#include "rpl_rli.h"
 
28
#include <drizzled/replication/replication.h>
 
29
#include <libdrizzle/libdrizzle.h>
 
30
#include <drizzled/replicator.h>
 
31
#include <mysys/hash.h>
 
32
#include <drizzled/replication/rli.h>
31
33
 
32
34
#include <mysys/my_dir.h>
33
35
#include <stdarg.h>
34
36
 
35
37
#include <drizzled/plugin.h>
36
 
#include <drizzled/drizzled_error_messages.h>
37
 
#include <libdrizzle/gettext.h>
 
38
#include <drizzled/error.h>
 
39
#include <drizzled/gettext.h>
 
40
#include <drizzled/data_home.h>
 
41
#include <drizzled/log_event.h>
 
42
 
 
43
#include <drizzled/errmsg.h>
38
44
 
39
45
/* max size of the log message */
40
 
#define MAX_LOG_BUFFER_SIZE 1024
41
 
#define MAX_USER_HOST_SIZE 512
42
 
#define MAX_TIME_SIZE 32
43
46
#define MY_OFF_T_UNDEF (~(my_off_t)0UL)
44
47
 
45
 
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
46
 
 
47
 
LOGGER logger;
48
 
 
49
 
DRIZZLE_BIN_LOG mysql_bin_log;
50
 
ulong sync_binlog_counter= 0;
 
48
DRIZZLE_BIN_LOG drizzle_bin_log;
 
49
uint64_t sync_binlog_counter= 0; /* We should rationalize the largest possible counters for binlog sync */
51
50
 
52
51
static bool test_if_number(const char *str,
53
 
                           long *res, bool allow_wildcards);
 
52
                           long *res, bool allow_wildcards);
54
53
static int binlog_init(void *p);
55
 
static int binlog_close_connection(handlerton *hton, THD *thd);
56
 
static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv);
57
 
static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv);
58
 
static int binlog_commit(handlerton *hton, THD *thd, bool all);
59
 
static int binlog_rollback(handlerton *hton, THD *thd, bool all);
60
 
static int binlog_prepare(handlerton *hton, THD *thd, bool all);
 
54
static int binlog_close_connection(handlerton *hton, Session *session);
 
55
static int binlog_savepoint_set(handlerton *hton, Session *session, void *sv);
 
56
static int binlog_savepoint_rollback(handlerton *hton, Session *session, void *sv);
 
57
static int binlog_commit(handlerton *hton, Session *session, bool all);
 
58
static int binlog_rollback(handlerton *hton, Session *session, bool all);
 
59
static int binlog_prepare(handlerton *hton, Session *session, bool all);
61
60
 
62
61
 
63
62
sql_print_message_func sql_print_message_handlers[3] =
68
67
};
69
68
 
70
69
 
71
 
char *make_default_log_name(char *buff,const char* log_ext)
 
70
char *make_default_log_name(char *buff,const char *log_ext)
72
71
{
73
 
  strmake(buff, pidfile_name, FN_REFLEN-5);
74
 
  return fn_format(buff, buff, mysql_data_home, log_ext,
 
72
  strncpy(buff, pidfile_name, FN_REFLEN-5);
 
73
  return fn_format(buff, buff, drizzle_data_home, log_ext,
75
74
                   MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
76
75
}
77
76
 
108
107
  void operator=(Mutex_sentry const&);
109
108
};
110
109
 
111
 
/*
112
 
  Helper class to store binary log transaction data.
113
 
*/
114
 
class binlog_trx_data {
115
 
public:
116
 
  binlog_trx_data()
117
 
    : at_least_one_stmt(0), m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF)
118
 
  {
119
 
    trans_log.end_of_file= max_binlog_cache_size;
120
 
  }
121
 
 
122
 
  ~binlog_trx_data()
123
 
  {
124
 
    assert(pending() == NULL);
125
 
    close_cached_file(&trans_log);
126
 
  }
127
 
 
128
 
  my_off_t position() const {
129
 
    return my_b_tell(&trans_log);
130
 
  }
131
 
 
132
 
  bool empty() const
133
 
  {
134
 
    return pending() == NULL && my_b_tell(&trans_log) == 0;
135
 
  }
136
 
 
137
 
  /*
138
 
    Truncate the transaction cache to a certain position. This
139
 
    includes deleting the pending event.
140
 
   */
141
 
  void truncate(my_off_t pos)
142
 
  {
143
 
    delete pending();
144
 
    set_pending(0);
145
 
    reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
146
 
    if (pos < before_stmt_pos)
147
 
      before_stmt_pos= MY_OFF_T_UNDEF;
148
 
 
149
 
    /*
150
 
      The only valid positions that can be truncated to are at the
151
 
      beginning of a statement. We are relying on this fact to be able
152
 
      to set the at_least_one_stmt flag correctly. In other word, if
153
 
      we are truncating to the beginning of the transaction cache,
154
 
      there will be no statements in the cache, otherwhise, we will
155
 
      have at least one statement in the transaction cache.
156
 
     */
157
 
    at_least_one_stmt= (pos > 0);
158
 
  }
159
 
 
160
 
  /*
161
 
    Reset the entire contents of the transaction cache, emptying it
162
 
    completely.
163
 
   */
164
 
  void reset() {
165
 
    if (!empty())
166
 
      truncate(0);
167
 
    before_stmt_pos= MY_OFF_T_UNDEF;
168
 
    trans_log.end_of_file= max_binlog_cache_size;
169
 
  }
170
 
 
171
 
  Rows_log_event *pending() const
172
 
  {
173
 
    return m_pending;
174
 
  }
175
 
 
176
 
  void set_pending(Rows_log_event *const pending)
177
 
  {
178
 
    m_pending= pending;
179
 
  }
180
 
 
181
 
  IO_CACHE trans_log;                         // The transaction cache
182
 
 
183
 
  /**
184
 
    Boolean that is true if there is at least one statement in the
185
 
    transaction cache.
186
 
  */
187
 
  bool at_least_one_stmt;
188
 
 
189
 
private:
190
 
  /*
191
 
    Pending binrows event. This event is the event where the rows are
192
 
    currently written.
193
 
   */
194
 
  Rows_log_event *m_pending;
195
 
 
196
 
public:
197
 
  /*
198
 
    Binlog position before the start of the current statement.
199
 
  */
200
 
  my_off_t before_stmt_pos;
201
 
};
202
 
 
203
110
handlerton *binlog_hton;
204
111
 
205
112
 
206
 
/* Check if a given table is opened log table */
207
 
int check_if_log_table(uint32_t db_len __attribute__((unused)),
208
 
                       const char *db __attribute__((unused)),
209
 
                       uint32_t table_name_len __attribute__((unused)),
210
 
                       const char *table_name __attribute__((unused)),
211
 
                       uint32_t check_if_opened __attribute__((unused)))
212
 
{
213
 
  return 0;
214
 
}
215
 
 
216
 
/*
217
 
  Log error with all enabled log event handlers
218
 
 
219
 
  SYNOPSIS
220
 
    error_log_print()
221
 
 
222
 
    level             The level of the error significance: NOTE,
223
 
                      WARNING or ERROR.
224
 
    format            format string for the error message
225
 
    args              list of arguments for the format string
226
 
 
227
 
  RETURN
228
 
    FALSE - OK
229
 
    TRUE - error occured
230
 
*/
231
 
 
232
 
bool LOGGER::error_log_print(enum loglevel level, const char *format,
233
 
                             va_list args)
234
 
{
235
 
  bool error= false;
236
 
  Log_event_handler **current_handler;
237
 
 
238
 
  /* currently we don't need locking here as there is no error_log table */
239
 
  for (current_handler= error_log_handler_list ; *current_handler ;)
240
 
    error= (*current_handler++)->log_error(level, format, args) || error;
241
 
 
242
 
  return error;
243
 
}
244
 
 
245
 
 
246
 
void LOGGER::cleanup_base()
247
 
{
248
 
  assert(inited == 1);
249
 
  rwlock_destroy(&LOCK_logger);
250
 
}
251
 
 
252
 
 
253
 
void LOGGER::cleanup_end()
254
 
{
255
 
  assert(inited == 1);
256
 
}
257
 
 
258
 
 
259
 
/**
260
 
  Perform basic log initialization: create file-based log handler and
261
 
  init error log.
262
 
*/
263
 
void LOGGER::init_base()
264
 
{
265
 
  assert(inited == 0);
266
 
  inited= 1;
267
 
 
268
 
  /* by default we use traditional error log */
269
 
  init_error_log(LOG_FILE);
270
 
 
271
 
  my_rwlock_init(&LOCK_logger, NULL);
272
 
}
273
 
 
274
 
 
275
 
bool LOGGER::flush_logs(THD *thd __attribute__((unused)))
276
 
{
277
 
  int rc= 0;
278
 
 
279
 
  /*
280
 
    Now we lock logger, as nobody should be able to use logging routines while
281
 
    log tables are closed
282
 
  */
283
 
  logger.lock_exclusive();
284
 
 
285
 
  /* end of log flush */
286
 
  logger.unlock();
287
 
  return rc;
288
 
}
289
 
 
290
 
void LOGGER::init_error_log(uint32_t error_log_printer)
291
 
{
292
 
  if (error_log_printer & LOG_NONE)
293
 
  {
294
 
    error_log_handler_list[0]= 0;
295
 
    return;
296
 
  }
297
 
 
298
 
}
299
 
 
300
 
int LOGGER::set_handlers(uint32_t error_log_printer)
301
 
{
302
 
  /* error log table is not supported yet */
303
 
  lock_exclusive();
304
 
 
305
 
  init_error_log(error_log_printer);
306
 
  unlock();
307
 
 
308
 
  return 0;
309
 
}
310
 
 
311
 
 
312
113
 /*
313
114
  Save position of binary log transaction cache.
314
115
 
315
116
  SYNPOSIS
316
117
    binlog_trans_log_savepos()
317
118
 
318
 
    thd      The thread to take the binlog data from
 
119
    session      The thread to take the binlog data from
319
120
    pos      Pointer to variable where the position will be stored
320
121
 
321
122
  DESCRIPTION
325
126
 */
326
127
 
327
128
static void
328
 
binlog_trans_log_savepos(THD *thd, my_off_t *pos)
 
129
binlog_trans_log_savepos(Session *, my_off_t *pos)
329
130
{
330
131
  assert(pos != NULL);
331
 
  if (thd_get_ha_data(thd, binlog_hton) == NULL)
332
 
    thd->binlog_setup_trx_data();
333
 
  binlog_trx_data *const trx_data=
334
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
335
 
  assert(mysql_bin_log.is_open());
336
 
  *pos= trx_data->position();
337
 
  return;
338
 
}
339
 
 
340
 
 
341
 
/*
342
 
  Truncate the binary log transaction cache.
343
 
 
344
 
  SYNPOSIS
345
 
    binlog_trans_log_truncate()
346
 
 
347
 
    thd      The thread to take the binlog data from
348
 
    pos      Position to truncate to
349
 
 
350
 
  DESCRIPTION
351
 
 
352
 
    Truncate the binary log to the given position. Will not change
353
 
    anything else.
354
 
 
355
 
 */
356
 
static void
357
 
binlog_trans_log_truncate(THD *thd, my_off_t pos)
358
 
{
359
 
  assert(thd_get_ha_data(thd, binlog_hton) != NULL);
360
 
  /* Only true if binlog_trans_log_savepos() wasn't called before */
361
 
  assert(pos != ~(my_off_t) 0);
362
 
 
363
 
  binlog_trx_data *const trx_data=
364
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
365
 
  trx_data->truncate(pos);
 
132
 
366
133
  return;
367
134
}
368
135
 
389
156
  return 0;
390
157
}
391
158
 
392
 
static int binlog_close_connection(handlerton *hton __attribute__((unused)),
393
 
                                   THD *thd)
 
159
static int binlog_close_connection(handlerton *, Session *)
394
160
{
395
 
  binlog_trx_data *const trx_data=
396
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
397
 
  assert(trx_data->empty());
398
 
  thd_set_ha_data(thd, binlog_hton, NULL);
399
 
  trx_data->~binlog_trx_data();
400
 
  free((unsigned char*)trx_data);
 
161
 
401
162
  return 0;
402
163
}
403
164
 
404
 
/*
405
 
  End a transaction.
406
 
 
407
 
  SYNOPSIS
408
 
    binlog_end_trans()
409
 
 
410
 
    thd      The thread whose transaction should be ended
411
 
    trx_data Pointer to the transaction data to use
412
 
    end_ev   The end event to use, or NULL
413
 
    all      True if the entire transaction should be ended, false if
414
 
             only the statement transaction should be ended.
415
 
 
416
 
  DESCRIPTION
417
 
 
418
 
    End the currently open transaction. The transaction can be either
419
 
    a real transaction (if 'all' is true) or a statement transaction
420
 
    (if 'all' is false).
421
 
 
422
 
    If 'end_ev' is NULL, the transaction is a rollback of only
423
 
    transactional tables, so the transaction cache will be truncated
424
 
    to either just before the last opened statement transaction (if
425
 
    'all' is false), or reset completely (if 'all' is true).
426
 
 */
427
 
static int
428
 
binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
429
 
                 Log_event *end_ev, bool all)
430
 
{
431
 
  int error=0;
432
 
  IO_CACHE *trans_log= &trx_data->trans_log;
433
 
 
434
 
  /*
435
 
    NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
436
 
    only transactional tables.  If the transaction contain changes to
437
 
    any non-transactiona tables, we need write the transaction and log
438
 
    a ROLLBACK last.
439
 
  */
440
 
  if (end_ev != NULL)
441
 
  {
442
 
    /*
443
 
      Doing a commit or a rollback including non-transactional tables,
444
 
      i.e., ending a transaction where we might write the transaction
445
 
      cache to the binary log.
446
 
 
447
 
      We can always end the statement when ending a transaction since
448
 
      transactions are not allowed inside stored functions.  If they
449
 
      were, we would have to ensure that we're not ending a statement
450
 
      inside a stored function.
451
 
     */
452
 
    thd->binlog_flush_pending_rows_event(true);
453
 
 
454
 
    error= mysql_bin_log.write(thd, &trx_data->trans_log, end_ev);
455
 
    trx_data->reset();
456
 
 
457
 
    /*
458
 
      We need to step the table map version after writing the
459
 
      transaction cache to disk.
460
 
    */
461
 
    mysql_bin_log.update_table_map_version();
462
 
    statistic_increment(binlog_cache_use, &LOCK_status);
463
 
    if (trans_log->disk_writes != 0)
464
 
    {
465
 
      statistic_increment(binlog_cache_disk_use, &LOCK_status);
466
 
      trans_log->disk_writes= 0;
467
 
    }
468
 
  }
469
 
  else
470
 
  {
471
 
    /*
472
 
      If rolling back an entire transaction or a single statement not
473
 
      inside a transaction, we reset the transaction cache.
474
 
 
475
 
      If rolling back a statement in a transaction, we truncate the
476
 
      transaction cache to remove the statement.
477
 
     */
478
 
    if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
479
 
    {
480
 
      trx_data->reset();
481
 
 
482
 
      assert(!thd->binlog_get_pending_rows_event());
483
 
      thd->clear_binlog_table_maps();
484
 
    }
485
 
    else                                        // ...statement
486
 
      trx_data->truncate(trx_data->before_stmt_pos);
487
 
 
488
 
    /*
489
 
      We need to step the table map version on a rollback to ensure
490
 
      that a new table map event is generated instead of the one that
491
 
      was written to the thrown-away transaction cache.
492
 
    */
493
 
    mysql_bin_log.update_table_map_version();
494
 
  }
495
 
 
496
 
  return(error);
497
 
}
498
 
 
499
 
static int binlog_prepare(handlerton *hton __attribute__((unused)),
500
 
                          THD *thd __attribute__((unused)),
501
 
                          bool all __attribute__((unused)))
 
165
static int binlog_prepare(handlerton *, Session *session, bool)
502
166
{
503
167
  /*
504
168
    do nothing.
506
170
    switch to 1pc.
507
171
    real work will be done in DRIZZLE_BIN_LOG::log_xid()
508
172
  */
 
173
 
 
174
  (void)replicator_prepare(session);
 
175
 
509
176
  return 0;
510
177
}
511
178
 
512
 
#define YESNO(X) ((X) ? "yes" : "no")
513
 
 
514
179
/**
515
180
  This function is called once after each statement.
516
181
 
518
183
  binlog file on commits.
519
184
 
520
185
  @param hton  The binlog handlerton.
521
 
  @param thd   The client thread that executes the transaction.
 
186
  @param session   The client thread that executes the transaction.
522
187
  @param all   This is @c true if this is a real transaction commit, and
523
188
               @false otherwise.
524
189
 
525
190
  @see handlerton::commit
526
191
*/
527
 
static int binlog_commit(handlerton *hton __attribute__((unused)),
528
 
                         THD *thd, bool all)
 
192
static int binlog_commit(handlerton *, Session *session, bool all)
529
193
{
530
 
  binlog_trx_data *const trx_data=
531
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
532
 
 
533
 
  if (trx_data->empty())
534
 
  {
535
 
    // we're here because trans_log was flushed in DRIZZLE_BIN_LOG::log_xid()
536
 
    trx_data->reset();
537
 
    return(0);
538
 
  }
539
 
 
540
194
  /*
541
195
    Decision table for committing a transaction. The top part, the
542
196
    *conditions* represent different cases that can occur, and hte
595
249
 
596
250
    Otherwise, we accumulate the statement
597
251
  */
598
 
  uint64_t const in_transaction=
599
 
    thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
600
 
  if ((in_transaction && (all || (!trx_data->at_least_one_stmt && thd->transaction.stmt.modified_non_trans_table))) || (!in_transaction && !all))
 
252
 
 
253
  if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) 
601
254
  {
602
 
    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), true, false);
603
 
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(THD, IO_CACHE)
604
 
    int error= binlog_end_trans(thd, trx_data, &qev, all);
605
 
    return(error);
 
255
    return replicator_end_transaction(session, all, true);
606
256
  }
 
257
 
607
258
  return(0);
608
259
}
609
260
 
616
267
  non-transactional tables, nothing needs to be logged.
617
268
 
618
269
  @param hton  The binlog handlerton.
619
 
  @param thd   The client thread that executes the transaction.
 
270
  @param session   The client thread that executes the transaction.
620
271
  @param all   This is @c true if this is a real transaction rollback, and
621
272
               @false otherwise.
622
273
 
623
274
  @see handlerton::rollback
624
275
*/
625
 
static int binlog_rollback(handlerton *hton __attribute__((unused)),
626
 
                           THD *thd, bool all)
 
276
static int binlog_rollback(handlerton *, Session *session, bool all)
627
277
{
628
278
  int error=0;
629
 
  binlog_trx_data *const trx_data=
630
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
631
 
 
632
 
  if (trx_data->empty()) {
633
 
    trx_data->reset();
634
 
    return(0);
635
 
  }
636
 
 
637
 
  if ((all && thd->transaction.all.modified_non_trans_table) ||
638
 
      (!all && thd->transaction.stmt.modified_non_trans_table) ||
639
 
      (thd->options & OPTION_KEEP_LOG))
640
 
  {
641
 
    /*
642
 
      We write the transaction cache with a rollback last if we have
643
 
      modified any non-transactional table. We do this even if we are
644
 
      committing a single statement that has modified a
645
 
      non-transactional table since it can have modified a
646
 
      transactional table in that statement as well, which needs to be
647
 
      rolled back on the slave.
648
 
    */
649
 
    Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), true, false);
650
 
    qev.error_code= 0; // see comment in DRIZZLE_LOG::write(THD, IO_CACHE)
651
 
    error= binlog_end_trans(thd, trx_data, &qev, all);
652
 
  }
653
 
  else if ((all && !thd->transaction.all.modified_non_trans_table) ||
654
 
           (!all && !thd->transaction.stmt.modified_non_trans_table))
655
 
  {
656
 
    /*
657
 
      If we have modified only transactional tables, we can truncate
658
 
      the transaction cache without writing anything to the binary
659
 
      log.
660
 
     */
661
 
    error= binlog_end_trans(thd, trx_data, 0, all);
662
 
  }
 
279
 
 
280
  /* TODO: Fix return type */
 
281
  (void)replicator_end_transaction(session, all, false);
 
282
 
663
283
  return(error);
664
284
}
665
285
 
687
307
  that case there is no need to have it in the binlog).
688
308
*/
689
309
 
690
 
static int binlog_savepoint_set(handlerton *hton __attribute__((unused)),
691
 
                                THD *thd, void *sv)
 
310
static int binlog_savepoint_set(handlerton *, Session *session, void *sv)
692
311
{
693
 
  binlog_trans_log_savepos(thd, (my_off_t*) sv);
 
312
  bool error;
 
313
  binlog_trans_log_savepos(session, (my_off_t*) sv);
694
314
  /* Write it to the binary log */
695
 
  
696
 
  int const error=
697
 
    thd->binlog_query(THD::STMT_QUERY_TYPE,
698
 
                      thd->query, thd->query_length, true, false);
 
315
 
 
316
  error= replicator_statement(session, session->query, session->query_length);
 
317
 
699
318
  return(error);
700
319
}
701
320
 
702
 
static int binlog_savepoint_rollback(handlerton *hton __attribute__((unused)),
703
 
                                     THD *thd, void *sv)
 
321
static int binlog_savepoint_rollback(handlerton *, Session *session, void *)
704
322
{
705
 
  /*
706
 
    Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some
707
 
    non-transactional table. Otherwise, truncate the binlog cache starting
708
 
    from the SAVEPOINT command.
709
 
  */
710
 
  if (unlikely(thd->transaction.all.modified_non_trans_table || 
711
 
               (thd->options & OPTION_KEEP_LOG)))
712
 
  {
713
 
    int error=
714
 
      thd->binlog_query(THD::STMT_QUERY_TYPE,
715
 
                        thd->query, thd->query_length, true, false);
716
 
    return(error);
717
 
  }
718
 
  binlog_trans_log_truncate(thd, *(my_off_t*)sv);
719
 
  return(0);
 
323
  bool error;
 
324
 
 
325
  error= replicator_statement(session, session->query, session->query_length);
 
326
 
 
327
  return error;
720
328
}
721
329
 
722
330
 
746
354
{
747
355
  File file;
748
356
 
749
 
  if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE, 
 
357
  if ((file = my_open(log_file_name, O_RDONLY,
750
358
                      MYF(MY_WME))) < 0)
751
359
  {
752
360
    sql_print_error(_("Failed to open log (file '%s', errno %d)"),
805
413
 
806
414
  if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
807
415
  {                                             // This shouldn't happen
808
 
    my_stpcpy(end,".1");                                // use name+1
 
416
    strcpy(end,".1");                           // use name+1
809
417
    return(0);
810
418
  }
811
419
  file_info= dir_info->dir_entry;
860
468
{
861
469
  char buff[FN_REFLEN];
862
470
  File file= -1;
863
 
  int open_flags= O_CREAT | O_BINARY;
 
471
  int open_flags= O_CREAT;
864
472
 
865
473
  write_error= 0;
866
474
 
867
475
  init(log_type_arg, io_cache_type_arg);
868
476
 
869
 
  if (!(name= my_strdup(log_name, MYF(MY_WME))))
 
477
  if (!(name= strdup(log_name)))
870
478
  {
871
479
    name= (char *)log_name; // for the error message
872
480
    goto err;
873
481
  }
874
482
 
875
483
  if (new_name)
876
 
    my_stpcpy(log_file_name, new_name);
 
484
    strcpy(log_file_name, new_name);
877
485
  else if (generate_new_name(log_file_name, name))
878
486
    goto err;
879
487
 
887
495
  if ((file= my_open(log_file_name, open_flags,
888
496
                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
889
497
      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
890
 
                    my_tell(file, MYF(MY_WME)), 0,
 
498
                    lseek(file, 0, SEEK_CUR), 0,
891
499
                    MYF(MY_WME | MY_NABP |
892
500
                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
893
501
    goto err;
894
502
 
895
503
  if (log_type == LOG_NORMAL)
896
504
  {
897
 
    char *end;
898
 
    int len=snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
899
 
                     "started with:\nTCP Port: %d, Named Pipe: %s\n",
900
 
                     my_progname, server_version, DRIZZLE_COMPILATION_COMMENT,
901
 
                     mysqld_port, ""
902
 
                     );
903
 
    end= my_stpncpy(buff + len, "Time                 Id Command    Argument\n",
904
 
                 sizeof(buff) - len);
905
 
    if (my_b_write(&log_file, (unsigned char*) buff, (uint) (end-buff)) ||
906
 
        flush_io_cache(&log_file))
 
505
    int len= snprintf(buff, sizeof(buff), "%s, Version: %s (%s). "
 
506
                      "started with:\nTCP Port: %d, Named Pipe: %s\n",
 
507
                      my_progname, server_version, COMPILATION_COMMENT,
 
508
                      drizzled_port, "");
 
509
    len+= sprintf(buff+len, "Time                 Id Command    Argument\n");
 
510
 
 
511
    if (my_b_write(&log_file, (unsigned char*) buff, len) ||
 
512
        flush_io_cache(&log_file))
907
513
      goto err;
908
514
  }
909
515
 
1007
613
 
1008
614
int DRIZZLE_LOG::generate_new_name(char *new_name, const char *log_name)
1009
615
{
1010
 
  fn_format(new_name, log_name, mysql_data_home, "", 4);
 
616
  fn_format(new_name, log_name, drizzle_data_home, "", 4);
1011
617
  if (log_type == LOG_BIN)
1012
618
  {
1013
619
    if (!fn_ext(log_name)[0])
1034
640
{
1035
641
  if (!log_name || !log_name[0])
1036
642
  {
1037
 
    strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
 
643
    strncpy(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
1038
644
    return (const char *)
1039
645
      fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR));
1040
646
  }
1042
648
  if (strip_ext)
1043
649
  {
1044
650
    char *p= fn_ext(log_name);
1045
 
    uint32_t length= (uint) (p - log_name);
1046
 
    strmake(buff, log_name, cmin(length, (uint)FN_REFLEN));
 
651
    uint32_t length= cmin((uint32_t)(p - log_name), FN_REFLEN);
 
652
    strncpy(buff, log_name, length);
 
653
    buff[length]= '\0';
1047
654
    return (const char*)buff;
1048
655
  }
1049
656
  return log_name;
1120
727
    index_file_name_arg= log_name;    // Use same basename for index file
1121
728
    opt= MY_UNPACK_FILENAME | MY_REPLACE_EXT;
1122
729
  }
1123
 
  fn_format(index_file_name, index_file_name_arg, mysql_data_home,
 
730
  fn_format(index_file_name, index_file_name_arg, drizzle_data_home,
1124
731
            ".index", opt);
1125
732
  if ((index_file_nr= my_open(index_file_name,
1126
 
                              O_RDWR | O_CREAT | O_BINARY ,
 
733
                              O_RDWR | O_CREAT,
1127
734
                              MYF(MY_WME))) < 0 ||
1128
735
       my_sync(index_file_nr, MYF(MY_WME)) ||
1129
736
       init_io_cache(&index_file, index_file_nr,
1130
737
                     IO_SIZE, WRITE_CACHE,
1131
 
                     my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
 
738
                     lseek(index_file_nr,0,SEEK_END),
1132
739
                        0, MYF(MY_WME | MY_WAIT_IF_FULL)))
1133
740
  {
1134
741
    /*
1305
912
 
1306
913
int DRIZZLE_BIN_LOG::raw_get_current_log(LOG_INFO* linfo)
1307
914
{
1308
 
  strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
 
915
  strncpy(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
1309
916
  linfo->pos = my_b_tell(&log_file);
1310
917
  return 0;
1311
918
}
1336
943
 
1337
944
  for (;; offset+= bytes_read)
1338
945
  {
1339
 
    (void) my_seek(file, offset, MY_SEEK_SET, MYF(0));
 
946
    (void) lseek(file, offset, SEEK_SET);
1340
947
    if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME)))
1341
948
        < 0)
1342
949
      goto err;
1343
950
    if (!bytes_read)
1344
951
      break;                                    // end of file
1345
 
    (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
 
952
    (void) lseek(file, offset-init_offset, SEEK_SET);
1346
953
    if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
1347
954
      goto err;
1348
955
  }
1489
1096
 
1490
1097
  The new index file will only contain this file.
1491
1098
 
1492
 
  @param thd            Thread
 
1099
  @param session                Thread
1493
1100
 
1494
1101
  @note
1495
1102
    If not called from slave thread, write start event to new log
1500
1107
    1   error
1501
1108
*/
1502
1109
 
1503
 
bool DRIZZLE_BIN_LOG::reset_logs(THD* thd)
 
1110
bool DRIZZLE_BIN_LOG::reset_logs(Session* session)
1504
1111
{
1505
1112
  LOG_INFO linfo;
1506
1113
  bool error=0;
1515
1122
 
1516
1123
  /*
1517
1124
    The following mutex is needed to ensure that no threads call
1518
 
    'delete thd' as we would then risk missing a 'rollback' from this
 
1125
    'delete session' as we would then risk missing a 'rollback' from this
1519
1126
    thread. If the transaction involved MyISAM tables, it should go
1520
1127
    into binlog even on rollback.
1521
1128
  */
1538
1145
  {
1539
1146
    if ((error= my_delete_allow_opened(linfo.log_file_name, MYF(0))) != 0)
1540
1147
    {
1541
 
      if (my_errno == ENOENT) 
 
1148
      if (my_errno == ENOENT)
1542
1149
      {
1543
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1150
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1544
1151
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1545
1152
                            linfo.log_file_name);
1546
1153
        sql_print_information(_("Failed to delete file '%s'"),
1550
1157
      }
1551
1158
      else
1552
1159
      {
1553
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1160
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1554
1161
                            ER_BINLOG_PURGE_FATAL_ERR,
1555
1162
                            _("a problem with deleting %s; "
1556
1163
                            "consider examining correspondence "
1569
1176
  close(LOG_CLOSE_INDEX);
1570
1177
  if ((error= my_delete_allow_opened(index_file_name, MYF(0)))) // Reset (open will update)
1571
1178
  {
1572
 
    if (my_errno == ENOENT) 
 
1179
    if (my_errno == ENOENT)
1573
1180
    {
1574
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1181
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1575
1182
                          ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1576
1183
                          index_file_name);
1577
1184
      sql_print_information(_("Failed to delete file '%s'"),
1581
1188
    }
1582
1189
    else
1583
1190
    {
1584
 
      push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1191
      push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1585
1192
                          ER_BINLOG_PURGE_FATAL_ERR,
1586
1193
                          "a problem with deleting %s; "
1587
1194
                          "consider examining correspondence "
1592
1199
      goto err;
1593
1200
    }
1594
1201
  }
1595
 
  if (!thd->slave_thread)
 
1202
  if (!session->slave_thread)
1596
1203
    need_start_event=1;
1597
1204
  if (!open_index_file(index_file_name, 0))
1598
1205
    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0);
1650
1257
 
1651
1258
  assert(is_open());
1652
1259
  assert(rli->slave_running == 1);
1653
 
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
 
1260
  assert(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name.c_str()));
1654
1261
 
1655
1262
  pthread_mutex_lock(&LOCK_index);
1656
1263
  pthread_mutex_lock(&rli->log_space_lock);
1657
 
  rli->relay_log.purge_logs(rli->group_relay_log_name, included,
 
1264
  rli->relay_log.purge_logs(rli->group_relay_log_name.c_str(), included,
1658
1265
                            0, 0, &rli->log_space_total);
1659
1266
  // Tell the I/O thread to take the relay_log_space_limit into account
1660
1267
  rli->ignore_log_space_limit= 0;
1666
1273
    context switches
1667
1274
  */
1668
1275
  pthread_cond_broadcast(&rli->log_space_cond);
1669
 
  
 
1276
 
1670
1277
  /*
1671
1278
    Read the next log file name from the index file and pass it back to
1672
1279
    the caller
1675
1282
  */
1676
1283
  if ((included && (error=find_log_pos(&rli->linfo, NULL, 0))) ||
1677
1284
      (!included &&
1678
 
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
 
1285
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name.c_str(), 0)) ||
1679
1286
        (error=find_next_log(&rli->linfo, 0)))))
1680
1287
  {
1681
1288
    char buff[22];
1682
1289
    sql_print_error(_("next log error: %d  offset: %s  log: %s included: %d"),
1683
1290
                    error,
1684
1291
                    llstr(rli->linfo.index_file_offset,buff),
1685
 
                    rli->group_relay_log_name,
 
1292
                    rli->group_relay_log_name.c_str(),
1686
1293
                    included);
1687
1294
    goto err;
1688
1295
  }
1691
1298
    Reset rli's coordinates to the current log.
1692
1299
  */
1693
1300
  rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE;
1694
 
  strmake(rli->event_relay_log_name,rli->linfo.log_file_name,
1695
 
          sizeof(rli->event_relay_log_name)-1);
 
1301
  rli->event_relay_log_name.assign(rli->linfo.log_file_name);
1696
1302
 
1697
1303
  /*
1698
1304
    If we removed the rli->group_relay_log_name file,
1702
1308
  if (included)
1703
1309
  {
1704
1310
    rli->group_relay_log_pos = BIN_LOG_HEADER_SIZE;
1705
 
    strmake(rli->group_relay_log_name,rli->linfo.log_file_name,
1706
 
            sizeof(rli->group_relay_log_name)-1);
 
1311
    rli->group_relay_log_name.assign(rli->linfo.log_file_name);
1707
1312
    rli->notify_group_relay_log_name_update();
1708
1313
  }
1709
1314
 
1754
1359
                                stat() or my_delete()
1755
1360
*/
1756
1361
 
1757
 
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log, 
 
1362
int DRIZZLE_BIN_LOG::purge_logs(const char *to_log,
1758
1363
                          bool included,
1759
 
                          bool need_mutex, 
1760
 
                          bool need_update_threads, 
 
1364
                          bool need_mutex,
 
1365
                          bool need_update_threads,
1761
1366
                          uint64_t *decrease_log_space)
1762
1367
{
1763
1368
  int error;
1782
1387
    struct stat s;
1783
1388
    if (stat(log_info.log_file_name, &s))
1784
1389
    {
1785
 
      if (errno == ENOENT) 
 
1390
      if (errno == ENOENT)
1786
1391
      {
1787
1392
        /*
1788
1393
          It's not fatal if we can't stat a log file that does not exist;
1789
1394
          If we could not stat, we won't delete.
1790
 
        */     
1791
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1395
        */
 
1396
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1792
1397
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1793
1398
                            log_info.log_file_name);
1794
1399
        sql_print_information(_("Failed to execute stat() on file '%s'"),
1800
1405
        /*
1801
1406
          Other than ENOENT are fatal
1802
1407
        */
1803
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1408
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1804
1409
                            ER_BINLOG_PURGE_FATAL_ERR,
1805
1410
                            _("a problem with getting info on being purged %s; "
1806
1411
                            "consider examining correspondence "
1820
1425
      }
1821
1426
      else
1822
1427
      {
1823
 
        if (my_errno == ENOENT) 
 
1428
        if (my_errno == ENOENT)
1824
1429
        {
1825
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1430
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1826
1431
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1827
1432
                              log_info.log_file_name);
1828
1433
          sql_print_information(_("Failed to delete file '%s'"),
1831
1436
        }
1832
1437
        else
1833
1438
        {
1834
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1439
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1835
1440
                              ER_BINLOG_PURGE_FATAL_ERR,
1836
1441
                              _("a problem with deleting %s; "
1837
1442
                              "consider examining correspondence "
1851
1456
    if (find_next_log(&log_info, 0) || exit_loop)
1852
1457
      break;
1853
1458
  }
1854
 
  
 
1459
 
1855
1460
  /*
1856
1461
    If we get killed -9 here, the sysadmin would have to edit
1857
1462
    the log index file after restart - otherwise, this should be safe
1871
1476
  Remove all logs before the given file date from disk and from the
1872
1477
  index file.
1873
1478
 
1874
 
  @param thd            Thread pointer
 
1479
  @param session                Thread pointer
1875
1480
  @param before_date    Delete all log files before given date.
1876
1481
 
1877
1482
  @note
1907
1512
  {
1908
1513
    if (stat(log_info.log_file_name, &stat_area))
1909
1514
    {
1910
 
      if (errno == ENOENT) 
 
1515
      if (errno == ENOENT)
1911
1516
      {
1912
1517
        /*
1913
1518
          It's not fatal if we can't stat a log file that does not exist.
1914
 
        */     
1915
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1519
        */
 
1520
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1916
1521
                            ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1917
1522
                            log_info.log_file_name);
1918
1523
        sql_print_information(_("Failed to execute stat() on file '%s'"),
1924
1529
        /*
1925
1530
          Other than ENOENT are fatal
1926
1531
        */
1927
 
        push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1532
        push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1928
1533
                            ER_BINLOG_PURGE_FATAL_ERR,
1929
1534
                            _("a problem with getting info on being purged %s; "
1930
1535
                            "consider examining correspondence "
1941
1546
        break;
1942
1547
      if (my_delete(log_info.log_file_name, MYF(0)))
1943
1548
      {
1944
 
        if (my_errno == ENOENT) 
 
1549
        if (my_errno == ENOENT)
1945
1550
        {
1946
1551
          /* It's not fatal even if we can't delete a log file */
1947
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1552
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1948
1553
                              ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
1949
1554
                              log_info.log_file_name);
1950
1555
          sql_print_information(_("Failed to delete file '%s'"),
1953
1558
        }
1954
1559
        else
1955
1560
        {
1956
 
          push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1561
          push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1957
1562
                              ER_BINLOG_PURGE_FATAL_ERR,
1958
1563
                              _("a problem with deleting %s; "
1959
1564
                              "consider examining correspondence "
1992
1597
 
1993
1598
void DRIZZLE_BIN_LOG::make_log_name(char* buf, const char* log_ident)
1994
1599
{
1995
 
  uint32_t dir_len = dirname_length(log_file_name); 
 
1600
  uint32_t dir_len = dirname_length(log_file_name);
1996
1601
  if (dir_len >= FN_REFLEN)
1997
1602
    dir_len=FN_REFLEN-1;
1998
 
  my_stpncpy(buf, log_file_name, dir_len);
1999
 
  strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
 
1603
  strncpy(buf, log_file_name, dir_len);
 
1604
  strncpy(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
2000
1605
}
2001
1606
 
2002
1607
 
2204
1809
  return err;
2205
1810
}
2206
1811
 
2207
 
void DRIZZLE_BIN_LOG::start_union_events(THD *thd, query_id_t query_id_param)
2208
 
{
2209
 
  assert(!thd->binlog_evt_union.do_union);
2210
 
  thd->binlog_evt_union.do_union= true;
2211
 
  thd->binlog_evt_union.unioned_events= false;
2212
 
  thd->binlog_evt_union.unioned_events_trans= false;
2213
 
  thd->binlog_evt_union.first_query_id= query_id_param;
2214
 
}
2215
 
 
2216
 
void DRIZZLE_BIN_LOG::stop_union_events(THD *thd)
2217
 
{
2218
 
  assert(thd->binlog_evt_union.do_union);
2219
 
  thd->binlog_evt_union.do_union= false;
2220
 
}
2221
 
 
2222
 
bool DRIZZLE_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
2223
 
{
2224
 
  return (thd->binlog_evt_union.do_union && 
2225
 
          query_id_param >= thd->binlog_evt_union.first_query_id);
2226
 
}
2227
 
 
2228
 
 
2229
 
/*
2230
 
  These functions are placed in this file since they need access to
2231
 
  binlog_hton, which has internal linkage.
2232
 
*/
2233
 
 
2234
 
int THD::binlog_setup_trx_data()
2235
 
{
2236
 
  binlog_trx_data *trx_data=
2237
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2238
 
 
2239
 
  if (trx_data)
2240
 
    return(0);                             // Already set up
2241
 
 
2242
 
  trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
2243
 
  if (!trx_data ||
2244
 
      open_cached_file(&trx_data->trans_log, mysql_tmpdir,
2245
 
                       LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
2246
 
  {
2247
 
    free((unsigned char*)trx_data);
2248
 
    return(1);                      // Didn't manage to set it up
2249
 
  }
2250
 
  thd_set_ha_data(this, binlog_hton, trx_data);
2251
 
 
2252
 
  trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data;
2253
 
 
2254
 
  return(0);
2255
 
}
2256
 
 
2257
 
/*
2258
 
  Function to start a statement and optionally a transaction for the
2259
 
  binary log.
2260
 
 
2261
 
  SYNOPSIS
2262
 
    binlog_start_trans_and_stmt()
2263
 
 
2264
 
  DESCRIPTION
2265
 
 
2266
 
    This function does three things:
2267
 
    - Start a transaction if not in autocommit mode or if a BEGIN
2268
 
      statement has been seen.
2269
 
 
2270
 
    - Start a statement transaction to allow us to truncate the binary
2271
 
      log.
2272
 
 
2273
 
    - Save the currrent binlog position so that we can roll back the
2274
 
      statement by truncating the transaction log.
2275
 
 
2276
 
      We only update the saved position if the old one was undefined,
2277
 
      the reason is that there are some cases (e.g., for CREATE-SELECT)
2278
 
      where the position is saved twice (e.g., both in
2279
 
      select_create::prepare() and THD::binlog_write_table_map()) , but
2280
 
      we should use the first. This means that calls to this function
2281
 
      can be used to start the statement before the first table map
2282
 
      event, to include some extra events.
2283
 
 */
2284
 
 
2285
 
void
2286
 
THD::binlog_start_trans_and_stmt()
2287
 
{
2288
 
  binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2289
 
 
2290
 
  if (trx_data == NULL ||
2291
 
      trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
2292
 
  {
2293
 
    this->binlog_set_stmt_begin();
2294
 
    if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2295
 
      trans_register_ha(this, true, binlog_hton);
2296
 
    trans_register_ha(this, false, binlog_hton);
2297
 
    /*
2298
 
      Mark statement transaction as read/write. We never start
2299
 
      a binary log transaction and keep it read-only,
2300
 
      therefore it's best to mark the transaction read/write just
2301
 
      at the same time we start it.
2302
 
      Not necessary to mark the normal transaction read/write
2303
 
      since the statement-level flag will be propagated automatically
2304
 
      inside ha_commit_trans.
2305
 
    */
2306
 
    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
2307
 
  }
2308
 
  return;
2309
 
}
2310
 
 
2311
 
void THD::binlog_set_stmt_begin() {
2312
 
  binlog_trx_data *trx_data=
2313
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2314
 
 
2315
 
  /*
2316
 
    The call to binlog_trans_log_savepos() might create the trx_data
2317
 
    structure, if it didn't exist before, so we save the position
2318
 
    into an auto variable and then write it into the transaction
2319
 
    data for the binary log (i.e., trx_data).
2320
 
  */
2321
 
  my_off_t pos= 0;
2322
 
  binlog_trans_log_savepos(this, &pos);
2323
 
  trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2324
 
  trx_data->before_stmt_pos= pos;
2325
 
}
2326
 
 
2327
 
 
2328
 
/*
2329
 
  Write a table map to the binary log.
2330
 
 */
2331
 
 
2332
 
int THD::binlog_write_table_map(Table *table, bool is_trans)
2333
 
{
2334
 
  int error;
2335
 
 
2336
 
  /* Pre-conditions */
2337
 
  assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2338
 
  assert(table->s->table_map_id != UINT32_MAX);
2339
 
 
2340
 
  Table_map_log_event::flag_set const
2341
 
    flags= Table_map_log_event::TM_NO_FLAGS;
2342
 
 
2343
 
  Table_map_log_event
2344
 
    the_event(this, table, table->s->table_map_id, is_trans, flags);
2345
 
 
2346
 
  if (is_trans && binlog_table_maps == 0)
2347
 
    binlog_start_trans_and_stmt();
2348
 
 
2349
 
  if ((error= mysql_bin_log.write(&the_event)))
2350
 
    return(error);
2351
 
 
2352
 
  binlog_table_maps++;
2353
 
  table->s->table_map_version= mysql_bin_log.table_map_version();
2354
 
  return(0);
2355
 
}
2356
 
 
2357
 
Rows_log_event*
2358
 
THD::binlog_get_pending_rows_event() const
2359
 
{
2360
 
  binlog_trx_data *const trx_data=
2361
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2362
 
  /*
2363
 
    This is less than ideal, but here's the story: If there is no
2364
 
    trx_data, prepare_pending_rows_event() has never been called
2365
 
    (since the trx_data is set up there). In that case, we just return
2366
 
    NULL.
2367
 
   */
2368
 
  return trx_data ? trx_data->pending() : NULL;
2369
 
}
2370
 
 
2371
 
void
2372
 
THD::binlog_set_pending_rows_event(Rows_log_event* ev)
2373
 
{
2374
 
  if (thd_get_ha_data(this, binlog_hton) == NULL)
2375
 
    binlog_setup_trx_data();
2376
 
 
2377
 
  binlog_trx_data *const trx_data=
2378
 
    (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
2379
 
 
2380
 
  assert(trx_data);
2381
 
  trx_data->set_pending(ev);
2382
 
}
2383
 
 
 
1812
void DRIZZLE_BIN_LOG::start_union_events(Session *session, query_id_t query_id_param)
 
1813
{
 
1814
  assert(!session->binlog_evt_union.do_union);
 
1815
  session->binlog_evt_union.do_union= true;
 
1816
  session->binlog_evt_union.unioned_events= false;
 
1817
  session->binlog_evt_union.unioned_events_trans= false;
 
1818
  session->binlog_evt_union.first_query_id= query_id_param;
 
1819
}
 
1820
 
 
1821
void DRIZZLE_BIN_LOG::stop_union_events(Session *session)
 
1822
{
 
1823
  assert(session->binlog_evt_union.do_union);
 
1824
  session->binlog_evt_union.do_union= false;
 
1825
}
 
1826
 
 
1827
bool DRIZZLE_BIN_LOG::is_query_in_union(Session *session, query_id_t query_id_param)
 
1828
{
 
1829
  return (session->binlog_evt_union.do_union &&
 
1830
          query_id_param >= session->binlog_evt_union.first_query_id);
 
1831
}
2384
1832
 
2385
1833
/*
2386
1834
  Moves the last bunch of rows from the pending Rows event to the binlog
2388
1836
  event.
2389
1837
*/
2390
1838
int
2391
 
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
2392
 
                                                Rows_log_event* event)
 
1839
DRIZZLE_BIN_LOG::flush_and_set_pending_rows_event(Session *, Rows_log_event*)
2393
1840
{
2394
 
  assert(mysql_bin_log.is_open());
2395
 
 
2396
 
  int error= 0;
2397
 
 
2398
 
  binlog_trx_data *const trx_data=
2399
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
2400
 
 
2401
 
  assert(trx_data);
2402
 
 
2403
 
  if (Rows_log_event* pending= trx_data->pending())
2404
 
  {
2405
 
    IO_CACHE *file= &log_file;
2406
 
 
2407
 
    /*
2408
 
      Decide if we should write to the log file directly or to the
2409
 
      transaction log.
2410
 
    */
2411
 
    if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log))
2412
 
      file= &trx_data->trans_log;
2413
 
 
2414
 
    /*
2415
 
      If we are writing to the log file directly, we could avoid
2416
 
      locking the log. This does not work since we need to step the
2417
 
      m_table_map_version below, and that change has to be protected
2418
 
      by the LOCK_log mutex.
2419
 
    */
2420
 
    pthread_mutex_lock(&LOCK_log);
2421
 
 
2422
 
    /*
2423
 
      Write pending event to log file or transaction cache
2424
 
    */
2425
 
    if (pending->write(file))
2426
 
    {
2427
 
      pthread_mutex_unlock(&LOCK_log);
2428
 
      return(1);
2429
 
    }
2430
 
 
2431
 
    /*
2432
 
      We step the table map version if we are writing an event
2433
 
      representing the end of a statement.  We do this regardless of
2434
 
      wheather we write to the transaction cache or to directly to the
2435
 
      file.
2436
 
 
2437
 
      In an ideal world, we could avoid stepping the table map version
2438
 
      if we were writing to a transaction cache, since we could then
2439
 
      reuse the table map that was written earlier in the transaction
2440
 
      cache.  This does not work since STMT_END_F implies closing all
2441
 
      table mappings on the slave side.
2442
 
 
2443
 
      TODO: Find a solution so that table maps does not have to be
2444
 
      written several times within a transaction.
2445
 
     */
2446
 
    if (pending->get_flags(Rows_log_event::STMT_END_F))
2447
 
      ++m_table_map_version;
2448
 
 
2449
 
    delete pending;
2450
 
 
2451
 
    if (file == &log_file)
2452
 
    {
2453
 
      error= flush_and_sync();
2454
 
      if (!error)
2455
 
      {
2456
 
        signal_update();
2457
 
        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
2458
 
      }
2459
 
    }
2460
 
 
2461
 
    pthread_mutex_unlock(&LOCK_log);
2462
 
  }
2463
 
 
2464
 
  thd->binlog_set_pending_rows_event(event);
2465
 
 
2466
 
  return(error);
 
1841
  assert(drizzle_bin_log.is_open());
 
1842
 
 
1843
  return false;
2467
1844
}
2468
1845
 
2469
1846
/**
2472
1849
 
2473
1850
bool DRIZZLE_BIN_LOG::write(Log_event *event_info)
2474
1851
{
2475
 
  THD *thd= event_info->thd;
 
1852
  Session *session= event_info->session;
2476
1853
  bool error= 1;
2477
1854
 
2478
 
  if (thd->binlog_evt_union.do_union)
 
1855
  if (session->binlog_evt_union.do_union)
2479
1856
  {
2480
1857
    /*
2481
1858
      In Stored function; Remember that function call caused an update.
2482
1859
      We will log the function call to the binary log on function exit
2483
1860
    */
2484
 
    thd->binlog_evt_union.unioned_events= true;
2485
 
    thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
 
1861
    session->binlog_evt_union.unioned_events= true;
 
1862
    session->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
2486
1863
    return(0);
2487
1864
  }
2488
1865
 
2496
1873
    we are inside a stored function, we do not end the statement since
2497
1874
    this will close all tables on the slave.
2498
1875
  */
2499
 
  bool const end_stmt= false;
2500
 
  thd->binlog_flush_pending_rows_event(end_stmt);
2501
1876
 
2502
1877
  pthread_mutex_lock(&LOCK_log);
2503
1878
 
2514
1889
      "do the involved tables match (to be implemented)
2515
1890
      binlog_[wild_]{do|ignore}_table?" (WL#1049)"
2516
1891
    */
2517
 
    const char *local_db= event_info->get_db();
2518
 
    if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
2519
 
        (!binlog_filter->db_ok(local_db)))
 
1892
    if (session && !(session->options & OPTION_BIN_LOG))
2520
1893
    {
2521
1894
      pthread_mutex_unlock(&LOCK_log);
2522
1895
      return(0);
2523
1896
    }
2524
1897
 
2525
1898
    /*
2526
 
      Should we write to the binlog cache or to the binlog on disk?
2527
 
      Write to the binlog cache if:
2528
 
      - it is already not empty (meaning we're in a transaction; note that the
2529
 
     present event could be about a non-transactional table, but still we need
2530
 
     to write to the binlog cache in that case to handle updates to mixed
2531
 
     trans/non-trans table types the best possible in binlogging)
2532
 
      - or if the event asks for it (cache_stmt == TRUE).
2533
 
    */
2534
 
    if (opt_using_transactions && thd)
2535
 
    {
2536
 
      if (thd->binlog_setup_trx_data())
2537
 
        goto err;
2538
 
 
2539
 
      binlog_trx_data *const trx_data=
2540
 
        (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
2541
 
      IO_CACHE *trans_log= &trx_data->trans_log;
2542
 
      my_off_t trans_log_pos= my_b_tell(trans_log);
2543
 
      if (event_info->get_cache_stmt() || trans_log_pos != 0)
2544
 
      {
2545
 
        if (trans_log_pos == 0)
2546
 
          thd->binlog_start_trans_and_stmt();
2547
 
        file= trans_log;
2548
 
      }
2549
 
      /*
2550
 
        TODO as Mats suggested, for all the cases above where we write to
2551
 
        trans_log, it sounds unnecessary to lock LOCK_log. We should rather
2552
 
        test first if we want to write to trans_log, and if not, lock
2553
 
        LOCK_log.
2554
 
      */
2555
 
    }
2556
 
 
2557
 
    /*
2558
 
      No check for auto events flag here - this write method should
2559
 
      never be called if auto-events are enabled
2560
 
    */
2561
 
 
2562
 
    /*
2563
 
      1. Write first log events which describe the 'run environment'
2564
 
      of the SQL command
2565
 
    */
2566
 
 
2567
 
    /*
2568
 
      If row-based binlogging, Insert_id, Rand and other kind of "setting
2569
 
      context" events are not needed.
2570
 
    */
2571
 
    if (thd)
2572
 
    {
2573
 
      if (!thd->current_stmt_binlog_row_based)
2574
 
      {
2575
 
        if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
2576
 
        {
2577
 
          Intvar_log_event e(thd,(unsigned char) LAST_INSERT_ID_EVENT,
2578
 
                             thd->first_successful_insert_id_in_prev_stmt_for_binlog);
2579
 
          if (e.write(file))
2580
 
            goto err;
2581
 
        }
2582
 
        if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
2583
 
        {
2584
 
          /*
2585
 
            If the auto_increment was second in a table's index (possible with
2586
 
            MyISAM or BDB) (table->next_number_keypart != 0), such event is
2587
 
            in fact not necessary. We could avoid logging it.
2588
 
          */
2589
 
          Intvar_log_event e(thd, (unsigned char) INSERT_ID_EVENT,
2590
 
                             thd->auto_inc_intervals_in_cur_stmt_for_binlog.
2591
 
                             minimum());
2592
 
          if (e.write(file))
2593
 
            goto err;
2594
 
        }
2595
 
        if (thd->rand_used)
2596
 
        {
2597
 
          Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
2598
 
          if (e.write(file))
2599
 
            goto err;
2600
 
        }
2601
 
        if (thd->user_var_events.elements)
2602
 
        {
2603
 
          for (uint32_t i= 0; i < thd->user_var_events.elements; i++)
2604
 
          {
2605
 
            BINLOG_USER_VAR_EVENT *user_var_event;
2606
 
            get_dynamic(&thd->user_var_events,(unsigned char*) &user_var_event, i);
2607
 
            User_var_log_event e(thd, user_var_event->user_var_event->name.str,
2608
 
                                 user_var_event->user_var_event->name.length,
2609
 
                                 user_var_event->value,
2610
 
                                 user_var_event->length,
2611
 
                                 user_var_event->type,
2612
 
                                 user_var_event->charset_number);
2613
 
            if (e.write(file))
2614
 
              goto err;
2615
 
          }
2616
 
        }
2617
 
      }
2618
 
    }
2619
 
 
2620
 
    /*
2621
1899
       Write the SQL command
2622
1900
     */
2623
1901
 
2651
1929
  return(error);
2652
1930
}
2653
1931
 
2654
 
 
2655
 
int error_log_print(enum loglevel level, const char *format,
2656
 
                    va_list args)
2657
 
{
2658
 
  return logger.error_log_print(level, format, args);
2659
 
}
2660
 
 
2661
1932
void DRIZZLE_BIN_LOG::rotate_and_purge(uint32_t flags)
2662
1933
{
2663
1934
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
2668
1939
    new_file_without_locking();
2669
1940
    if (expire_logs_days)
2670
1941
    {
2671
 
      time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
 
1942
      time_t purge_time= time(0) - expire_logs_days*24*60*60;
2672
1943
      if (purge_time >= 0)
2673
1944
        purge_logs_before_date(purge_time);
2674
1945
    }
2836
2107
  was updated in a transaction which was rolled back. This is to ensure
2837
2108
  that the same updates are run on the slave.
2838
2109
 
2839
 
  @param thd
 
2110
  @param session
2840
2111
  @param cache          The cache to copy to the binlog
2841
2112
  @param commit_event   The commit event to print after writing the
2842
2113
                        contents of the cache.
2849
2120
    'cache' needs to be reinitialized after this functions returns.
2850
2121
*/
2851
2122
 
2852
 
bool DRIZZLE_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
 
2123
bool DRIZZLE_BIN_LOG::write(Session *session, IO_CACHE *cache, Log_event *commit_event)
2853
2124
{
2854
2125
  pthread_mutex_lock(&LOCK_log);
2855
2126
 
2870
2141
        transaction is either a BEGIN..COMMIT block or a single
2871
2142
        statement in autocommit mode.
2872
2143
      */
2873
 
      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), true, false);
 
2144
      Query_log_event qinfo(session, STRING_WITH_LEN("BEGIN"), true, false);
2874
2145
      /*
2875
2146
        Imagine this is rollback due to net timeout, after all
2876
2147
        statements of the transaction succeeded. Then we want a
2880
2151
        generated event, and as this event is generated late it would
2881
2152
        lead to false alarms.
2882
2153
 
2883
 
        This is safer than thd->clear_error() against kills at shutdown.
 
2154
        This is safer than session->clear_error() against kills at shutdown.
2884
2155
      */
2885
2156
      qinfo.error_code= 0;
2886
2157
      /*
2945
2216
/**
2946
2217
  Wait until we get a signal that the relay log has been updated
2947
2218
 
2948
 
  @param[in] thd   a THD struct
 
2219
  @param[in] session   a Session struct
2949
2220
  @note
2950
2221
    LOCK_log must be taken before calling this function.
2951
2222
    It will be released at the end of the function.
2952
2223
*/
2953
2224
 
2954
 
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(THD* thd)
 
2225
void DRIZZLE_BIN_LOG::wait_for_update_relay_log(Session* session)
2955
2226
{
2956
2227
  const char *old_msg;
2957
 
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
2958
 
                           "Slave has read all relay log; " 
 
2228
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
 
2229
                           "Slave has read all relay log; "
2959
2230
                           "waiting for the slave I/O "
2960
2231
                           "thread to update it" );
2961
2232
  pthread_cond_wait(&update_cond, &LOCK_log);
2962
 
  thd->exit_cond(old_msg);
 
2233
  session->exit_cond(old_msg);
2963
2234
  return;
2964
2235
}
2965
2236
 
2967
2238
/**
2968
2239
  Wait until we get a signal that the binary log has been updated.
2969
2240
  Applies to master only.
2970
 
     
 
2241
 
2971
2242
  NOTES
2972
 
  @param[in] thd        a THD struct
 
2243
  @param[in] session        a Session struct
2973
2244
  @param[in] timeout    a pointer to a timespec;
2974
2245
                        NULL means to wait w/o timeout.
2975
2246
  @retval    0          if got signalled on update
2980
2251
    LOCK_log is released by the caller.
2981
2252
*/
2982
2253
 
2983
 
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(THD* thd,
 
2254
int DRIZZLE_BIN_LOG::wait_for_update_bin_log(Session* session,
2984
2255
                                           const struct timespec *timeout)
2985
2256
{
2986
2257
  int ret= 0;
2987
 
  const char* old_msg = thd->get_proc_info();
2988
 
  old_msg= thd->enter_cond(&update_cond, &LOCK_log,
 
2258
  const char* old_msg = session->get_proc_info();
 
2259
  old_msg= session->enter_cond(&update_cond, &LOCK_log,
2989
2260
                           "Master has sent all binlog to slave; "
2990
2261
                           "waiting for binlog to be updated");
2991
2262
  if (!timeout)
3029
2300
    {
3030
2301
      my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
3031
2302
      unsigned char flags= 0;            // clearing LOG_EVENT_BINLOG_IN_USE_F
3032
 
      pwrite(log_file.file, &flags, 1, offset);
 
2303
      assert(pwrite(log_file.file, &flags, 1, offset)==1);
3033
2304
    }
3034
2305
 
3035
2306
    /* this will cleanup IO_CACHE, sync and close the file */
3100
2371
  register int flag;
3101
2372
  const char *start;
3102
2373
 
3103
 
  flag= 0; 
 
2374
  flag= 0;
3104
2375
  start= str;
3105
2376
  while (*str++ == ' ') ;
3106
2377
  if (*--str == '-' || *str == '+')
3134
2405
 
3135
2406
bool flush_error_log()
3136
2407
{
3137
 
  bool result=0;
 
2408
  bool result = 0;
3138
2409
  if (opt_error_log)
3139
2410
  {
3140
 
    char err_renamed[FN_REFLEN], *end;
3141
 
    end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
3142
 
    my_stpcpy(end, "-old");
3143
2411
    pthread_mutex_lock(&LOCK_error_log);
3144
 
    char err_temp[FN_REFLEN+4];
3145
 
    /*
3146
 
     On Windows is necessary a temporary file for to rename
3147
 
     the current error file.
3148
 
    */
3149
 
    strxmov(err_temp, err_renamed,"-tmp",NULL);
3150
 
    (void) my_delete(err_temp, MYF(0)); 
3151
 
    if (freopen(err_temp,"a+",stdout))
3152
 
    {
3153
 
      int fd;
3154
 
      size_t bytes;
3155
 
      unsigned char buf[IO_SIZE];
3156
 
 
3157
 
      freopen(err_temp,"a+",stderr);
3158
 
      (void) my_delete(err_renamed, MYF(0));
3159
 
      my_rename(log_error_file,err_renamed,MYF(0));
3160
 
      if (freopen(log_error_file,"a+",stdout))
3161
 
        freopen(log_error_file,"a+",stderr);
3162
 
 
3163
 
      if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
3164
 
      {
3165
 
        while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
3166
 
               bytes != MY_FILE_ERROR)
3167
 
          my_fwrite(stderr, buf, bytes, MYF(0));
3168
 
        my_close(fd, MYF(0));
3169
 
      }
3170
 
      (void) my_delete(err_temp, MYF(0)); 
3171
 
    }
3172
 
    else
3173
 
     result= 1;
 
2412
    if (freopen(log_error_file,"a+",stdout)==NULL)
 
2413
      result = 1;
 
2414
    if (freopen(log_error_file,"a+",stderr)==NULL)
 
2415
      result = 1;
3174
2416
    pthread_mutex_unlock(&LOCK_error_log);
3175
2417
  }
3176
2418
   return result;
3182
2424
  return;
3183
2425
}
3184
2426
 
3185
 
/**
3186
 
  Prints a printf style message to the error log and, under NT, to the
3187
 
  Windows event log.
3188
 
 
3189
 
  This function prints the message into a buffer and then sends that buffer
3190
 
  to other functions to write that message to other logging sources.
3191
 
 
3192
 
  @param event_type          Type of event to write (Error, Warning, or Info)
3193
 
  @param format              Printf style format of message
3194
 
  @param args                va_list list of arguments for the message
3195
 
 
3196
 
  @returns
3197
 
    The function always returns 0. The return value is present in the
3198
 
    signature to be compatible with other logging routines, which could
3199
 
    return an error (e.g. logging to the log tables)
3200
 
*/
3201
 
static void print_buffer_to_file(enum loglevel level,
3202
 
                                 int error_code __attribute__((unused)),
3203
 
                                 const char *buffer,
3204
 
                                 size_t buffer_length __attribute__((unused)))
3205
 
{
3206
 
  time_t skr;
3207
 
  struct tm tm_tmp;
3208
 
  struct tm *start;
3209
 
 
3210
 
  pthread_mutex_lock(&LOCK_error_log);
3211
 
 
3212
 
  skr= my_time(0);
3213
 
  localtime_r(&skr, &tm_tmp);
3214
 
  start=&tm_tmp;
3215
 
 
3216
 
  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
3217
 
          start->tm_year % 100,
3218
 
          start->tm_mon+1,
3219
 
          start->tm_mday,
3220
 
          start->tm_hour,
3221
 
          start->tm_min,
3222
 
          start->tm_sec,
3223
 
          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
3224
 
           "Warning" : "Note"),
3225
 
          buffer);
3226
 
 
3227
 
  fflush(stderr);
3228
 
 
3229
 
  pthread_mutex_unlock(&LOCK_error_log);
3230
 
  return;
3231
 
}
3232
 
 
3233
 
 
3234
 
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
3235
 
{
3236
 
  char   buff[1024];
3237
 
  size_t length;
3238
 
  int error_code= errno;
3239
 
 
3240
 
  length= vsnprintf(buff, sizeof(buff), format, args);
3241
 
 
3242
 
  print_buffer_to_file(level, error_code, buff, length);
3243
 
 
3244
 
  return(0);
3245
 
}
3246
 
 
3247
 
 
3248
 
void sql_print_error(const char *format, ...) 
3249
 
{
3250
 
  va_list args;
3251
 
 
3252
 
  va_start(args, format);
3253
 
  error_log_print(ERROR_LEVEL, format, args);
3254
 
  va_end(args);
3255
 
 
3256
 
  return;
3257
 
}
3258
 
 
3259
 
 
3260
 
void sql_print_warning(const char *format, ...) 
3261
 
{
3262
 
  va_list args;
3263
 
 
3264
 
  va_start(args, format);
3265
 
  error_log_print(WARNING_LEVEL, format, args);
3266
 
  va_end(args);
3267
 
 
3268
 
  return;
3269
 
}
3270
 
 
3271
 
 
3272
 
void sql_print_information(const char *format, ...) 
3273
 
{
3274
 
  va_list args;
3275
 
 
3276
 
  va_start(args, format);
3277
 
  error_log_print(INFORMATION_LEVEL, format, args);
 
2427
void sql_print_error(const char *format, ...)
 
2428
{
 
2429
  va_list args;
 
2430
 
 
2431
  va_start(args, format);
 
2432
  errmsg_vprintf (current_session, ERROR_LEVEL, format, args);
 
2433
  va_end(args);
 
2434
 
 
2435
  return;
 
2436
}
 
2437
 
 
2438
 
 
2439
void sql_print_warning(const char *format, ...)
 
2440
{
 
2441
  va_list args;
 
2442
 
 
2443
  va_start(args, format);
 
2444
  errmsg_vprintf (current_session, WARNING_LEVEL, format, args);
 
2445
  va_end(args);
 
2446
 
 
2447
  return;
 
2448
}
 
2449
 
 
2450
 
 
2451
void sql_print_information(const char *format, ...)
 
2452
{
 
2453
  va_list args;
 
2454
 
 
2455
  va_start(args, format);
 
2456
  errmsg_vprintf (current_session, INFORMATION_LEVEL, format, args);
3278
2457
  va_end(args);
3279
2458
 
3280
2459
  return;
3319
2498
  dirty - we don't sync removals to disk.
3320
2499
*/
3321
2500
 
3322
 
ulong tc_log_page_waits= 0;
 
2501
uint64_t tc_log_page_waits= 0;
3323
2502
 
3324
2503
#ifdef HAVE_MMAP
3325
2504
 
3327
2506
 
3328
2507
static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
3329
2508
 
3330
 
ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
3331
 
ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
 
2509
uint64_t opt_tc_log_size= TC_LOG_MIN_SIZE;
 
2510
uint64_t tc_log_max_pages_used= 0;
 
2511
uint64_t tc_log_page_size= 0;
 
2512
uint64_t tc_log_cur_pages_used= 0;
3332
2513
 
3333
2514
int TC_LOG_MMAP::open(const char *opt_name)
3334
2515
{
3342
2523
  tc_log_page_size= getpagesize();
3343
2524
  assert(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
3344
2525
 
3345
 
  fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
 
2526
  fn_format(logname,opt_name,drizzle_data_home,"",MY_UNPACK_FILENAME);
3346
2527
  if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
3347
2528
  {
3348
2529
    if (my_errno != ENOENT)
3367
2548
                      "--tc-heuristic-recover is used"));
3368
2549
      goto err;
3369
2550
    }
3370
 
    file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
3371
 
    if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
 
2551
    file_length= lseek(fd, 0, SEEK_END);
 
2552
    if (file_length == OFF_T_MAX || file_length % tc_log_page_size)
3372
2553
      goto err;
3373
2554
  }
3374
2555
 
3383
2564
 
3384
2565
  npages=(uint)file_length/tc_log_page_size;
3385
2566
  assert(npages >= 3);             // to guarantee non-empty pool
3386
 
  if (!(pages=(PAGE *)my_malloc(npages*sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
 
2567
  if (!(pages=(PAGE *)malloc(npages*sizeof(PAGE))))
3387
2568
    goto err;
 
2569
  memset(pages, 0, npages*sizeof(PAGE));
3388
2570
  inited=3;
3389
2571
  for (pg=pages, i=0; i < npages; i++, pg++)
3390
2572
  {
3409
2591
 
3410
2592
  memcpy(data, tc_log_magic, sizeof(tc_log_magic));
3411
2593
  data[sizeof(tc_log_magic)]= (unsigned char)total_ha_2pc;
3412
 
  msync(data, tc_log_page_size, MS_SYNC);
 
2594
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
 
2595
  //   so the cast should be fine.
 
2596
  msync((char *)data, tc_log_page_size, MS_SYNC);
3413
2597
  my_sync(fd, MYF(0));
3414
2598
  inited=5;
3415
2599
 
3530
2714
    to the position in memory where xid was logged to.
3531
2715
*/
3532
2716
 
3533
 
int TC_LOG_MMAP::log_xid(THD *thd __attribute__((unused)), my_xid xid)
 
2717
int TC_LOG_MMAP::log_xid(Session *, my_xid xid)
3534
2718
{
3535
2719
  int err;
3536
2720
  PAGE *p;
3615
2799
    sit down and relax - this can take a while...
3616
2800
    note - no locks are held at this point
3617
2801
  */
3618
 
  err= msync(syncing->start, 1, MS_SYNC);
 
2802
  // must cast data to (char *) for solaris. Arg1 is (void *) on linux
 
2803
  //   so the cast should be fine.
 
2804
  err= msync((char *)syncing->start, 1, MS_SYNC);
3619
2805
  if(err==0)
3620
2806
    err= my_sync(fd, MYF(0));
3621
2807
 
3642
2828
  cookie points directly to the memory where xid was logged.
3643
2829
*/
3644
2830
 
3645
 
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid __attribute__((unused)))
 
2831
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
3646
2832
{
3647
2833
  PAGE *p=pages+(cookie/tc_log_page_size);
3648
2834
  my_xid *x=(my_xid *)(data+cookie);
3834
3020
 
3835
3021
    do
3836
3022
    {
3837
 
      strmake(log_name, log_info.log_file_name, sizeof(log_name)-1);
 
3023
      strncpy(log_name, log_info.log_file_name, sizeof(log_name)-1);
3838
3024
    } while (!(error= find_next_log(&log_info, 1)));
3839
3025
 
3840
3026
    if (error !=  LOG_INFO_EOF)
3888
3074
  @retval
3889
3075
    1    success
3890
3076
*/
3891
 
int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
 
3077
int TC_LOG_BINLOG::log_xid(Session *session, my_xid xid)
3892
3078
{
3893
 
  Xid_log_event xle(thd, xid);
3894
 
  binlog_trx_data *trx_data=
3895
 
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
 
3079
  Xid_log_event xle(session, xid);
 
3080
  /* TODO: Fix return type */
3896
3081
  /*
3897
3082
    We always commit the entire transaction when writing an XID. Also
3898
3083
    note that the return value is inverted.
 
3084
 
 
3085
    TODO: fix backasswards logic on this method
3899
3086
   */
3900
 
  return(!binlog_end_trans(thd, trx_data, &xle, true));
 
3087
 
 
3088
  return replicator_end_transaction(session, true, true) ? false : true;
3901
3089
}
3902
3090
 
3903
 
void TC_LOG_BINLOG::unlog(ulong cookie __attribute__((unused)),
3904
 
                          my_xid xid __attribute__((unused)))
 
3091
void TC_LOG_BINLOG::unlog(ulong, my_xid)
3905
3092
{
3906
3093
  pthread_mutex_lock(&LOCK_prep_xids);
3907
3094
  assert(prepared_xids > 0);
3960
3147
}
3961
3148
 
3962
3149
 
3963
 
#ifdef INNODB_COMPATIBILITY_HOOKS
 
3150
bool DRIZZLE_BIN_LOG::is_table_mapped(Table *table) const
 
3151
{
 
3152
  return table->s->table_map_version == table_map_version();
 
3153
}
 
3154
 
3964
3155
/**
3965
3156
  Get the file name of the MySQL binlog.
3966
3157
  @return the name of the binlog file
3967
3158
*/
3968
3159
extern "C"
3969
 
const char* mysql_bin_log_file_name(void)
 
3160
const char* drizzle_bin_log_file_name(void)
3970
3161
{
3971
 
  return mysql_bin_log.get_log_fname();
 
3162
  return drizzle_bin_log.get_log_fname();
3972
3163
}
 
3164
 
 
3165
 
3973
3166
/**
3974
3167
  Get the current position of the MySQL binlog.
3975
3168
  @return byte offset from the beginning of the binlog
3976
3169
*/
3977
3170
extern "C"
3978
 
uint64_t mysql_bin_log_file_pos(void)
 
3171
uint64_t drizzle_bin_log_file_pos(void)
3979
3172
{
3980
 
  return (uint64_t) mysql_bin_log.get_log_file()->pos_in_file;
 
3173
  return (uint64_t) drizzle_bin_log.get_log_file()->pos_in_file;
3981
3174
}
3982
 
#endif /* INNODB_COMPATIBILITY_HOOKS */
3983
3175
 
3984
3176
 
3985
3177
mysql_declare_plugin(binlog)