1 /* Copyright (c) 2005, 2016, 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 
22 class Relay_log_info;
23 
24 class Format_description_log_event;
25 
26 bool trans_has_updated_trans_table(const THD* thd);
27 bool stmt_has_updated_trans_table(Ha_trx_info* ha_list);
28 bool use_trans_cache(const THD* thd, bool is_transactional);
29 bool ending_trans(THD* thd, const bool all);
30 bool ending_single_stmt_trans(THD* thd, const bool all);
31 bool trans_has_updated_non_trans_table(const THD* thd);
32 bool stmt_has_updated_non_trans_table(const THD* thd);
33 
34 /*
35   Transaction Coordinator log - a base abstract class
36   for two different implementations
37 */
38 class TC_LOG
39 {
40   public:
41   int using_heuristic_recover();
TC_LOG()42   TC_LOG() {}
~TC_LOG()43   virtual ~TC_LOG() {}
44 
45   virtual int open(const char *opt_name)=0;
46   virtual void close()=0;
47   virtual int log_xid(THD *thd, my_xid xid)=0;
48   virtual int unlog(ulong cookie, my_xid xid)=0;
49 };
50 
51 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
52 {
53 public:
TC_LOG_DUMMY()54   TC_LOG_DUMMY() {}
open(const char * opt_name)55   int open(const char *opt_name)        { return 0; }
close()56   void close()                          { }
log_xid(THD * thd,my_xid xid)57   int log_xid(THD *thd, my_xid xid)         { return 1; }
unlog(ulong cookie,my_xid xid)58   int unlog(ulong cookie, my_xid xid)  { return 0; }
59 };
60 
61 #ifdef HAVE_MMAP
62 class TC_LOG_MMAP: public TC_LOG
63 {
64   public:                // only to keep Sun Forte on sol9x86 happy
65   typedef enum {
66     PS_POOL,                 // page is in pool
67     PS_ERROR,                // last sync failed
68     PS_DIRTY                 // new xids added since last sync
69   } PAGE_STATE;
70 
71   private:
72   typedef struct st_page {
73     struct st_page *next; // page a linked in a fifo queue
74     my_xid *start, *end;  // usable area of a page
75     my_xid *ptr;          // next xid will be written here
76     int size, free;       // max and current number of free xid slots on the page
77     int waiters;          // number of waiters on condition
78     PAGE_STATE state;     // see above
79     mysql_mutex_t lock; // to access page data or control structure
80     mysql_cond_t  cond; // to wait for a sync
81   } PAGE;
82 
83   char logname[FN_REFLEN];
84   File fd;
85   my_off_t file_length;
86   uint npages, inited;
87   uchar *data;
88   struct st_page *pages, *syncing, *active, *pool, *pool_last;
89   /*
90     note that, e.g. LOCK_active is only used to protect
91     'active' pointer, to protect the content of the active page
92     one has to use active->lock.
93     Same for LOCK_pool and LOCK_sync
94   */
95   mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
96   mysql_cond_t COND_pool, COND_active;
97 
98   public:
TC_LOG_MMAP()99   TC_LOG_MMAP(): inited(0) {}
100   int open(const char *opt_name);
101   void close();
102   int log_xid(THD *thd, my_xid xid);
103   int unlog(ulong cookie, my_xid xid);
104   int recover();
105 
106   private:
107   void get_active_from_pool();
108   int sync();
109   int overflow();
110 };
111 #else
112 #define TC_LOG_MMAP TC_LOG_DUMMY
113 #endif
114 
115 extern TC_LOG *tc_log;
116 extern TC_LOG_MMAP tc_log_mmap;
117 extern TC_LOG_DUMMY tc_log_dummy;
118 
119 /* log info errors */
120 #define LOG_INFO_EOF -1
121 #define LOG_INFO_IO  -2
122 #define LOG_INFO_INVALID -3
123 #define LOG_INFO_SEEK -4
124 #define LOG_INFO_MEM -6
125 #define LOG_INFO_FATAL -7
126 #define LOG_INFO_IN_USE -8
127 #define LOG_INFO_EMFILE -9
128 
129 
130 /* bitmap to SQL_LOG::close() */
131 #define LOG_CLOSE_INDEX		1
132 #define LOG_CLOSE_TO_BE_OPENED	2
133 #define LOG_CLOSE_STOP_EVENT	4
134 
135 /*
136   Maximum unique log filename extension.
137   Note: setting to 0x7FFFFFFF due to atol windows
138         overflow/truncate.
139  */
140 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
141 
142 /*
143    Number of warnings that will be printed to error log
144    before extension number is exhausted.
145 */
146 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000
147 
148 class Relay_log_info;
149 
150 #ifdef HAVE_PSI_INTERFACE
151 extern PSI_mutex_key key_LOG_INFO_lock;
152 #endif
153 
154 /*
155   Note that we destroy the lock mutex in the desctructor here.
156   This means that object instances cannot be destroyed/go out of scope,
157   until we have reset thd->current_linfo to NULL;
158  */
159 typedef struct st_log_info
160 {
161   char log_file_name[FN_REFLEN];
162   my_off_t index_file_offset, index_file_start_offset;
163   my_off_t pos;
164   bool fatal; // if the purge happens to give us a negative offset
165   mysql_mutex_t lock;
st_log_infost_log_info166   st_log_info()
167     : index_file_offset(0), index_file_start_offset(0),
168       pos(0), fatal(0)
169     {
170       log_file_name[0] = '\0';
171       mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST);
172     }
~st_log_infost_log_info173   ~st_log_info() { mysql_mutex_destroy(&lock);}
174 } LOG_INFO;
175 
176 /*
177   Currently we have only 3 kinds of logging functions: old-fashioned
178   logs, stdout and csv logging routines.
179 */
180 #define MAX_LOG_HANDLERS_NUM 3
181 
182 /* log event handler flags */
183 #define LOG_NONE       1
184 #define LOG_FILE       2
185 #define LOG_TABLE      4
186 
187 class Log_event;
188 class Rows_log_event;
189 
190 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
191 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
192 
193 /*
194   TODO use mmap instead of IO_CACHE for binlog
195   (mmap+fsync is two times faster than write+fsync)
196 */
197 
198 class MYSQL_LOG
199 {
200 public:
201   MYSQL_LOG();
202   void init_pthread_objects();
203   void cleanup();
204   bool open(
205 #ifdef HAVE_PSI_INTERFACE
206             PSI_file_key log_file_key,
207 #endif
208             const char *log_name,
209             enum_log_type log_type,
210             const char *new_name,
211             enum cache_type io_cache_type_arg);
212   bool init_and_set_log_file_name(const char *log_name,
213                                   const char *new_name,
214                                   enum_log_type log_type_arg,
215                                   enum cache_type io_cache_type_arg);
216   void init(enum_log_type log_type_arg,
217             enum cache_type io_cache_type_arg);
218   void close(uint exiting);
is_open()219   inline bool is_open() { return log_state != LOG_CLOSED; }
220   const char *generate_name(const char *log_name, const char *suffix,
221                             bool strip_ext, char *buff);
222   int generate_new_name(char *new_name, const char *log_name);
223  protected:
224   /* LOCK_log is inited by init_pthread_objects() */
225   mysql_mutex_t LOCK_log;
226   char *name;
227   char log_file_name[FN_REFLEN];
228   char time_buff[20], db[NAME_LEN + 1];
229   bool write_error, inited;
230   IO_CACHE log_file;
231   enum_log_type log_type;
232   volatile enum_log_state log_state;
233   enum cache_type io_cache_type;
234   friend class Log_event;
235 #ifdef HAVE_PSI_INTERFACE
236   /** Instrumentation key to use for file io in @c log_file */
237   PSI_file_key m_log_file_key;
238 #endif
239 };
240 
241 class MYSQL_QUERY_LOG: public MYSQL_LOG
242 {
243 public:
MYSQL_QUERY_LOG()244   MYSQL_QUERY_LOG() : last_time(0) {}
245   void reopen_file();
246   bool write(time_t event_time, const char *user_host,
247              uint user_host_len, int thread_id,
248              const char *command_type, uint command_type_len,
249              const char *sql_text, uint sql_text_len);
250   bool write(THD *thd, time_t current_time, time_t query_start_arg,
251              const char *user_host, uint user_host_len,
252              ulonglong query_utime, ulonglong lock_utime, bool is_command,
253              const char *sql_text, uint sql_text_len);
open_slow_log(const char * log_name)254   bool open_slow_log(const char *log_name)
255   {
256     char buf[FN_REFLEN];
257     return open(
258 #ifdef HAVE_PSI_INTERFACE
259                 key_file_slow_log,
260 #endif
261                 generate_name(log_name, "-slow.log", 0, buf),
262                 LOG_NORMAL, 0, WRITE_CACHE);
263   }
open_query_log(const char * log_name)264   bool open_query_log(const char *log_name)
265   {
266     char buf[FN_REFLEN];
267     return open(
268 #ifdef HAVE_PSI_INTERFACE
269                 key_file_query_log,
270 #endif
271                 generate_name(log_name, ".log", 0, buf),
272                 LOG_NORMAL, 0, WRITE_CACHE);
273   }
274 
275 private:
276   time_t last_time;
277 };
278 
279 class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
280 {
281  private:
282 #ifdef HAVE_PSI_INTERFACE
283   /** The instrumentation key to use for @ LOCK_index. */
284   PSI_mutex_key m_key_LOCK_index;
285   /** The instrumentation key to use for @ update_cond. */
286   PSI_cond_key m_key_update_cond;
287   /** The instrumentation key to use for opening the log file. */
288   PSI_file_key m_key_file_log;
289   /** The instrumentation key to use for opening the log index file. */
290   PSI_file_key m_key_file_log_index;
291 #endif
292   /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
293   mysql_mutex_t LOCK_index;
294   mysql_mutex_t LOCK_prep_xids;
295   mysql_cond_t  COND_prep_xids;
296   mysql_cond_t update_cond;
297   ulonglong bytes_written;
298   IO_CACHE index_file;
299   char index_file_name[FN_REFLEN];
300   /*
301     purge_file is a temp file used in purge_logs so that the index file
302     can be updated before deleting files from disk, yielding better crash
303     recovery. It is created on demand the first time purge_logs is called
304     and then reused for subsequent calls. It is cleaned up in cleanup().
305   */
306   IO_CACHE purge_index_file;
307   char purge_index_file_name[FN_REFLEN];
308   /*
309      The max size before rotation (usable only if log_type == LOG_BIN: binary
310      logs and relay logs).
311      For a binlog, max_size should be max_binlog_size.
312      For a relay log, it should be max_relay_log_size if this is non-zero,
313      max_binlog_size otherwise.
314      max_size is set in init(), and dynamically changed (when one does SET
315      GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
316      fix_max_relay_log_size).
317   */
318   ulong max_size;
319   long prepared_xids; /* for tc log - number of xids to remember */
320   // current file sequence number for load data infile binary logging
321   uint file_id;
322   uint open_count;				// For replication
323   int readers_count;
324   bool need_start_event;
325   /*
326     no_auto_events means we don't want any of these automatic events :
327     Start/Rotate/Stop. That is, in 4.x when we rotate a relay log, we don't
328     want a Rotate_log event to be written to the relay log. When we start a
329     relay log etc. So in 4.x this is 1 for relay logs, 0 for binlogs.
330     In 5.0 it's 0 for relay logs too!
331   */
332   bool no_auto_events;
333 
334   /* pointer to the sync period variable, for binlog this will be
335      sync_binlog_period, for relay log this will be
336      sync_relay_log_period
337   */
338   uint *sync_period_ptr;
339   uint sync_counter;
340 
get_sync_period()341   inline uint get_sync_period()
342   {
343     return *sync_period_ptr;
344   }
345 
346   int write_to_file(IO_CACHE *cache);
347   /*
348     This is used to start writing to a new log file. The difference from
349     new_file() is locking. new_file_without_locking() does not acquire
350     LOCK_log.
351   */
352   int new_file_without_locking();
353   int new_file_impl(bool need_lock);
354 
355 public:
356   using MYSQL_LOG::generate_name;
357   using MYSQL_LOG::is_open;
358 
359   /* This is relay log */
360   bool is_relay_log;
361   ulong signal_cnt;  // update of the counter is checked by heartbeat
362   /*
363     These describe the log's format. This is used only for relay logs.
364     _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
365     necessary to have 2 distinct objects, because the I/O thread may be reading
366     events in a different format from what the SQL thread is reading (consider
367     the case of a master which has been upgraded from 5.0 to 5.1 without doing
368     RESET MASTER, or from 4.x to 5.0).
369   */
370   Format_description_log_event *description_event_for_exec,
371     *description_event_for_queue;
372 
373   MYSQL_BIN_LOG(uint *sync_period);
374   /*
375     note that there's no destructor ~MYSQL_BIN_LOG() !
376     The reason is that we don't want it to be automatically called
377     on exit() - but only during the correct shutdown process
378   */
379 
380 #ifdef HAVE_PSI_INTERFACE
set_psi_keys(PSI_mutex_key key_LOCK_index,PSI_cond_key key_update_cond,PSI_file_key key_file_log,PSI_file_key key_file_log_index)381   void set_psi_keys(PSI_mutex_key key_LOCK_index,
382                     PSI_cond_key key_update_cond,
383                     PSI_file_key key_file_log,
384                     PSI_file_key key_file_log_index)
385   {
386     m_key_LOCK_index= key_LOCK_index;
387     m_key_update_cond= key_update_cond;
388     m_key_file_log= key_file_log;
389     m_key_file_log_index= key_file_log_index;
390   }
391 #endif
392 
393   int open(const char *opt_name);
394   void close();
395   int log_xid(THD *thd, my_xid xid);
396   int unlog(ulong cookie, my_xid xid);
397   int recover(IO_CACHE *log, Format_description_log_event *fdle);
398 #if !defined(MYSQL_CLIENT)
399 
400   int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
401                                        bool is_transactional);
402   int remove_pending_rows_event(THD *thd, bool is_transactional);
403 
404 #endif /* !defined(MYSQL_CLIENT) */
reset_bytes_written()405   void reset_bytes_written()
406   {
407     bytes_written = 0;
408   }
harvest_bytes_written(ulonglong * counter)409   void harvest_bytes_written(ulonglong* counter)
410   {
411 #ifndef DBUG_OFF
412     char buf1[22],buf2[22];
413 #endif
414     DBUG_ENTER("harvest_bytes_written");
415     (*counter)+=bytes_written;
416     DBUG_PRINT("info",("counter: %s  bytes_written: %s", llstr(*counter,buf1),
417 		       llstr(bytes_written,buf2)));
418     bytes_written=0;
419     DBUG_VOID_RETURN;
420   }
421   void set_max_size(ulong max_size_arg);
422   void signal_update();
423   void wait_for_update_relay_log(THD* thd);
424   int  wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
set_need_start_event()425   void set_need_start_event() { need_start_event = 1; }
426   void init(bool no_auto_events_arg, ulong max_size);
427   void init_pthread_objects();
428   void cleanup();
429   bool open(const char *log_name,
430             enum_log_type log_type,
431             const char *new_name,
432 	    enum cache_type io_cache_type_arg,
433 	    bool no_auto_events_arg, ulong max_size,
434             bool null_created,
435             bool need_mutex);
436   bool open_index_file(const char *index_file_name_arg,
437                        const char *log_name, bool need_mutex);
438   /* Use this to start writing a new log file */
439   int new_file();
440 
441   bool write(Log_event* event_info); // binary log write
442   bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
443   bool write_incident(THD *thd, bool lock);
444 
445   int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
446   void set_write_error(THD *thd, bool is_transactional);
447   bool check_write_error(THD *thd);
448 
449   void start_union_events(THD *thd, query_id_t query_id_param);
450   void stop_union_events(THD *thd);
451   bool is_query_in_union(THD *thd, query_id_t query_id_param);
452 
453   /*
454     v stands for vector
455     invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
456   */
457   bool appendv(const char* buf,uint len,...);
458   bool append(Log_event* ev);
459 
460   void make_log_name(char* buf, const char* log_ident);
461   bool is_active(const char* log_file_name);
462   int update_log_index(LOG_INFO* linfo, bool need_update_threads);
463   int rotate(bool force_rotate, bool* check_purge);
464   void purge();
465   int rotate_and_purge(bool force_rotate);
466   /**
467      Flush binlog cache and synchronize to disk.
468 
469      This function flushes events in binlog cache to binary log file,
470      it will do synchronizing according to the setting of system
471      variable 'sync_binlog'. If file is synchronized, @c synced will
472      be set to 1, otherwise 0.
473 
474      @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
475 
476      @retval 0 Success
477      @retval other Failure
478   */
479   bool flush_and_sync(bool *synced);
480   int purge_logs(const char *to_log, bool included,
481                  bool need_mutex, bool need_update_threads,
482                  ulonglong *decrease_log_space);
483   int purge_logs_before_date(time_t purge_time);
484   int purge_first_log(Relay_log_info* rli, bool included);
485   int set_purge_index_file_name(const char *base_file_name);
486   int open_purge_index_file(bool destroy);
487   bool is_inited_purge_index_file();
488   int close_purge_index_file();
489   int clean_purge_index_file();
490   int sync_purge_index_file();
491   int register_purge_index_entry(const char* entry);
492   int register_create_index_entry(const char* entry);
493   int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
494                         bool need_mutex);
495   bool reset_logs(THD* thd);
496   void close(uint exiting);
497 
498   // iterating through the log index file
499   int find_log_pos(LOG_INFO* linfo, const char* log_name,
500 		   bool need_mutex);
501   int find_next_log(LOG_INFO* linfo, bool need_mutex);
502   int get_current_log(LOG_INFO* linfo);
503   int raw_get_current_log(LOG_INFO* linfo);
504   uint next_file_id();
get_index_fname()505   inline char* get_index_fname() { return index_file_name;}
get_log_fname()506   inline char* get_log_fname() { return log_file_name; }
get_name()507   inline char* get_name() { return name; }
get_log_lock()508   inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_log_cond()509   inline mysql_cond_t* get_log_cond() { return &update_cond; }
get_log_file()510   inline IO_CACHE* get_log_file() { return &log_file; }
511 
lock_index()512   inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()513   inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()514   inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()515   inline uint32 get_open_count() { return open_count; }
516 };
517 
518 class Log_event_handler
519 {
520 public:
Log_event_handler()521   Log_event_handler() {}
522   virtual bool init()= 0;
523   virtual void cleanup()= 0;
524 
525   virtual bool log_slow(THD *thd, time_t current_time,
526                         time_t query_start_arg, const char *user_host,
527                         uint user_host_len, ulonglong query_utime,
528                         ulonglong lock_utime, bool is_command,
529                         const char *sql_text, uint sql_text_len)= 0;
530   virtual bool log_error(enum loglevel level, const char *format,
531                          va_list args)= 0;
532   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
533                            uint user_host_len, int thread_id,
534                            const char *command_type, uint command_type_len,
535                            const char *sql_text, uint sql_text_len,
536                            CHARSET_INFO *client_cs)= 0;
~Log_event_handler()537   virtual ~Log_event_handler() {}
538 };
539 
540 
541 int check_if_log_table(size_t db_len, const char *db, size_t table_name_len,
542                        const char *table_name, bool check_if_opened);
543 
544 class Log_to_csv_event_handler: public Log_event_handler
545 {
546   friend class LOGGER;
547 
548 public:
549   Log_to_csv_event_handler();
550   ~Log_to_csv_event_handler();
551   virtual bool init();
552   virtual void cleanup();
553 
554   virtual bool log_slow(THD *thd, time_t current_time,
555                         time_t query_start_arg, const char *user_host,
556                         uint user_host_len, ulonglong query_utime,
557                         ulonglong lock_utime, bool is_command,
558                         const char *sql_text, uint sql_text_len);
559   virtual bool log_error(enum loglevel level, const char *format,
560                          va_list args);
561   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
562                            uint user_host_len, int thread_id,
563                            const char *command_type, uint command_type_len,
564                            const char *sql_text, uint sql_text_len,
565                            CHARSET_INFO *client_cs);
566 
567   int activate_log(THD *thd, uint log_type);
568 };
569 
570 
571 /* type of the log table */
572 #define QUERY_LOG_SLOW 1
573 #define QUERY_LOG_GENERAL 2
574 
575 class Log_to_file_event_handler: public Log_event_handler
576 {
577   MYSQL_QUERY_LOG mysql_log;
578   MYSQL_QUERY_LOG mysql_slow_log;
579   bool is_initialized;
580 public:
Log_to_file_event_handler()581   Log_to_file_event_handler(): is_initialized(FALSE)
582   {}
583   virtual bool init();
584   virtual void cleanup();
585 
586   virtual bool log_slow(THD *thd, time_t current_time,
587                         time_t query_start_arg, const char *user_host,
588                         uint user_host_len, ulonglong query_utime,
589                         ulonglong lock_utime, bool is_command,
590                         const char *sql_text, uint sql_text_len);
591   virtual bool log_error(enum loglevel level, const char *format,
592                          va_list args);
593   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
594                            uint user_host_len, int thread_id,
595                            const char *command_type, uint command_type_len,
596                            const char *sql_text, uint sql_text_len,
597                            CHARSET_INFO *client_cs);
598   void flush();
599   void init_pthread_objects();
get_mysql_slow_log()600   MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
get_mysql_log()601   MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
602 };
603 
604 
605 /* Class which manages slow, general and error log event handlers */
606 class LOGGER
607 {
608   mysql_rwlock_t LOCK_logger;
609   /* flag to check whether logger mutex is initialized */
610   uint inited;
611 
612   /* available log handlers */
613   Log_to_csv_event_handler *table_log_handler;
614   Log_to_file_event_handler *file_log_handler;
615 
616   /* NULL-terminated arrays of log handlers */
617   Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
618   Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
619   Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
620 
621 public:
622 
623   bool is_log_tables_initialized;
624 
LOGGER()625   LOGGER() : inited(0), table_log_handler(NULL),
626              file_log_handler(NULL), is_log_tables_initialized(FALSE)
627   {}
lock_shared()628   void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); }
lock_exclusive()629   void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); }
unlock()630   void unlock() { mysql_rwlock_unlock(&LOCK_logger); }
631   bool is_log_table_enabled(uint log_table_type);
632   bool log_command(THD *thd, enum enum_server_command command);
633 
634   /*
635     We want to initialize all log mutexes as soon as possible,
636     but we cannot do it in constructor, as safe_mutex relies on
637     initialization, performed by MY_INIT(). This why this is done in
638     this function.
639   */
640   void init_base();
641   void init_log_tables();
642   bool flush_logs(THD *thd);
643   bool flush_slow_log();
644   bool flush_general_log();
645   /* Perform basic logger cleanup. this will leave e.g. error log open. */
646   void cleanup_base();
647   /* Free memory. Nothing could be logged after this function is called */
648   void cleanup_end();
649   bool error_log_print(enum loglevel level, const char *format,
650                       va_list args);
651   bool slow_log_print(THD *thd, const char *query, uint query_length,
652                       ulonglong current_utime);
653   bool general_log_print(THD *thd,enum enum_server_command command,
654                          const char *format, va_list args);
655   bool general_log_write(THD *thd, enum enum_server_command command,
656                          const char *query, uint query_length);
657 
658   /* we use this function to setup all enabled log event handlers */
659   int set_handlers(uint error_log_printer,
660                    uint slow_log_printer,
661                    uint general_log_printer);
662   void init_error_log(uint error_log_printer);
663   void init_slow_log(uint slow_log_printer);
664   void init_general_log(uint general_log_printer);
665   void deactivate_log_handler(THD* thd, uint log_type);
666   bool activate_log_handler(THD* thd, uint log_type);
get_slow_log_file_handler()667   MYSQL_QUERY_LOG *get_slow_log_file_handler() const
668   {
669     if (file_log_handler)
670       return file_log_handler->get_mysql_slow_log();
671     return NULL;
672   }
get_log_file_handler()673   MYSQL_QUERY_LOG *get_log_file_handler() const
674   {
675     if (file_log_handler)
676       return file_log_handler->get_mysql_log();
677     return NULL;
678   }
679 };
680 
681 enum enum_binlog_format {
682   BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected
683   BINLOG_FORMAT_STMT=  1, ///< statement-based
684   BINLOG_FORMAT_ROW=   2, ///< row-based
685   BINLOG_FORMAT_UNSPEC=3  ///< thd_binlog_format() returns it when binlog is closed
686 };
687 
688 int query_error_code(THD *thd, bool not_killed);
689 uint purge_log_get_error_code(int res);
690 
691 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
692 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
693 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
694 void sql_print_information(const char *format, ...)
695   ATTRIBUTE_FORMAT(printf, 1, 2);
696 typedef void (*sql_print_message_func)(const char *format, ...)
697   ATTRIBUTE_FORMAT_FPTR(printf, 1, 2);
698 extern sql_print_message_func sql_print_message_handlers[];
699 
700 int error_log_print(enum loglevel level, const char *format,
701                     va_list args);
702 
703 bool slow_log_print(THD *thd, const char *query, uint query_length,
704                     ulonglong current_utime);
705 
706 bool general_log_print(THD *thd, enum enum_server_command command,
707                        const char *format,...);
708 
709 bool general_log_write(THD *thd, enum enum_server_command command,
710                        const char *query, uint query_length);
711 
712 void sql_perror(const char *message);
713 bool flush_error_log();
714 
715 File open_binlog(IO_CACHE *log, const char *log_file_name,
716                  const char **errmsg);
717 
718 char *make_log_name(char *buff, const char *name, const char* log_ext);
719 
720 /**
721   Check given log name against certain blacklisted names/extensions.
722 
723   @param name     Log name to check
724   @param len      Length of log name
725 
726   @returns true if name is valid, false otherwise.
727 */
728 bool is_valid_log_name(const char *name, size_t len);
729 
730 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
731 extern LOGGER logger;
732 
733 
734 /**
735   Turns a relative log binary log path into a full path, based on the
736   opt_bin_logname or opt_relay_logname.
737 
738   @param from         The log name we want to make into an absolute path.
739   @param to           The buffer where to put the results of the
740                       normalization.
741   @param is_relay_log Switch that makes is used inside to choose which
742                       option (opt_bin_logname or opt_relay_logname) to
743                       use when calculating the base path.
744 
745   @returns true if a problem occurs, false otherwise.
746  */
747 
normalize_binlog_name(char * to,const char * from,bool is_relay_log)748 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
749 {
750   DBUG_ENTER("normalize_binlog_name");
751   bool error= false;
752   char buff[FN_REFLEN];
753   char *ptr= (char*) from;
754   char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
755 
756   DBUG_ASSERT(from);
757 
758   /* opt_name is not null and not empty and from is a relative path */
759   if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
760   {
761     // take the path from opt_name
762     // take the filename from from
763     char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
764     size_t log_dirpart_len, log_dirname_len;
765     dirname_part(log_dirpart, opt_name, &log_dirpart_len);
766     dirname_part(log_dirname, from, &log_dirname_len);
767 
768     /* log may be empty => relay-log or log-bin did not
769         hold paths, just filename pattern */
770     if (log_dirpart_len > 0)
771     {
772       /* create the new path name */
773       if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
774                    MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
775       {
776         error= true;
777         goto end;
778       }
779 
780       ptr= buff;
781     }
782   }
783 
784   DBUG_ASSERT(ptr);
785 
786   if (ptr)
787     strmake(to, ptr, strlen(ptr));
788 
789 end:
790   DBUG_RETURN(error);
791 }
792 
793 
794 
795 #endif /* LOG_H */
796