MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
log.h
1 /* Copyright (c) 2005, 2011, 2012 Oracle and/or its affiliates. All rights reserved.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #ifndef LOG_H
17 #define LOG_H
18 
19 #include "unireg.h" // REQUIRED: for other includes
20 #include "handler.h" /* my_xid */
21 
31 typedef struct event_coordinates
32 {
33  char * file_name; // binlog file name (directories stripped)
34  my_off_t pos; // event's position in the binlog file
36 
48 class TC_LOG
49 {
50  public:
52  TC_LOG() {}
53  virtual ~TC_LOG() {}
54 
55  enum enum_result {
56  RESULT_SUCCESS,
57  RESULT_ABORTED,
58  RESULT_INCONSISTENT
59  };
60 
61  virtual int open(const char *opt_name)=0;
62  virtual void close()=0;
63 
77  virtual enum_result commit(THD *thd, bool all) = 0;
78 
93  virtual int rollback(THD *thd, bool all) = 0;
104  virtual int prepare(THD *thd, bool all) = 0;
105 };
106 
107 
108 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
109 {
110 public:
111  TC_LOG_DUMMY() {}
112  int open(const char *opt_name) { return 0; }
113  void close() { }
114  enum_result commit(THD *thd, bool all) {
115  return ha_commit_low(thd, all) ? RESULT_ABORTED : RESULT_SUCCESS;
116  }
117  int rollback(THD *thd, bool all) {
118  return ha_rollback_low(thd, all);
119  }
120  int prepare(THD *thd, bool all) {
121  return ha_prepare_low(thd, all);
122  }
123 };
124 
125 #ifdef HAVE_MMAP
126 class TC_LOG_MMAP: public TC_LOG
127 {
128  public: // only to keep Sun Forte on sol9x86 happy
129  typedef enum {
130  PS_POOL, // page is in pool
131  PS_ERROR, // last sync failed
132  PS_DIRTY // new xids added since last sync
133  } PAGE_STATE;
134 
135  private:
136  typedef struct st_page {
137  struct st_page *next; // page a linked in a fifo queue
138  my_xid *start, *end; // usable area of a page
139  my_xid *ptr; // next xid will be written here
140  int size, free; // max and current number of free xid slots on the page
141  int waiters; // number of waiters on condition
142  PAGE_STATE state; // see above
143  mysql_mutex_t lock; // to access page data or control structure
144  mysql_cond_t cond; // to wait for a sync
145  } PAGE;
146 
147  char logname[FN_REFLEN];
148  File fd;
149  my_off_t file_length;
150  uint npages, inited;
151  uchar *data;
152  struct st_page *pages, *syncing, *active, *pool, *pool_last;
153  /*
154  note that, e.g. LOCK_active is only used to protect
155  'active' pointer, to protect the content of the active page
156  one has to use active->lock.
157  Same for LOCK_pool and LOCK_sync
158  */
159  mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
160  mysql_cond_t COND_pool, COND_active;
161 
162  public:
163  TC_LOG_MMAP(): inited(0) {}
164  int open(const char *opt_name);
165  void close();
166  enum_result commit(THD *thd, bool all);
167  int rollback(THD *thd, bool all) { return ha_rollback_low(thd, all); }
168  int prepare(THD *thd, bool all) { return ha_prepare_low(thd, all); }
169  int recover();
170 
171 private:
172  int log_xid(THD *thd, my_xid xid);
173  int unlog(ulong cookie, my_xid xid);
174  void get_active_from_pool();
175  int sync();
176  int overflow();
177 };
178 #else
179 #define TC_LOG_MMAP TC_LOG_DUMMY
180 #endif
181 
182 extern TC_LOG *tc_log;
183 extern TC_LOG_MMAP tc_log_mmap;
184 extern TC_LOG_DUMMY tc_log_dummy;
185 
186 /* log info errors */
187 #define LOG_INFO_EOF -1
188 #define LOG_INFO_IO -2
189 #define LOG_INFO_INVALID -3
190 #define LOG_INFO_SEEK -4
191 #define LOG_INFO_MEM -6
192 #define LOG_INFO_FATAL -7
193 #define LOG_INFO_IN_USE -8
194 #define LOG_INFO_EMFILE -9
195 
196 
197 /* bitmap to SQL_LOG::close() */
198 #define LOG_CLOSE_INDEX 1
199 #define LOG_CLOSE_TO_BE_OPENED 2
200 #define LOG_CLOSE_STOP_EVENT 4
201 
202 /*
203  Maximum unique log filename extension.
204  Note: setting to 0x7FFFFFFF due to atol windows
205  overflow/truncate.
206  */
207 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
208 
209 /*
210  Number of warnings that will be printed to error log
211  before extension number is exhausted.
212 */
213 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000
214 
215 #ifdef HAVE_PSI_INTERFACE
216 extern PSI_mutex_key key_LOG_INFO_lock;
217 #endif
218 
219 /*
220  Note that we destroy the lock mutex in the desctructor here.
221  This means that object instances cannot be destroyed/go out of scope,
222  until we have reset thd->current_linfo to NULL;
223  */
224 typedef struct st_log_info
225 {
226  char log_file_name[FN_REFLEN];
227  my_off_t index_file_offset, index_file_start_offset;
228  my_off_t pos;
229  bool fatal; // if the purge happens to give us a negative offset
230  int entry_index; //used in purge_logs(), calculatd in find_log_pos().
231  mysql_mutex_t lock;
232  st_log_info()
233  : index_file_offset(0), index_file_start_offset(0),
234  pos(0), fatal(0), entry_index(0)
235  {
236  log_file_name[0] = '\0';
237  mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST);
238  }
239  ~st_log_info() { mysql_mutex_destroy(&lock);}
240 } LOG_INFO;
241 
242 /*
243  Currently we have only 3 kinds of logging functions: old-fashioned
244  logs, stdout and csv logging routines.
245 */
246 #define MAX_LOG_HANDLERS_NUM 3
247 
248 /* log event handler flags */
249 #define LOG_NONE 1
250 #define LOG_FILE 2
251 #define LOG_TABLE 4
252 
253 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
254 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
255 
256 /*
257  TODO use mmap instead of IO_CACHE for binlog
258  (mmap+fsync is two times faster than write+fsync)
259 */
260 
262 {
263 public:
264  MYSQL_LOG();
265  void init_pthread_objects();
266  void cleanup();
267  bool open(
268 #ifdef HAVE_PSI_INTERFACE
269  PSI_file_key log_file_key,
270 #endif
271  const char *log_name,
272  enum_log_type log_type,
273  const char *new_name,
274  enum cache_type io_cache_type_arg);
275  bool init_and_set_log_file_name(const char *log_name,
276  const char *new_name,
277  enum_log_type log_type_arg,
278  enum cache_type io_cache_type_arg);
279  void init(enum_log_type log_type_arg,
280  enum cache_type io_cache_type_arg);
281  void close(uint exiting);
282  inline bool is_open() { return log_state != LOG_CLOSED; }
283  const char *generate_name(const char *log_name, const char *suffix,
284  bool strip_ext, char *buff);
285  int generate_new_name(char *new_name, const char *log_name);
286  protected:
287  /* LOCK_log is inited by init_pthread_objects() */
288  mysql_mutex_t LOCK_log;
289  char *name;
290  char log_file_name[FN_REFLEN];
291  char time_buff[20], db[NAME_LEN + 1];
292  bool write_error, inited;
293  IO_CACHE log_file;
294  enum_log_type log_type;
295  volatile enum_log_state log_state;
296  enum cache_type io_cache_type;
297  friend class Log_event;
298 #ifdef HAVE_PSI_INTERFACE
299 
300  PSI_file_key m_log_file_key;
302  PSI_mutex_key m_key_LOCK_log;
303 #endif
304 };
305 
306 
307 enum enum_general_log_table_field
308 {
309  GLT_FIELD_EVENT_TIME = 0,
310  GLT_FIELD_USER_HOST,
311  GLT_FIELD_THREAD_ID,
312  GLT_FIELD_SERVER_ID,
313  GLT_FIELD_COMMAND_TYPE,
314  GLT_FIELD_ARGUMENT,
315  GLT_FIELD_COUNT
316 };
317 
318 
319 enum enum_slow_query_log_table_field
320 {
321  SQLT_FIELD_START_TIME = 0,
322  SQLT_FIELD_USER_HOST,
323  SQLT_FIELD_QUERY_TIME,
324  SQLT_FIELD_LOCK_TIME,
325  SQLT_FIELD_ROWS_SENT,
326  SQLT_FIELD_ROWS_EXAMINED,
327  SQLT_FIELD_DATABASE,
328  SQLT_FIELD_LAST_INSERT_ID,
329  SQLT_FIELD_INSERT_ID,
330  SQLT_FIELD_SERVER_ID,
331  SQLT_FIELD_SQL_TEXT,
332  SQLT_FIELD_THREAD_ID,
333  SQLT_FIELD_COUNT
334 };
335 
336 
338 {
339 public:
340  MYSQL_QUERY_LOG() : last_time(0) {}
341  void reopen_file();
342  bool write(time_t event_time, const char *user_host,
343  uint user_host_len, my_thread_id thread_id,
344  const char *command_type, uint command_type_len,
345  const char *sql_text, uint sql_text_len);
346  bool write(THD *thd, time_t current_time, time_t query_start_arg,
347  const char *user_host, uint user_host_len,
348  ulonglong query_utime, ulonglong lock_utime, bool is_command,
349  const char *sql_text, uint sql_text_len);
350  bool open_slow_log(const char *log_name)
351  {
352  char buf[FN_REFLEN];
353  return open(
354 #ifdef HAVE_PSI_INTERFACE
355  key_file_slow_log,
356 #endif
357  generate_name(log_name, "-slow.log", 0, buf),
358  LOG_NORMAL, 0, WRITE_CACHE);
359  }
360  bool open_query_log(const char *log_name)
361  {
362  char buf[FN_REFLEN];
363  return open(
364 #ifdef HAVE_PSI_INTERFACE
365  key_file_query_log,
366 #endif
367  generate_name(log_name, ".log", 0, buf),
368  LOG_NORMAL, 0, WRITE_CACHE);
369  }
370 
371 private:
372  time_t last_time;
373 };
374 
376 {
377 public:
378  Log_event_handler() {}
379  virtual bool init()= 0;
380  virtual void cleanup()= 0;
381 
382  virtual bool log_slow(THD *thd, time_t current_time,
383  time_t query_start_arg, const char *user_host,
384  uint user_host_len, ulonglong query_utime,
385  ulonglong lock_utime, bool is_command,
386  const char *sql_text, uint sql_text_len)= 0;
387  virtual bool log_error(enum loglevel level, const char *format,
388  va_list args)= 0;
389  virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
390  uint user_host_len, my_thread_id thread_id,
391  const char *command_type, uint command_type_len,
392  const char *sql_text, uint sql_text_len,
393  const CHARSET_INFO *client_cs)= 0;
394  virtual ~Log_event_handler() {}
395 };
396 
397 
398 int check_if_log_table(size_t db_len, const char *db, size_t table_name_len,
399  const char *table_name, bool check_if_opened);
400 
402 {
403 public:
406  virtual bool init();
407  virtual void cleanup();
408 
409  virtual bool log_slow(THD *thd, time_t current_time,
410  time_t query_start_arg, const char *user_host,
411  uint user_host_len, ulonglong query_utime,
412  ulonglong lock_utime, bool is_command,
413  const char *sql_text, uint sql_text_len);
414  virtual bool log_error(enum loglevel level, const char *format,
415  va_list args);
416  virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
417  uint user_host_len, my_thread_id thread_id,
418  const char *command_type, uint command_type_len,
419  const char *sql_text, uint sql_text_len,
420  const CHARSET_INFO *client_cs);
421 
422  int activate_log(THD *thd, uint log_type);
423 };
424 
425 
426 /* type of the log table */
427 #define QUERY_LOG_SLOW 1
428 #define QUERY_LOG_GENERAL 2
429 
431 {
432  MYSQL_QUERY_LOG mysql_log;
433  MYSQL_QUERY_LOG mysql_slow_log;
434  bool is_initialized;
435 public:
436  Log_to_file_event_handler(): is_initialized(FALSE)
437  {}
438  virtual bool init();
439  virtual void cleanup();
440 
441  virtual bool log_slow(THD *thd, time_t current_time,
442  time_t query_start_arg, const char *user_host,
443  uint user_host_len, ulonglong query_utime,
444  ulonglong lock_utime, bool is_command,
445  const char *sql_text, uint sql_text_len);
446  virtual bool log_error(enum loglevel level, const char *format,
447  va_list args);
448  virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
449  uint user_host_len, my_thread_id thread_id,
450  const char *command_type, uint command_type_len,
451  const char *sql_text, uint sql_text_len,
452  const CHARSET_INFO *client_cs);
453  void flush();
454  void init_pthread_objects();
455  MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
456  MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
457 };
458 
459 
460 /* Class which manages slow, general and error log event handlers */
461 class LOGGER
462 {
463  mysql_rwlock_t LOCK_logger;
464  /* flag to check whether logger mutex is initialized */
465  uint inited;
466 
467  /* available log handlers */
468  Log_to_csv_event_handler *table_log_handler;
469  Log_to_file_event_handler *file_log_handler;
470 
471  /* NULL-terminated arrays of log handlers */
472  Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
473  Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
474  Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
475 
476 public:
477 
478  bool is_log_tables_initialized;
479 
480  LOGGER() : inited(0), table_log_handler(NULL),
481  file_log_handler(NULL), is_log_tables_initialized(FALSE)
482  {}
483  void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); }
484  void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); }
485  void unlock() { mysql_rwlock_unlock(&LOCK_logger); }
486  bool is_log_table_enabled(uint log_table_type);
487  bool log_command(THD *thd, enum enum_server_command command);
488 
489  /*
490  We want to initialize all log mutexes as soon as possible,
491  but we cannot do it in constructor, as safe_mutex relies on
492  initialization, performed by MY_INIT(). This why this is done in
493  this function.
494  */
495  void init_base();
496  void init_log_tables();
497  bool flush_logs(THD *thd);
498  bool flush_slow_log();
499  bool flush_general_log();
500  /* Perform basic logger cleanup. this will leave e.g. error log open. */
501  void cleanup_base();
502  /* Free memory. Nothing could be logged after this function is called */
503  void cleanup_end();
504  bool error_log_print(enum loglevel level, const char *format,
505  va_list args);
506  bool slow_log_print(THD *thd, const char *query, uint query_length);
507  bool general_log_print(THD *thd,enum enum_server_command command,
508  const char *format, va_list args);
509  bool general_log_write(THD *thd, enum enum_server_command command,
510  const char *query, uint query_length);
511 
512  /* we use this function to setup all enabled log event handlers */
513  int set_handlers(uint error_log_printer,
514  uint slow_log_printer,
515  uint general_log_printer);
516  void init_error_log(uint error_log_printer);
517  void init_slow_log(uint slow_log_printer);
518  void init_general_log(uint general_log_printer);
519  void deactivate_log_handler(THD* thd, uint log_type);
520  bool activate_log_handler(THD* thd, uint log_type);
521  MYSQL_QUERY_LOG *get_slow_log_file_handler() const
522  {
523  if (file_log_handler)
524  return file_log_handler->get_mysql_slow_log();
525  return NULL;
526  }
527  MYSQL_QUERY_LOG *get_log_file_handler() const
528  {
529  if (file_log_handler)
530  return file_log_handler->get_mysql_log();
531  return NULL;
532  }
533 };
534 
535 enum enum_binlog_row_image {
537  BINLOG_ROW_IMAGE_MINIMAL= 0,
539  BINLOG_ROW_IMAGE_NOBLOB= 1,
541  BINLOG_ROW_IMAGE_FULL= 2
542 };
543 
544 enum enum_binlog_format {
545  BINLOG_FORMAT_MIXED= 0,
546  BINLOG_FORMAT_STMT= 1,
547  BINLOG_FORMAT_ROW= 2,
548  BINLOG_FORMAT_UNSPEC=3
549 };
550 
551 int query_error_code(THD *thd, bool not_killed);
552 uint purge_log_get_error_code(int res);
553 
554 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
555 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
556 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
557 void sql_print_information(const char *format, ...)
558  ATTRIBUTE_FORMAT(printf, 1, 2);
559 typedef void (*sql_print_message_func)(const char *format, ...)
560  ATTRIBUTE_FORMAT_FPTR(printf, 1, 2);
561 extern sql_print_message_func sql_print_message_handlers[];
562 
563 int error_log_print(enum loglevel level, const char *format,
564  va_list args);
565 
566 bool slow_log_print(THD *thd, const char *query, uint query_length);
567 
568 bool general_log_print(THD *thd, enum enum_server_command command,
569  const char *format,...);
570 
571 bool general_log_write(THD *thd, enum enum_server_command command,
572  const char *query, uint query_length);
573 
574 void sql_perror(const char *message);
575 bool flush_error_log();
576 
577 char *make_log_name(char *buff, const char *name, const char* log_ext);
578 
579 extern LOGGER logger;
580 
581 #endif /* LOG_H */