From 5c01f1ac1498a9b32bdccb817cdbc0b3ca3687d6 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sat, 24 Mar 2012 11:24:20 +0100 Subject: MDEV-15 Log all sql errors. modified for MySQL 5.5. Logger service moved to the plugin/sql_errlog directory to be properly used later. plugin/sql_errlog/sql_errlog.c: Fixes for bugs #956427 (SQL_ERROR_LOG plugin produces bogus warnings about sql-error-log-size-limit value) and #956463 (Server crashes if SQL_ERROR_LOG fails to initialize) they're also MDEV-184 and MDEV-183 The sql_error_log_deinit() should be prepared for the logger_file to be NULL. The logger_file_size_limit upper limit wasn't properly set. --- include/mysql/plugin_audit.h.pp | 18 ---- include/mysql/plugin_auth.h.pp | 18 ---- include/mysql/plugin_ftparser.h.pp | 18 ---- include/mysql/service_logger.h | 98 ------------------- include/mysql/services.h | 1 - include/service_versions.h | 1 - libmysqld/CMakeLists.txt | 1 - libservices/CMakeLists.txt | 3 +- libservices/logger_service.c | 20 ---- plugin/sql_errlog/CMakeLists.txt | 2 +- plugin/sql_errlog/logger_service.c | 21 ++++ plugin/sql_errlog/service_logger.h | 100 +++++++++++++++++++ plugin/sql_errlog/sql_errlog.c | 27 +++++- plugin/sql_errlog/sql_logger.cc | 194 +++++++++++++++++++++++++++++++++++++ sql/CMakeLists.txt | 1 - sql/mysqld.cc | 3 - sql/sql_logger.cc | 183 ---------------------------------- sql/sql_plugin_services.h | 9 -- 18 files changed, 342 insertions(+), 376 deletions(-) delete mode 100644 include/mysql/service_logger.h delete mode 100644 libservices/logger_service.c create mode 100644 plugin/sql_errlog/logger_service.c create mode 100644 plugin/sql_errlog/service_logger.h create mode 100644 plugin/sql_errlog/sql_logger.cc delete mode 100644 sql/sql_logger.cc diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index dd7dde7973c..cdd9324a5f7 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -80,24 +80,6 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index cf3b60d128b..e06494746dd 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -80,24 +80,6 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 14129aec85e..a990c62e8e9 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -80,24 +80,6 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/service_logger.h b/include/mysql/service_logger.h deleted file mode 100644 index 47a478ef5b4..00000000000 --- a/include/mysql/service_logger.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2012 Monty Program Ab - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#ifndef MYSQL_SERVICE_LOGGER_INCLUDED -#define MYSQL_SERVICE_LOGGER_INCLUDED - -#ifndef MYSQL_ABI_CHECK -#include -#endif - -/** - @file - logger service - - Log file with rotation implementation. - - This service implements logging with possible rotation - of the log files. Interface intentionally tries to be similar to FILE* - related functions. - - So that one can open the log with logger_open(), specifying - the limit on the logfile size and the rotations number. - - Then it's possible to write messages to the log with - logger_printf or logger_vprintf functions. - - As the size of the logfile grows over the specified limit, - it is renamed to 'logfile.1'. The former 'logfile.1' becomes - 'logfile.2', etc. The file 'logfile.rotations' is removed. - That's how the rotation works. - - The rotation can be forced with the logger_rotate() call. - - Finally the log should be closed with logger_close(). - -@notes: - Implementation checks the size of the log file before it starts new - printf into it. So the size of the file gets over the limit when it rotates. - - The access is secured with the mutex, so the log is threadsafe. -*/ - - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct logger_handle_st LOGGER_HANDLE; - -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - -#ifdef MYSQL_DYNAMIC_PLUGIN - -#define logger_open(path, size_limit, rotations) \ - (logger_service->open(path, size_limit, rotations)) -#define logger_close(log) (logger_service->close(log)) -#define logger_rotate(log) (logger_service->rotate(log)) -#define logger_vprintf(log, fmt, argptr) (logger_service->\ - vprintf(log, fmt, argptr)) -#define logger_printf logger_service->printf -#else - - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /*MYSQL_SERVICE_LOGGER_INCLUDED*/ - diff --git a/include/mysql/services.h b/include/mysql/services.h index 258f7b90658..dd0fa58db89 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -23,7 +23,6 @@ extern "C" { #include #include #include -#include #ifdef __cplusplus diff --git a/include/service_versions.h b/include/service_versions.h index 8a397d71b12..ee50d4856e9 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -24,4 +24,3 @@ #define VERSION_thd_wait 0x0100 #define VERSION_my_thread_scheduler 0x0100 #define VERSION_progress_report 0x0100 -#define VERSION_logger 0x0100 diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 6603983e69b..14db8327897 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -95,7 +95,6 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/create_options.cc ../sql/rpl_utility.cc ../sql/rpl_reporting.cc ../sql/sql_expression_cache.cc - ../sql/sql_logger.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index dd16558ef9c..ee6a7c73abe 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -20,8 +20,7 @@ SET(MYSQLSERVICES_SOURCES thd_alloc_service.c thd_wait_service.c my_thread_scheduler_service.c - progress_report_service.c - logger_service.c) + progress_report_service.c) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development) diff --git a/libservices/logger_service.c b/libservices/logger_service.c deleted file mode 100644 index 896b0714293..00000000000 --- a/libservices/logger_service.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 2012 Monty Program Ab - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include - - -SERVICE_VERSION *logger_service= (void *) VERSION_logger; - diff --git a/plugin/sql_errlog/CMakeLists.txt b/plugin/sql_errlog/CMakeLists.txt index 18fb9f5421d..50c4b7d806d 100644 --- a/plugin/sql_errlog/CMakeLists.txt +++ b/plugin/sql_errlog/CMakeLists.txt @@ -13,4 +13,4 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c MODULE_ONLY) +MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c sql_logger.cc service_logger.h MODULE_ONLY) diff --git a/plugin/sql_errlog/logger_service.c b/plugin/sql_errlog/logger_service.c new file mode 100644 index 00000000000..c45e978413c --- /dev/null +++ b/plugin/sql_errlog/logger_service.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include + + +/* file reserved for the future use */ +SERVICE_VERSION *logger_service= (void *) VERSION_logger; + diff --git a/plugin/sql_errlog/service_logger.h b/plugin/sql_errlog/service_logger.h new file mode 100644 index 00000000000..2aa4d94f010 --- /dev/null +++ b/plugin/sql_errlog/service_logger.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef MYSQL_SERVICE_LOGGER_INCLUDED +#define MYSQL_SERVICE_LOGGER_INCLUDED + +#ifndef MYSQL_ABI_CHECK +#include +#endif + +/** + @file + logger service + + Log file with rotation implementation. + + This service implements logging with possible rotation + of the log files. Interface intentionally tries to be similar to FILE* + related functions. + + So that one can open the log with logger_open(), specifying + the limit on the logfile size and the rotations number. + + Then it's possible to write messages to the log with + logger_printf or logger_vprintf functions. + + As the size of the logfile grows over the specified limit, + it is renamed to 'logfile.1'. The former 'logfile.1' becomes + 'logfile.2', etc. The file 'logfile.rotations' is removed. + That's how the rotation works. + + The rotation can be forced with the logger_rotate() call. + + Finally the log should be closed with logger_close(). + +@notes: + Implementation checks the size of the log file before it starts new + printf into it. So the size of the file gets over the limit when it rotates. + + The access is secured with the mutex, so the log is threadsafe. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct logger_handle_st LOGGER_HANDLE; + +extern struct logger_service_st { + LOGGER_HANDLE* (*open)(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int (*close)(LOGGER_HANDLE *log); + int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); + int (*rotate)(LOGGER_HANDLE *log); +} *logger_service; + +#if 0 /*MYSQL_DYNAMIC_PLUGIN*/ + +#define logger_open(path, size_limit, rotations) \ + (logger_service->open(path, size_limit, rotations)) +#define logger_close(log) (logger_service->close(log)) +#define logger_rotate(log) (logger_service->rotate(log)) +#define logger_vprintf(log, fmt, argptr) (logger_service->\ + vprintf(log, fmt, argptr)) +#define logger_printf logger_service->printf +#else + + LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations); + int logger_close(LOGGER_HANDLE *log); + int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); + int logger_rotate(LOGGER_HANDLE *log); + int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + + void init_logger_mutexes(); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_LOGGER_INCLUDED*/ + diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index ee2765a7143..ce383916621 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -16,6 +16,7 @@ #include #include #include +#include "service_logger.h" /* Disable __attribute__() on non-gcc compilers. @@ -32,6 +33,7 @@ rate 0 means the logging was disabled. */ + static char *filename; static unsigned int rate; static unsigned long long size_limit; @@ -50,7 +52,7 @@ static MYSQL_SYSVAR_UINT(rate, rate, PLUGIN_VAR_RQCMDARG, static MYSQL_SYSVAR_ULONGLONG(size_limit, size_limit, PLUGIN_VAR_READONLY, "Log file size limit", NULL, NULL, - 1000000, 100, 0, 1); + 1000000, 100, ((long long) 0x7FFFFFFFFFFFFFFFLL), 1); static MYSQL_SYSVAR_UINT(rotations, rotations, PLUGIN_VAR_READONLY, "Number of rotations before log is removed.", @@ -104,6 +106,8 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), static int sql_error_log_init(void *p __attribute__((unused))) { + init_logger_mutexes(); + logfile= logger_open(filename, size_limit, rotations); if (logfile == NULL) { fprintf(stderr, "Could not create file '%s'\n", @@ -117,7 +121,8 @@ static int sql_error_log_init(void *p __attribute__((unused))) static int sql_error_log_deinit(void *p __attribute__((unused))) { - logger_close(logfile); + if (logfile) + logger_close(logfile); return 0; } @@ -139,6 +144,24 @@ static struct st_mysql_audit descriptor = { MYSQL_AUDIT_GENERAL_CLASSMASK } }; +mysql_declare_plugin(sql_errlog) +{ + MYSQL_AUDIT_PLUGIN, + &descriptor, + "SQL_ERROR_LOG", + "Alexey Botchkov", + "Log SQL level errors to a file with rotation", + PLUGIN_LICENSE_GPL, + sql_error_log_init, + sql_error_log_deinit, + 0x0100, + NULL, + vars, + NULL, + 0 +} +mysql_declare_plugin_end; + maria_declare_plugin(sql_errlog) { MYSQL_AUDIT_PLUGIN, diff --git a/plugin/sql_errlog/sql_logger.cc b/plugin/sql_errlog/sql_logger.cc new file mode 100644 index 00000000000..8bf757f2fd7 --- /dev/null +++ b/plugin/sql_errlog/sql_logger.cc @@ -0,0 +1,194 @@ +/* Copyright (C) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "my_global.h" +#include +#include "service_logger.h" +#include + +extern MYSQL_PLUGIN_IMPORT char *mysql_data_home; + +/* These belong to the service initialization */ +static PSI_mutex_key key_LOCK_logger_service; +static PSI_mutex_info mutex_list[]= +{{ &key_LOCK_logger_service, "logger_service_file_st::lock", PSI_FLAG_GLOBAL}}; + +typedef struct logger_handle_st { + File file; + char path[FN_REFLEN]; + unsigned long long size_limit; + unsigned int rotations; + size_t path_len; + mysql_mutex_t lock; +} LSFS; + + +#define LOG_FLAGS (O_APPEND | O_CREAT | O_WRONLY) + +static unsigned int n_dig(unsigned int i) +{ + return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); +} + + +LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations) +{ + LOGGER_HANDLE new_log, *l_perm; + + /* + I don't think we ever need more rotations, + but if it's so, the rotation procedure should be adapted to it. + */ + if (rotations > 999) + return 0; + + new_log.rotations= rotations; + new_log.size_limit= size_limit; + new_log.path_len= strlen(fn_format(new_log.path, path, + mysql_data_home, "", MY_UNPACK_FILENAME)); + + if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN) + { + errno= ENAMETOOLONG; + /* File path too long */ + return 0; + } + if ((new_log.file= my_open(new_log.path, LOG_FLAGS, MYF(0))) < 0) + { + errno= my_errno; + /* Check errno for the cause */ + return 0; + } + + if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) + { + my_close(new_log.file, MYF(0)); + new_log.file= -1; + return 0; /* End of memory */ + } + *l_perm= new_log; + mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST); + return l_perm; +} + +int logger_close(LOGGER_HANDLE *log) +{ + int result; + File file= log->file; + mysql_mutex_destroy(&log->lock); + my_free(log); + if ((result= my_close(file, MYF(0)))) + errno= my_errno; + return result; +} + + +static char *logname(LOGGER_HANDLE *log, char *buf, unsigned int n_log) +{ + sprintf(buf+log->path_len, ".%0*u", n_dig(log->rotations), n_log); + return buf; +} + + +static int do_rotate(LOGGER_HANDLE *log) +{ + char namebuf[FN_REFLEN]; + int result; + unsigned int i; + char *buf_old, *buf_new, *tmp; + + memcpy(namebuf, log->path, log->path_len); + + buf_new= logname(log, namebuf, log->rotations); + buf_old= log->path; + for (i=log->rotations-1; i>0; i--) + { + logname(log, buf_old, i); + if (!access(buf_old, F_OK) && + (result= my_rename(buf_old, buf_new, MYF(0)))) + goto exit; + tmp= buf_old; + buf_old= buf_new; + buf_new= tmp; + } + if ((result= my_close(log->file, MYF(0)))) + goto exit; + namebuf[log->path_len]= 0; + result= my_rename(namebuf, logname(log, log->path, 1), MYF(0)); + log->file= my_open(namebuf, LOG_FLAGS, MYF(0)); +exit: + errno= my_errno; + return log->file < 0 || result; +} + + +int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap) +{ + int result; + my_off_t filesize; + char cvtbuf[1024]; + size_t n_bytes; + + mysql_mutex_lock(&log->lock); + if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 || + ((unsigned long long)filesize >= log->size_limit && + do_rotate(log))) + { + result= -1; + errno= my_errno; + goto exit; /* Log rotation needed but failed */ + } + + n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap); + if (n_bytes >= sizeof(cvtbuf)) + n_bytes= sizeof(cvtbuf) - 1; + + result= my_write(log->file, (uchar *) cvtbuf, n_bytes, MYF(0)); + +exit: + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_rotate(LOGGER_HANDLE *log) +{ + int result; + mysql_mutex_lock(&log->lock); + result= do_rotate(log); + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...) +{ + int result; + va_list args; + va_start(args,fmt); + result= logger_vprintf(log, fmt, args); + va_end(args); + return result; +} + +void init_logger_mutexes() +{ + if (PSI_server) + PSI_server->register_mutex("sql_logger", mutex_list, 1); +} + diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 22c51f3ce23..446db5d128a 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -85,7 +85,6 @@ SET (SQL_SOURCE gcalc_slicescan.cc gcalc_tools.cc threadpool_common.cc ../sql-common/mysql_async.c - sql_logger.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 21653e96854..a73177f9fea 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -748,7 +748,6 @@ PSI_mutex_key key_LOCK_stats, key_LOCK_wakeup_ready; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; -PSI_mutex_key key_LOCK_logger_service; static PSI_mutex_info all_server_mutexes[]= { @@ -808,8 +807,6 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, - { &key_LOCK_logger_service, "logger_service_file_st::lock", - PSI_FLAG_GLOBAL}, { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0} }; diff --git a/sql/sql_logger.cc b/sql/sql_logger.cc deleted file mode 100644 index fe3c9a87d20..00000000000 --- a/sql/sql_logger.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* Copyright (C) 2012 Monty Program Ab - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -#include "my_global.h" -#include -#include - -extern char *mysql_data_home; -extern PSI_mutex_key key_LOCK_logger_service; - -typedef struct logger_handle_st { - File file; - char path[FN_REFLEN]; - unsigned long long size_limit; - unsigned int rotations; - size_t path_len; - mysql_mutex_t lock; -} LSFS; - - -#define LOG_FLAGS (O_APPEND | O_CREAT | O_WRONLY) - -static unsigned int n_dig(unsigned int i) -{ - return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); -} - - -LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations) -{ - LOGGER_HANDLE new_log, *l_perm; - - /* - I don't think we ever need more rotations, - but if it's so, the rotation procedure should be adapted to it. - */ - if (rotations > 999) - return 0; - - new_log.rotations= rotations; - new_log.size_limit= size_limit; - new_log.path_len= strlen(fn_format(new_log.path, path, - mysql_data_home, "", MY_UNPACK_FILENAME)); - - if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN) - { - errno= ENAMETOOLONG; - /* File path too long */ - return 0; - } - if ((new_log.file= my_open(new_log.path, LOG_FLAGS, MYF(0))) < 0) - { - errno= my_errno; - /* Check errno for the cause */ - return 0; - } - - if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) - { - my_close(new_log.file, MYF(0)); - new_log.file= -1; - return 0; /* End of memory */ - } - *l_perm= new_log; - mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST); - return l_perm; -} - -int logger_close(LOGGER_HANDLE *log) -{ - int result; - File file= log->file; - mysql_mutex_destroy(&log->lock); - my_free(log); - if ((result= my_close(file, MYF(0)))) - errno= my_errno; - return result; -} - - -static char *logname(LOGGER_HANDLE *log, char *buf, unsigned int n_log) -{ - sprintf(buf+log->path_len, ".%0*u", n_dig(log->rotations), n_log); - return buf; -} - - -static int do_rotate(LOGGER_HANDLE *log) -{ - char namebuf[FN_REFLEN]; - int result; - unsigned int i; - char *buf_old, *buf_new, *tmp; - - memcpy(namebuf, log->path, log->path_len); - - buf_new= logname(log, namebuf, log->rotations); - buf_old= log->path; - for (i=log->rotations-1; i>0; i--) - { - logname(log, buf_old, i); - if (!access(buf_old, F_OK) && - (result= my_rename(buf_old, buf_new, MYF(0)))) - goto exit; - tmp= buf_old; - buf_old= buf_new; - buf_new= tmp; - } - if ((result= my_close(log->file, MYF(0)))) - goto exit; - namebuf[log->path_len]= 0; - result= my_rename(namebuf, logname(log, log->path, 1), MYF(0)); - log->file= my_open(namebuf, LOG_FLAGS, MYF(0)); -exit: - errno= my_errno; - return log->file < 0 || result; -} - - -int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap) -{ - int result; - my_off_t filesize; - char cvtbuf[1024]; - size_t n_bytes; - - mysql_mutex_lock(&log->lock); - if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 || - ((unsigned long long)filesize >= log->size_limit && - do_rotate(log))) - { - result= -1; - errno= my_errno; - goto exit; /* Log rotation needed but failed */ - } - - n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap); - if (n_bytes >= sizeof(cvtbuf)) - n_bytes= sizeof(cvtbuf) - 1; - - result= my_write(log->file, (uchar *) cvtbuf, n_bytes, MYF(0)); - -exit: - mysql_mutex_unlock(&log->lock); - return result; -} - - -int logger_rotate(LOGGER_HANDLE *log) -{ - int result; - mysql_mutex_lock(&log->lock); - result= do_rotate(log); - mysql_mutex_unlock(&log->lock); - return result; -} - - -int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...) -{ - int result; - va_list args; - va_start(args,fmt); - result= logger_vprintf(log, fmt, args); - va_end(args); - return result; -} - diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h index bd6d136585a..e6302f6d345 100644 --- a/sql/sql_plugin_services.h +++ b/sql/sql_plugin_services.h @@ -54,14 +54,6 @@ static struct progress_report_service_st progress_report_handler= { set_thd_proc_info }; -static struct logger_service_st logger_handler= { - logger_open, - logger_close, - logger_vprintf, - logger_printf, - logger_rotate -}; - static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, @@ -69,6 +61,5 @@ static struct st_service_ref list_of_services[]= { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "my_thread_scheduler_service", VERSION_my_thread_scheduler, &my_thread_scheduler_handler }, { "progress_report_service", VERSION_progress_report, &progress_report_handler }, - { "logger_service", VERSION_logger, &logger_handler }, }; -- cgit v1.2.1