[Commits] Rev 3860: MDEV-4472 Auditing Plugin. in file:///home/hf/wmar/mdev-4472/

holyfoot at askmonty.org holyfoot at askmonty.org
Thu Aug 22 22:07:33 EEST 2013


At file:///home/hf/wmar/mdev-4472/

------------------------------------------------------------
revno: 3860
revision-id: holyfoot at askmonty.org-20130822175731-1vv1j2y5cgy9s6ua
parent: bar at mariadb.org-20130822122354-1z4rv3p1bttdul3d
committer: Alexey Botchkov <holyfoot at askmonty.org>
branch nick: mdev-4472
timestamp: Thu 2013-08-22 22:57:31 +0500
message:
  MDEV-4472 Auditing Plugin.
-------------- next part --------------
=== modified file 'VERSION'
--- a/VERSION	2013-07-16 17:09:54 +0000
+++ b/VERSION	2013-08-22 17:57:31 +0000
@@ -1,4 +1,4 @@
 MYSQL_VERSION_MAJOR=5
 MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=32
+MYSQL_VERSION_PATCH=33
 MYSQL_VERSION_EXTRA=

=== modified file 'include/mysql/plugin_audit.h'
--- a/include/mysql/plugin_audit.h	2013-04-19 10:50:16 +0000
+++ b/include/mysql/plugin_audit.h	2013-08-22 17:57:31 +0000
@@ -25,7 +25,7 @@
 
 #define MYSQL_AUDIT_CLASS_MASK_SIZE 1
 
-#define MYSQL_AUDIT_INTERFACE_VERSION 0x0301
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0302
 
 
 /*************************************************************************
@@ -59,6 +59,10 @@ struct mysql_event_general
   struct charset_info_st *general_charset;
   unsigned long long general_time;
   unsigned long long general_rows;
+  /* Added for 0x302 */
+  long long query_id;
+  const char *database;
+  unsigned int database_length;
 };
 
 
@@ -140,6 +144,8 @@ struct mysql_event_table
   unsigned int new_database_length;
   const char *new_table;
   unsigned int new_table_length;
+  /* Added for 0x302 */
+  long long query_id;
 };
 
 /*************************************************************************

=== modified file 'include/mysql/plugin_audit.h.pp'
--- a/include/mysql/plugin_audit.h.pp	2013-04-19 10:50:16 +0000
+++ b/include/mysql/plugin_audit.h.pp	2013-08-22 17:57:31 +0000
@@ -92,6 +92,28 @@ extern struct kill_statement_service_st 
   enum thd_kill_levels (*thd_kill_level_func)(const void*);
 } *thd_kill_statement_service;
 enum thd_kill_levels thd_kill_level(const void*);
+#include <mysql/service_logger.h>
+typedef struct logger_handle_st LOGGER_HANDLE;
+extern struct logger_service_st {
+  void (*logger_init_mutexes)();
+  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 (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int (*rotate)(LOGGER_HANDLE *log);
+} *logger_service;
+  void logger_init_mutexes();
+  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_printf(LOGGER_HANDLE *log, const char *fmt, ...);
+  int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int logger_rotate(LOGGER_HANDLE *log);
 struct st_mysql_xid {
   long formatID;
   long gtrid_length;
@@ -258,6 +280,9 @@ struct mysql_event_general
   struct charset_info_st *general_charset;
   unsigned long long general_time;
   unsigned long long general_rows;
+  long long query_id;
+  const char *database;
+  unsigned int database_length;
 };
 struct mysql_event_connection
 {
@@ -299,6 +324,7 @@ struct mysql_event_table
   unsigned int new_database_length;
   const char *new_table;
   unsigned int new_table_length;
+  long long query_id;
 };
 struct st_mysql_audit
 {

=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp	2013-03-26 18:17:26 +0000
+++ b/include/mysql/plugin_auth.h.pp	2013-08-22 17:57:31 +0000
@@ -92,6 +92,28 @@ extern struct kill_statement_service_st 
   enum thd_kill_levels (*thd_kill_level_func)(const void*);
 } *thd_kill_statement_service;
 enum thd_kill_levels thd_kill_level(const void*);
+#include <mysql/service_logger.h>
+typedef struct logger_handle_st LOGGER_HANDLE;
+extern struct logger_service_st {
+  void (*logger_init_mutexes)();
+  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 (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int (*rotate)(LOGGER_HANDLE *log);
+} *logger_service;
+  void logger_init_mutexes();
+  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_printf(LOGGER_HANDLE *log, const char *fmt, ...);
+  int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int logger_rotate(LOGGER_HANDLE *log);
 struct st_mysql_xid {
   long formatID;
   long gtrid_length;

=== modified file 'include/mysql/plugin_ftparser.h.pp'
--- a/include/mysql/plugin_ftparser.h.pp	2013-01-18 18:04:23 +0000
+++ b/include/mysql/plugin_ftparser.h.pp	2013-08-22 17:57:31 +0000
@@ -92,6 +92,28 @@ extern struct kill_statement_service_st 
   enum thd_kill_levels (*thd_kill_level_func)(const void*);
 } *thd_kill_statement_service;
 enum thd_kill_levels thd_kill_level(const void*);
+#include <mysql/service_logger.h>
+typedef struct logger_handle_st LOGGER_HANDLE;
+extern struct logger_service_st {
+  void (*logger_init_mutexes)();
+  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 (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int (*rotate)(LOGGER_HANDLE *log);
+} *logger_service;
+  void logger_init_mutexes();
+  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_printf(LOGGER_HANDLE *log, const char *fmt, ...);
+  int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int logger_rotate(LOGGER_HANDLE *log);
 struct st_mysql_xid {
   long formatID;
   long gtrid_length;

=== renamed file 'plugin/sql_errlog/service_logger.h' => 'include/mysql/service_logger.h'
--- a/plugin/sql_errlog/service_logger.h	2012-03-24 10:24:20 +0000
+++ b/include/mysql/service_logger.h	2013-08-22 17:57:31 +0000
@@ -60,17 +60,20 @@ extern "C" {
 typedef struct logger_handle_st LOGGER_HANDLE;
 
 extern struct logger_service_st {
+  void (*logger_init_mutexes)();
   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 (*write)(LOGGER_HANDLE *log, const char *buffer, size_t size);
   int (*rotate)(LOGGER_HANDLE *log);
 } *logger_service;
 
-#if 0 /*MYSQL_DYNAMIC_PLUGIN*/
+#if MYSQL_DYNAMIC_PLUGIN
 
+#define logger_init_mutexes logger_service->logger_init_mutexes
 #define logger_open(path, size_limit, rotations) \
   (logger_service->open(path, size_limit, rotations))
 #define logger_close(log) (logger_service->close(log))
@@ -78,17 +81,19 @@ extern struct logger_service_st {
 #define logger_vprintf(log, fmt, argptr) (logger_service->\
     vprintf(log, fmt, argptr))
 #define logger_printf logger_service->printf
+#define logger_write(log, buffer, size) \
+  (logger_service->write(log, buffer, size))
 #else
 
+  void logger_init_mutexes();
   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();
+  int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size);
+  int logger_rotate(LOGGER_HANDLE *log); 
 #endif
 
 

=== modified file 'include/mysql/services.h'
--- a/include/mysql/services.h	2013-01-18 18:04:23 +0000
+++ b/include/mysql/services.h	2013-08-22 17:57:31 +0000
@@ -25,6 +25,7 @@ extern "C" {
 #include <mysql/service_progress_report.h>
 #include <mysql/service_debug_sync.h>
 #include <mysql/service_kill_statement.h>
+#include <mysql/service_logger.h>
 
 #ifdef __cplusplus
 }

=== modified file 'include/service_versions.h'
--- a/include/service_versions.h	2013-01-18 18:04:23 +0000
+++ b/include/service_versions.h	2013-08-22 17:57:31 +0000
@@ -26,4 +26,5 @@
 #define VERSION_progress_report         0x0100
 #define VERSION_debug_sync              0x1000
 #define VERSION_kill_statement          0x1000
+#define VERSION_logger                  0x0100
 

=== modified file 'libservices/CMakeLists.txt'
--- a/libservices/CMakeLists.txt	2013-01-18 18:04:23 +0000
+++ b/libservices/CMakeLists.txt	2013-08-22 17:57:31 +0000
@@ -22,7 +22,8 @@ SET(MYSQLSERVICES_SOURCES
   my_thread_scheduler_service.c
   progress_report_service.c
   debug_sync_service.c
-  kill_statement_service.c)
+  kill_statement_service.c
+  logger_service.c)
 
 ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
 INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development)

=== renamed file 'plugin/sql_errlog/logger_service.c' => 'libservices/logger_service.c'
=== modified file 'mysql-test/r/handlersocket.result'
--- a/mysql-test/r/handlersocket.result	2013-01-18 18:04:23 +0000
+++ b/mysql-test/r/handlersocket.result	2013-08-22 17:57:31 +0000
@@ -5,7 +5,7 @@ plugin_version	1.0
 plugin_status   ACTIVE
 plugin_type     DAEMON
 plugin_library  handlersocket.so
-plugin_library_version  1.4
+plugin_library_version  1.5
 plugin_author   higuchi dot akira at dena dot jp
 plugin_description      Direct access into InnoDB
 plugin_license  BSD

=== modified file 'mysql-test/r/plugin.result'
--- a/mysql-test/r/plugin.result	2013-06-13 18:19:11 +0000
+++ b/mysql-test/r/plugin.result	2013-08-22 17:57:31 +0000
@@ -15,7 +15,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE     STORAGE ENGINE
 PLUGIN_TYPE_VERSION     #
 PLUGIN_LIBRARY  ha_example.so
-PLUGIN_LIBRARY_VERSION  1.4
+PLUGIN_LIBRARY_VERSION  1.5
 PLUGIN_AUTHOR   Brian Aker, MySQL AB
 PLUGIN_DESCRIPTION      Example storage engine
 PLUGIN_LICENSE  GPL
@@ -28,7 +28,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE     DAEMON
 PLUGIN_TYPE_VERSION     #
 PLUGIN_LIBRARY  ha_example.so
-PLUGIN_LIBRARY_VERSION  1.4
+PLUGIN_LIBRARY_VERSION  1.5
 PLUGIN_AUTHOR   Sergei Golubchik
 PLUGIN_DESCRIPTION      Unusable Daemon
 PLUGIN_LICENSE  GPL
@@ -57,7 +57,7 @@ PLUGIN_STATUS	DELETED
 PLUGIN_TYPE     STORAGE ENGINE
 PLUGIN_TYPE_VERSION     #
 PLUGIN_LIBRARY  ha_example.so
-PLUGIN_LIBRARY_VERSION  1.4
+PLUGIN_LIBRARY_VERSION  1.5
 PLUGIN_AUTHOR   Brian Aker, MySQL AB
 PLUGIN_DESCRIPTION      Example storage engine
 PLUGIN_LICENSE  GPL

=== added file 'mysql-test/suite/plugins/r/server_audit.result'
--- a/mysql-test/suite/plugins/r/server_audit.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/r/server_audit.result	2013-08-22 17:57:31 +0000
@@ -0,0 +1,113 @@
+install plugin server_audit soname 'server_audit';
+show variables like 'server_audit%';
+Variable_name   Value
+server_audit_events     
+server_audit_excl_users 
+server_audit_file_path  
+server_audit_file_rotate_now    
+server_audit_file_rotate_size   1000000
+server_audit_file_rotations     9
+server_audit_incl_users 
+server_audit_logging    OFF
+server_audit_mode       0
+server_audit_output_type        null
+server_audit_syslog_facility    LOG_USER
+server_audit_syslog_ident       mysql-server_auditing
+server_audit_syslog_info        
+server_audit_syslog_priority    LOG_INFO
+set global server_audit_file_path='server_audit.log';
+set global server_audit_output_type=file;
+set global server_audit_logging=on;
+connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET);
+ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO)
+set global server_audit_incl_users='odin, dva, tri';
+create table t1 (id int);
+set global server_audit_incl_users='odin, root, dva, tri';
+create table t2 (id int);
+set global server_audit_excl_users='odin, dva, tri';
+insert into t1 values (1), (2);
+select * from t1;
+id
+1
+2
+set global server_audit_incl_users='odin, root, dva, tri';
+insert into t2 values (1), (2);
+select * from t2;
+id
+1
+2
+set global server_audit_events='connect,query';
+insert into t2 values (1), (2);
+select * from t2;
+id
+1
+2
+1
+2
+select * from t_doesnt_exist;
+ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist
+syntax_error_query;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'syntax_error_query' at line 1
+drop table t1, t2;
+show variables like 'server_audit%';
+Variable_name   Value
+server_audit_events     CONNECT,QUERY
+server_audit_excl_users odin, root, dva, tri
+server_audit_file_path  server_audit.log
+server_audit_file_rotate_now    
+server_audit_file_rotate_size   1000000
+server_audit_file_rotations     9
+server_audit_incl_users odin, root, dva, tri
+server_audit_logging    ON
+server_audit_mode       0
+server_audit_output_type        file
+server_audit_syslog_facility    LOG_USER
+server_audit_syslog_ident       mysql-server_auditing
+server_audit_syslog_info        
+server_audit_syslog_priority    LOG_INFO
+set global server_audit_mode=1;
+set global server_audit_events='';
+create table t1 (id2 int);
+insert into t1 values (1), (2);
+select * from t1;
+id2
+1
+2
+drop table t1;
+uninstall plugin server_audit;
+Warnings:
+Warning 1620    Plugin is busy and will be uninstalled on shutdown
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0
+TIME,HOSTNAME,root,localhost,ID,0,CONNECT,mysql,,0
+TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
+TIME,HOSTNAME,no_such_user,localhost,ID,0,FAILED_CONNECT,,,ID
+TIME,HOSTNAME,no_such_user,localhost,ID,0,DISCONNECT,,,0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t2,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t2 (id int)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t2,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t2,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_events=\'connect,query\'',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t_doesnt_exist',ID
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'syntax_error_query',ID
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'drop table t1, t2',0
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'show variables like \'server_audit%\'',0
+TIME,HOSTNAME,root,localhost,ID,0,QUERY,,'set global server_audit_mode=1',0
+TIME,HOSTNAME,root,localhost,ID,0,QUERY,,'set global server_audit_events=\'\'',0
+TIME,HOSTNAME,root,localhost,ID,0,CONNECT,test,,0
+TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t1,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t1 (id2 int)',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t1 values (1), (2)',0
+TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t1,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t1',0
+TIME,HOSTNAME,root,localhost,ID,ID,DROP,test,t1,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'drop table t1',0
+TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,plugin,
+TIME,HOSTNAME,root,localhost,ID,0,QUERY,,'uninstall plugin server_audit',0

=== added file 'mysql-test/suite/plugins/t/server_audit.test'
--- a/mysql-test/suite/plugins/t/server_audit.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/t/server_audit.test	2013-08-22 17:57:31 +0000
@@ -0,0 +1,56 @@
+
+--source include/not_embedded.inc
+
+if (!$SERVER_AUDIT_SO) {
+  skip No SERVER_AUDIT plugin;
+}
+
+install plugin server_audit soname 'server_audit';
+
+show variables like 'server_audit%';
+set global server_audit_file_path='server_audit.log';
+set global server_audit_output_type=file;
+set global server_audit_logging=on;
+connect (con1,localhost,root,,mysql);
+connection default;
+disconnect con1;
+--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
+--error ER_ACCESS_DENIED_ERROR
+connect (con1,localhost,no_such_user,,mysql);
+connection default;
+set global server_audit_incl_users='odin, dva, tri';
+create table t1 (id int);
+set global server_audit_incl_users='odin, root, dva, tri';
+create table t2 (id int);
+set global server_audit_excl_users='odin, dva, tri';
+insert into t1 values (1), (2);
+select * from t1;
+set global server_audit_incl_users='odin, root, dva, tri';
+insert into t2 values (1), (2);
+select * from t2;
+set global server_audit_events='connect,query';
+insert into t2 values (1), (2);
+select * from t2;
+--error ER_NO_SUCH_TABLE
+select * from t_doesnt_exist;
+--error 1064
+syntax_error_query;
+drop table t1, t2;
+show variables like 'server_audit%';
+set global server_audit_mode=1;
+set global server_audit_events='';
+connect (con1,localhost,root,,test);
+create table t1 (id2 int);
+insert into t1 values (1), (2);
+select * from t1;
+drop table t1;
+connection default;
+disconnect con1;
+
+uninstall plugin server_audit;
+
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+# replace the timestamp and the hostname with constant values
+--replace_regex /[0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\,[^,]*\,/TIME,HOSTNAME,/ /\,[1-9][0-9]*\,/,1,/ /\,[1-9][0-9]*/,ID/
+cat_file $MYSQLD_DATADIR/server_audit.log;
+

=== modified file 'mysys/CMakeLists.txt'
--- a/mysys/CMakeLists.txt	2012-05-04 12:02:35 +0000
+++ b/mysys/CMakeLists.txt	2013-08-22 17:57:31 +0000
@@ -37,7 +37,7 @@ SET(MYSYS_SOURCES  array.c charset-def.c
                 safemalloc.c my_new.cc
                                 my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
                                 my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c
-                                my_rdtsc.c my_context.c)
+                                my_rdtsc.c my_context.c file_logger.c)
 
 IF (WIN32)
  SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c)

=== renamed file 'plugin/sql_errlog/sql_logger.cc' => 'mysys/file_logger.c'
--- a/plugin/sql_errlog/sql_logger.cc	2013-06-22 12:02:03 +0000
+++ b/mysys/file_logger.c	2013-08-22 17:57:31 +0000
@@ -16,10 +16,12 @@
 
 #include "my_global.h"
 #include <my_sys.h>
-#include "service_logger.h"
+#include <mysql/service_logger.h>
 #include <my_pthread.h>
 
+#ifndef _WIN32
 extern MYSQL_PLUGIN_IMPORT char  *mysql_data_home;
+#endif /*!_WIN32*/
 
 #ifdef HAVE_PSI_INTERFACE
 /* These belong to the service initialization */
@@ -51,6 +53,12 @@ LOGGER_HANDLE *logger_open(const char *p
                            unsigned int rotations)
 {
   LOGGER_HANDLE new_log, *l_perm;
+  char *local_mysql_data_home;
+#ifdef _WIN32
+  local_mysql_data_home= (char *)GetProcAddress(0, "mysql_data_home");
+#else
+  local_mysql_data_home= mysql_data_home;
+#endif /*_WIN32*/
 
   /*
     I don't think we ever need more rotations,
@@ -62,7 +70,7 @@ LOGGER_HANDLE *logger_open(const char *p
   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));
+        local_mysql_data_home, "", MY_UNPACK_FILENAME));
 
   if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN)
   {
@@ -168,6 +176,29 @@ int logger_vprintf(LOGGER_HANDLE *log, c
 }
 
 
+int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size)
+{
+  int result;
+  my_off_t filesize;
+
+  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 */
+  }
+
+  result= my_write(log->file, (uchar *) buffer, size, MYF(0));
+
+exit:
+  mysql_mutex_unlock(&log->lock);
+  return result;
+}
+
+
 int logger_rotate(LOGGER_HANDLE *log)
 {
   int result;
@@ -188,7 +219,7 @@ int logger_printf(LOGGER_HANDLE *log, co
   return result;
 }
 
-void init_logger_mutexes()
+void logger_init_mutexes()
 {
 #ifdef HAVE_PSI_INTERFACE
   if (PSI_server)

=== added directory 'plugin/server_audit'
=== added file 'plugin/server_audit/CMakeLists.txt'
--- a/plugin/server_audit/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ b/plugin/server_audit/CMakeLists.txt	2013-08-22 17:57:31 +0000
@@ -0,0 +1,16 @@
+# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+MYSQL_ADD_PLUGIN(server_audit server_audit.c MODULE_ONLY)

=== added file 'plugin/server_audit/server_audit.c'
--- a/plugin/server_audit/server_audit.c	1970-01-01 00:00:00 +0000
+++ b/plugin/server_audit/server_audit.c	2013-08-22 17:57:31 +0000
@@ -0,0 +1,1125 @@
+/* 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 <stdio.h>
+#include <time.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <syslog.h>
+#else
+#define syslog(PRIORITY, FORMAT, INFO, MESSAGE_LEN, MESSAGE) do {}while(0)
+static void closelog() {}
+#define openlog(IDENT, LOG_NOWAIT, LOG_USER)  do {}while(0)
+
+/* priorities */
+#define LOG_EMERG       0       /* system is unusable */
+#define LOG_ALERT       1       /* action must be taken immediately */
+#define LOG_CRIT        2       /* critical conditions */
+#define LOG_ERR         3       /* error conditions */
+#define LOG_WARNING     4       /* warning conditions */
+#define LOG_NOTICE      5       /* normal but significant condition */
+#define LOG_INFO        6       /* informational */
+#define LOG_DEBUG       7       /* debug-level messages */
+
+#define LOG_MAKEPRI(fac, pri)   (((fac) << 3) | (pri))
+
+/* facility codes */
+#define LOG_KERN        (0<<3)  /* kernel messages */
+#define LOG_USER        (1<<3)  /* random user-level messages */
+#define LOG_MAIL        (2<<3)  /* mail system */
+#define LOG_DAEMON      (3<<3)  /* system daemons */
+#define LOG_AUTH        (4<<3)  /* security/authorization messages */
+#define LOG_SYSLOG      (5<<3)  /* messages generated internally by syslogd */
+#define LOG_LPR         (6<<3)  /* line printer subsystem */
+#define LOG_NEWS        (7<<3)  /* network news subsystem */
+#define LOG_UUCP        (8<<3)  /* UUCP subsystem */
+#define LOG_CRON        (9<<3)  /* clock daemon */
+#define LOG_AUTHPRIV    (10<<3) /* security/authorization messages (private) */
+#define LOG_FTP         (11<<3) /* ftp daemon */
+#define LOG_LOCAL0      (16<<3) /* reserved for local use */
+#define LOG_LOCAL1      (17<<3) /* reserved for local use */
+#define LOG_LOCAL2      (18<<3) /* reserved for local use */
+#define LOG_LOCAL3      (19<<3) /* reserved for local use */
+#define LOG_LOCAL4      (20<<3) /* reserved for local use */
+#define LOG_LOCAL5      (21<<3) /* reserved for local use */
+#define LOG_LOCAL6      (22<<3) /* reserved for local use */
+#define LOG_LOCAL7      (23<<3) /* reserved for local use */
+
+#endif /*!_WIN32*/
+
+/*
+   Defines that can be used to reshape the pluging:
+   #define MARIADB_ONLY
+   #define USE_MARIA_PLUGIN_INTERFACE
+*/
+
+#if !defined(MYSQL_DYNAMIC_PLUGIN) && !defined(MARIADB_ONLY)
+#define MARIADB_ONLY
+#endif /*MYSQL_PLUGIN_DYNAMIC*/
+
+#ifndef MARIADB_ONLY
+#define MYSQL_SERVICE_LOGGER_INCLUDED
+#endif /*MARIADB_ONLY*/
+
+#include <hash.h>
+#include <typelib.h>
+#include <mysql/plugin.h>
+#include <mysql/plugin_audit.h>
+
+#ifndef MARIADB_ONLY
+#undef MYSQL_SERVICE_LOGGER_INCLUDED
+#undef MYSQL_DYNAMIC_PLUGIN
+#include "../../mysys/file_logger.c"
+#endif /*MARIADB_ONLY*/
+
+/*
+ Disable __attribute__() on non-gcc compilers.
+*/
+#if !defined(__attribute__) && !defined(__GNUC__)
+#define __attribute__(A)
+#endif
+
+#ifdef _WIN32
+#define localtime_r(a, b) localtime_s(b, a)
+#endif /*WIN32*/
+
+
+extern char server_version[];
+static const char *serv_ver= NULL;
+static int started_mysql= 0;
+static char *incl_users, *excl_users,
+            *file_path, *syslog_info;
+static unsigned int mode, mode_readonly= 0;
+static ulong output_type= 0;
+static ulong syslog_facility, syslog_priority;
+
+static ulonglong events; /* mask for events to log */
+static unsigned long long file_rotate_size;
+static unsigned int rotations;
+static char *rotate;
+static char logging;
+static char user_buffer[1024];
+
+static char servhost[256];
+static size_t servhost_len;
+static char *syslog_ident;
+static char syslog_ident_buffer[128]= "mysql-server_auditing";
+
+static void update_incl_users(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                              void *var_ptr, const void *save);
+static void update_excl_users(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                              void *var_ptr, const void *save);
+static void update_output_type(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                               void *var_ptr, const void *save);
+static void update_syslog_facility(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                                   void *var_ptr, const void *save);
+static void update_syslog_priority(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                                   void *var_ptr, const void *save);
+static void update_mode(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                        void *var_ptr, const void *save);
+static void update_logging(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                           void *var_ptr, const void *save);
+static void update_syslog_ident(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                                void *var_ptr, const void *save);
+static void rotate_log(MYSQL_THD thd, struct st_mysql_sys_var *var,
+                       void *var_ptr, const void *save);
+
+static MYSQL_SYSVAR_STR(incl_users, incl_users, PLUGIN_VAR_RQCMDARG,
+       "Comma separated list of users to monitor.",
+       NULL, update_incl_users, NULL);
+static MYSQL_SYSVAR_STR(excl_users, excl_users, PLUGIN_VAR_RQCMDARG,
+       "Comma separated list of users to exclude from auditing.",
+       NULL, update_excl_users, NULL);
+/* bits in the event filter. */
+#define EVENT_CONNECT 1
+#define EVENT_QUERY 2
+#define EVENT_TABLE 4
+static const char *event_names[]=
+{
+  "CONNECT", "QUERY", "TABLE",
+  NULL
+};
+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.",
+       NULL, NULL, 0, &events_typelib);
+#define OUTPUT_NULL 0
+#define OUTPUT_SYSLOG 1
+#define OUTPUT_FILE 2
+static const char *output_type_names[]= { "null", "syslog", "file", 0 };
+static TYPELIB output_typelib=
+{
+    array_elements(output_type_names) - 1, "output_typelib",
+    output_type_names, NULL
+};
+static MYSQL_SYSVAR_ENUM(output_type, output_type, PLUGIN_VAR_RQCMDARG,
+       "Desired output type. Possible values - 'syslog', 'file'"
+       " or 'null' as no output.", 0, update_output_type, 0,
+       &output_typelib);
+static MYSQL_SYSVAR_STR(file_path, file_path,
+       PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+       "Path to the log file.", NULL, NULL, "");
+static MYSQL_SYSVAR_ULONGLONG(file_rotate_size, file_rotate_size,
+       PLUGIN_VAR_RQCMDARG, "Maximum size of the log to start the rotation.",
+       NULL, NULL,
+       1000000, 100, ((long long) 0x7FFFFFFFFFFFFFFFLL), 1);
+static MYSQL_SYSVAR_UINT(file_rotations, rotations,
+       PLUGIN_VAR_READONLY, "Number of rotations before log is removed.",
+       NULL, NULL, 9, 1, 999, 1);
+static MYSQL_SYSVAR_STR(file_rotate_now, rotate, PLUGIN_VAR_OPCMDARG,
+       "Force log rotation.", NULL, rotate_log, "");
+static MYSQL_SYSVAR_BOOL(logging, logging,
+       PLUGIN_VAR_OPCMDARG, "Turn on/off the logging.", NULL,
+       update_logging, 0);
+static MYSQL_SYSVAR_UINT(mode, mode,
+       PLUGIN_VAR_OPCMDARG, "Auditing mode.", NULL, update_mode, 0, 0, 1, 1);
+static MYSQL_SYSVAR_STR(syslog_ident, syslog_ident, PLUGIN_VAR_RQCMDARG,
+       "The SYSLOG identifier - the beginning of each SYSLOG record.",
+       NULL, update_syslog_ident, syslog_ident_buffer);
+static MYSQL_SYSVAR_STR(syslog_info, syslog_info,
+       PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+       "The <info> string to be added to the SYSLOG record.", NULL, NULL, "");
+
+static const char *syslog_facility_names[]=
+{
+  "LOG_USER", "LOG_MAIL", "LOG_DAEMON", "LOG_AUTH",
+  "LOG_SYSLOG", "LOG_LPR", "LOG_NEWS", "LOG_UUCP",
+  "LOG_CRON", "LOG_AUTHPRIV", "LOG_FTP",
+  "LOG_LOCAL0", "LOG_LOCAL1", "LOG_LOCAL2", "LOG_LOCAL3",
+  "LOG_LOCAL4", "LOG_LOCAL5", "LOG_LOCAL6", "LOG_LOCAL7",
+  0
+};
+static unsigned int syslog_facility_codes[]=
+{
+  LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH,
+  LOG_SYSLOG, LOG_LPR, LOG_NEWS, LOG_UUCP,
+  LOG_CRON, LOG_AUTHPRIV, LOG_FTP,
+  LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3,
+  LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7,
+};
+static TYPELIB syslog_facility_typelib=
+{
+    array_elements(syslog_facility_names) - 1, "syslog_facility_typelib",
+    syslog_facility_names, NULL
+};
+static MYSQL_SYSVAR_ENUM(syslog_facility, syslog_facility, PLUGIN_VAR_RQCMDARG,
+       "The 'facility' parameter of the SYSLOG record."
+       " The default is LOG_USER.", 0, update_syslog_facility, 0/*LOG_USER*/,
+       &syslog_facility_typelib);
+
+static const char *syslog_priority_names[]=
+{
+  "LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR",
+  "LOG_WARNING", "LOG_NOTICE", "LOG_INFO", "LOG_DEBUG",
+  0
+};
+
+static unsigned int syslog_priority_codes[]=
+{
+  LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
+  LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG,
+};
+
+static TYPELIB syslog_priority_typelib=
+{
+    array_elements(syslog_priority_names) - 1, "syslog_priority_typelib",
+    syslog_priority_names, NULL
+};
+static MYSQL_SYSVAR_ENUM(syslog_priority, syslog_priority, PLUGIN_VAR_RQCMDARG,
+       "The 'priority' parameter of the SYSLOG record."
+       " The default is LOG_INFO.", 0, update_syslog_priority, 6/*LOG_INFO*/,
+       &syslog_priority_typelib);
+
+
+static struct st_mysql_sys_var* vars[] = {
+    MYSQL_SYSVAR(incl_users),
+    MYSQL_SYSVAR(excl_users),
+    MYSQL_SYSVAR(events),
+    MYSQL_SYSVAR(output_type),
+    MYSQL_SYSVAR(file_path),
+    MYSQL_SYSVAR(file_rotate_size),
+    MYSQL_SYSVAR(file_rotations),
+    MYSQL_SYSVAR(file_rotate_now),
+    MYSQL_SYSVAR(logging),
+    MYSQL_SYSVAR(mode),
+    MYSQL_SYSVAR(syslog_info),
+    MYSQL_SYSVAR(syslog_ident),
+    MYSQL_SYSVAR(syslog_facility),
+    MYSQL_SYSVAR(syslog_priority),
+    NULL
+};
+
+
+static uchar *getkey_user(const char *entry, size_t *length,
+                          my_bool nu __attribute__((unused)) )
+{
+  const char *e= entry;
+  while (*e && *e != ' ' && *e != ',')
+    ++e;
+  *length= e - entry;
+  return (uchar *) entry;
+}
+
+
+static int user_hash_fill(HASH *h, const char *users)
+{
+  if (my_hash_inited(h))
+    my_hash_reset(h);
+  else
+    my_hash_init(h, &my_charset_bin, 0x100, 0, 0,
+                 (my_hash_get_key) getkey_user, 0, 0);
+
+  while (*users)
+  {
+    while (*users == ' ')
+      users++;
+    if (!*users)
+      return 0;
+
+    if (my_hash_insert(h, (const uchar *) users))
+      return 1;
+    while (*users && *users != ',')
+      users++;
+    if (!*users)
+      break;
+    users++;
+  }
+  return 0;
+}
+
+
+static void error_header()
+{
+  struct tm tm_time;
+  time_t curtime;
+
+  (void) time(&curtime);
+  (void) localtime_r(&curtime, &tm_time);
+
+  (void) fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d server_audit: ",
+    tm_time.tm_year % 100, tm_time.tm_mon + 1,
+    tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
+}
+
+
+static LOGGER_HANDLE *logfile;
+static HASH incl_user_hash, excl_user_hash;
+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;
+};
+
+
+static HASH connection_hash;
+
+
+void free_connection(void* pconn)
+{
+  (void) free(pconn);
+}
+
+
+static struct connection_info *find_connection(unsigned long id)
+{
+  return (struct connection_info *)
+    my_hash_search(&connection_hash, (const uchar *) &id, sizeof(id));
+}
+
+
+static void get_str_n(char *dest, int *dest_len, size_t dest_size,
+                      const char *src, size_t src_len)
+{
+  if (src_len >= dest_size)
+    src_len= dest_size - 1;
+
+  memcpy(dest, src, src_len);
+  dest[src_len]= 0;
+  *dest_len= src_len;
+}
+
+
+static int get_user_host(const char *uh_line, unsigned int uh_len,
+                         char *buffer, size_t buf_len,
+                         size_t *user_len, size_t *host_len)
+{
+  const char *buf_end= buffer + buf_len - 1;
+  const char *buf_start;
+  const char *uh_end= uh_line + uh_len;
+
+  while (uh_line < uh_end && *uh_line != '[')
+    ++uh_line;
+
+  if (uh_line == uh_end)
+    return 1;
+  ++uh_line;
+
+  buf_start= buffer;
+  while (uh_line < uh_end && *uh_line != ']')
+  {
+    if (buffer == buf_end)
+      return 1;
+    *(buffer++)= *(uh_line++);
+  }
+  if (uh_line == uh_end)
+    return 1;
+  *user_len= buffer - buf_start;
+  *(buffer++)= 0;
+
+  while (uh_line < uh_end && *uh_line != '@')
+    ++uh_line;
+  if (uh_line == uh_end || *(++uh_line) == 0)
+    return 1;
+  ++uh_line;
+
+  buf_start= buffer;
+  while (uh_line < uh_end && *uh_line != ' ' && *uh_line != '[')
+  {
+    if (buffer == buf_end)
+      break;
+    *(buffer++)= *(uh_line++);
+  }
+  *host_len= buffer - buf_start;
+  *(buffer++)= 0;
+  return 0;
+}
+
+
+static struct connection_info *
+  add_connection(const struct mysql_event_connection *event)
+{
+  struct connection_info *cn= malloc(sizeof(struct connection_info));
+  if (!cn)
+    return 0;
+  cn->thread_id= event->thread_id;
+  cn->query_id= 0;
+  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),
+            event->user, event->user_length);
+  get_str_n(cn->host, &cn->host_length, sizeof(cn->host),
+            event->host, event->host_length);
+
+  if (my_hash_insert(&connection_hash, (const uchar *) cn))
+    return 0;
+
+  return cn;
+}
+
+
+static struct connection_info *
+  add_connection_initdb(const struct mysql_event_general *event)
+{
+  struct connection_info *cn;
+  size_t user_len, host_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) ||
+      (cn= malloc(sizeof(struct connection_info))) == NULL)
+    return 0;
+
+  cn->thread_id= event->general_thread_id;
+  cn->query_id= 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);
+
+  if (my_hash_insert(&connection_hash, (const uchar *) cn))
+    return 0;
+
+  return cn;
+}
+
+
+static void change_connection(const struct mysql_event_connection *event)
+{
+  struct connection_info *cn= find_connection(event->thread_id);
+  if (!cn)
+    return;
+  get_str_n(cn->user, &cn->user_length, sizeof(cn->db),
+            event->user, event->user_length);
+}
+
+static int write_log(const char *message, int len)
+{
+  if (output_type == OUTPUT_FILE && logfile)
+  {
+    return logger_write(logfile, message, len);
+  }
+  else if (output_type == OUTPUT_SYSLOG)
+  {
+    syslog(LOG_MAKEPRI(syslog_facility_codes[syslog_facility],
+                       syslog_priority_codes[syslog_priority]),
+           "%s %.*s", syslog_info, len, message);
+  }
+  return 0;
+}
+
+
+static size_t log_header(char *message, size_t message_len,
+                      time_t *ts,
+                      const char *serverhost, unsigned int serverhost_len,
+                      const char *username, unsigned int username_len,
+                      const char *host, unsigned int hostlen,
+                      unsigned int connection_id, long long query_id,
+                      const char *operation)
+{
+  struct tm tm_time;
+
+  if (output_type == OUTPUT_SYSLOG)
+    return my_snprintf(message, message_len,
+        "%.*s,%.*s,%.*s,%d,%lld,%s",
+        serverhost_len, serverhost,
+        username_len, username,
+        hostlen, host,
+        connection_id, query_id, operation);
+
+  (void) localtime_r(ts, &tm_time);
+  return my_snprintf(message, message_len,
+      "%04d%02d%02d %02d:%02d:%02d,%.*s,%.*s,%.*s,%d,%lld,%s",
+      tm_time.tm_year+1900, tm_time.tm_mon+1, tm_time.tm_mday,
+      tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
+      serverhost_len, serverhost,
+      username_len, username,
+      hostlen, host,
+      connection_id, query_id, operation);
+}
+
+
+static int log_connection(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->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 int log_disconnect_mysql(const struct mysql_event_connection *event,
+                                const char *user, unsigned int user_length,
+                                const char *host, unsigned int host_length)
+{
+  time_t ctime;
+  size_t csize;
+  char message[1024];
+
+  (void) time(&ctime);
+  csize= log_header(message, sizeof(message)-1, &ctime,
+                    servhost, servhost_len,
+                    user, user_length, host, host_length,
+                    event->thread_id, 0, "DISCONNECT");
+  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)
+{
+  const char *res_start= result;
+  const char *res_end= result + result_len - 2;
+  while (len)
+  {
+    if (result >= res_end)
+      break;
+    if (*str == '\'')
+    {
+      *(result++)= '\\';
+      *(result++)= '\'';
+    }
+    else if (*str == '\\')
+    {
+      *(result++)= '\\';
+      *(result++)= '\\';
+    }
+    else
+      *(result++)= *str;
+    str++;
+    len--;
+  }
+  *result= 0;
+  return result - res_start;
+}
+
+
+static int do_log_user(const char *name)
+{
+  size_t len;
+
+  if (!name)
+    return 0;
+  len= strlen(name);
+
+  if (incl_user_hash.records)
+    return my_hash_search(&incl_user_hash, (const uchar *) name, len) != 0;
+
+  if (excl_user_hash.records)
+    return my_hash_search(&excl_user_hash, (const uchar *) name, len) == 0;
+
+  return 1;
+}
+
+
+static int log_statement(const struct mysql_event_general *event,
+                         const char *type)
+{
+  size_t csize, user_len, host_len, esc_q_len;
+  char message[1024];
+  char uh_buffer[512];
+  time_t ev_time= (time_t) event->general_time;
+  const char *db= NULL;
+  unsigned int db_length;
+  long long query_id= 0;
+
+  if (mode)
+  {
+    const struct connection_info *cn=
+      find_connection(event->general_thread_id);
+    if (cn)
+    {
+      db= cn->db;
+      db_length= cn->db_length;
+      query_id= cn->query_id;
+    }
+  }
+  else
+  {
+    db= event->database;
+    db_length= event->database_length;
+    query_id= event->query_id;
+  }
+  if (!db)
+  {
+    db= "";
+    db_length= 0;
+  }
+
+  if (get_user_host(event->general_user, event->general_user_length,
+                    uh_buffer, sizeof(uh_buffer), &user_len, &host_len))
+  {
+    csize= log_header(message, sizeof(message)-1, &ev_time,
+                      servhost, servhost_len,
+                      event->general_user, event->general_user_length,
+                      "", 0, event->general_thread_id, query_id, type);
+  }
+  else
+  {
+    if (!do_log_user(uh_buffer))
+      return 0;
+
+    csize= log_header(message, sizeof(message)-1, &ev_time,
+                      servhost, servhost_len,
+                      uh_buffer, user_len, uh_buffer+user_len+1, host_len,
+                      event->general_thread_id, query_id, type);
+  }
+
+  csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+      ",%.*s", db_length, db);
+
+  esc_q_len= escape_string(event->general_query, event->general_query_length,
+                           uh_buffer, sizeof(uh_buffer)); 
+  csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+           ",\'%.*s\',%d", esc_q_len, uh_buffer, event->general_error_code);
+  message[csize]= '\n';
+  return write_log(message, csize + 1);
+}
+
+
+static int log_table(const struct mysql_event_table *event, const char *type)
+{
+  size_t csize;
+  char message[1024];
+  time_t ctime;
+  long long query_id= event->query_id;
+
+  if (mode)
+  {
+    const struct connection_info *cn;
+    if ((cn= find_connection(event->thread_id)))
+      query_id= cn->query_id;
+  }
+
+  (void) time(&ctime);
+  csize= log_header(message, sizeof(message)-1, &ctime,
+                    servhost, servhost_len,
+                    event->user, strlen(event->user),
+                    event->host, strlen(event->host),
+                    event->thread_id, query_id, type);
+  csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+            ",%.*s,%.*s,",event->database_length, event->database,
+                          event->table_length, event->table);
+  message[csize]= '\n';
+  return write_log(message, csize + 1);
+}
+
+
+static int log_rename(const struct mysql_event_table *event)
+{
+  size_t csize;
+  char message[1024];
+  time_t ctime;
+  long long query_id= event->query_id;
+
+  if (mode)
+  {
+    const struct connection_info *cn;
+    if ((cn= find_connection(event->thread_id)))
+      query_id= cn->query_id;
+  }
+
+  (void) time(&ctime);
+  csize= log_header(message, sizeof(message)-1, &ctime,
+                    servhost, servhost_len,
+                    event->user, strlen(event->user),
+                    event->host, strlen(event->host),
+                    event->thread_id, query_id, "RENAME");
+  csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
+            ",%.*s,%.*s,%.*s,%.*s",event->database_length, event->database,
+                         event->table_length, event->table,
+                         event->new_database_length, event->new_database,
+                         event->new_table_length, event->new_table);
+  message[csize]= '\n';
+  return write_log(message, csize + 1);
+}
+
+
+#define FILTER(MASK) (events == 0 || (events & MASK))
+static void auditing(MYSQL_THD thd __attribute__((unused)),
+                     unsigned int event_class,
+                     const void *ev)
+{
+  if (!logging)
+    return;
+
+  if (event_class == MYSQL_AUDIT_GENERAL_CLASS && FILTER(EVENT_QUERY))
+  {
+    const struct mysql_event_general *event =
+      (const struct mysql_event_general *) ev;
+    switch (event->event_subclass)
+    {
+      case MYSQL_AUDIT_GENERAL_LOG:
+        if (mode)
+        {
+          struct connection_info *cn;
+          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)))
+          {
+            cn->query_id= query_counter++;
+            if (init_db_command)
+            {
+              /* Change DB */
+              get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
+                  event->general_query, event->general_query_length);
+            }
+          }
+          else if (init_db_command)
+            add_connection_initdb(event);
+        }
+        break;
+      case MYSQL_AUDIT_GENERAL_ERROR:
+        break;
+      case MYSQL_AUDIT_GENERAL_RESULT:
+        break;
+      case MYSQL_AUDIT_GENERAL_STATUS:
+        if (event->general_command_length == 5 &&
+            strncmp(event->general_command, "Query", 5) == 0)
+        log_statement(event, "QUERY");
+        break;
+      default:;
+    }
+  }
+  else if (event_class == MYSQL_AUDIT_TABLE_CLASS && FILTER(EVENT_TABLE))
+  {
+    const struct mysql_event_table *event =
+      (const struct mysql_event_table *) ev;
+    switch (event->event_subclass)
+    {
+      case MYSQL_AUDIT_TABLE_LOCK:
+        if (do_log_user(event->user))
+          log_table(event, event->read_only ? "READ" : "WRITE");
+        break;
+      case MYSQL_AUDIT_TABLE_CREATE:
+        if (do_log_user(event->user))
+          log_table(event, "CREATE");
+        break;
+      case MYSQL_AUDIT_TABLE_DROP:
+        if (do_log_user(event->user))
+          log_table(event, "DROP");
+        break;
+      case MYSQL_AUDIT_TABLE_RENAME:
+        if (do_log_user(event->user))
+          log_rename(event);
+        break;
+      case MYSQL_AUDIT_TABLE_ALTER:
+        if (do_log_user(event->user))
+          log_table(event, "ALTER");
+        break;
+      default:;
+    }
+  }
+  else if (event_class == MYSQL_AUDIT_CONNECTION_CLASS && FILTER(EVENT_CONNECT))
+  {
+    const struct mysql_event_connection *event =
+      (const struct mysql_event_connection *) ev;
+    switch (event->event_subclass)
+    {
+      case MYSQL_AUDIT_CONNECTION_CONNECT:
+        if (mode)
+          (void) add_connection(ev);
+        log_connection(event, event->status ? "FAILED_CONNECT": "CONNECT");
+        break;
+      case MYSQL_AUDIT_CONNECTION_DISCONNECT:
+        if (mode)
+        {
+          struct connection_info *cn= find_connection(event->thread_id);
+          if (cn)
+          {
+            log_disconnect_mysql(event, cn->user, cn->user_length,
+                                 cn->host, cn->host_length);
+            my_hash_delete(&connection_hash, (uchar *) cn);
+          }
+          else
+            log_disconnect_mysql(event, "", 0, "", 0);
+        }
+        else
+          log_connection(event, "DISCONNECT");
+        break;
+      case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
+        if (mode)
+          change_connection(ev);
+        log_connection(event, "CHANGEUSER");
+        break;
+      default:;
+    }
+  }
+}
+
+
+static int server_audit_init(void *p __attribute__((unused)))
+{
+#ifdef _WIN32
+  serv_ver= (const char *)GetProcAddress(0, "server_version");
+#else
+  serv_ver= server_version;
+#endif /*_WIN32*/
+
+  if (!started_mysql)
+  {
+    if (serv_ver[5]<'3')
+    {
+      mode= 1;
+      mode_readonly= 1;
+    }
+  }
+
+  if (gethostname(servhost, sizeof(servhost)))
+    strcpy(servhost, "unknown");
+
+  servhost_len= strlen(servhost);
+
+  my_hash_clear(&incl_user_hash);
+  my_hash_clear(&excl_user_hash);
+
+  if (incl_users)
+  {
+    if (excl_users)
+    {
+      incl_users= excl_users= NULL;
+      error_header();
+      fprintf(stderr, "INCL_DML_USERS and EXCL_DML_USERS specified"
+                      " simultaneously - both set to empty\n");
+    }
+    update_incl_users(NULL, NULL, NULL, &incl_users);
+  }
+  else if (excl_users)
+  {
+    update_excl_users(NULL, NULL, NULL, &excl_users);
+  }
+
+  logger_init_mutexes();
+  my_hash_init(&connection_hash, &my_charset_bin, 0x100, 0,
+               sizeof(unsigned long), 0, free_connection, 0); 
+
+  error_header();
+  fprintf(stderr, "STARTED\n");
+
+  if (output_type != OUTPUT_NULL)
+  {
+    ulong param_output_type= output_type;
+    output_type= OUTPUT_NULL;
+    update_output_type(NULL, NULL, NULL, &param_output_type);
+    error_header();
+    fprintf(stderr, "logging is %s.\n", logging ? "enabled" : "disabled");
+  }
+
+  return 0;
+}
+
+
+static int server_audit_init_mysql(void *p)
+{
+  started_mysql= 1;
+  mode= 1;
+  mode_readonly= 1;
+  return server_audit_init(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);
+
+  if (output_type == OUTPUT_FILE && logfile)
+    logger_close(logfile);
+  else if (output_type == OUTPUT_SYSLOG)
+    closelog();
+
+  error_header();
+  fprintf(stderr, "STOPPED\n");
+  return 0;
+}
+
+
+static void rotate_log(MYSQL_THD thd  __attribute__((unused)),
+                       struct st_mysql_sys_var *var  __attribute__((unused)),
+                       void *var_ptr  __attribute__((unused)),
+                       const void *save  __attribute__((unused)))
+{
+  if (output_type == OUTPUT_FILE && logfile)
+    (void) logger_rotate(logfile);
+}
+
+
+static struct st_mysql_audit mysql_descriptor =
+{
+  0x300,
+  NULL,
+  auditing,
+  { MYSQL_AUDIT_GENERAL_CLASSMASK | MYSQL_AUDIT_CONNECTION_CLASSMASK }
+};
+
+mysql_declare_plugin(server_audit)
+{
+  MYSQL_AUDIT_PLUGIN,
+  &mysql_descriptor,
+  "SERVER_AUDIT",
+  "Alexey Botchkov",
+  "Audit the server activity.",
+  PLUGIN_LICENSE_GPL,
+  server_audit_init_mysql,
+  server_audit_deinit,
+  0x0200,
+  NULL,
+  vars,
+  NULL,
+  0
+}
+mysql_declare_plugin_end;
+
+
+static struct st_mysql_audit maria_descriptor =
+{
+  MYSQL_AUDIT_INTERFACE_VERSION,
+  NULL,
+  auditing,
+  { MYSQL_AUDIT_GENERAL_CLASSMASK |
+    MYSQL_AUDIT_TABLE_CLASSMASK |
+    MYSQL_AUDIT_CONNECTION_CLASSMASK }
+};
+maria_declare_plugin(server_audit)
+{
+  MYSQL_AUDIT_PLUGIN,
+  &maria_descriptor,
+  "SERVER_AUDIT",
+  "Alexey Botchkov",
+  "Audit the server activity.",
+  PLUGIN_LICENSE_GPL,
+  server_audit_init,
+  server_audit_deinit,
+  0x0200,
+  NULL,
+  vars,
+  "2.0",
+  MariaDB_PLUGIN_MATURITY_ALPHA
+}
+maria_declare_plugin_end;
+
+
+static void update_incl_users(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  strncpy(user_buffer, *(const char **) save, sizeof(user_buffer));
+  incl_users= user_buffer;
+  user_hash_fill(&incl_user_hash, incl_users);
+}
+
+
+static void update_excl_users(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  strncpy(user_buffer, *(const char **) save, sizeof(user_buffer));
+  excl_users= user_buffer;
+  user_hash_fill(&excl_user_hash, excl_users);
+}
+
+
+static void update_output_type(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  ulong new_output_type= *((ulong *) save);
+  if (output_type == new_output_type)
+    return;
+
+  if (output_type == OUTPUT_FILE && logfile)
+  {
+    logger_close(logfile);
+  }
+  else if (output_type == OUTPUT_SYSLOG)
+  {
+    closelog();
+  }
+
+  output_type= OUTPUT_NULL;
+
+  if (new_output_type == OUTPUT_FILE)
+  {
+    logfile= logger_open(file_path, file_rotate_size, rotations);
+    if (logfile == NULL)
+    {
+      error_header();
+      fprintf(stderr, "Could not create file '%s'\n", file_path);
+      return;
+    }
+  }
+  else if (new_output_type == OUTPUT_SYSLOG)
+  {
+    openlog(syslog_ident, LOG_NOWAIT, syslog_facility_codes[syslog_facility]);
+  }
+
+  output_type= new_output_type;
+  error_header();
+  fprintf(stderr, "Output was redirected to '%s'\n",
+          output_type_names[output_type]);
+}
+
+
+static void update_syslog_facility(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  ulong new_facility= *((ulong *) save);
+  if (syslog_facility == new_facility)
+    return;
+
+  error_header();
+  fprintf(stderr, "SysLog facility was changed from '%s' to '%s'.\n",
+          syslog_facility_names[syslog_facility],
+          syslog_facility_names[new_facility]);
+  syslog_facility= new_facility;
+}
+
+
+static void update_syslog_priority(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  ulong new_priority= *((ulong *) save);
+  if (syslog_priority == new_priority)
+    return;
+
+  error_header();
+  fprintf(stderr, "SysLog priority was changed from '%s' to '%s'.\n",
+          syslog_priority_names[syslog_priority],
+          syslog_priority_names[new_priority]);
+  syslog_priority= new_priority;
+}
+
+
+static void update_logging(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  char new_logging= *(char *) save;
+  if (new_logging == logging)
+    return;
+
+  logging= new_logging;
+  error_header();
+  fprintf(stderr, "logging was %s.\n", logging ? "enabled" : "disabled");
+}
+
+
+static void update_mode(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  unsigned int new_mode= *(unsigned int *) save;
+  if (mode_readonly || new_mode == mode)
+    return;
+
+  error_header();
+  fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
+  mode= new_mode;
+}
+
+static void update_syslog_ident(MYSQL_THD thd  __attribute__((unused)),
+              struct st_mysql_sys_var *var  __attribute__((unused)),
+              void *var_ptr  __attribute__((unused)), const void *save)
+{
+  strncpy(syslog_ident_buffer, *(const char **) save,
+          sizeof(syslog_ident_buffer));
+  syslog_ident= syslog_ident_buffer;
+}
+
+

=== modified file 'plugin/sql_errlog/CMakeLists.txt'
--- a/plugin/sql_errlog/CMakeLists.txt	2012-03-24 10:24:20 +0000
+++ b/plugin/sql_errlog/CMakeLists.txt	2013-08-22 17:57:31 +0000
@@ -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 sql_logger.cc service_logger.h MODULE_ONLY)
+MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c MODULE_ONLY)

=== modified file 'plugin/sql_errlog/sql_errlog.c'
--- a/plugin/sql_errlog/sql_errlog.c	2012-03-24 10:24:20 +0000
+++ b/plugin/sql_errlog/sql_errlog.c	2013-08-22 17:57:31 +0000
@@ -16,7 +16,7 @@
 #include <mysql/plugin_audit.h>
 #include <stdio.h>
 #include <time.h>
-#include "service_logger.h"
+#include <mysql/service_logger.h>
 
 /*
  Disable __attribute__() on non-gcc compilers.
@@ -106,7 +106,7 @@ static void log_sql_errors(MYSQL_THD thd
 
 static int sql_error_log_init(void *p __attribute__((unused)))
 {
-  init_logger_mutexes();
+  logger_init_mutexes();
 
   logfile= logger_open(filename, size_limit, rotations);
   if (logfile == NULL) {

=== modified file 'sql/sql_audit.cc'
--- a/sql/sql_audit.cc	2013-04-19 10:50:16 +0000
+++ b/sql/sql_audit.cc	2013-08-22 17:57:31 +0000
@@ -82,6 +82,9 @@ static void general_class_handler(THD *t
   event.general_query_length= va_arg(ap, unsigned int);
   event.general_charset= va_arg(ap, struct charset_info_st *);
   event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
+  event.database= va_arg(ap, const char *);
+  event.database_length= va_arg(ap, unsigned int);
+  event.query_id= thd->query_id;
   event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
 }
 
@@ -131,6 +134,7 @@ static void table_class_handler(THD *thd
   event.new_database_length= va_arg(ap, unsigned int);
   event.new_table= va_arg(ap, const char *);
   event.new_table_length= va_arg(ap, unsigned int);
+  event.query_id= thd->query_id;
   event_class_dispatch(thd, MYSQL_AUDIT_TABLE_CLASS, &event);
 }
 

=== modified file 'sql/sql_audit.h'
--- a/sql/sql_audit.h	2013-04-19 10:50:16 +0000
+++ b/sql/sql_audit.h	2013-08-22 17:57:31 +0000
@@ -93,7 +93,8 @@ void mysql_audit_general_log(THD *thd, t
 
     mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG,
                        0, time, user, userlen, cmd, cmdlen,
-                       query, querylen, clientcs, 0);
+                       query, querylen, clientcs, (ha_rows) 0,
+                       thd->db, thd->db_length);
   }
 }
 
@@ -139,7 +140,8 @@ void mysql_audit_general(THD *thd, uint 
 
     mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype,
                        error_code, time, user, userlen, msg, msglen,
-                       query.str(), query.length(), query.charset(), rows);
+                       query.str(), query.length(), query.charset(), rows,
+                       thd->db, thd->db_length);
   }
 }
 
@@ -162,7 +164,11 @@ void mysql_audit_general(THD *thd, uint 
 #define MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, errcode)\
   mysql_audit_notify(\
   (thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_DISCONNECT,\
-  (errcode), (thd)->thread_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+  (errcode), (thd)->thread_id, (thd)->security_ctx->user,\
+        (thd)->security_ctx->user ? strlen((thd)->security_ctx->user) : 0,\
+         0, 0, 0, 0, 0, 0, (thd)->security_ctx->host,\
+         (thd)->security_ctx->host ? strlen((thd)->security_ctx->host) : 0,\
+         0, 0, 0, 0)
 
 #define MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER(thd) mysql_audit_notify(\
   (thd), MYSQL_AUDIT_CONNECTION_CLASS, MYSQL_AUDIT_CONNECTION_CHANGE_USER,\

=== modified file 'sql/sql_plugin_services.h'
--- a/sql/sql_plugin_services.h	2013-01-18 18:04:23 +0000
+++ b/sql/sql_plugin_services.h	2013-08-22 17:57:31 +0000
@@ -58,6 +58,16 @@ static struct kill_statement_service_st 
   thd_kill_level
 };
 
+static struct logger_service_st logger_service_handler= {
+  logger_init_mutexes,
+  logger_open,
+  logger_close,
+  logger_vprintf,
+  logger_printf,
+  logger_write,
+  logger_rotate
+};
+
 static struct st_service_ref list_of_services[]=
 {
   { "my_snprintf_service",         VERSION_my_snprintf,         &my_snprintf_handler },
@@ -66,6 +76,7 @@ static struct st_service_ref list_of_ser
   { "my_thread_scheduler_service", VERSION_my_thread_scheduler, &my_thread_scheduler_handler },
   { "progress_report_service",     VERSION_progress_report,     &progress_report_handler },
   { "debug_sync_service",          VERSION_debug_sync,          0 }, // updated in plugin_init()
-  { "thd_kill_statement_service",  VERSION_kill_statement,      &thd_kill_statement_handler }
+  { "thd_kill_statement_service",  VERSION_kill_statement,      &thd_kill_statement_handler },
+  { "logger_service",              VERSION_logger,              &logger_service_handler },
 };
 



More information about the commits mailing list