My Project
log.h
00001 /* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00015 
00016 #ifndef LOG_H
00017 #define LOG_H
00018 
00019 #include "unireg.h"                    // REQUIRED: for other includes
00020 #include "handler.h"                            /* my_xid */
00021 
00031 typedef struct event_coordinates
00032 {
00033   char * file_name; // binlog file name (directories stripped)
00034   my_off_t  pos;       // event's position in the binlog file
00035 } LOG_POS_COORD;
00036 
00048 class TC_LOG
00049 {
00050   public:
00051   int using_heuristic_recover();
00052   TC_LOG() {}
00053   virtual ~TC_LOG() {}
00054 
00055   enum enum_result {
00056     RESULT_SUCCESS,
00057     RESULT_ABORTED,
00058     RESULT_INCONSISTENT
00059   };
00060 
00061   virtual int open(const char *opt_name)=0;
00062   virtual void close()=0;
00063 
00077   virtual enum_result commit(THD *thd, bool all) = 0;
00078 
00093   virtual int rollback(THD *thd, bool all) = 0;
00104   virtual int prepare(THD *thd, bool all) = 0;
00105 };
00106 
00107 
00108 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging
00109 {
00110 public:
00111   TC_LOG_DUMMY() {}
00112   int open(const char *opt_name)        { return 0; }
00113   void close()                          { }
00114   enum_result commit(THD *thd, bool all) {
00115     return ha_commit_low(thd, all) ? RESULT_ABORTED : RESULT_SUCCESS;
00116   }
00117   int rollback(THD *thd, bool all) {
00118     return ha_rollback_low(thd, all);
00119   }
00120   int prepare(THD *thd, bool all) {
00121     return ha_prepare_low(thd, all);
00122   }
00123 };
00124 
00125 #ifdef HAVE_MMAP
00126 class TC_LOG_MMAP: public TC_LOG
00127 {
00128   public:                // only to keep Sun Forte on sol9x86 happy
00129   typedef enum {
00130     PS_POOL,                 // page is in pool
00131     PS_ERROR,                // last sync failed
00132     PS_DIRTY                 // new xids added since last sync
00133   } PAGE_STATE;
00134 
00135   private:
00136   typedef struct st_page {
00137     struct st_page *next; // page a linked in a fifo queue
00138     my_xid *start, *end;  // usable area of a page
00139     my_xid *ptr;          // next xid will be written here
00140     int size, free;       // max and current number of free xid slots on the page
00141     int waiters;          // number of waiters on condition
00142     PAGE_STATE state;     // see above
00143     mysql_mutex_t lock; // to access page data or control structure
00144     mysql_cond_t  cond; // to wait for a sync
00145   } PAGE;
00146 
00147   char logname[FN_REFLEN];
00148   File fd;
00149   my_off_t file_length;
00150   uint npages, inited;
00151   uchar *data;
00152   struct st_page *pages, *syncing, *active, *pool, *pool_last;
00153   /*
00154     note that, e.g. LOCK_active is only used to protect
00155     'active' pointer, to protect the content of the active page
00156     one has to use active->lock.
00157     Same for LOCK_pool and LOCK_sync
00158   */
00159   mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync;
00160   mysql_cond_t COND_pool, COND_active;
00161 
00162   public:
00163   TC_LOG_MMAP(): inited(0) {}
00164   int open(const char *opt_name);
00165   void close();
00166   enum_result commit(THD *thd, bool all);
00167   int rollback(THD *thd, bool all)      { return ha_rollback_low(thd, all); }
00168   int prepare(THD *thd, bool all)       { return ha_prepare_low(thd, all); }
00169   int recover();
00170 
00171 private:
00172   int log_xid(THD *thd, my_xid xid);
00173   int unlog(ulong cookie, my_xid xid);
00174   void get_active_from_pool();
00175   int sync();
00176   int overflow();
00177 };
00178 #else
00179 #define TC_LOG_MMAP TC_LOG_DUMMY
00180 #endif
00181 
00182 extern TC_LOG *tc_log;
00183 extern TC_LOG_MMAP tc_log_mmap;
00184 extern TC_LOG_DUMMY tc_log_dummy;
00185 
00186 /* log info errors */
00187 #define LOG_INFO_EOF -1
00188 #define LOG_INFO_IO  -2
00189 #define LOG_INFO_INVALID -3
00190 #define LOG_INFO_SEEK -4
00191 #define LOG_INFO_MEM -6
00192 #define LOG_INFO_FATAL -7
00193 #define LOG_INFO_IN_USE -8
00194 #define LOG_INFO_EMFILE -9
00195 
00196 
00197 /* bitmap to SQL_LOG::close() */
00198 #define LOG_CLOSE_INDEX         1
00199 #define LOG_CLOSE_TO_BE_OPENED  2
00200 #define LOG_CLOSE_STOP_EVENT    4
00201 
00202 /* 
00203   Maximum unique log filename extension.
00204   Note: setting to 0x7FFFFFFF due to atol windows 
00205         overflow/truncate.
00206  */
00207 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
00208 
00209 /* 
00210    Number of warnings that will be printed to error log
00211    before extension number is exhausted.
00212 */
00213 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000
00214 
00215 #ifdef HAVE_PSI_INTERFACE
00216 extern PSI_mutex_key key_LOG_INFO_lock;
00217 #endif
00218 
00219 /*
00220   Note that we destroy the lock mutex in the desctructor here.
00221   This means that object instances cannot be destroyed/go out of scope,
00222   until we have reset thd->current_linfo to NULL;
00223  */
00224 typedef struct st_log_info
00225 {
00226   char log_file_name[FN_REFLEN];
00227   my_off_t index_file_offset, index_file_start_offset;
00228   my_off_t pos;
00229   bool fatal; // if the purge happens to give us a negative offset
00230   int entry_index; //used in purge_logs(), calculatd in find_log_pos().
00231   mysql_mutex_t lock;
00232   st_log_info()
00233     : index_file_offset(0), index_file_start_offset(0),
00234       pos(0), fatal(0), entry_index(0)
00235     {
00236       log_file_name[0] = '\0';
00237       mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST);
00238     }
00239   ~st_log_info() { mysql_mutex_destroy(&lock);}
00240 } LOG_INFO;
00241 
00242 /*
00243   Currently we have only 3 kinds of logging functions: old-fashioned
00244   logs, stdout and csv logging routines.
00245 */
00246 #define MAX_LOG_HANDLERS_NUM 3
00247 
00248 /* log event handler flags */
00249 #define LOG_NONE       1
00250 #define LOG_FILE       2
00251 #define LOG_TABLE      4
00252 
00253 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
00254 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
00255 
00256 /*
00257   TODO use mmap instead of IO_CACHE for binlog
00258   (mmap+fsync is two times faster than write+fsync)
00259 */
00260 
00261 class MYSQL_LOG
00262 {
00263 public:
00264   MYSQL_LOG();
00265   void init_pthread_objects();
00266   void cleanup();
00267   bool open(
00268 #ifdef HAVE_PSI_INTERFACE
00269             PSI_file_key log_file_key,
00270 #endif
00271             const char *log_name,
00272             enum_log_type log_type,
00273             const char *new_name,
00274             enum cache_type io_cache_type_arg);
00275   bool init_and_set_log_file_name(const char *log_name,
00276                                   const char *new_name,
00277                                   enum_log_type log_type_arg,
00278                                   enum cache_type io_cache_type_arg);
00279   void init(enum_log_type log_type_arg,
00280             enum cache_type io_cache_type_arg);
00281   void close(uint exiting);
00282   inline bool is_open() { return log_state != LOG_CLOSED; }
00283   const char *generate_name(const char *log_name, const char *suffix,
00284                             bool strip_ext, char *buff);
00285   int generate_new_name(char *new_name, const char *log_name);
00286  protected:
00287   /* LOCK_log is inited by init_pthread_objects() */
00288   mysql_mutex_t LOCK_log;
00289   char *name;
00290   char log_file_name[FN_REFLEN];
00291   char time_buff[20], db[NAME_LEN + 1];
00292   bool write_error, inited;
00293   IO_CACHE log_file;
00294   enum_log_type log_type;
00295   volatile enum_log_state log_state;
00296   enum cache_type io_cache_type;
00297   friend class Log_event;
00298 #ifdef HAVE_PSI_INTERFACE
00299 
00300   PSI_file_key m_log_file_key;
00302   PSI_mutex_key m_key_LOCK_log;
00303 #endif
00304 };
00305 
00306 
00307 enum enum_general_log_table_field
00308 {
00309   GLT_FIELD_EVENT_TIME = 0,
00310   GLT_FIELD_USER_HOST,
00311   GLT_FIELD_THREAD_ID,
00312   GLT_FIELD_SERVER_ID,
00313   GLT_FIELD_COMMAND_TYPE,
00314   GLT_FIELD_ARGUMENT,
00315   GLT_FIELD_COUNT
00316 };
00317 
00318 
00319 enum enum_slow_query_log_table_field
00320 {
00321   SQLT_FIELD_START_TIME = 0,
00322   SQLT_FIELD_USER_HOST,
00323   SQLT_FIELD_QUERY_TIME,
00324   SQLT_FIELD_LOCK_TIME,
00325   SQLT_FIELD_ROWS_SENT,
00326   SQLT_FIELD_ROWS_EXAMINED,
00327   SQLT_FIELD_DATABASE,
00328   SQLT_FIELD_LAST_INSERT_ID,
00329   SQLT_FIELD_INSERT_ID,
00330   SQLT_FIELD_SERVER_ID,
00331   SQLT_FIELD_SQL_TEXT,
00332   SQLT_FIELD_THREAD_ID,
00333   SQLT_FIELD_COUNT
00334 };
00335 
00336 
00337 class MYSQL_QUERY_LOG: public MYSQL_LOG
00338 {
00339 public:
00340   MYSQL_QUERY_LOG() : last_time(0) {}
00341   void reopen_file();
00342   bool write(time_t event_time, const char *user_host,
00343              uint user_host_len, my_thread_id thread_id,
00344              const char *command_type, uint command_type_len,
00345              const char *sql_text, uint sql_text_len);
00346   bool write(THD *thd, time_t current_time, time_t query_start_arg,
00347              const char *user_host, uint user_host_len,
00348              ulonglong query_utime, ulonglong lock_utime, bool is_command,
00349              const char *sql_text, uint sql_text_len);
00350   bool open_slow_log(const char *log_name)
00351   {
00352     char buf[FN_REFLEN];
00353     return open(
00354 #ifdef HAVE_PSI_INTERFACE
00355                 key_file_slow_log,
00356 #endif
00357                 generate_name(log_name, "-slow.log", 0, buf),
00358                 LOG_NORMAL, 0, WRITE_CACHE);
00359   }
00360   bool open_query_log(const char *log_name)
00361   {
00362     char buf[FN_REFLEN];
00363     return open(
00364 #ifdef HAVE_PSI_INTERFACE
00365                 key_file_query_log,
00366 #endif
00367                 generate_name(log_name, ".log", 0, buf),
00368                 LOG_NORMAL, 0, WRITE_CACHE);
00369   }
00370 
00371 private:
00372   time_t last_time;
00373 };
00374 
00375 class Log_event_handler
00376 {
00377 public:
00378   Log_event_handler() {}
00379   virtual bool init()= 0;
00380   virtual void cleanup()= 0;
00381 
00382   virtual bool log_slow(THD *thd, time_t current_time,
00383                         time_t query_start_arg, const char *user_host,
00384                         uint user_host_len, ulonglong query_utime,
00385                         ulonglong lock_utime, bool is_command,
00386                         const char *sql_text, uint sql_text_len)= 0;
00387   virtual bool log_error(enum loglevel level, const char *format,
00388                          va_list args)= 0;
00389   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
00390                            uint user_host_len, my_thread_id thread_id,
00391                            const char *command_type, uint command_type_len,
00392                            const char *sql_text, uint sql_text_len,
00393                            const CHARSET_INFO *client_cs)= 0;
00394   virtual ~Log_event_handler() {}
00395 };
00396 
00397 
00398 int check_if_log_table(size_t db_len, const char *db, size_t table_name_len,
00399                        const char *table_name, bool check_if_opened);
00400 
00401 class Log_to_csv_event_handler: public Log_event_handler
00402 {
00403 public:
00404   Log_to_csv_event_handler();
00405   ~Log_to_csv_event_handler();
00406   virtual bool init();
00407   virtual void cleanup();
00408 
00409   virtual bool log_slow(THD *thd, time_t current_time,
00410                         time_t query_start_arg, const char *user_host,
00411                         uint user_host_len, ulonglong query_utime,
00412                         ulonglong lock_utime, bool is_command,
00413                         const char *sql_text, uint sql_text_len);
00414   virtual bool log_error(enum loglevel level, const char *format,
00415                          va_list args);
00416   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
00417                            uint user_host_len, my_thread_id thread_id,
00418                            const char *command_type, uint command_type_len,
00419                            const char *sql_text, uint sql_text_len,
00420                            const CHARSET_INFO *client_cs);
00421 
00422   int activate_log(THD *thd, uint log_type);
00423 };
00424 
00425 
00426 /* type of the log table */
00427 #define QUERY_LOG_SLOW 1
00428 #define QUERY_LOG_GENERAL 2
00429 
00430 class Log_to_file_event_handler: public Log_event_handler
00431 {
00432   MYSQL_QUERY_LOG mysql_log;
00433   MYSQL_QUERY_LOG mysql_slow_log;
00434   bool is_initialized;
00435 public:
00436   Log_to_file_event_handler(): is_initialized(FALSE)
00437   {}
00438   virtual bool init();
00439   virtual void cleanup();
00440 
00441   virtual bool log_slow(THD *thd, time_t current_time,
00442                         time_t query_start_arg, const char *user_host,
00443                         uint user_host_len, ulonglong query_utime,
00444                         ulonglong lock_utime, bool is_command,
00445                         const char *sql_text, uint sql_text_len);
00446   virtual bool log_error(enum loglevel level, const char *format,
00447                          va_list args);
00448   virtual bool log_general(THD *thd, time_t event_time, const char *user_host,
00449                            uint user_host_len, my_thread_id thread_id,
00450                            const char *command_type, uint command_type_len,
00451                            const char *sql_text, uint sql_text_len,
00452                            const CHARSET_INFO *client_cs);
00453   void flush();
00454   void init_pthread_objects();
00455   MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
00456   MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
00457 };
00458 
00459 
00460 /* Class which manages slow, general and error log event handlers */
00461 class LOGGER
00462 {
00463   mysql_rwlock_t LOCK_logger;
00464   /* flag to check whether logger mutex is initialized */
00465   uint inited;
00466 
00467   /* available log handlers */
00468   Log_to_csv_event_handler *table_log_handler;
00469   Log_to_file_event_handler *file_log_handler;
00470 
00471   /* NULL-terminated arrays of log handlers */
00472   Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
00473   Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
00474   Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
00475 
00476 public:
00477 
00478   bool is_log_tables_initialized;
00479 
00480   LOGGER() : inited(0), table_log_handler(NULL),
00481              file_log_handler(NULL), is_log_tables_initialized(FALSE)
00482   {}
00483   void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); }
00484   void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); }
00485   void unlock() { mysql_rwlock_unlock(&LOCK_logger); }
00486   bool is_log_table_enabled(uint log_table_type);
00487   bool log_command(THD *thd, enum enum_server_command command,
00488                    const char *query_str, size_t query_length);
00489 
00490   /*
00491     We want to initialize all log mutexes as soon as possible,
00492     but we cannot do it in constructor, as safe_mutex relies on
00493     initialization, performed by MY_INIT(). This why this is done in
00494     this function.
00495   */
00496   void init_base();
00497   void init_log_tables();
00498   bool flush_logs(THD *thd);
00499   bool flush_slow_log();
00500   bool flush_general_log();
00501   /* Perform basic logger cleanup. this will leave e.g. error log open. */
00502   void cleanup_base();
00503   /* Free memory. Nothing could be logged after this function is called */
00504   void cleanup_end();
00505   bool error_log_print(enum loglevel level, const char *format,
00506                       va_list args);
00507   bool slow_log_print(THD *thd, const char *query, uint query_length);
00508   bool general_log_print(THD *thd,enum enum_server_command command,
00509                          const char *format, va_list args);
00510   bool general_log_write(THD *thd, enum enum_server_command command,
00511                          const char *query, uint query_length);
00512 
00513   /* we use this function to setup all enabled log event handlers */
00514   int set_handlers(uint error_log_printer,
00515                    uint slow_log_printer,
00516                    uint general_log_printer);
00517   void init_error_log(uint error_log_printer);
00518   void init_slow_log(uint slow_log_printer);
00519   void init_general_log(uint general_log_printer);
00520   void deactivate_log_handler(THD* thd, uint log_type);
00521   bool activate_log_handler(THD* thd, uint log_type);
00522   MYSQL_QUERY_LOG *get_slow_log_file_handler() const
00523   { 
00524     if (file_log_handler)
00525       return file_log_handler->get_mysql_slow_log();
00526     return NULL;
00527   }
00528   MYSQL_QUERY_LOG *get_log_file_handler() const
00529   { 
00530     if (file_log_handler)
00531       return file_log_handler->get_mysql_log();
00532     return NULL;
00533   }
00534 };
00535 
00536 enum enum_binlog_row_image {
00538   BINLOG_ROW_IMAGE_MINIMAL= 0,
00540   BINLOG_ROW_IMAGE_NOBLOB= 1,
00542   BINLOG_ROW_IMAGE_FULL= 2
00543 };
00544 
00545 enum enum_binlog_format {
00546   BINLOG_FORMAT_MIXED= 0, 
00547   BINLOG_FORMAT_STMT=  1, 
00548   BINLOG_FORMAT_ROW=   2, 
00549   BINLOG_FORMAT_UNSPEC=3  
00550 };
00551 
00552 int query_error_code(THD *thd, bool not_killed);
00553 uint purge_log_get_error_code(int res);
00554 
00555 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
00556 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
00557 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
00558 void sql_print_information(const char *format, ...)
00559   ATTRIBUTE_FORMAT(printf, 1, 2);
00560 typedef void (*sql_print_message_func)(const char *format, ...)
00561   ATTRIBUTE_FORMAT_FPTR(printf, 1, 2);
00562 extern sql_print_message_func sql_print_message_handlers[];
00563 
00564 int error_log_print(enum loglevel level, const char *format,
00565                     va_list args);
00566 
00567 bool slow_log_print(THD *thd, const char *query, uint query_length);
00568 
00569 bool general_log_print(THD *thd, enum enum_server_command command,
00570                        const char *format,...);
00571 
00572 bool general_log_write(THD *thd, enum enum_server_command command,
00573                        const char *query, uint query_length);
00574 
00575 void sql_perror(const char *message);
00576 bool flush_error_log();
00577 
00578 char *make_log_name(char *buff, const char *name, const char* log_ext);
00579 
00580 extern LOGGER logger;
00581 
00582 #endif /* LOG_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines