summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/SETUP.sh1
-rw-r--r--client/mysqltest.cc5
-rw-r--r--cmake/libutils.cmake5
-rw-r--r--include/violite.h2
-rw-r--r--mysql-test/extra/rpl_tests/rpl_flsh_tbls.test8
-rw-r--r--mysql-test/suite/plugins/r/server_audit.result5
-rw-r--r--mysql-test/suite/plugins/r/thread_pool_server_audit.result5
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result3
-rw-r--r--mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result8
-rw-r--r--mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result3
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test6
-rw-r--r--mysys/file_logger.c2
-rw-r--r--plugin/server_audit/CMakeLists.txt5
-rw-r--r--plugin/server_audit/plugin_audit_v4.h561
-rw-r--r--plugin/server_audit/server_audit.c868
-rw-r--r--plugin/server_audit/test_audit_v4.c162
-rw-r--r--sql/mysqld.cc39
-rw-r--r--sql/net_serv.cc20
-rw-r--r--sql/rpl_mi.cc18
-rw-r--r--sql/rpl_mi.h2
-rw-r--r--sql/rpl_rli.cc2
-rw-r--r--sql/slave.cc21
-rw-r--r--sql/slave.h9
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--storage/connect/json.cpp2
-rw-r--r--storage/connect/jsonudf.cpp2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/change_column_bin.py1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/change_column_bin.test1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/change_column_char.py1
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/change_column_char.test1
32 files changed, 1461 insertions, 318 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index f443c5da680..36072ebaa7e 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -31,6 +31,7 @@ Usage: $0 [-h|-n] [configure-options]
-h, --help Show this help message.
-n, --just-print Don't actually run any commands; just print them.
-c, --just-configure Stop after running configure.
+ Combined with --just-print shows configure options.
--extra-configs=xxx Add this to configure options
--extra-flags=xxx Add this C and CXX flags
--extra-cflags=xxx Add this to C flags
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 3bbfc70eaed..860e442a290 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -4977,12 +4977,13 @@ static int my_kill(int pid, int sig)
{
#ifdef __WIN__
HANDLE proc;
- if ((proc= OpenProcess(PROCESS_TERMINATE, FALSE, pid)) == NULL)
+ if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL)
return -1;
if (sig == 0)
{
+ DWORD wait_result= WaitForSingleObject(proc, 0);
CloseHandle(proc);
- return 0;
+ return wait_result == WAIT_OBJECT_0?-1:0;
}
(void)TerminateProcess(proc, 201);
CloseHandle(proc);
diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake
index 636737b2083..5125b9482cd 100644
--- a/cmake/libutils.cmake
+++ b/cmake/libutils.cmake
@@ -87,6 +87,11 @@ MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS)
ENDFOREACH()
SET(CONTENT "${CONTENT} (void *)0\n}\;")
CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
+ # Avoid "function redeclared as variable" error
+ # when using gcc/clang option -flto(link time optimization)
+ IF(" ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS} " MATCHES " -flto")
+ SET_SOURCE_FILES_PROPERTIES(${EXPORTS} PROPERTIES COMPILE_FLAGS "-fno-lto")
+ ENDIF()
SET(${VAR} ${EXPORTS})
ENDIF()
ENDMACRO()
diff --git a/include/violite.h b/include/violite.h
index d5ce66c3061..a7165ca91a9 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -208,7 +208,7 @@ void vio_end(void);
/* shutdown(2) flags */
#ifndef SHUT_RD
-#define SHUT_RD SD_BOTH
+#define SHUT_RD SD_RECEIVE
#endif
/*
diff --git a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
index 5cbda2d591f..a8cec3d2a1a 100644
--- a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
+++ b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test
@@ -45,7 +45,13 @@ drop table t1;
connection slave;
flush tables with read lock;
start slave;
-source include/wait_for_slave_to_start.inc;
+
+# The IO thread will not be able to read the GTID because of flush tables
+let $slave_param= Slave_IO_Running;
+let $slave_param_value= Preparing;
+source include/wait_for_slave_param.inc;
+
+--source include/wait_for_slave_sql_to_start.inc
--error 1192
stop slave;
diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result
index bf71e518f97..2577a36cad4 100644
--- a/mysql-test/suite/plugins/r/server_audit.result
+++ b/mysql-test/suite/plugins/r/server_audit.result
@@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users
+server_audit_loc_info
server_audit_logging OFF
server_audit_mode 0
server_audit_output_type file
@@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users odin, root, dva, tri
+server_audit_loc_info
server_audit_logging ON
server_audit_mode 0
server_audit_output_type file
@@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users odin, root, dva, tri
+server_audit_loc_info
server_audit_logging ON
server_audit_mode 1
server_audit_output_type file
@@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
+TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result
index bf71e518f97..2577a36cad4 100644
--- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result
+++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result
@@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users
+server_audit_loc_info
server_audit_logging OFF
server_audit_mode 0
server_audit_output_type file
@@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users odin, root, dva, tri
+server_audit_loc_info
server_audit_logging ON
server_audit_mode 0
server_audit_output_type file
@@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF
server_audit_file_rotate_size 1000000
server_audit_file_rotations 9
server_audit_incl_users odin, root, dva, tri
+server_audit_loc_info
server_audit_logging ON
server_audit_mode 1
server_audit_output_type file
@@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0
-TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0
+TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user,
diff --git a/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result b/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result
index 6aca4282ccd..27b23739831 100644
--- a/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result
+++ b/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result
@@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc
drop table t1;
flush tables with read lock;
start slave;
-include/wait_for_slave_to_start.inc
+include/wait_for_slave_param.inc [Slave_IO_Running]
+include/wait_for_slave_sql_to_start.inc
stop slave;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
unlock tables;
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
index 0809af5f943..36d862dedce 100644
--- a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result
@@ -14,6 +14,10 @@ DROP TABLE t1;
[connection slave]
include/install_semisync.inc
[connection slave]
+show global status like "Slave%_running";
+Variable_name Value
+Slave_running ON
+Slaves_running 1
UNINSTALL PLUGIN rpl_semi_sync_slave;
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown
@@ -21,6 +25,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na
plugin_name plugin_status
rpl_semi_sync_slave DELETED
[connection master]
+show global status like "Slave%_connect%";
+Variable_name Value
+Slave_connections 2
+Slaves_connected 1
UNINSTALL PLUGIN rpl_semi_sync_master;
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown
diff --git a/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result b/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result
index 6aca4282ccd..27b23739831 100644
--- a/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result
+++ b/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result
@@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc
drop table t1;
flush tables with read lock;
start slave;
-include/wait_for_slave_to_start.inc
+include/wait_for_slave_param.inc [Slave_IO_Running]
+include/wait_for_slave_sql_to_start.inc
stop slave;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
unlock tables;
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
index 4ee345e54ba..0f86789cced 100644
--- a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test
@@ -57,6 +57,8 @@ DROP TABLE t1;
# possible at this state
--connection slave
--echo [connection slave]
+show global status like "Slave%_running";
+
UNINSTALL PLUGIN rpl_semi_sync_slave;
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
@@ -64,6 +66,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na
# possible at this state
--connection master
--echo [connection master]
+
+# The following is to catch errors if the next uninstall plugin would succeed
+show global status like "Slave%_connect%";
+
UNINSTALL PLUGIN rpl_semi_sync_master;
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
diff --git a/mysys/file_logger.c b/mysys/file_logger.c
index 394b59f6378..b94cb705d3f 100644
--- a/mysys/file_logger.c
+++ b/mysys/file_logger.c
@@ -14,11 +14,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifndef FLOGGER_SKIP_INCLUDES
#include "my_global.h"
#include <my_sys.h>
#include <m_string.h>
#include <mysql/service_logger.h>
#include <my_pthread.h>
+#endif /*FLOGGER_SKIP_INCLUDES*/
#ifndef flogger_mutex_init
#define flogger_mutex_init(A,B,C) mysql_mutex_init(A,B,C)
diff --git a/plugin/server_audit/CMakeLists.txt b/plugin/server_audit/CMakeLists.txt
index 527d0d702da..3de8c43c871 100644
--- a/plugin/server_audit/CMakeLists.txt
+++ b/plugin/server_audit/CMakeLists.txt
@@ -13,4 +13,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-MYSQL_ADD_PLUGIN(server_audit server_audit.c MODULE_ONLY)
+SET(SERVER_AUDIT_SOURCES
+ server_audit.c test_audit_v4.c plugin_audit_v4.h)
+
+ MYSQL_ADD_PLUGIN(server_audit ${SERVER_AUDIT_SOURCES} MODULE_ONLY)
diff --git a/plugin/server_audit/plugin_audit_v4.h b/plugin/server_audit/plugin_audit_v4.h
new file mode 100644
index 00000000000..5f8e43b3811
--- /dev/null
+++ b/plugin/server_audit/plugin_audit_v4.h
@@ -0,0 +1,561 @@
+/* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifndef _my_audit_h
+#define _my_audit_h
+
+#ifndef PLUGIN_CONTEXT
+#include "plugin.h"
+#include "mysql/mysql_lex_string.h"
+#ifndef MYSQL_ABI_CHECK
+#include "m_string.h"
+#endif
+#include "my_command.h"
+#include "my_sqlcommand.h"
+#endif /*PLUGIN_CONTEXT*/
+
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0401
+
+/**
+ @enum mysql_event_class_t
+
+ Audit event classes.
+*/
+typedef enum
+{
+ MYSQL_AUDIT_GENERAL_CLASS = 0,
+ MYSQL_AUDIT_CONNECTION_CLASS = 1,
+ MYSQL_AUDIT_PARSE_CLASS = 2,
+ MYSQL_AUDIT_AUTHORIZATION_CLASS = 3,
+ MYSQL_AUDIT_TABLE_ACCESS_CLASS = 4,
+ MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS = 5,
+ MYSQL_AUDIT_SERVER_STARTUP_CLASS = 6,
+ MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS = 7,
+ MYSQL_AUDIT_COMMAND_CLASS = 8,
+ MYSQL_AUDIT_QUERY_CLASS = 9,
+ MYSQL_AUDIT_STORED_PROGRAM_CLASS = 10,
+ /* This item must be last in the list. */
+ MYSQL_AUDIT_CLASS_MASK_SIZE
+} mysql_event_class_t;
+
+/**
+ @struct st_mysql_audit
+
+ The descriptor structure that is referred from st_mysql_plugin.
+*/
+struct st_mysql_audit
+{
+ /**
+ Interface version.
+ */
+ int interface_version;
+
+ /**
+ Event occurs when the event class consumer is to be
+ disassociated from the specified THD.This would typically occur
+ before some operation which may require sleeping - such as when
+ waiting for the next query from the client.
+ */
+ void (*release_thd)(MYSQL_THD);
+
+ /**
+ Invoked whenever an event occurs which is of any
+ class for which the plugin has interest.The second argument
+ indicates the specific event class and the third argument is data
+ as required for that class.
+ */
+ int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
+
+ /**
+ An array of bits used to indicate what event classes
+ that this plugin wants to receive.
+ */
+ unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
+};
+
+/**
+ @typedef enum_sql_command_t
+
+ SQL command type definition.
+*/
+typedef enum enum_sql_command enum_sql_command_t;
+
+/**
+ @enum mysql_event_general_subclass_t
+
+ Events for the MYSQL_AUDIT_GENERAL_CLASS event class.
+*/
+typedef enum
+{
+ /** occurs before emitting to the general query log. */
+ MYSQL_AUDIT_GENERAL_LOG = 1 << 0,
+ /** occurs before transmitting errors to the user. */
+ MYSQL_AUDIT_GENERAL_ERROR = 1 << 1,
+ /** occurs after transmitting a resultset to the user. */
+ MYSQL_AUDIT_GENERAL_RESULT = 1 << 2,
+ /** occurs after transmitting a resultset or errors */
+ MYSQL_AUDIT_GENERAL_STATUS = 1 << 3
+} mysql_event_general_subclass_t;
+
+#define MYSQL_AUDIT_GENERAL_ALL (MYSQL_AUDIT_GENERAL_LOG | \
+ MYSQL_AUDIT_GENERAL_ERROR | \
+ MYSQL_AUDIT_GENERAL_RESULT | \
+ MYSQL_AUDIT_GENERAL_STATUS)
+/**
+ @struct mysql_event_general
+
+ Structure for the MYSQL_AUDIT_GENERAL_CLASS event class.
+*/
+struct mysql_event_general
+{
+ mysql_event_general_subclass_t event_subclass;
+ int general_error_code;
+ unsigned long general_thread_id;
+ MYSQL_LEX_CSTRING general_user;
+ MYSQL_LEX_CSTRING general_command;
+ MYSQL_LEX_CSTRING general_query;
+ struct charset_info_st *general_charset;
+ unsigned long long general_time;
+ unsigned long long general_rows;
+ MYSQL_LEX_CSTRING general_host;
+ MYSQL_LEX_CSTRING general_sql_command;
+ MYSQL_LEX_CSTRING general_external_user;
+ MYSQL_LEX_CSTRING general_ip;
+};
+
+/**
+ @enum mysql_event_connection_subclass_t
+
+ Events for MYSQL_AUDIT_CONNECTION_CLASS event class.
+*/
+typedef enum
+{
+ /** occurs after authentication phase is completed. */
+ MYSQL_AUDIT_CONNECTION_CONNECT = 1 << 0,
+ /** occurs after connection is terminated. */
+ MYSQL_AUDIT_CONNECTION_DISCONNECT = 1 << 1,
+ /** occurs after COM_CHANGE_USER RPC is completed. */
+ MYSQL_AUDIT_CONNECTION_CHANGE_USER = 1 << 2,
+ /** occurs before authentication. */
+ MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE = 1 << 3
+} mysql_event_connection_subclass_t;
+
+#define MYSQL_AUDIT_CONNECTION_ALL (MYSQL_AUDIT_CONNECTION_CONNECT | \
+ MYSQL_AUDIT_CONNECTION_DISCONNECT | \
+ MYSQL_AUDIT_CONNECTION_CHANGE_USER | \
+ MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE)
+/**
+ @struct mysql_event_connection
+
+ Structure for the MYSQL_AUDIT_CONNECTION_CLASS event class.
+*/
+struct mysql_event_connection
+{
+ /** Event subclass. */
+ mysql_event_connection_subclass_t event_subclass;
+ /** Current status of the connection. */
+ int status;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** User name of this connection. */
+ MYSQL_LEX_CSTRING user;
+ /** Priv user name. */
+ MYSQL_LEX_CSTRING priv_user;
+ /** External user name. */
+ MYSQL_LEX_CSTRING external_user;
+ /** Proxy user used for this connection. */
+ MYSQL_LEX_CSTRING proxy_user;
+ /** Connection host. */
+ MYSQL_LEX_CSTRING host;
+ /** IP of the connection. */
+ MYSQL_LEX_CSTRING ip;
+ /** Database name specified at connection time. */
+ MYSQL_LEX_CSTRING database;
+ /** Connection type:
+ - 0 Undefined
+ - 1 TCP/IP
+ - 2 Socket
+ - 3 Named pipe
+ - 4 SSL
+ - 5 Shared memory
+ */
+ int connection_type;
+};
+
+/**
+@enum mysql_event_parse_subclass_t
+
+Events for MYSQL_AUDIT_PARSE_CLASS event class.
+*/
+typedef enum
+{
+ /** occurs before the query parsing. */
+ MYSQL_AUDIT_PARSE_PREPARSE = 1 << 0,
+ /** occurs after the query parsing. */
+ MYSQL_AUDIT_PARSE_POSTPARSE = 1 << 1
+} mysql_event_parse_subclass_t;
+
+#define MYSQL_AUDIT_PARSE_ALL (MYSQL_AUDIT_PARSE_PREPARSE | \
+ MYSQL_AUDIT_PARSE_POSTPARSE)
+
+typedef enum
+{
+ MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_NONE = 0,
+ /// mysql_event_parse::flags Must be set by a plugin if the query is rewritten.
+ MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_QUERY_REWRITTEN = 1 << 0,
+ /// mysql_event_parse::flags Is set by the server if the query is prepared statement.
+ MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_IS_PREPARED_STATEMENT = 1 << 1
+} mysql_event_parse_rewrite_plugin_flag;
+
+/** Data for the MYSQL_AUDIT_PARSE events */
+struct mysql_event_parse
+{
+ /** MYSQL_AUDIT_[PRE|POST]_PARSE event id */
+ mysql_event_parse_subclass_t event_subclass;
+
+ /** one of FLAG_REWRITE_PLUGIN_* */
+ mysql_event_parse_rewrite_plugin_flag *flags;
+
+ /** input: the original query text */
+ MYSQL_LEX_CSTRING query;
+
+ /** output: returns the null-terminated rewriten query allocated by my_malloc() */
+ MYSQL_LEX_CSTRING *rewritten_query;
+};
+
+/**
+ @enum mysql_event_authorization_subclass_t
+
+ Events for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
+*/
+typedef enum
+{
+ MYSQL_AUDIT_AUTHORIZATION_USER = 1 << 0,
+ /** Occurs when database privilege is checked. */
+ MYSQL_AUDIT_AUTHORIZATION_DB = 1 << 1,
+ /** Occurs when table privilege is checked. */
+ MYSQL_AUDIT_AUTHORIZATION_TABLE = 1 << 2,
+ /** Occurs when column privilege is checked. */
+ MYSQL_AUDIT_AUTHORIZATION_COLUMN = 1 << 3,
+ /** Occurs when procedure privilege is checked. */
+ MYSQL_AUDIT_AUTHORIZATION_PROCEDURE = 1 << 4,
+ /** Occurs when proxy privilege is checked. */
+ MYSQL_AUDIT_AUTHORIZATION_PROXY = 1 << 5
+} mysql_event_authorization_subclass_t;
+
+#define MYSQL_AUDIT_AUTHORIZATION_ALL (MYSQL_AUDIT_AUTHORIZATION_USER | \
+ MYSQL_AUDIT_AUTHORIZATION_DB | \
+ MYSQL_AUDIT_AUTHORIZATION_TABLE | \
+ MYSQL_AUDIT_AUTHORIZATION_COLUMN | \
+ MYSQL_AUDIT_AUTHORIZATION_PROCEDURE | \
+ MYSQL_AUDIT_AUTHORIZATION_PROXY)
+/**
+ @struct mysql_event_authorization
+
+ Structure for MYSQL_AUDIT_AUTHORIZATION_CLASS event class.
+*/
+struct mysql_event_authorization
+{
+ /** Event subclass. */
+ mysql_event_authorization_subclass_t event_subclass;
+ /** Event status. */
+ int status;
+ /** Connection id. */
+ unsigned int connection_id;
+ /** SQL command id. */
+ enum_sql_command_t sql_command_id;
+ /** SQL query text. */
+ MYSQL_LEX_CSTRING query;
+ /** SQL query charset. */
+ const struct charset_info_st *query_charset;
+ /** Database name. */
+ MYSQL_LEX_CSTRING database;
+ /** Table name. */
+ MYSQL_LEX_CSTRING table;
+ /** Other name associated with the event. */
+ MYSQL_LEX_CSTRING object;
+ /** Requested authorization privileges. */
+ unsigned long requested_privilege;
+ /** Currently granted authorization privileges. */
+ unsigned long granted_privilege;
+};
+
+/**
+ @enum mysql_event_table_row_access_subclass_t
+
+ Events for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
+*/
+typedef enum
+{
+ /** Occurs when table data are read. */
+ MYSQL_AUDIT_TABLE_ACCESS_READ = 1 << 0,
+ /** Occurs when table data are inserted. */
+ MYSQL_AUDIT_TABLE_ACCESS_INSERT = 1 << 1,
+ /** Occurs when table data are updated. */
+ MYSQL_AUDIT_TABLE_ACCESS_UPDATE = 1 << 2,
+ /** Occurs when table data are deleted. */
+ MYSQL_AUDIT_TABLE_ACCESS_DELETE = 1 << 3
+} mysql_event_table_access_subclass_t;
+
+#define MYSQL_AUDIT_TABLE_ACCESS_ALL (MYSQL_AUDIT_TABLE_ACCESS_READ | \
+ MYSQL_AUDIT_TABLE_ACCESS_INSERT | \
+ MYSQL_AUDIT_TABLE_ACCESS_UPDATE | \
+ MYSQL_AUDIT_TABLE_ACCESS_DELETE)
+
+/**
+ @struct mysql_event_table_row_access
+
+ Structure for MYSQL_AUDIT_TABLE_ACCES_CLASS event class.
+*/
+struct mysql_event_table_access
+{
+ /** Event subclass. */
+ mysql_event_table_access_subclass_t event_subclass;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** SQL command id. */
+ enum_sql_command_t sql_command_id;
+ /** SQL query. */
+ MYSQL_LEX_CSTRING query;
+ /** SQL query charset. */
+ const struct charset_info_st *query_charset;
+ /** Database name. */
+ MYSQL_LEX_CSTRING table_database;
+ /** Table name. */
+ MYSQL_LEX_CSTRING table_name;
+};
+
+/**
+ @enum mysql_event_global_variable_subclass_t
+
+ Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class.
+*/
+typedef enum
+{
+ /** Occurs when global variable is retrieved. */
+ MYSQL_AUDIT_GLOBAL_VARIABLE_GET = 1 << 0,
+ /** Occurs when global variable is set. */
+ MYSQL_AUDIT_GLOBAL_VARIABLE_SET = 1 << 1
+} mysql_event_global_variable_subclass_t;
+
+#define MYSQL_AUDIT_GLOBAL_VARIABLE_ALL (MYSQL_AUDIT_GLOBAL_VARIABLE_GET | \
+ MYSQL_AUDIT_GLOBAL_VARIABLE_SET)
+
+/** Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class. */
+struct mysql_event_global_variable
+{
+ /** Event subclass. */
+ mysql_event_global_variable_subclass_t event_subclass;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** SQL command id. */
+ enum_sql_command_t sql_command_id;
+ /** Variable name. */
+ MYSQL_LEX_CSTRING variable_name;
+ /** Variable value. */
+ MYSQL_LEX_CSTRING variable_value;
+};
+
+/**
+ @enum mysql_event_server_startup_subclass_t
+
+ Events for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
+*/
+typedef enum
+{
+ /** Occurs after all subsystem are initialized during system start. */
+ MYSQL_AUDIT_SERVER_STARTUP_STARTUP = 1 << 0
+} mysql_event_server_startup_subclass_t;
+
+#define MYSQL_AUDIT_SERVER_STARTUP_ALL (MYSQL_AUDIT_SERVER_STARTUP_STARTUP)
+
+/**
+ @struct mysql_event_server_startup
+
+ Structure for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class.
+*/
+struct mysql_event_server_startup
+{
+ /** Event subclass. */
+ mysql_event_server_startup_subclass_t event_subclass;
+ /** Command line arguments. */
+ const char **argv;
+ /** Command line arguments count. */
+ unsigned int argc;
+};
+
+/**
+ @enum mysql_event_server_shutdown_subclass_t
+
+ Events for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
+*/
+typedef enum
+{
+ /** Occurs when global variable is set. */
+ MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN = 1 << 0
+} mysql_event_server_shutdown_subclass_t;
+
+#define MYSQL_AUDIT_SERVER_SHUTDOWN_ALL (MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN)
+
+/**
+ @enum mysql_server_shutdown_reason_t
+
+ Server shutdown reason.
+*/
+typedef enum
+{
+ /** User requested shut down. */
+ MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
+ /** The server aborts. */
+ MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT
+} mysql_server_shutdown_reason_t;
+
+/**
+ @struct mysql_event_server_shutdown
+
+ Structure for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class.
+*/
+struct mysql_event_server_shutdown
+{
+ /** Shutdown event. */
+ mysql_event_server_shutdown_subclass_t event_subclass;
+ /** Exit code associated with the shutdown event. */
+ int exit_code;
+ /** Shutdown reason. */
+ mysql_server_shutdown_reason_t reason;
+};
+
+/**
+ @enum mysql_event_command_subclass_t
+
+ Events for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+typedef enum
+{
+ /** Command start event. */
+ MYSQL_AUDIT_COMMAND_START = 1 << 0,
+ /** Command end event. */
+ MYSQL_AUDIT_COMMAND_END = 1 << 1
+} mysql_event_command_subclass_t;
+
+#define MYSQL_AUDIT_COMMAND_ALL (MYSQL_AUDIT_COMMAND_START | \
+ MYSQL_AUDIT_COMMAND_END)
+/**
+ @typedef enum_server_command_t
+
+ Server command type definition.
+*/
+typedef enum enum_server_command enum_server_command_t;
+
+/**
+ @struct mysql_event_command
+
+ Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+ Events generated as a result of RPC command requests.
+*/
+struct mysql_event_command
+{
+ /** Command event subclass. */
+ mysql_event_command_subclass_t event_subclass;
+ /** Command event status. */
+ int status;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** Command id. */
+ enum_server_command_t command_id;
+};
+
+/**
+ @enum mysql_event_query_subclass_t
+
+ Events for MYSQL_AUDIT_QUERY_CLASS event class.
+*/
+typedef enum
+{
+ /** Query start event. */
+ MYSQL_AUDIT_QUERY_START = 1 << 0,
+ /** Nested query start event. */
+ MYSQL_AUDIT_QUERY_NESTED_START = 1 << 1,
+ /** Query post parse event. */
+ MYSQL_AUDIT_QUERY_STATUS_END = 1 << 2,
+ /** Nested query status end event. */
+ MYSQL_AUDIT_QUERY_NESTED_STATUS_END = 1 << 3
+} mysql_event_query_subclass_t;
+
+#define MYSQL_AUDIT_QUERY_ALL (MYSQL_AUDIT_QUERY_START | \
+ MYSQL_AUDIT_QUERY_NESTED_START | \
+ MYSQL_AUDIT_QUERY_STATUS_END | \
+ MYSQL_AUDIT_QUERY_NESTED_STATUS_END)
+/**
+ @struct mysql_event_command
+
+ Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+struct mysql_event_query
+{
+ /** Event subclass. */
+ mysql_event_query_subclass_t event_subclass;
+ /** Event status. */
+ int status;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** SQL command id. */
+ enum_sql_command_t sql_command_id;
+ /** SQL query. */
+ MYSQL_LEX_CSTRING query;
+ /** SQL query charset. */
+ const struct charset_info_st *query_charset;
+};
+
+/**
+ @enum mysql_event_stored_program_subclass_t
+
+ Events for MYSQL_AUDIT_STORED_PROGRAM_CLASS event class.
+*/
+typedef enum
+{
+ /** Stored program execution event. */
+ MYSQL_AUDIT_STORED_PROGRAM_EXECUTE = 1 << 0
+} mysql_event_stored_program_subclass_t;
+
+#define MYSQL_AUDIT_STORED_PROGRAM_ALL (MYSQL_AUDIT_STORED_PROGRAM_EXECUTE)
+
+/**
+ @struct mysql_event_command
+
+Event for MYSQL_AUDIT_COMMAND_CLASS event class.
+*/
+struct mysql_event_stored_program
+{
+ /** Event subclass. */
+ mysql_event_stored_program_subclass_t event_subclass;
+ /** Connection id. */
+ unsigned long connection_id;
+ /** SQL command id. */
+ enum_sql_command_t sql_command_id;
+ /** SQL query text. */
+ MYSQL_LEX_CSTRING query;
+ /** SQL query charset. */
+ const struct charset_info_st *query_charset;
+ /** The Database the procedure is defined in. */
+ MYSQL_LEX_CSTRING database;
+ /** Name of the stored program. */
+ MYSQL_LEX_CSTRING name;
+ /** Stored program parameters. */
+ void *parameters;
+};
+
+#endif
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index 1c91c66759d..d988f7e8317 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -14,13 +14,16 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define PLUGIN_VERSION 0x103
-#define PLUGIN_STR_VERSION "1.3.0"
+#define PLUGIN_VERSION 0x104
+#define PLUGIN_STR_VERSION "1.4.0"
+
+#define _my_thread_var loc_thread_var
#include <my_config.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
+#include <fcntl.h>
#ifndef _WIN32
#include <syslog.h>
@@ -80,8 +83,7 @@ static void closelog() {}
#endif /*MARIADB_ONLY*/
#include <my_base.h>
-//#include <hash.h>
-#include <my_dir.h>
+//#include <my_dir.h>
#include <typelib.h>
#include <mysql/plugin.h>
#include <mysql/plugin_audit.h>
@@ -89,75 +91,176 @@ static void closelog() {}
#define RTLD_DEFAULT NULL
#endif
-#undef my_init_dynamic_array_ci
-#define init_dynamic_array2 loc_init_dynamic_array2
-#define my_init_dynamic_array_ci(A,B,C,D) loc_init_dynamic_array2(A,B,NULL,C,D)
-#define my_hash_init2 loc_my_hash_init
-#define my_hash_search loc_my_hash_search
-#define my_hash_insert loc_my_hash_insert
-#define my_hash_delete loc_my_hash_delete
-#define my_hash_update loc_my_hash_update
-#define my_hash_free loc_my_hash_free
-#define my_hash_first loc_my_hash_first
-#define my_hash_reset loc_my_hash_reset
-#define my_hash_search_using_hash_value loc_my_hash_search_using_hash_value
-#define my_hash_first_from_hash_value loc_my_hash_first_from_hash_value
-#define my_hash_sort loc_my_hash_sort
-#undef my_hash_first_from_hash_value
-#define my_hash_first_from_hash_value loc_my_my_hash_first_from_hash_value
-#define my_hash_next loc_my_hash_next
-#define my_hash_element loc_my_hash_element
-#define my_hash_replace loc_my_hash_replace
-#define my_hash_iterate loc_my_hash_iterate
-
-#define alloc_dynamic loc_alloc_dynamic
-#define pop_dynamic loc_pop_dynamic
-#define delete_dynamic loc_delete_dynamic
-void *loc_alloc_dynamic(DYNAMIC_ARRAY *array);
-#ifdef my_strnncoll
-#undef my_strnncoll
-#define my_strnncoll(s, a, b, c, d) (my_strnncoll_binary((s), (a), (b), (c), (d), 0))
-#endif
-
-static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
- const uchar *s, size_t slen,
- const uchar *t, size_t tlen,
- my_bool t_is_prefix)
-{
- size_t len= slen < tlen ? slen : tlen;
- int cmp= memcmp(s,t,len);
- return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
-}
-
-#include "../../mysys/array.c"
-#include "../../mysys/hash.c"
-
#ifndef MARIADB_ONLY
#undef MYSQL_SERVICE_LOGGER_INCLUDED
#undef MYSQL_DYNAMIC_PLUGIN
#define FLOGGER_NO_PSI
/* How to access the pthread_mutex in mysql_mutex_t */
-#ifdef SAFE_MUTEX
-#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
-#elif defined(MY_PTHREAD_FASTMUTEX)
-#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
-#else
+//#ifdef SAFE_MUTEX
+//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
+//#elif defined(MY_PTHREAD_FASTMUTEX)
+//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
+//#else
#define mysql_mutex_real_mutex(A) &(A)->m_mutex
-#endif
+//#endif
-#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C)
-#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A))
-#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A))
-#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A))
+#define flogger_mutex_init(A,B,C) do{}while(0)
+#define flogger_mutex_destroy(A) do{}while(0)
+#define flogger_mutex_lock(A) do{}while(0)
+#define flogger_mutex_unlock(A) do{}while(0)
static char **int_mysql_data_home;
static char *default_home= (char *)".";
#define mysql_data_home (*int_mysql_data_home)
+#define FLOGGER_SKIP_INCLUDES
+#define my_open(A, B, C) loc_open(A, B)
+#define my_close(A, B) loc_close(A)
+#define my_rename(A, B, C) loc_rename(A, B)
+#define my_tell(A, B) loc_tell(A)
+#define my_write(A, B, C, D) loc_write(A, B, C)
+#define my_malloc(A, B) malloc(A)
+#define my_free(A) free(A)
+#ifdef my_errno
+ #undef my_errno
+#endif
+static int loc_file_errno;
+#define my_errno loc_file_errno
+#ifdef my_vsnprintf
+ #undef my_vsnprintf
+#endif
+#define my_vsnprintf vsnprintf
+#define logger_open loc_logger_open
+#define logger_close loc_logger_close
+#define logger_write loc_logger_write
+#define logger_rotate loc_logger_rotate
+#define logger_init_mutexts loc_logger_init_mutexts
+
+
+static size_t loc_write(File Filedes, const uchar *Buffer, size_t Count)
+{
+ size_t writtenbytes;
+#ifdef _WIN32
+ writtenbytes= my_win_write(Filedes, Buffer, Count);
+#else
+ writtenbytes= write(Filedes, Buffer, Count);
+#endif
+ return writtenbytes;
+}
+
+
+static File loc_open(const char *FileName, int Flags)
+ /* Path-name of file */
+ /* Read | write .. */
+ /* Special flags */
+{
+ File fd;
+#if defined(_WIN32)
+ fd= my_win_open(FileName, Flags);
+#elif !defined(NO_OPEN_3)
+ fd = open(FileName, Flags, my_umask); /* Normal unix */
+#else
+ fd = open((char *) FileName, Flags);
+#endif
+ my_errno= errno;
+ return fd;
+}
+
+
+static int loc_close(File fd)
+{
+ int err;
+#ifndef _WIN32
+ do
+ {
+ err= close(fd);
+ } while (err == -1 && errno == EINTR);
+#else
+ err= my_win_close(fd);
+#endif
+ my_errno=errno;
+ return err;
+}
+
+
+static int loc_rename(const char *from, const char *to)
+{
+ int error = 0;
+
+#if defined(__WIN__)
+ if (!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED |
+ MOVEFILE_REPLACE_EXISTING))
+ {
+ my_osmaperr(GetLastError());
+#elif defined(HAVE_RENAME)
+ if (rename(from,to))
+ {
+#else
+ if (link(from, to) || unlink(from))
+ {
+#endif
+ my_errno=errno;
+ error = -1;
+ }
+ return error;
+}
+
+
+static my_off_t loc_seek(File fd, my_off_t pos, int whence)
+{
+ os_off_t newpos= -1;
+#ifdef _WIN32
+ newpos= my_win_lseek(fd, pos, whence);
+#else
+ newpos= lseek(fd, pos, whence);
+#endif
+ if (newpos == (os_off_t) -1)
+ {
+ my_errno= errno;
+ return MY_FILEPOS_ERROR;
+ }
+
+ return (my_off_t) newpos;
+}
+
+
+static my_off_t loc_tell(File fd)
+{
+ os_off_t pos;
+#if defined (HAVE_TELL) && !defined (_WIN32)
+ pos= tell(fd);
+#else
+ pos= loc_seek(fd, 0L, MY_SEEK_CUR);
+#endif
+ if (pos == (os_off_t) -1)
+ {
+ my_errno= errno;
+ }
+ return (my_off_t) pos;
+}
+
+#ifdef HAVE_PSI_INTERFACE
+#undef HAVE_PSI_INTERFACE
+#include <mysql/service_logger.h>
+#include "../../mysys/file_logger.c"
+#define HAVE_PSI_INTERFACE
+#else
+#include <mysql/service_logger.h>
#include "../../mysys/file_logger.c"
+#endif
#endif /*!MARIADB_ONLY*/
+#undef flogger_mutex_init
+#undef flogger_mutex_destroy
+#undef flogger_mutex_lock
+#undef flogger_mutex_unlock
+
+#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C)
+#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A))
+#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A))
+#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A))
+
#ifndef DBUG_OFF
#define PLUGIN_DEBUG_VERSION "-debug"
#else
@@ -178,7 +281,11 @@ static char *default_home= (char *)".";
extern char server_version[];
static const char *serv_ver= NULL;
static int started_mysql= 0;
+static int mysql_57_started= 0;
+static int debug_server_started= 0;
+static int use_event_data_for_disconnect= 0;
static int started_mariadb= 0;
+static int maria_55_started= 0;
static int maria_above_5= 0;
static char *incl_users, *excl_users,
*file_path, *syslog_info;
@@ -203,6 +310,27 @@ static char servhost[256];
static size_t servhost_len;
static char *syslog_ident;
static char syslog_ident_buffer[128]= "mysql-server_auditing";
+
+struct connection_info
+{
+ int header;
+ unsigned long thread_id;
+ unsigned long long query_id;
+ char db[256];
+ int db_length;
+ char user[64];
+ int user_length;
+ char host[64];
+ int host_length;
+ char ip[64];
+ int ip_length;
+ const char *query;
+ int query_length;
+ char query_buffer[1024];
+ time_t query_time;
+ int log_always;
+};
+
#define DEFAULT_FILENAME_LEN 16
static char default_file_name[DEFAULT_FILENAME_LEN+1]= "server_audit.log";
@@ -256,7 +384,8 @@ static TYPELIB events_typelib=
array_elements(event_names) - 1, "", event_names, NULL
};
static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG,
- "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE, QUERY_DDL, QUERY_DML.",
+ "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE,"
+ " QUERY_DDL, QUERY_DML, QUERY_DCL.",
NULL, NULL, 0, &events_typelib);
#define OUTPUT_SYSLOG 0
#define OUTPUT_FILE 1
@@ -297,6 +426,13 @@ static MYSQL_SYSVAR_UINT(query_log_limit, query_log_limit,
PLUGIN_VAR_OPCMDARG, "Limit on the length of the query string in a record.",
NULL, NULL, 1024, 0, 0x7FFFFFFF, 1);
+char locinfo_ini_value[sizeof(struct connection_info)+4];
+
+static MYSQL_THDVAR_STR(loc_info,
+ PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
+ "Auxiliary info.", NULL, NULL,
+ locinfo_ini_value);
+
static const char *syslog_facility_names[]=
{
"LOG_USER", "LOG_MAIL", "LOG_DAEMON", "LOG_AUTH",
@@ -376,6 +512,7 @@ static struct st_mysql_sys_var* vars[] = {
MYSQL_SYSVAR(syslog_facility),
MYSQL_SYSVAR(syslog_priority),
MYSQL_SYSVAR(query_log_limit),
+ MYSQL_SYSVAR(loc_info),
NULL
};
@@ -386,6 +523,8 @@ static long log_write_failures= 0;
static char current_log_buf[FN_REFLEN]= "";
static char last_error_buf[512]= "";
+extern void *mysql_v4_descriptor;
+
static struct st_mysql_show_var audit_status[]=
{
{"server_audit_active", (char *)&is_active, SHOW_BOOL},
@@ -425,7 +564,7 @@ static uchar *getkey_user(const char *entry, size_t *length,
}
-static void blank_user(uchar *user)
+static void blank_user(char *user)
{
for (; *user && *user != ','; user++)
*user= ' ';
@@ -485,19 +624,98 @@ static void remove_blanks(char *user)
}
-static int user_hash_fill(HASH *h, char *users,
- HASH *cmp_hash, int take_over_cmp)
+struct user_name
+{
+ int name_len;
+ char *name;
+};
+
+
+struct user_coll
+{
+ int n_users;
+ struct user_name *users;
+ int n_alloced;
+};
+
+
+static void coll_init(struct user_coll *c)
+{
+ c->n_users= 0;
+ c->users= 0;
+ c->n_alloced= 0;
+}
+
+
+static void coll_free(struct user_coll *c)
+{
+ if (c->users)
+ {
+ free(c->users);
+ coll_init(c);
+ }
+}
+
+
+static int cmp_users(const void *ia, const void *ib)
+{
+ const struct user_name *a= (const struct user_name *) ia;
+ const struct user_name *b= (const struct user_name *) ib;
+ int dl= a->name_len - b->name_len;
+ if (dl != 0)
+ return dl;
+
+ return strncmp(a->name, b->name, a->name_len);
+}
+
+
+static char *coll_search(struct user_coll *c, const char *n, int len)
+{
+ struct user_name un;
+ struct user_name *found;
+ un.name_len= len;
+ un.name= (char *) n;
+ found= (struct user_name*) bsearch(&un, c->users, c->n_users,
+ sizeof(c->users[0]), cmp_users);
+ return found ? found->name : 0;
+}
+
+
+static int coll_insert(struct user_coll *c, char *n, int len)
+{
+ if (c->n_users >= c->n_alloced)
+ {
+ c->n_alloced+= 128;
+ if (c->users == NULL)
+ c->users= malloc(c->n_alloced * sizeof(c->users[0]));
+ else
+ c->users= realloc(c->users, c->n_alloced * sizeof(c->users[0]));
+
+ if (c->users == NULL)
+ return 1;
+ }
+ c->users[c->n_users].name= n;
+ c->users[c->n_users].name_len= len;
+ c->n_users++;
+ return 0;
+}
+
+
+static void coll_sort(struct user_coll *c)
+{
+ qsort(c->users, c->n_users, sizeof(c->users[0]), cmp_users);
+}
+
+
+static int user_coll_fill(struct user_coll *c, char *users,
+ struct user_coll *cmp_c, int take_over_cmp)
{
char *orig_users= users;
- uchar *cmp_user= 0;
+ char *cmp_user= 0;
size_t cmp_length;
- int refill_cmp_hash= 0;
+ int refill_cmp_coll= 0;
- if (my_hash_inited(h))
- my_hash_reset(h);
- else
- loc_my_hash_init(h, 0, &my_charset_bin, 0x100, 0, 0,
- (my_hash_get_key) getkey_user, 0, 0, 0);
+ c->n_users= 0;
while (*users)
{
@@ -506,11 +724,10 @@ static int user_hash_fill(HASH *h, char *users,
if (!*users)
return 0;
-
- if (cmp_hash)
+ (void) getkey_user(users, &cmp_length, FALSE);
+ if (cmp_c)
{
- (void) getkey_user(users, &cmp_length, FALSE);
- cmp_user= my_hash_search(cmp_hash, (const uchar *) users, cmp_length);
+ cmp_user= coll_search(cmp_c, users, cmp_length);
if (cmp_user && take_over_cmp)
{
@@ -520,7 +737,7 @@ static int user_hash_fill(HASH *h, char *users,
MYF(ME_JUST_WARNING), (int) cmp_length, users);
internal_stop_logging= 0;
blank_user(cmp_user);
- refill_cmp_hash= 1;
+ refill_cmp_coll= 1;
}
else if (cmp_user)
{
@@ -532,7 +749,7 @@ static int user_hash_fill(HASH *h, char *users,
continue;
}
}
- if (my_hash_insert(h, (const uchar *) users))
+ if (coll_insert(c, users, cmp_length))
return 1;
while (*users && *users != ',')
users++;
@@ -541,15 +758,17 @@ static int user_hash_fill(HASH *h, char *users,
users++;
}
- if (refill_cmp_hash)
+ if (refill_cmp_coll)
{
remove_blanks(excl_users);
- return user_hash_fill(cmp_hash, excl_users, 0, 0);
+ return user_coll_fill(cmp_c, excl_users, 0, 0);
}
if (users > orig_users && users[-1] == ',')
users[-1]= 0;
+ coll_sort(c);
+
return 0;
}
@@ -678,48 +897,19 @@ static void error_header()
static LOGGER_HANDLE *logfile;
-static HASH incl_user_hash, excl_user_hash;
+static struct user_coll incl_user_coll, excl_user_coll;
static unsigned long long query_counter= 1;
-struct connection_info
-{
- unsigned long thread_id;
- unsigned long long query_id;
- char db[256];
- int db_length;
- char user[64];
- int user_length;
- char host[64];
- int host_length;
- char ip[64];
- int ip_length;
- const char *query;
- int query_length;
- char query_buffer[1024];
- time_t query_time;
- int log_always;
-};
-
-static HASH connection_hash;
-
-
-struct connection_info *alloc_connection()
-{
- return malloc(ALIGN_SIZE(sizeof(struct connection_info)));
-}
-
-
-void free_connection(void* pconn)
+static struct connection_info *get_loc_info(MYSQL_THD thd)
{
- (void) free(pconn);
+ return (struct connection_info *) THDVAR(thd, loc_info);
}
-static struct connection_info *find_connection(unsigned long id)
+static int ci_needs_setup(const struct connection_info *ci)
{
- return (struct connection_info *)
- my_hash_search(&connection_hash, (const uchar *) &id, sizeof(id));
+ return ci->header != 0;
}
@@ -883,15 +1073,24 @@ static int stop_logging()
return 0;
}
-static struct connection_info *
- add_connection(const struct mysql_event_connection *event)
+
+static void setup_connection_simple(struct connection_info *ci)
+{
+ ci->db_length= 0;
+ ci->user_length= 0;
+ ci->host_length= 0;
+ ci->ip_length= 0;
+ ci->query_length= 0;
+ ci->header= 0;
+}
+
+
+static void setup_connection_connect(struct connection_info *cn,
+ const struct mysql_event_connection *event)
{
- struct connection_info *cn= alloc_connection();
- if (!cn)
- return 0;
- cn->thread_id= event->thread_id;
cn->query_id= 0;
cn->log_always= 0;
+ cn->thread_id= event->thread_id;
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
event->database, event->database_length);
get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
@@ -900,11 +1099,7 @@ static struct connection_info *
event->host, event->host_length);
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
event->ip, event->ip_length);
-
- if (my_hash_insert(&connection_hash, (const uchar *) cn))
- return 0;
-
- return cn;
+ cn->header= 0;
}
@@ -927,46 +1122,43 @@ do { \
-static struct connection_info *
- add_connection_initdb(const struct mysql_event_general *event)
+static void setup_connection_initdb(struct connection_info *cn,
+ const struct mysql_event_general *event)
{
- struct connection_info *cn;
size_t user_len, host_len, ip_len;
char uh_buffer[512];
- if (get_user_host(event->general_user, event->general_user_length,
- uh_buffer, sizeof(uh_buffer),
- &user_len, &host_len, &ip_len) ||
- (cn= alloc_connection()) == NULL)
- return 0;
-
cn->thread_id= event->general_thread_id;
cn->query_id= 0;
cn->log_always= 0;
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
event->general_query, event->general_query_length);
- get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
- uh_buffer, user_len);
- get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
- uh_buffer+user_len+1, host_len);
- get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
- uh_buffer+user_len+1+host_len+1, ip_len);
- if (my_hash_insert(&connection_hash, (const uchar *) cn))
- return 0;
-
- return cn;
+ if (get_user_host(event->general_user, event->general_user_length,
+ uh_buffer, sizeof(uh_buffer),
+ &user_len, &host_len, &ip_len))
+ {
+ /* The user@host line is incorrect. */
+ cn->user_length= 0;
+ cn->host_length= 0;
+ cn->ip_length= 0;
+ }
+ else
+ {
+ get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
+ uh_buffer, user_len);
+ get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
+ uh_buffer+user_len+1, host_len);
+ get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
+ uh_buffer+user_len+1+host_len+1, ip_len);
+ }
+ cn->header= 0;
}
-static struct connection_info *
- add_connection_table(const struct mysql_event_table *event)
+static void setup_connection_table(struct connection_info *cn,
+ const struct mysql_event_table *event)
{
- struct connection_info *cn;
-
- if ((cn= alloc_connection()) == NULL)
- return 0;
-
cn->thread_id= event->thread_id;
cn->query_id= query_counter++;
cn->log_always= 0;
@@ -978,42 +1170,40 @@ static struct connection_info *
event->host, SAFE_STRLEN(event->host));
get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
event->ip, SAFE_STRLEN(event->ip));
-
- if (my_hash_insert(&connection_hash, (const uchar *) cn))
- return 0;
-
- return cn;
+ cn->header= 0;
}
-static struct connection_info *
- add_connection_query(const struct mysql_event_general *event)
+static void setup_connection_query(struct connection_info *cn,
+ const struct mysql_event_general *event)
{
- struct connection_info *cn;
size_t user_len, host_len, ip_len;
char uh_buffer[512];
- if (get_user_host(event->general_user, event->general_user_length,
- uh_buffer, sizeof(uh_buffer),
- &user_len, &host_len, &ip_len) ||
- (cn= alloc_connection()) == NULL)
- return 0;
-
cn->thread_id= event->general_thread_id;
cn->query_id= query_counter++;
cn->log_always= 0;
get_str_n(cn->db, &cn->db_length, sizeof(cn->db), "", 0);
- get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
- uh_buffer, user_len);
- get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
- uh_buffer+user_len+1, host_len);
- get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
- uh_buffer+user_len+1+host_len+1, ip_len);
-
- if (my_hash_insert(&connection_hash, (const uchar *) cn))
- return 0;
- return cn;
+ if (get_user_host(event->general_user, event->general_user_length,
+ uh_buffer, sizeof(uh_buffer),
+ &user_len, &host_len, &ip_len))
+ {
+ /* The user@host line is incorrect. */
+ cn->user_length= 0;
+ cn->host_length= 0;
+ cn->ip_length= 0;
+ }
+ else
+ {
+ get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
+ uh_buffer, user_len);
+ get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
+ uh_buffer+user_len+1, host_len);
+ get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip),
+ uh_buffer+user_len+1+host_len+1, ip_len);
+ }
+ cn->header= 0;
}
@@ -1105,6 +1295,27 @@ static int log_connection(const struct connection_info *cn,
}
+static int log_connection_event(const struct mysql_event_connection *event,
+ const char *type)
+{
+ time_t ctime;
+ size_t csize;
+ char message[1024];
+
+ (void) time(&ctime);
+ csize= log_header(message, sizeof(message)-1, &ctime,
+ servhost, servhost_len,
+ event->user, event->user_length,
+ event->host, event->host_length,
+ event->ip, event->ip_length,
+ event->thread_id, 0, type);
+ csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+ ",%.*s,,%d", event->database_length, event->database, event->status);
+ message[csize]= '\n';
+ return write_log(message, csize + 1);
+}
+
+
static size_t escape_string(const char *str, unsigned int len,
char *result, size_t result_len)
{
@@ -1250,11 +1461,11 @@ static int do_log_user(const char *name)
return 0;
len= strlen(name);
- if (incl_user_hash.records)
- return my_hash_search(&incl_user_hash, (const uchar *) name, len) != 0;
+ if (incl_user_coll.n_users)
+ return coll_search(&incl_user_coll, name, len) != 0;
- if (excl_user_hash.records)
- return my_hash_search(&excl_user_hash, (const uchar *) name, len) == 0;
+ if (excl_user_coll.n_users)
+ return coll_search(&excl_user_coll, name, len) == 0;
return 1;
}
@@ -1592,14 +1803,14 @@ static void update_general_user(struct connection_info *cn,
}
+static struct connection_info ci_disconnect_buffer;
+
#define AA_FREE_CONNECTION 1
#define AA_CHANGE_USER 2
-static struct connection_info *update_connection_hash(unsigned int event_class,
- const void *ev,
- int *after_action)
+static void update_connection_info(struct connection_info *cn,
+ unsigned int event_class, const void *ev, int *after_action)
{
- struct connection_info *cn= NULL;
*after_action= 0;
switch (event_class) {
@@ -1612,13 +1823,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
{
int init_db_command= event->general_command_length == 7 &&
strncmp(event->general_command, "Init DB", 7) == 0;
- if ((cn= find_connection(event->general_thread_id)))
+ if (!ci_needs_setup(cn))
{
if (init_db_command)
{
/* Change DB */
- get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
- event->general_query, event->general_query_length);
+ if (mysql_57_started)
+ get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
+ event->database, event->database_length);
+ else
+ get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
+ event->general_query, event->general_query_length);
}
cn->query_id= mode ? query_counter++ : event->query_id;
cn->query= event->general_query;
@@ -1627,18 +1842,19 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
update_general_user(cn, event);
}
else if (init_db_command)
- cn= add_connection_initdb(event);
+ setup_connection_initdb(cn, event);
else if (event_query_command(event))
- cn= add_connection_query(event);
+ setup_connection_query(cn, event);
+ else
+ setup_connection_simple(cn);
break;
}
case MYSQL_AUDIT_GENERAL_STATUS:
if (event_query_command(event))
{
- if (!(cn= find_connection(event->general_thread_id)) &&
- !(cn= add_connection_query(event)))
- return 0;
+ if (ci_needs_setup(cn))
+ setup_connection_query(cn, event);
if (mode == 0 && cn->db_length == 0 && event->database_length > 0)
get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
@@ -1664,13 +1880,13 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
}
break;
case MYSQL_AUDIT_GENERAL_ERROR:
- /* We need this because of a bug in the MariaDB */
- /* that it returns NULL query field for the */
- /* MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare. */
- /* As a result we get empty QUERY field for errors. */
- if (!(cn= find_connection(event->general_thread_id)) &&
- !(cn= add_connection_query(event)))
- return 0;
+ /*
+ We need this because the MariaDB returns NULL query field for the
+ MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare.
+ As a result we get empty QUERY field for errors.
+ */
+ if (ci_needs_setup(cn))
+ setup_connection_query(cn, event);
cn->query_id= mode ? query_counter++ : event->query_id;
get_str_n(cn->query_buffer, &cn->query_length, sizeof(cn->query_buffer),
event->general_query, event->general_query_length);
@@ -1685,9 +1901,9 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
{
const struct mysql_event_table *event =
(const struct mysql_event_table *) ev;
- if (!(cn= find_connection(event->thread_id)) &&
- !(cn= add_connection_table(event)))
- return 0;
+ if (ci_needs_setup(cn))
+ setup_connection_table(cn, event);
+
if (cn->user_length == 0 && cn->host_length == 0 && cn->ip_length == 0)
{
get_str_n(cn->user, &cn->user_length, sizeof(cn->user),
@@ -1713,17 +1929,10 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
switch (event->event_subclass)
{
case MYSQL_AUDIT_CONNECTION_CONNECT:
- cn= add_connection(ev);
- break;
- case MYSQL_AUDIT_CONNECTION_DISCONNECT:
- cn= find_connection(event->thread_id);
- if (cn)
- *after_action= AA_FREE_CONNECTION;
+ setup_connection_connect(cn, event);
break;
case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
- cn= find_connection(event->thread_id);
- if (cn)
- *after_action= AA_CHANGE_USER;
+ *after_action= AA_CHANGE_USER;
break;
default:;
}
@@ -1732,17 +1941,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class,
default:
break;
}
- return cn;
}
+struct connection_info cn_error_buffer;
+
+
#define FILTER(MASK) (events == 0 || (events & MASK))
-static void auditing(MYSQL_THD thd __attribute__((unused)),
- unsigned int event_class,
- const void *ev)
+void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
{
- struct connection_info *cn;
- int after_action;
+ struct connection_info *cn= 0;
+ int after_action= 0;
/* That one is important as this function can be called with */
/* &lock_operations locked when the server logs an error reported */
@@ -1752,8 +1961,35 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
flogger_mutex_lock(&lock_operations);
- if (!(cn= update_connection_hash(event_class, ev, &after_action)))
- goto exit_func;
+ if (maria_55_started && debug_server_started &&
+ event_class == MYSQL_AUDIT_GENERAL_CLASS)
+ {
+ /*
+ There's a bug in MariaDB 5.5 that prevents using thread local
+ variables in some cases.
+ The 'select * from notexisting_table;' query produces such case.
+ So just use the static buffer in this case.
+ */
+ const struct mysql_event_general *event =
+ (const struct mysql_event_general *) ev;
+
+ if (event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR ||
+ (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
+ event->general_query_length == 0 &&
+ cn_error_buffer.query_id == event->query_id))
+ {
+ cn= &cn_error_buffer;
+ cn->header= 1;
+ }
+ else
+ cn= get_loc_info(thd);
+ }
+ else
+ {
+ cn= get_loc_info(thd);
+ }
+
+ update_connection_info(cn, event_class, ev, &after_action);
if (!logging)
goto exit_func;
@@ -1767,8 +2003,11 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
/*
Only one subclass is logged.
*/
- if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS)
+ if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS &&
+ event_query_command(event))
+ {
log_statement(cn, event, "QUERY");
+ }
}
else if (event_class == MYSQL_AUDIT_TABLE_CLASS && FILTER(EVENT_TABLE) && cn)
{
@@ -1809,7 +2048,10 @@ static void auditing(MYSQL_THD thd __attribute__((unused)),
log_connection(cn, event, event->status ? "FAILED_CONNECT": "CONNECT");
break;
case MYSQL_AUDIT_CONNECTION_DISCONNECT:
- log_connection(cn, event, "DISCONNECT");
+ if (use_event_data_for_disconnect)
+ log_connection_event(event, "DISCONNECT");
+ else
+ log_connection(&ci_disconnect_buffer, event, "DISCONNECT");
break;
case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
log_connection(cn, event, "CHANGEUSER");
@@ -1824,10 +2066,6 @@ exit_func:
if (after_action)
{
switch (after_action) {
- case AA_FREE_CONNECTION:
- my_hash_delete(&connection_hash, (uchar *) cn);
- cn= 0;
- break;
case AA_CHANGE_USER:
{
const struct mysql_event_connection *event =
@@ -1845,28 +2083,6 @@ exit_func:
}
-#ifdef DBUG_OFF
- #ifdef __x86_64__
-static const int cmd_off= 4200;
-static const int db_off= 120;
-static const int db_len_off= 128;
- #else
-static const int cmd_off= 2668;
-static const int db_off= 60;
-static const int db_len_off= 64;
- #endif /*x86_64*/
-#else
- #ifdef __x86_64__
-static const int cmd_off= 4432;
-static const int db_off= 120;
-static const int db_len_off= 128;
- #else
-static const int cmd_off= 2808;
-static const int db_off= 64;
-static const int db_len_off= 68;
- #endif /*x86_64*/
-#endif /*DBUG_OFF*/
-
struct mysql_event_general_v8
{
unsigned int event_class;
@@ -1884,8 +2100,31 @@ struct mysql_event_general_v8
unsigned long long general_rows;
};
+
static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8)
{
+#ifdef DBUG_OFF
+ #ifdef __x86_64__
+ static const int cmd_off= 4200;
+ static const int db_off= 120;
+ static const int db_len_off= 128;
+ #else
+ static const int cmd_off= 2668;
+ static const int db_off= 60;
+ static const int db_len_off= 64;
+ #endif /*x86_64*/
+#else
+ #ifdef __x86_64__
+ static const int cmd_off= 4432;
+ static const int db_off= 120;
+ static const int db_len_off= 128;
+ #else
+ static const int cmd_off= 2808;
+ static const int db_off= 64;
+ static const int db_len_off= 68;
+ #endif /*x86_64*/
+#endif /*DBUG_OFF*/
+
struct mysql_event_general event;
if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS)
@@ -1944,6 +2183,41 @@ static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0)
}
+int get_db_mysql57(MYSQL_THD thd, char **name, int *len)
+{
+ int db_off;
+ int db_len_off;
+ if (debug_server_started)
+ {
+#ifdef __x86_64__
+ db_off= 608;
+ db_len_off= 616;
+#else
+ db_off= 0;
+ db_len_off= 0;
+#endif /*x86_64*/
+ }
+ else
+ {
+#ifdef __x86_64__
+ db_off= 536;
+ db_len_off= 544;
+#else
+ db_off= 0;
+ db_len_off= 0;
+#endif /*x86_64*/
+ }
+
+#ifdef __linux__
+ *name= *(char **) (((char *) thd) + db_off);
+ *len= *((int *) (((char*) thd) + db_len_off));
+ if (*name && (*name)[*len] != 0)
+ return 1;
+ return 0;
+#else
+ return 1;
+#endif
+}
/*
As it's just too difficult to #include "sql_class.h",
let's just copy the necessary part of the system_variables
@@ -2070,8 +2344,8 @@ static int server_audit_init(void *p __attribute__((unused)))
flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST);
flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
- my_hash_clear(&incl_user_hash);
- my_hash_clear(&excl_user_hash);
+ coll_init(&incl_user_coll);
+ coll_init(&excl_user_coll);
if (incl_users)
{
@@ -2089,9 +2363,6 @@ static int server_audit_init(void *p __attribute__((unused)))
update_excl_users(NULL, NULL, NULL, &excl_users);
}
- loc_my_hash_init(&connection_hash, 0, &my_charset_bin, 0x100, 0,
- sizeof(unsigned long), 0, 0, free_connection, 0);
-
error_header();
fprintf(stderr, "MariaDB Audit Plugin version %s%s STARTED.\n",
PLUGIN_STR_VERSION, PLUGIN_DEBUG_VERSION);
@@ -2115,6 +2386,16 @@ static int server_audit_init(void *p __attribute__((unused)))
}
}
+ ci_disconnect_buffer.header= 10;
+ ci_disconnect_buffer.thread_id= 0;
+ ci_disconnect_buffer.query_id= 0;
+ ci_disconnect_buffer.db_length= 0;
+ ci_disconnect_buffer.user_length= 0;
+ ci_disconnect_buffer.host_length= 0;
+ ci_disconnect_buffer.ip_length= 0;
+ ci_disconnect_buffer.query= empty_str;
+ ci_disconnect_buffer.query_length= 0;
+
if (logging)
start_logging();
@@ -2133,13 +2414,8 @@ static int server_audit_init_mysql(void *p)
static int server_audit_deinit(void *p __attribute__((unused)))
{
- if (my_hash_inited(&incl_user_hash))
- my_hash_free(&incl_user_hash);
-
- if (my_hash_inited(&excl_user_hash))
- my_hash_free(&excl_user_hash);
-
- my_hash_free(&connection_hash);
+ coll_free(&incl_user_coll);
+ coll_free(&excl_user_coll);
if (output_type == OUTPUT_FILE && logfile)
logger_close(logfile);
@@ -2174,6 +2450,7 @@ static struct st_mysql_audit mysql_descriptor =
{ MYSQL_AUDIT_GENERAL_CLASSMASK | MYSQL_AUDIT_CONNECTION_CLASSMASK }
};
+
mysql_declare_plugin(server_audit)
{
MYSQL_AUDIT_PLUGIN,
@@ -2224,22 +2501,21 @@ maria_declare_plugin_end;
static void mark_always_logged(MYSQL_THD thd)
{
struct connection_info *cn;
- if (thd && (cn= find_connection(thd_get_thread_id(thd))))
+ if (thd && (cn= get_loc_info(thd)))
cn->log_always= 1;
}
static void log_current_query(MYSQL_THD thd)
{
- unsigned long thd_id;
struct connection_info *cn;
- if (!thd ||
- !(cn= find_connection((thd_id= thd_get_thread_id(thd)))))
+ if (!thd)
return;
- if (FILTER(EVENT_QUERY) && do_log_user(cn->user))
+ cn= get_loc_info(thd);
+ if (!ci_needs_setup(cn) && FILTER(EVENT_QUERY) && do_log_user(cn->user))
{
- log_statement_ex(cn, cn->query_time, thd_id, cn->query, cn->query_length,
- 0, "QUERY");
+ log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),
+ cn->query, cn->query_length, 0, "QUERY");
cn->log_always= 1;
}
}
@@ -2251,7 +2527,8 @@ static void update_file_path(MYSQL_THD thd,
{
char *new_name= (*(char **) save) ? *(char **) save : empty_str;
- flogger_mutex_lock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
internal_stop_logging= 1;
error_header();
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
@@ -2287,7 +2564,8 @@ static void update_file_path(MYSQL_THD thd,
file_path= path_buffer;
exit_func:
internal_stop_logging= 0;
- flogger_mutex_unlock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_unlock(&lock_operations);
}
@@ -2331,14 +2609,16 @@ static void update_incl_users(MYSQL_THD thd,
void *var_ptr __attribute__((unused)), const void *save)
{
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
- flogger_mutex_lock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
mark_always_logged(thd);
strncpy(incl_user_buffer, new_users, sizeof(incl_user_buffer));
incl_users= incl_user_buffer;
- user_hash_fill(&incl_user_hash, incl_users, &excl_user_hash, 1);
+ user_coll_fill(&incl_user_coll, incl_users, &excl_user_coll, 1);
error_header();
fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
- flogger_mutex_unlock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_unlock(&lock_operations);
}
@@ -2347,14 +2627,16 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
void *var_ptr __attribute__((unused)), const void *save)
{
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
- flogger_mutex_lock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
mark_always_logged(thd);
strncpy(excl_user_buffer, new_users, sizeof(excl_user_buffer));
excl_users= excl_user_buffer;
- user_hash_fill(&excl_user_hash, excl_users, &incl_user_hash, 0);
+ user_coll_fill(&excl_user_coll, excl_users, &incl_user_coll, 0);
error_header();
fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
- flogger_mutex_unlock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_unlock(&lock_operations);
}
@@ -2430,7 +2712,8 @@ static void update_logging(MYSQL_THD thd,
if (new_logging == logging)
return;
- flogger_mutex_lock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
internal_stop_logging= 1;
if ((logging= new_logging))
{
@@ -2447,7 +2730,8 @@ static void update_logging(MYSQL_THD thd,
}
internal_stop_logging= 0;
- flogger_mutex_unlock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_unlock(&lock_operations);
}
@@ -2459,14 +2743,16 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)),
if (mode_readonly || new_mode == mode)
return;
- flogger_mutex_lock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
internal_stop_logging= 1;
mark_always_logged(thd);
error_header();
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
mode= new_mode;
internal_stop_logging= 0;
- flogger_mutex_unlock(&lock_operations);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_unlock(&lock_operations);
}
@@ -2490,6 +2776,13 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
}
+struct st_my_thread_var *loc_thread_var(void)
+{
+ return 0;
+}
+
+
+
#ifdef _WIN32
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
@@ -2507,9 +2800,18 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void)
goto exit;
started_mariadb= strstr(serv_ver, "MariaDB") != 0;
+ debug_server_started= strstr(serv_ver, "debug") != 0;
- if (!started_mariadb)
+ if (started_mariadb)
{
+ if (serv_ver[0] == '1')
+ use_event_data_for_disconnect= 1;
+ else
+ maria_55_started= 1;
+ }
+ else
+ {
+ /* Started MySQL. */
if (serv_ver[0] == '5' && serv_ver[2] == '5')
{
int sc= serv_ver[4] - '0';
@@ -2526,7 +2828,25 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void)
mysql_descriptor.event_notify= (void *) auditing_v13;
}
}
+ else if (serv_ver[0] == '5' && serv_ver[2] == '6')
+ {
+ int sc= serv_ver[4] - '0';
+ if (serv_ver[5] >= '0' && serv_ver[5] <= '9')
+ sc= sc * 10 + serv_ver[5] - '0';
+ if (sc >= 24)
+ use_event_data_for_disconnect= 1;
+ }
+ else if (serv_ver[0] == '5' && serv_ver[2] == '7')
+ {
+ mysql_57_started= 1;
+ _mysql_plugin_declarations_[0].info= mysql_v4_descriptor;
+ use_event_data_for_disconnect= 1;
+ }
}
+
+ memset(locinfo_ini_value, 'O', sizeof(locinfo_ini_value)-1);
+ locinfo_ini_value[sizeof(locinfo_ini_value)]= 0;
+
exit:
#ifdef _WIN32
return 1;
diff --git a/plugin/server_audit/test_audit_v4.c b/plugin/server_audit/test_audit_v4.c
new file mode 100644
index 00000000000..ae7527f8449
--- /dev/null
+++ b/plugin/server_audit/test_audit_v4.c
@@ -0,0 +1,162 @@
+#define PLUGIN_CONTEXT
+
+#include <stdio.h>
+
+typedef void *MYSQL_THD;
+struct st_mysql_const_lex_string
+{
+ const char *str;
+ size_t length;
+};
+typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING;
+enum enum_sql_command{ SQLCOM_A, SQLCOM_B };
+enum enum_server_command{ SERVCOM_A, SERVCOM_B };
+
+#include "plugin_audit_v4.h"
+
+extern void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev);
+extern int get_db_mysql57(MYSQL_THD thd, char **name, int *len);
+
+
+struct mysql_event_general_302
+{
+ unsigned int event_subclass;
+ int general_error_code;
+ unsigned long general_thread_id;
+ const char *general_user;
+ unsigned int general_user_length;
+ const char *general_command;
+ unsigned int general_command_length;
+ const char *general_query;
+ unsigned int general_query_length;
+ struct charset_info_st *general_charset;
+ unsigned long long general_time;
+ unsigned long long general_rows;
+ unsigned long long query_id;
+ char *database;
+ int database_length;
+};
+
+
+static int auditing_v4(MYSQL_THD thd, mysql_event_class_t class, const void *ev)
+{
+ int *subclass= (int *)ev;
+ struct mysql_event_general_302 ev_302;
+ int subclass_v3, subclass_orig;
+
+ if (class != MYSQL_AUDIT_GENERAL_CLASS &&
+ class != MYSQL_AUDIT_CONNECTION_CLASS)
+ return 0;
+
+ subclass_orig= *subclass;
+
+ if (class == MYSQL_AUDIT_GENERAL_CLASS)
+ {
+ struct mysql_event_general *event= (struct mysql_event_general *) ev;
+ ev_302.general_error_code= event->general_error_code;
+ ev_302.general_thread_id= event->general_thread_id;
+ ev_302.general_user= event->general_user.str;
+ ev_302.general_user_length= event->general_user.length;
+ ev_302.general_command= event->general_command.str;
+ ev_302.general_command_length= event->general_command.length;
+ ev_302.general_query= event->general_query.str;
+ ev_302.general_query_length= event->general_query.length;
+ ev_302.general_charset= event->general_charset;
+ ev_302.general_time= event->general_time;
+ ev_302.general_rows= event->general_rows;
+ if (get_db_mysql57(thd, &ev_302.database, &ev_302.database_length))
+ {
+ ev_302.database= 0;
+ ev_302.database_length= 0;
+ }
+ ev= &ev_302;
+ switch (subclass_orig)
+ {
+ case MYSQL_AUDIT_GENERAL_LOG:
+ subclass_v3= 0;
+ ev_302.event_subclass= 0;
+ break;
+ case MYSQL_AUDIT_GENERAL_ERROR:
+ subclass_v3= 1;
+ ev_302.event_subclass= 1;
+ break;
+ case MYSQL_AUDIT_GENERAL_RESULT:
+ subclass_v3= 2;
+ ev_302.event_subclass= 2;
+ break;
+ case MYSQL_AUDIT_GENERAL_STATUS:
+ {
+ subclass_v3= 3;
+ ev_302.event_subclass= 3;
+ break;
+ }
+ default:
+ return 0;
+ }
+ }
+ else /* if (class == MYSQL_AUDIT_CONNECTION_CLASS) */
+ {
+ switch (subclass_orig)
+ {
+ case MYSQL_AUDIT_CONNECTION_CONNECT:
+ subclass_v3= 0;
+ break;
+ case MYSQL_AUDIT_CONNECTION_DISCONNECT:
+ subclass_v3= 1;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ *subclass= subclass_v3;
+
+ auditing(thd, (int) class, ev);
+
+ *subclass= subclass_orig;
+ return 0;
+}
+
+
+static struct st_mysql_audit mysql_descriptor =
+{
+ MYSQL_AUDIT_INTERFACE_VERSION,
+ NULL,
+ auditing_v4,
+ { (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
+ (unsigned long) MYSQL_AUDIT_CONNECTION_ALL,
+ (unsigned long) MYSQL_AUDIT_PARSE_ALL,
+ 0, /* This event class is currently not supported. */
+ 0, /* This event class is currently not supported. */
+ (unsigned long) MYSQL_AUDIT_GLOBAL_VARIABLE_ALL,
+ (unsigned long) MYSQL_AUDIT_SERVER_STARTUP_ALL,
+ (unsigned long) MYSQL_AUDIT_SERVER_SHUTDOWN_ALL,
+ (unsigned long) MYSQL_AUDIT_COMMAND_ALL,
+ (unsigned long) MYSQL_AUDIT_QUERY_ALL,
+ (unsigned long) MYSQL_AUDIT_STORED_PROGRAM_ALL }
+#ifdef WHEN_MYSQL_BUG_FIXED
+ /*
+ By this moment MySQL just sends no notifications at all
+ when we request only those we actually need.
+ So we have to request everything and filter them inside the
+ handling function.
+ */
+ { (unsigned long) MYSQL_AUDIT_GENERAL_ALL,
+ (unsigned long) (MYSQL_AUDIT_CONNECTION_CONNECT |
+ MYSQL_AUDIT_CONNECTION_DISCONNECT),
+ 0,
+ 0, /* This event class is currently not supported. */
+ 0, /* This event class is currently not supported. */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ }
+#endif /*WHEN_MYSQL_BUG_FIXED*/
+};
+
+
+void *mysql_v4_descriptor= &mysql_descriptor;
+
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index fa8fb3f0a9a..eec9892743b 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -7703,8 +7703,8 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff,
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE);
if (mi)
- tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
- mi->rli.slave_running);
+ tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING &&
+ mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN);
}
mysql_mutex_unlock(&LOCK_active_mi);
if (mi)
@@ -7715,6 +7715,38 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff,
}
+/* How many slaves are connected to this master */
+
+static int show_slaves_connected(THD *thd, SHOW_VAR *var, char *buff)
+{
+
+ var->type= SHOW_LONGLONG;
+ var->value= buff;
+ mysql_mutex_lock(&LOCK_slave_list);
+
+ *((longlong *)buff)= slave_list.records;
+
+ mysql_mutex_unlock(&LOCK_slave_list);
+ return 0;
+}
+
+
+/* How many masters this slave is connected to */
+
+
+static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff)
+{
+ var->type= SHOW_LONGLONG;
+ var->value= buff;
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ *((longlong *)buff)= master_info_index->any_slave_sql_running();
+
+ mysql_mutex_unlock(&LOCK_active_mi);
+ return 0;
+}
+
+
static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff,
enum enum_var_type scope)
{
@@ -8423,6 +8455,9 @@ SHOW_VAR status_vars[]= {
{"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count_), SHOW_LONG_STATUS},
{"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_INT},
#ifdef HAVE_REPLICATION
+ {"Slaves_connected", (char*) &show_slaves_connected, SHOW_SIMPLE_FUNC },
+ {"Slaves_running", (char*) &show_slaves_running, SHOW_SIMPLE_FUNC },
+ {"Slave_connections", (char*) offsetof(STATUS_VAR, com_register_slave), SHOW_LONG_STATUS},
{"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC},
{"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC},
{"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index b6da7933bb1..d81c89fe534 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -34,6 +34,7 @@
HFTODO this must be hidden if we don't want client capabilities in
embedded library
*/
+
#include <my_global.h>
#include <mysql.h>
#include <mysql_com.h>
@@ -107,13 +108,12 @@ extern void query_cache_insert(void *thd, const char *packet, ulong length,
unsigned pkt_nr);
#endif // HAVE_QUERY_CACHE
#define update_statistics(A) A
-#else
-#define update_statistics(A)
-#endif
-
-#ifdef MYSQL_SERVER
+extern my_bool thd_net_is_killed();
/* Additional instrumentation hooks for the server */
#include "mysql_com_server.h"
+#else
+#define update_statistics(A)
+#define thd_net_is_killed() 0
#endif
#define TEST_BLOCKING 8
@@ -876,6 +876,16 @@ my_real_read(NET *net, size_t *complen,
DBUG_PRINT("info",("vio_read returned %ld errno: %d",
(long) length, vio_errno(net->vio)));
+
+ if (i== 0 && thd_net_is_killed())
+ {
+ len= packet_error;
+ net->error= 0;
+ net->last_errno= ER_CONNECTION_KILLED;
+ MYSQL_SERVER_my_error(net->last_errno, MYF(0));
+ goto end;
+ }
+
#if !defined(__WIN__) && defined(MYSQL_SERVER)
/*
We got an error that there was no data on the socket. We now set up
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 216fbde0177..df721342d1d 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -35,7 +35,8 @@ Master_info::Master_info(LEX_STRING *connection_name_arg,
rli(is_slave_recovery), port(MYSQL_PORT),
checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF),
connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0),
- slave_running(0), slave_run_id(0), clock_diff_with_master(0),
+ slave_running(MYSQL_SLAVE_NOT_RUN), slave_run_id(0),
+ clock_diff_with_master(0),
sync_counter(0), heartbeat_period(0), received_heartbeats(0),
master_id(0), prev_master_id(0),
using_gtid(USE_GTID_NO), events_queued_since_last_gtid(0),
@@ -1396,23 +1397,24 @@ bool Master_info_index::give_error_if_slave_running()
The LOCK_active_mi must be held while calling this function.
@return
- TRUE If some slave SQL thread is running.
- FALSE No slave SQL thread is running
+ 0 No Slave SQL thread is running
+ # Number of slave SQL thread running
*/
-bool Master_info_index::any_slave_sql_running()
+uint Master_info_index::any_slave_sql_running()
{
+ uint count= 0;
DBUG_ENTER("any_slave_sql_running");
if (!this) // master_info_index is set to NULL on server shutdown
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(count);
for (uint i= 0; i< master_info_hash.records; ++i)
{
Master_info *mi= (Master_info *)my_hash_element(&master_info_hash, i);
if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN)
- DBUG_RETURN(TRUE);
+ count++;
}
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(count);
}
@@ -1442,7 +1444,7 @@ bool Master_info_index::start_all_slaves(THD *thd)
Try to start all slaves that are configured (host is defined)
and are not already running
*/
- if ((mi->slave_running != MYSQL_SLAVE_RUN_CONNECT ||
+ if ((mi->slave_running == MYSQL_SLAVE_NOT_RUN ||
!mi->rli.slave_running) && *mi->host)
{
if ((error= start_slave(thd, mi, 1)))
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
index 69d602c1dcb..9365c065ea9 100644
--- a/sql/rpl_mi.h
+++ b/sql/rpl_mi.h
@@ -345,7 +345,7 @@ public:
Master_info *get_master_info(const LEX_STRING *connection_name,
Sql_condition::enum_warning_level warning);
bool give_error_if_slave_running();
- bool any_slave_sql_running();
+ uint any_slave_sql_running();
bool start_all_slaves(THD *thd);
bool stop_all_slaves(THD *thd);
};
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index ba4badd0d5e..2dd6f7d7afc 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -63,7 +63,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0),
abort_pos_wait(0), slave_run_id(0), sql_driver_thd(),
gtid_skip_flag(GTID_SKIP_NOT), inited(0), abort_slave(0), stop_for_until(0),
- slave_running(0), until_condition(UNTIL_NONE),
+ slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE),
until_log_pos(0), retried_trans(0), executed_entries(0),
m_flags(0)
{
diff --git a/sql/slave.cc b/sql/slave.cc
index 94c8835d31b..244b2f14643 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -117,7 +117,7 @@ static const char *reconnect_messages[SLAVE_RECON_ACT_MAX][SLAVE_RECON_MSG_MAX]=
{
{
"Waiting to reconnect after a failed registration on master",
- "Slave I/O thread killed while waitnig to reconnect after a failed \
+ "Slave I/O thread killed while waiting to reconnect after a failed \
registration on master",
"Reconnecting after a failed registration on master",
"failed registering on master, reconnecting to try again, \
@@ -2728,6 +2728,8 @@ static bool send_show_master_info_header(THD *thd, bool full,
DBUG_RETURN(FALSE);
}
+/* Text for Slave_IO_Running */
+static const char *slave_running[]= { "No", "Connecting", "Preparing", "Yes" };
static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
String *gtid_pos)
@@ -2780,9 +2782,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
&my_charset_bin);
protocol->store((ulonglong) mi->rli.group_relay_log_pos);
protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
- protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ?
- "Yes" : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ?
- "Connecting" : "No"), &my_charset_bin);
+ protocol->store(slave_running[mi->slave_running], &my_charset_bin);
protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
protocol->store(rpl_filter->get_do_db());
protocol->store(rpl_filter->get_ignore_db());
@@ -2825,7 +2825,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
Seconds_Behind_Master: if SQL thread is running and I/O thread is
connected, we can compute it otherwise show NULL (i.e. unknown).
*/
- if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) &&
+ if ((mi->slave_running == MYSQL_SLAVE_RUN_READING) &&
mi->rli.slave_running)
{
long time_diff;
@@ -4128,16 +4128,16 @@ connected:
if (request_dump(thd, mysql, mi, &suppress_warnings))
{
sql_print_error("Failed on request_dump()");
- if (check_io_slave_killed(mi, "Slave I/O thread killed while \
-requesting master dump") ||
- try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
- reconnect_messages[SLAVE_RECON_ACT_DUMP]))
+ if (check_io_slave_killed(mi, NullS) ||
+ try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
+ reconnect_messages[SLAVE_RECON_ACT_DUMP]))
goto err;
goto connected;
}
const char *event_buf;
+ mi->slave_running= MYSQL_SLAVE_RUN_READING;
DBUG_ASSERT(mi->last_error().number == 0);
while (!io_slave_killed(mi))
{
@@ -4150,8 +4150,7 @@ requesting master dump") ||
*/
THD_STAGE_INFO(thd, stage_waiting_for_master_to_send_event);
event_len= read_event(mysql, mi, &suppress_warnings);
- if (check_io_slave_killed(mi, "Slave I/O thread killed while \
-reading event"))
+ if (check_io_slave_killed(mi, NullS))
goto err;
if (event_len == packet_error)
diff --git a/sql/slave.h b/sql/slave.h
index a519229fac1..361c19557b1 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -135,11 +135,11 @@ extern const char *relay_log_index;
extern const char *relay_log_basename;
/*
- 3 possible values for Master_info::slave_running and
+ 4 possible values for Master_info::slave_running and
Relay_log_info::slave_running.
- The values 0,1,2 are very important: to keep the diff small, I didn't
- substitute places where we use 0/1 with the newly defined symbols. So don't change
- these values.
+ The values 0,1,2,3 are very important: to keep the diff small, I didn't
+ substitute places where we use 0/1 with the newly defined symbols.
+ So don't change these values.
The same way, code is assuming that in Relay_log_info we use only values
0/1.
I started with using an enum, but
@@ -148,6 +148,7 @@ extern const char *relay_log_basename;
#define MYSQL_SLAVE_NOT_RUN 0
#define MYSQL_SLAVE_RUN_NOT_CONNECT 1
#define MYSQL_SLAVE_RUN_CONNECT 2
+#define MYSQL_SLAVE_RUN_READING 3
#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
"FIRST")
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 421ad627190..0865f7ee375 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1817,7 +1817,8 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
void THD::awake(killed_state state_to_set)
{
DBUG_ENTER("THD::awake");
- DBUG_PRINT("enter", ("this: %p current_thd: %p", this, current_thd));
+ DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d",
+ this, current_thd, (int) state_to_set));
THD_CHECK_SENTRY(this);
mysql_mutex_assert_owner(&LOCK_thd_data);
@@ -4026,6 +4027,12 @@ void thd_increment_bytes_sent(void *thd, ulong length)
}
}
+my_bool thd_net_is_killed()
+{
+ THD *thd= current_thd;
+ return thd && thd->killed ? 1 : 0;
+}
+
void thd_increment_bytes_received(void *thd, ulong length)
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 27837e4f60a..6468f301082 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -703,6 +703,7 @@ typedef struct system_status_var
ulong com_stmt_reset;
ulong com_stmt_close;
+ ulong com_register_slave;
ulong created_tmp_disk_tables_;
ulong created_tmp_tables_;
ulong ha_commit_count;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 663864a95bd..7c4bfb96bb5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1353,6 +1353,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifdef HAVE_REPLICATION
case COM_REGISTER_SLAVE:
{
+ status_var_increment(thd->status_var.com_register_slave);
if (!register_slave(thd, (uchar*)packet, packet_length))
my_ok(thd);
break;
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index fc7edb84c0f..aa677342fac 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -594,7 +594,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
if (fs) {
fputs(EL, fs);
fclose(fs);
- str = (err) ? NULL : "Ok";
+ str = (err) ? NULL : (char*) "Ok";
} else if (!err) {
str = ((JOUTSTR*)jp)->Strp;
jp->WriteChr('\0');
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 40685ae0f0e..215562af46e 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -3365,7 +3365,7 @@ my_bool jsoncontains_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
long long jsoncontains(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *is_null, char *error)
{
- char *p, res[256];
+ char *p __attribute__((unused)), res[256];
long long n;
unsigned long reslen;
diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py
index 0ddee301d1b..b94a80ec7be 100644
--- a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py
+++ b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py
@@ -24,6 +24,7 @@ def gen_test(n):
def main():
print "# this test is generated by change_bin.py"
print "# test binary expansion is hot"
+ print "--source include/big_test.inc"
print "--disable_warnings"
print "DROP TABLE IF EXISTS t,ti;"
print "--enable_warnings"
diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test
index 0365c155302..6053a263cf0 100644
--- a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test
+++ b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test
@@ -1,6 +1,7 @@
source include/have_tokudb.inc;
# this test is generated by change_bin.py
# test binary expansion is hot
+--source include/big_test.inc
--disable_warnings
DROP TABLE IF EXISTS t,ti;
--enable_warnings
diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_char.py b/storage/tokudb/mysql-test/tokudb/t/change_column_char.py
index 99d99d1c017..7481d9092f2 100644
--- a/storage/tokudb/mysql-test/tokudb/t/change_column_char.py
+++ b/storage/tokudb/mysql-test/tokudb/t/change_column_char.py
@@ -24,6 +24,7 @@ def gen_test(n):
def main():
print "# this test is generated by change_char.py"
print "# test char expansion"
+ print "--source include/big_test.inc"
print "--disable_warnings"
print "DROP TABLE IF EXISTS t,ti;"
print "--enable_warnings"
diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_char.test b/storage/tokudb/mysql-test/tokudb/t/change_column_char.test
index 8a0b0a9abd8..977420ad07e 100644
--- a/storage/tokudb/mysql-test/tokudb/t/change_column_char.test
+++ b/storage/tokudb/mysql-test/tokudb/t/change_column_char.test
@@ -1,6 +1,7 @@
source include/have_tokudb.inc;
# this test is generated by change_char.py
# test char expansion
+--source include/big_test.inc
--disable_warnings
DROP TABLE IF EXISTS t,ti;
--enable_warnings