~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2005 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
#ifndef LOG_H
17
#define LOG_H
18
19
class Relay_log_info;
20
21
class Format_description_log_event;
22
23
/*
24
  Transaction Coordinator log - a base abstract class
25
  for two different implementations
26
*/
27
class TC_LOG
28
{
29
  public:
30
  int using_heuristic_recover();
31
  TC_LOG() {}
32
  virtual ~TC_LOG() {}
33
34
  virtual int open(const char *opt_name)=0;
35
  virtual void close()=0;
36
  virtual int log_xid(THD *thd, my_xid xid)=0;
37
  virtual void unlog(ulong cookie, my_xid xid)=0;
38
};
39
40
class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
41
{
42
public:
43
  TC_LOG_DUMMY() {}
53.2.32 by Monty Taylor
First large swath at getting handler stuff clean.
44
  int open(const char *opt_name __attribute__((__unused__)))
45
  { return 0; }
46
  void close(void)                          { }
47
  int log_xid(THD *thd __attribute__((__unused__)),
48
              my_xid xid __attribute__((__unused__)))         { return 1; }
49
  void unlog(ulong cookie __attribute__((__unused__)),
50
             my_xid xid __attribute__((__unused__)))  { }
1 by brian
clean slate
51
};
52
53
#ifdef HAVE_MMAP
54
class TC_LOG_MMAP: public TC_LOG
55
{
56
  public:                // only to keep Sun Forte on sol9x86 happy
57
  typedef enum {
58
    POOL,                 // page is in pool
59
    ERROR,                // last sync failed
60
    DIRTY                 // new xids added since last sync
61
  } PAGE_STATE;
62
63
  private:
64
  typedef struct st_page {
65
    struct st_page *next; // page a linked in a fifo queue
66
    my_xid *start, *end;  // usable area of a page
67
    my_xid *ptr;          // next xid will be written here
68
    int size, free;       // max and current number of free xid slots on the page
69
    int waiters;          // number of waiters on condition
70
    PAGE_STATE state;     // see above
71
    pthread_mutex_t lock; // to access page data or control structure
72
    pthread_cond_t  cond; // to wait for a sync
73
  } PAGE;
74
75
  char logname[FN_REFLEN];
76
  File fd;
77
  my_off_t file_length;
78
  uint npages, inited;
79
  uchar *data;
80
  struct st_page *pages, *syncing, *active, *pool, *pool_last;
81
  /*
82
    note that, e.g. LOCK_active is only used to protect
83
    'active' pointer, to protect the content of the active page
84
    one has to use active->lock.
85
    Same for LOCK_pool and LOCK_sync
86
  */
87
  pthread_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
88
  pthread_cond_t COND_pool, COND_active;
89
90
  public:
91
  TC_LOG_MMAP(): inited(0) {}
92
  int open(const char *opt_name);
93
  void close();
94
  int log_xid(THD *thd, my_xid xid);
95
  void unlog(ulong cookie, my_xid xid);
96
  int recover();
97
98
  private:
99
  void get_active_from_pool();
100
  int sync();
101
  int overflow();
102
};
103
#else
104
#define TC_LOG_MMAP TC_LOG_DUMMY
105
#endif
106
107
extern TC_LOG *tc_log;
108
extern TC_LOG_MMAP tc_log_mmap;
109
extern TC_LOG_DUMMY tc_log_dummy;
110
111
/* log info errors */
112
#define LOG_INFO_EOF -1
113
#define LOG_INFO_IO  -2
114
#define LOG_INFO_INVALID -3
115
#define LOG_INFO_SEEK -4
116
#define LOG_INFO_MEM -6
117
#define LOG_INFO_FATAL -7
118
#define LOG_INFO_IN_USE -8
119
#define LOG_INFO_EMFILE -9
120
121
122
/* bitmap to SQL_LOG::close() */
123
#define LOG_CLOSE_INDEX		1
124
#define LOG_CLOSE_TO_BE_OPENED	2
125
#define LOG_CLOSE_STOP_EVENT	4
126
127
class Relay_log_info;
128
129
typedef struct st_log_info
130
{
131
  char log_file_name[FN_REFLEN];
132
  my_off_t index_file_offset, index_file_start_offset;
133
  my_off_t pos;
134
  bool fatal; // if the purge happens to give us a negative offset
135
  pthread_mutex_t lock;
136
  st_log_info()
137
    : index_file_offset(0), index_file_start_offset(0),
138
      pos(0), fatal(0)
139
    {
140
      log_file_name[0] = '\0';
141
      pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST);
142
    }
143
  ~st_log_info() { pthread_mutex_destroy(&lock);}
144
} LOG_INFO;
145
146
/*
147
  Currently we have only 3 kinds of logging functions: old-fashioned
148
  logs, stdout and csv logging routines.
149
*/
150
#define MAX_LOG_HANDLERS_NUM 3
151
152
/* log event handler flags */
153
#define LOG_NONE       1
154
#define LOG_FILE       2
155
#define LOG_TABLE      4
156
157
class Log_event;
158
class Rows_log_event;
159
160
enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
161
enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
162
163
/*
164
  TODO use mmap instead of IO_CACHE for binlog
165
  (mmap+fsync is two times faster than write+fsync)
166
*/
167
168
class MYSQL_LOG
169
{
170
public:
171
  MYSQL_LOG();
172
  void init_pthread_objects();
173
  void cleanup();
174
  bool open(const char *log_name,
175
            enum_log_type log_type,
176
            const char *new_name,
177
            enum cache_type io_cache_type_arg);
178
  void init(enum_log_type log_type_arg,
179
            enum cache_type io_cache_type_arg);
180
  void close(uint exiting);
181
  inline bool is_open() { return log_state != LOG_CLOSED; }
182
  const char *generate_name(const char *log_name, const char *suffix,
183
                            bool strip_ext, char *buff);
184
  int generate_new_name(char *new_name, const char *log_name);
185
 protected:
186
  /* LOCK_log is inited by init_pthread_objects() */
187
  pthread_mutex_t LOCK_log;
188
  char *name;
189
  char log_file_name[FN_REFLEN];
190
  char time_buff[20], db[NAME_LEN + 1];
191
  bool write_error, inited;
192
  IO_CACHE log_file;
193
  enum_log_type log_type;
194
  volatile enum_log_state log_state;
195
  enum cache_type io_cache_type;
196
  friend class Log_event;
197
};
198
199
class MYSQL_QUERY_LOG: public MYSQL_LOG
200
{
201
public:
202
  MYSQL_QUERY_LOG() : last_time(0) {}
203
  void reopen_file();
204
  bool write(time_t event_time, const char *user_host,
205
             uint user_host_len, int thread_id,
206
             const char *command_type, uint command_type_len,
207
             const char *sql_text, uint sql_text_len);
208
  bool write(THD *thd, time_t current_time, time_t query_start_arg,
209
             const char *user_host, uint user_host_len,
210
             ulonglong query_utime, ulonglong lock_utime, bool is_command,
211
             const char *sql_text, uint sql_text_len);
212
  bool open_slow_log(const char *log_name)
213
  {
214
    char buf[FN_REFLEN];
215
    return open(generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0,
216
                WRITE_CACHE);
217
  }
218
  bool open_query_log(const char *log_name)
219
  {
220
    char buf[FN_REFLEN];
221
    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
222
                WRITE_CACHE);
223
  }
224
225
private:
226
  time_t last_time;
227
};
228
229
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
230
{
231
 private:
232
  /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
233
  pthread_mutex_t LOCK_index;
234
  pthread_mutex_t LOCK_prep_xids;
235
  pthread_cond_t  COND_prep_xids;
236
  pthread_cond_t update_cond;
237
  ulonglong bytes_written;
238
  IO_CACHE index_file;
239
  char index_file_name[FN_REFLEN];
240
  /*
241
     The max size before rotation (usable only if log_type == LOG_BIN: binary
242
     logs and relay logs).
243
     For a binlog, max_size should be max_binlog_size.
244
     For a relay log, it should be max_relay_log_size if this is non-zero,
245
     max_binlog_size otherwise.
246
     max_size is set in init(), and dynamically changed (when one does SET
247
     GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
248
     fix_max_relay_log_size).
249
  */
250
  ulong max_size;
251
  long prepared_xids; /* for tc log - number of xids to remember */
252
  // current file sequence number for load data infile binary logging
253
  uint file_id;
254
  uint open_count;				// For replication
255
  int readers_count;
256
  bool need_start_event;
257
  /*
258
    no_auto_events means we don't want any of these automatic events :
259
    Start/Rotate/Stop. That is, in 4.x when we rotate a relay log, we don't
260
    want a Rotate_log event to be written to the relay log. When we start a
261
    relay log etc. So in 4.x this is 1 for relay logs, 0 for binlogs.
262
    In 5.0 it's 0 for relay logs too!
263
  */
264
  bool no_auto_events;
265
266
  ulonglong m_table_map_version;
267
268
  int write_to_file(IO_CACHE *cache);
269
  /*
270
    This is used to start writing to a new log file. The difference from
271
    new_file() is locking. new_file_without_locking() does not acquire
272
    LOCK_log.
273
  */
274
  void new_file_without_locking();
275
  void new_file_impl(bool need_lock);
276
277
public:
278
  MYSQL_LOG::generate_name;
279
  MYSQL_LOG::is_open;
280
  /*
281
    These describe the log's format. This is used only for relay logs.
282
    _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
283
    necessary to have 2 distinct objects, because the I/O thread may be reading
284
    events in a different format from what the SQL thread is reading (consider
285
    the case of a master which has been upgraded from 5.0 to 5.1 without doing
286
    RESET MASTER, or from 4.x to 5.0).
287
  */
288
  Format_description_log_event *description_event_for_exec,
289
    *description_event_for_queue;
290
291
  MYSQL_BIN_LOG();
292
  /*
293
    note that there's no destructor ~MYSQL_BIN_LOG() !
294
    The reason is that we don't want it to be automatically called
295
    on exit() - but only during the correct shutdown process
296
  */
297
298
  int open(const char *opt_name);
299
  void close();
300
  int log_xid(THD *thd, my_xid xid);
301
  void unlog(ulong cookie, my_xid xid);
302
  int recover(IO_CACHE *log, Format_description_log_event *fdle);
303
#if !defined(MYSQL_CLIENT)
304
  bool is_table_mapped(TABLE *table) const
305
  {
306
    return table->s->table_map_version == table_map_version();
307
  }
308
309
  ulonglong table_map_version() const { return m_table_map_version; }
310
  void update_table_map_version() { ++m_table_map_version; }
311
312
  int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event);
313
314
#endif /* !defined(MYSQL_CLIENT) */
315
  void reset_bytes_written()
316
  {
317
    bytes_written = 0;
318
  }
319
  void harvest_bytes_written(ulonglong* counter)
320
  {
321
#ifndef DBUG_OFF
322
    char buf1[22],buf2[22];
323
#endif
324
    DBUG_ENTER("harvest_bytes_written");
325
    (*counter)+=bytes_written;
326
    DBUG_PRINT("info",("counter: %s  bytes_written: %s", llstr(*counter,buf1),
327
		       llstr(bytes_written,buf2)));
328
    bytes_written=0;
329
    DBUG_VOID_RETURN;
330
  }
331
  void set_max_size(ulong max_size_arg);
332
  void signal_update();
333
  void wait_for_update_relay_log(THD* thd);
334
  int  wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
335
  void set_need_start_event() { need_start_event = 1; }
336
  void init(bool no_auto_events_arg, ulong max_size);
337
  void init_pthread_objects();
338
  void cleanup();
339
  bool open(const char *log_name,
340
            enum_log_type log_type,
341
            const char *new_name,
342
	    enum cache_type io_cache_type_arg,
343
	    bool no_auto_events_arg, ulong max_size,
344
            bool null_created);
345
  bool open_index_file(const char *index_file_name_arg,
346
                       const char *log_name);
347
  /* Use this to start writing a new log file */
348
  void new_file();
349
350
  bool write(Log_event* event_info); // binary log write
351
  bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
352
353
  int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
354
355
  void start_union_events(THD *thd, query_id_t query_id_param);
356
  void stop_union_events(THD *thd);
357
  bool is_query_in_union(THD *thd, query_id_t query_id_param);
358
359
  /*
360
    v stands for vector
361
    invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
362
  */
363
  bool appendv(const char* buf,uint len,...);
364
  bool append(Log_event* ev);
365
366
  void make_log_name(char* buf, const char* log_ident);
367
  bool is_active(const char* log_file_name);
368
  int update_log_index(LOG_INFO* linfo, bool need_update_threads);
369
  void rotate_and_purge(uint flags);
370
  bool flush_and_sync();
371
  int purge_logs(const char *to_log, bool included,
372
                 bool need_mutex, bool need_update_threads,
373
                 ulonglong *decrease_log_space);
374
  int purge_logs_before_date(time_t purge_time);
375
  int purge_first_log(Relay_log_info* rli, bool included);
376
  bool reset_logs(THD* thd);
377
  void close(uint exiting);
378
379
  // iterating through the log index file
380
  int find_log_pos(LOG_INFO* linfo, const char* log_name,
381
		   bool need_mutex);
382
  int find_next_log(LOG_INFO* linfo, bool need_mutex);
383
  int get_current_log(LOG_INFO* linfo);
384
  int raw_get_current_log(LOG_INFO* linfo);
385
  uint next_file_id();
386
  inline char* get_index_fname() { return index_file_name;}
387
  inline char* get_log_fname() { return log_file_name; }
388
  inline char* get_name() { return name; }
389
  inline pthread_mutex_t* get_log_lock() { return &LOCK_log; }
390
  inline IO_CACHE* get_log_file() { return &log_file; }
391
392
  inline void lock_index() { pthread_mutex_lock(&LOCK_index);}
393
  inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);}
394
  inline IO_CACHE *get_index_file() { return &index_file;}
395
  inline uint32 get_open_count() { return open_count; }
396
};
397
398
class Log_event_handler
399
{
400
public:
401
  Log_event_handler() {}
402
  virtual bool init()= 0;
403
  virtual void cleanup()= 0;
404
405
  virtual bool log_slow(THD *thd, time_t current_time,
406
                        time_t query_start_arg, const char *user_host,
407
                        uint user_host_len, ulonglong query_utime,
408
                        ulonglong lock_utime, bool is_command,
409
                        const char *sql_text, uint sql_text_len)= 0;
410
  virtual bool log_error(enum loglevel level, const char *format,
411
                         va_list args)= 0;
412
  virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
413
                           uint user_host_len, int thread_id,
414
                           const char *command_type, uint command_type_len,
415
                           const char *sql_text, uint sql_text_len,
416
                           CHARSET_INFO *client_cs)= 0;
417
  virtual ~Log_event_handler() {}
418
};
419
420
421
/* type of the log table */
422
#define QUERY_LOG_SLOW 1
423
#define QUERY_LOG_GENERAL 2
424
425
class Log_to_file_event_handler: public Log_event_handler
426
{
427
  MYSQL_QUERY_LOG mysql_log;
428
  MYSQL_QUERY_LOG mysql_slow_log;
429
  bool is_initialized;
430
public:
431
  Log_to_file_event_handler(): is_initialized(FALSE)
432
  {}
433
  virtual bool init();
434
  virtual void cleanup();
435
436
  virtual bool log_slow(THD *thd, time_t current_time,
437
                        time_t query_start_arg, const char *user_host,
438
                        uint user_host_len, ulonglong query_utime,
439
                        ulonglong lock_utime, bool is_command,
440
                        const char *sql_text, uint sql_text_len);
441
  virtual bool log_error(enum loglevel level, const char *format,
442
                         va_list args);
443
  virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
444
                           uint user_host_len, int thread_id,
445
                           const char *command_type, uint command_type_len,
446
                           const char *sql_text, uint sql_text_len,
447
                           CHARSET_INFO *client_cs);
448
  void flush();
449
  void init_pthread_objects();
450
  MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
451
  MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
452
};
453
454
455
/* Class which manages slow, general and error log event handlers */
456
class LOGGER
457
{
458
  rw_lock_t LOCK_logger;
459
  /* flag to check whether logger mutex is initialized */
460
  uint inited;
461
462
  /* available log handlers */
463
  Log_to_file_event_handler *file_log_handler;
464
465
  /* NULL-terminated arrays of log handlers */
466
  Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
467
  Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
468
  Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
469
470
public:
471
472
  LOGGER() : inited(0), file_log_handler(NULL)
473
  {}
474
  void lock_shared() { rw_rdlock(&LOCK_logger); }
475
  void lock_exclusive() { rw_wrlock(&LOCK_logger); }
476
  void unlock() { rw_unlock(&LOCK_logger); }
477
  bool is_log_table_enabled(uint log_table_type);
478
  bool log_command(THD *thd, enum enum_server_command command);
479
480
  /*
481
    We want to initialize all log mutexes as soon as possible,
482
    but we cannot do it in constructor, as safe_mutex relies on
483
    initialization, performed by MY_INIT(). This why this is done in
484
    this function.
485
  */
486
  void init_base();
487
  bool flush_logs(THD *thd);
488
  /* Perform basic logger cleanup. this will leave e.g. error log open. */
489
  void cleanup_base();
490
  /* Free memory. Nothing could be logged after this function is called */
491
  void cleanup_end();
492
  bool error_log_print(enum loglevel level, const char *format,
493
                      va_list args);
494
  bool slow_log_print(THD *thd, const char *query, uint query_length,
495
                      ulonglong current_utime);
496
  bool general_log_print(THD *thd,enum enum_server_command command,
497
                         const char *format, va_list args);
498
  bool general_log_write(THD *thd, enum enum_server_command command,
499
                         const char *query, uint query_length);
500
501
  /* we use this function to setup all enabled log event handlers */
502
  int set_handlers(uint error_log_printer,
503
                   uint slow_log_printer,
504
                   uint general_log_printer);
505
  void init_error_log(uint error_log_printer);
506
  void init_slow_log(uint slow_log_printer);
507
  void init_general_log(uint general_log_printer);
508
  void deactivate_log_handler(THD* thd, uint log_type);
509
  bool activate_log_handler(THD* thd, uint log_type);
510
  MYSQL_QUERY_LOG *get_slow_log_file_handler()
511
  { 
512
    if (file_log_handler)
513
      return file_log_handler->get_mysql_slow_log();
514
    return NULL;
515
  }
516
  MYSQL_QUERY_LOG *get_log_file_handler()
517
  { 
518
    if (file_log_handler)
519
      return file_log_handler->get_mysql_log();
520
    return NULL;
521
  }
522
};
523
524
enum enum_binlog_format {
525
  /*
526
    statement-based except for cases where only row-based can work (UUID()
527
    etc):
528
  */
529
  BINLOG_FORMAT_MIXED= 0,
530
  BINLOG_FORMAT_STMT= 1, // statement-based
531
  BINLOG_FORMAT_ROW= 2, // row_based
532
/*
533
  This value is last, after the end of binlog_format_typelib: it has no
534
  corresponding cell in this typelib. We use this value to be able to know if
535
  the user has explicitely specified a binlog format at startup or not.
536
*/
537
  BINLOG_FORMAT_UNSPEC= 3
538
};
539
extern TYPELIB binlog_format_typelib;
540
541
#endif /* LOG_H */