MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:antony Date:December 12 2007 9:36am
Subject:bk commit into 6.0 tree (antony:1.2699) WL#3771
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of antony. When antony does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-12-12 01:36:30-08:00, antony@stripped +24 -0
  WL#3771 - Plugable Audit Interface
    Second commit for review.
    Have run default tests with/without plugin:
    mysql-test-run.pl --mysqld=--plugin-dir=<path to plugin>
                      --mysqld=--plugin-load=adt_null.so

  include/Makefile.am@stripped, 2007-12-12 01:36:21-08:00, antony@stripped +2 -1
    add new source files: mysql/ftparser.h mysql/audit.h

  include/mysql/plugin.h@stripped, 2007-12-12 01:36:21-08:00, antony@stripped +26 -202
    New plugin type: MYSQL_AUDIT_PLUGIN
    Allow declaration of Opaque thread variables.
    New flag so that thread variables have no user-modifiable GLOBAL 
    value - requested by Kevin Lewis.
    Move MYSQL_FTPARSER_PLUGIN declarations into mysql/ftparser.h

  include/mysql/plugin_audit.h@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +75 -0
    New BitKeeper file ``include/mysql/plugin_audit.h''

  include/mysql/plugin_audit.h@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  include/mysql/plugin_ftparser.h@stripped, 2007-12-12 01:36:25-08:00, antony@stripped +211 -0
    New BitKeeper file ``include/mysql/plugin_ftparser.h''

  include/mysql/plugin_ftparser.h@stripped, 2007-12-12 01:36:25-08:00, antony@stripped +0 -0

  libmysqld/CMakeLists.txt@stripped, 2007-12-12 01:36:21-08:00, antony@stripped +1 -1
    Add sql_audit.cc to the Windows build

  libmysqld/Makefile.am@stripped, 2007-12-12 01:36:21-08:00, antony@stripped +1 -1
    Add new file to build: sql_audit.cc

  mysql-test/r/plugin.result@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +1 -1
    error message returns correct variable name

  plugin/audit_null/Makefile.am@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +27 -0
    New BitKeeper file ``plugin/audit_null/Makefile.am''

  plugin/audit_null/Makefile.am@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  plugin/audit_null/audit_null.c@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +135 -0
    New BitKeeper file ``plugin/audit_null/audit_null.c''

  plugin/audit_null/audit_null.c@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  plugin/audit_null/plug.in@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +3 -0
    New BitKeeper file ``plugin/audit_null/plug.in''

  plugin/audit_null/plug.in@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  sql/CMakeLists.txt@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +1 -1
    Add sql_audit.cc to the Windows build

  sql/Makefile.am@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +2 -2
    add new files to build: sql_audit.h sql_audit.cc

  sql/event_queue.cc@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +8 -0
    Release Audit resources before waiting

  sql/log.cc@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +15 -2
    add locations to audit

  sql/mysqld.cc@stripped, 2007-12-12 01:36:22-08:00, antony@stripped +8 -0
    initialize/finalize audit globals

  sql/protocol.cc@stripped, 2007-12-12 01:36:23-08:00, antony@stripped +13 -0
    add locations to audit

  sql/scheduler.cc@stripped, 2007-12-12 01:36:23-08:00, antony@stripped +5 -0
    release audit resources before waiting

  sql/set_var.cc@stripped, 2007-12-12 01:36:23-08:00, antony@stripped +18 -0
    new internal function to assist enumerating system variables.

  sql/sql_audit.cc@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +417 -0
    New BitKeeper file ``sql/sql_audit.cc''

  sql/sql_audit.cc@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  sql/sql_audit.h@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +49 -0
    New BitKeeper file ``sql/sql_audit.h''

  sql/sql_audit.h@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +0 -0

  sql/sql_class.cc@stripped, 2007-12-12 01:36:23-08:00, antony@stripped +4 -0
    initialize/finalize audit variables

  sql/sql_class.h@stripped, 2007-12-12 01:36:23-08:00, antony@stripped +5 -0
    Audit variables in THD

  sql/sql_insert.cc@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +3 -0
    release audit resources before waiting

  sql/sql_plugin.cc@stripped, 2007-12-12 01:36:24-08:00, antony@stripped +99 -45
    Handle new plugin type: MYSQL_AUDIT_PLUGIN
    Correctly handle --plugin-load=xxx without crashing.
    Correctly report variable name in error message.

diff -Nrup a/include/Makefile.am b/include/Makefile.am
--- a/include/Makefile.am	2007-10-09 12:42:15 -07:00
+++ b/include/Makefile.am	2007-12-12 01:36:21 -08:00
@@ -18,7 +18,8 @@
 BUILT_SOURCES =		$(HEADERS_GEN) link_sources
 HEADERS_GEN =		mysql_version.h my_config.h
 HEADERS_ABI =		mysql.h mysql_com.h mysql_time.h \
-			my_list.h my_alloc.h typelib.h mysql/plugin.h
+			my_list.h my_alloc.h typelib.h mysql/plugin.h \
+			mysql/plugin_ftparser.h mysql/plugin_audit.h
 pkginclude_HEADERS =	$(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \
 			my_xml.h mysql_embed.h \
 		  	my_pthread.h my_no_pthread.h \
diff -Nrup a/include/mysql/plugin.h b/include/mysql/plugin.h
--- a/include/mysql/plugin.h	2007-08-30 23:19:49 -07:00
+++ b/include/mysql/plugin.h	2007-12-12 01:36:21 -08:00
@@ -65,7 +65,8 @@ typedef struct st_mysql_xid MYSQL_XID;
 #define MYSQL_FTPARSER_PLUGIN        2  /* Full-text parser plugin      */
 #define MYSQL_DAEMON_PLUGIN          3  /* The daemon/raw plugin type */
 #define MYSQL_INFORMATION_SCHEMA_PLUGIN  4  /* The I_S plugin type */
-#define MYSQL_MAX_PLUGIN_TYPE_NUM    5  /* The number of plugin types   */
+#define MYSQL_AUDIT_PLUGIN           5  /* The Audit plugin type        */
+#define MYSQL_MAX_PLUGIN_TYPE_NUM    6  /* The number of plugin types   */
 
 /* We use the following strings to define licenses for plugins */
 #define PLUGIN_LICENSE_PROPRIETARY 0
@@ -367,6 +368,12 @@ DECLARE_MYSQL_THDVAR_TYPELIB(name, unsig
   PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL | ((opt) & PLUGIN_VAR_MASK), \
   #name, comment, check, update, -1, def, NULL, typelib }
 
+#define MYSQL_THDVAR_OPAQUE(name, type) \
+DECLARE_MYSQL_THDVAR_BASIC(name, __typeof__ (type *)) = { \
+  PLUGIN_VAR_OPAQUE | PLUGIN_VAR_THDLOCAL | \
+  PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT, #name, \
+  NULL, NULL, NULL, -1, NULL, NULL }
+
 /* accessor macros */
 
 #define SYSVAR(name) \
@@ -397,208 +404,45 @@ struct st_mysql_plugin
   void * __reserved1;   /* reserved for dependency checking             */
 };
 
-/*************************************************************************
-  API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
-*/
-
-#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100
-
-/* Parsing modes. Set in  MYSQL_FTPARSER_PARAM::mode */
-enum enum_ftparser_mode
-{
-/*
-  Fast and simple mode.  This mode is used for indexing, and natural
-  language queries.
-
-  The parser is expected to return only those words that go into the
-  index. Stopwords or too short/long words should not be returned. The
-  'boolean_info' argument of mysql_add_word() does not have to be set.
-*/
-  MYSQL_FTPARSER_SIMPLE_MODE= 0,
-
-/*
-  Parse with stopwords mode.  This mode is used in boolean searches for
-  "phrase matching."
+#include "plugin_ftparser.h"
+#include "plugin_audit.h"
 
-  The parser is not allowed to ignore words in this mode.  Every word
-  should be returned, including stopwords and words that are too short
-  or long.  The 'boolean_info' argument of mysql_add_word() does not
-  have to be set.
+/*************************************************************************
+  API for Daemon/raw plugin. (MYSQL_DAEMON_PLUGIN)
 */
-  MYSQL_FTPARSER_WITH_STOPWORDS= 1,
 
-/*
-  Parse in boolean mode.  This mode is used to parse a boolean query string.
-
-  The parser should provide a valid MYSQL_FTPARSER_BOOLEAN_INFO
-  structure in the 'boolean_info' argument to mysql_add_word().
-  Usually that means that the parser should recognize boolean operators
-  in the parsing stream and set appropriate fields in
-  MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly.  As for
-  MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored.
-  Instead, use FT_TOKEN_STOPWORD for the token type of such a word.
-*/
-  MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
-};
+/* handlertons of different MySQL releases are incompatible */
+#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
 
 /*
-  Token types for boolean mode searching (used for the type member of
-  MYSQL_FTPARSER_BOOLEAN_INFO struct)
-
-  FT_TOKEN_EOF: End of data.
-  FT_TOKEN_WORD: Regular word.
-  FT_TOKEN_LEFT_PAREN: Left parenthesis (start of group/sub-expression).
-  FT_TOKEN_RIGHT_PAREN: Right parenthesis (end of group/sub-expression).
-  FT_TOKEN_STOPWORD: Stopword.
+  Here we define only the descriptor structure, that is referred from
+  st_mysql_plugin.
 */
 
-enum enum_ft_token_type
+struct st_mysql_daemon
 {
-  FT_TOKEN_EOF= 0,
-  FT_TOKEN_WORD= 1,
-  FT_TOKEN_LEFT_PAREN= 2,
-  FT_TOKEN_RIGHT_PAREN= 3,
-  FT_TOKEN_STOPWORD= 4
+  int interface_version;
 };
 
-/*
-  This structure is used in boolean search mode only. It conveys
-  boolean-mode metadata to the MySQL search engine for every word in
-  the search query. A valid instance of this structure must be filled
-  in by the plugin parser and passed as an argument in the call to
-  mysql_add_word (the callback function in the MYSQL_FTPARSER_PARAM
-  structure) when a query is parsed in boolean mode.
-
-  type: The token type.  Should be one of the enum_ft_token_type values.
-
-  yesno: Whether the word must be present for a match to occur:
-    >0 Must be present
-    <0 Must not be present
-    0  Neither; the word is optional but its presence increases the relevance
-  With the default settings of the ft_boolean_syntax system variable,
-  >0 corresponds to the '+' operator, <0 corrresponds to the '-' operator,
-  and 0 means neither operator was used.
-
-  weight_adjust: A weighting factor that determines how much a match
-  for the word counts.  Positive values increase, negative - decrease the
-  relative word's importance in the query.
-
-  wasign: The sign of the word's weight in the query. If it's non-negative
-  the match for the word will increase document relevance, if it's
-  negative - decrease (the word becomes a "noise word", the less of it the
-  better).
 
-  trunc: Corresponds to the '*' operator in the default setting of the
-  ft_boolean_syntax system variable.
+/*************************************************************************
+  API for I_S plugin. (MYSQL_INFORMATION_SCHEMA_PLUGIN)
 */
 
-typedef struct st_mysql_ftparser_boolean_info
-{
-  enum enum_ft_token_type type;
-  int yesno;
-  int weight_adjust;
-  char wasign;
-  char trunc;
-  /* These are parser state and must be removed. */
-  char prev;
-  char *quot;
-} MYSQL_FTPARSER_BOOLEAN_INFO;
-
-/*
-  The following flag means that buffer with a string (document, word)
-  may be overwritten by the caller before the end of the parsing (that is
-  before st_mysql_ftparser::deinit() call). If one needs the string
-  to survive between two successive calls of the parsing function, she
-  needs to save a copy of it. The flag may be set by MySQL before calling
-  st_mysql_ftparser::parse(), or it may be set by a plugin before calling
-  st_mysql_ftparser_param::mysql_parse() or
-  st_mysql_ftparser_param::mysql_add_word().
-*/
-#define MYSQL_FTFLAGS_NEED_COPY 1
+/* handlertons of different MySQL releases are incompatible */
+#define MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
 
 /*
-  An argument of the full-text parser plugin. This structure is
-  filled in by MySQL server and passed to the parsing function of the
-  plugin as an in/out parameter.
-
-  mysql_parse: A pointer to the built-in parser implementation of the
-  server. It's set by the server and can be used by the parser plugin
-  to invoke the MySQL default parser.  If plugin's role is to extract
-  textual data from .doc, .pdf or .xml content, it might extract
-  plaintext from the content, and then pass the text to the default
-  MySQL parser to be parsed.
-
-  mysql_add_word: A server callback to add a new word.  When parsing
-  a document, the server sets this to point at a function that adds
-  the word to MySQL full-text index.  When parsing a search query,
-  this function will add the new word to the list of words to search
-  for.  The boolean_info argument can be NULL for all cases except
-  when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO.
-
-  ftparser_state: A generic pointer. The plugin can set it to point
-  to information to be used internally for its own purposes.
-
-  mysql_ftparam: This is set by the server.  It is used by MySQL functions
-  called via mysql_parse() and mysql_add_word() callback.  The plugin
-  should not modify it.
-
-  cs: Information about the character set of the document or query string.
-
-  doc: A pointer to the document or query string to be parsed.
-
-  length: Length of the document or query string, in bytes.
-
-  flags: See MYSQL_FTFLAGS_* constants above.
-
-  mode: The parsing mode.  With boolean operators, with stopwords, or
-  nothing.  See  enum_ftparser_mode above.
-*/
-
-typedef struct st_mysql_ftparser_param
-{
-  int (*mysql_parse)(struct st_mysql_ftparser_param *,
-                     char *doc, int doc_len);
-  int (*mysql_add_word)(struct st_mysql_ftparser_param *,
-                        char *word, int word_len,
-                        MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
-  void *ftparser_state;
-  void *mysql_ftparam;
-  struct charset_info_st *cs;
-  char *doc;
-  int length;
-  int flags;
-  enum enum_ftparser_mode mode;
-} MYSQL_FTPARSER_PARAM;
-
-/*
-  Full-text parser descriptor.
-
-  interface_version is, e.g., MYSQL_FTPARSER_INTERFACE_VERSION.
-  The parsing, initialization, and deinitialization functions are
-  invoked per SQL statement for which the parser is used.
+  Here we define only the descriptor structure, that is referred from
+  st_mysql_plugin.
 */
 
-struct st_mysql_ftparser
+struct st_mysql_information_schema
 {
   int interface_version;
-  int (*parse)(MYSQL_FTPARSER_PARAM *param);
-  int (*init)(MYSQL_FTPARSER_PARAM *param);
-  int (*deinit)(MYSQL_FTPARSER_PARAM *param);
 };
 
-/*************************************************************************
-  API for Storage Engine plugin. (MYSQL_DAEMON_PLUGIN)
-*/
-
-/* handlertons of different MySQL releases are incompatible */
-#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
-
-/*************************************************************************
-  API for I_S plugin. (MYSQL_INFORMATION_SCHEMA_PLUGIN)
-*/
 
-/* handlertons of different MySQL releases are incompatible */
-#define MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
 
 /*************************************************************************
   API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN)
@@ -620,28 +464,8 @@ struct st_mysql_storage_engine
 
 struct handlerton;
 
-/*
-  Here we define only the descriptor structure, that is referred from
-  st_mysql_plugin.
-*/
-
-struct st_mysql_daemon
-{
-  int interface_version;
-};
-
-/*
-  Here we define only the descriptor structure, that is referred from
-  st_mysql_plugin.
-*/
-
-struct st_mysql_information_schema
-{
-  int interface_version;
-};
-
 
-/*
+/*************************************************************************
   st_mysql_value struct for reading values from mysqld.
   Used by server variables framework to parse user-provided values.
   Will be used for arguments when implementing UDFs.
diff -Nrup a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/mysql/plugin_audit.h	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,75 @@
+/* Copyright (C) 2007 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _my_audit_h
+#define _my_audit_h
+
+/*************************************************************************
+  API for Audit plugin. (MYSQL_AUDIT_PLUGIN)
+*/
+
+#include "plugin.h"
+
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0100
+
+
+struct mysql_event
+{
+  int event_class;
+};
+
+
+/*************************************************************************
+  AUDIT CLASS : GENERAL
+*/
+
+#define MYSQL_AUDIT_GENERAL_CLASS 0
+#define MYSQL_AUDIT_GENERAL_CLASSMASK (1 << MYSQL_AUDIT_GENERAL_CLASS)
+#define MYSQL_AUDIT_GENERAL_LOG 0
+#define MYSQL_AUDIT_GENERAL_ERROR 1
+#define MYSQL_AUDIT_GENERAL_RESULT 2
+
+struct mysql_event_general
+{
+  int event_class;
+  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;
+};
+
+
+/*************************************************************************
+  Here we define the descriptor structure, that is referred from
+  st_mysql_plugin.
+*/
+
+struct st_mysql_audit
+{
+  int interface_version;
+  const unsigned long long *class_mask;
+  void (*release_thd)(MYSQL_THD);
+  void (*event_notify)(MYSQL_THD, const struct mysql_event *);
+};
+
+
+#endif
diff -Nrup a/include/mysql/plugin_ftparser.h b/include/mysql/plugin_ftparser.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/mysql/plugin_ftparser.h	2007-12-12 01:36:25 -08:00
@@ -0,0 +1,211 @@
+/* Copyright (C) 2005 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef _my_ftparser_h
+#define _my_ftparser_h
+
+/*************************************************************************
+  API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
+*/
+
+#include "plugin.h"
+
+#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100
+
+/* Parsing modes. Set in  MYSQL_FTPARSER_PARAM::mode */
+enum enum_ftparser_mode
+{
+/*
+  Fast and simple mode.  This mode is used for indexing, and natural
+  language queries.
+
+  The parser is expected to return only those words that go into the
+  index. Stopwords or too short/long words should not be returned. The
+  'boolean_info' argument of mysql_add_word() does not have to be set.
+*/
+  MYSQL_FTPARSER_SIMPLE_MODE= 0,
+
+/*
+  Parse with stopwords mode.  This mode is used in boolean searches for
+  "phrase matching."
+
+  The parser is not allowed to ignore words in this mode.  Every word
+  should be returned, including stopwords and words that are too short
+  or long.  The 'boolean_info' argument of mysql_add_word() does not
+  have to be set.
+*/
+  MYSQL_FTPARSER_WITH_STOPWORDS= 1,
+
+/*
+  Parse in boolean mode.  This mode is used to parse a boolean query string.
+
+  The parser should provide a valid MYSQL_FTPARSER_BOOLEAN_INFO
+  structure in the 'boolean_info' argument to mysql_add_word().
+  Usually that means that the parser should recognize boolean operators
+  in the parsing stream and set appropriate fields in
+  MYSQL_FTPARSER_BOOLEAN_INFO structure accordingly.  As for
+  MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored.
+  Instead, use FT_TOKEN_STOPWORD for the token type of such a word.
+*/
+  MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
+};
+
+/*
+  Token types for boolean mode searching (used for the type member of
+  MYSQL_FTPARSER_BOOLEAN_INFO struct)
+
+  FT_TOKEN_EOF: End of data.
+  FT_TOKEN_WORD: Regular word.
+  FT_TOKEN_LEFT_PAREN: Left parenthesis (start of group/sub-expression).
+  FT_TOKEN_RIGHT_PAREN: Right parenthesis (end of group/sub-expression).
+  FT_TOKEN_STOPWORD: Stopword.
+*/
+
+enum enum_ft_token_type
+{
+  FT_TOKEN_EOF= 0,
+  FT_TOKEN_WORD= 1,
+  FT_TOKEN_LEFT_PAREN= 2,
+  FT_TOKEN_RIGHT_PAREN= 3,
+  FT_TOKEN_STOPWORD= 4
+};
+
+/*
+  This structure is used in boolean search mode only. It conveys
+  boolean-mode metadata to the MySQL search engine for every word in
+  the search query. A valid instance of this structure must be filled
+  in by the plugin parser and passed as an argument in the call to
+  mysql_add_word (the callback function in the MYSQL_FTPARSER_PARAM
+  structure) when a query is parsed in boolean mode.
+
+  type: The token type.  Should be one of the enum_ft_token_type values.
+
+  yesno: Whether the word must be present for a match to occur:
+    >0 Must be present
+    <0 Must not be present
+    0  Neither; the word is optional but its presence increases the relevance
+  With the default settings of the ft_boolean_syntax system variable,
+  >0 corresponds to the '+' operator, <0 corrresponds to the '-' operator,
+  and 0 means neither operator was used.
+
+  weight_adjust: A weighting factor that determines how much a match
+  for the word counts.  Positive values increase, negative - decrease the
+  relative word's importance in the query.
+
+  wasign: The sign of the word's weight in the query. If it's non-negative
+  the match for the word will increase document relevance, if it's
+  negative - decrease (the word becomes a "noise word", the less of it the
+  better).
+
+  trunc: Corresponds to the '*' operator in the default setting of the
+  ft_boolean_syntax system variable.
+*/
+
+typedef struct st_mysql_ftparser_boolean_info
+{
+  enum enum_ft_token_type type;
+  int yesno;
+  int weight_adjust;
+  char wasign;
+  char trunc;
+  /* These are parser state and must be removed. */
+  char prev;
+  char *quot;
+} MYSQL_FTPARSER_BOOLEAN_INFO;
+
+/*
+  The following flag means that buffer with a string (document, word)
+  may be overwritten by the caller before the end of the parsing (that is
+  before st_mysql_ftparser::deinit() call). If one needs the string
+  to survive between two successive calls of the parsing function, she
+  needs to save a copy of it. The flag may be set by MySQL before calling
+  st_mysql_ftparser::parse(), or it may be set by a plugin before calling
+  st_mysql_ftparser_param::mysql_parse() or
+  st_mysql_ftparser_param::mysql_add_word().
+*/
+#define MYSQL_FTFLAGS_NEED_COPY 1
+
+/*
+  An argument of the full-text parser plugin. This structure is
+  filled in by MySQL server and passed to the parsing function of the
+  plugin as an in/out parameter.
+
+  mysql_parse: A pointer to the built-in parser implementation of the
+  server. It's set by the server and can be used by the parser plugin
+  to invoke the MySQL default parser.  If plugin's role is to extract
+  textual data from .doc, .pdf or .xml content, it might extract
+  plaintext from the content, and then pass the text to the default
+  MySQL parser to be parsed.
+
+  mysql_add_word: A server callback to add a new word.  When parsing
+  a document, the server sets this to point at a function that adds
+  the word to MySQL full-text index.  When parsing a search query,
+  this function will add the new word to the list of words to search
+  for.  The boolean_info argument can be NULL for all cases except
+  when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO.
+
+  ftparser_state: A generic pointer. The plugin can set it to point
+  to information to be used internally for its own purposes.
+
+  mysql_ftparam: This is set by the server.  It is used by MySQL functions
+  called via mysql_parse() and mysql_add_word() callback.  The plugin
+  should not modify it.
+
+  cs: Information about the character set of the document or query string.
+
+  doc: A pointer to the document or query string to be parsed.
+
+  length: Length of the document or query string, in bytes.
+
+  flags: See MYSQL_FTFLAGS_* constants above.
+
+  mode: The parsing mode.  With boolean operators, with stopwords, or
+  nothing.  See  enum_ftparser_mode above.
+*/
+
+typedef struct st_mysql_ftparser_param
+{
+  int (*mysql_parse)(struct st_mysql_ftparser_param *,
+                     char *doc, int doc_len);
+  int (*mysql_add_word)(struct st_mysql_ftparser_param *,
+                        char *word, int word_len,
+                        MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
+  void *ftparser_state;
+  void *mysql_ftparam;
+  struct charset_info_st *cs;
+  char *doc;
+  int length;
+  int flags;
+  enum enum_ftparser_mode mode;
+} MYSQL_FTPARSER_PARAM;
+
+
+/*
+  Full-text parser descriptor.
+
+  interface_version is, e.g., MYSQL_FTPARSER_INTERFACE_VERSION.
+  The parsing, initialization, and deinitialization functions are
+  invoked per SQL statement for which the parser is used.
+*/
+
+struct st_mysql_ftparser
+{
+  int interface_version;
+  int (*parse)(MYSQL_FTPARSER_PARAM *param);
+  int (*init)(MYSQL_FTPARSER_PARAM *param);
+  int (*deinit)(MYSQL_FTPARSER_PARAM *param);
+};
+
+#endif
diff -Nrup a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
--- a/libmysqld/CMakeLists.txt	2007-08-06 14:14:47 -07:00
+++ b/libmysqld/CMakeLists.txt	2007-12-12 01:36:21 -08:00
@@ -187,7 +187,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
            ../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
            ../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
            ../sql/partition_info.cc ../sql/sql_connect.cc 
-           ../sql/scheduler.cc
+           ../sql/scheduler.cc ../sql/sql_audit.cc
            ${GEN_SOURCES}
            ${LIB_SOURCES})
 
diff -Nrup a/libmysqld/Makefile.am b/libmysqld/Makefile.am
--- a/libmysqld/Makefile.am	2007-11-01 11:37:47 -07:00
+++ b/libmysqld/Makefile.am	2007-12-12 01:36:21 -08:00
@@ -76,7 +76,7 @@ sqlsources = derror.cc field.cc field_co
 	rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
 	sql_tablespace.cc \
 	rpl_injector.cc my_user.c partition_info.cc \
-	sql_servers.cc
+	sql_servers.cc sql_audit.cc
 
 libmysqld_int_a_SOURCES= $(libmysqld_sources)
 nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)
diff -Nrup a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
--- a/mysql-test/r/plugin.result	2007-11-14 01:48:18 -08:00
+++ b/mysql-test/r/plugin.result	2007-12-12 01:36:22 -08:00
@@ -25,5 +25,5 @@ INSTALL PLUGIN example SONAME 'ha_exampl
 SET GLOBAL example_enum_var= e1;
 SET GLOBAL example_enum_var= e2;
 SET GLOBAL example_enum_var= impossible;
-ERROR 42000: Variable 'enum_var' can't be set to the value of 'impossible'
+ERROR 42000: Variable 'example_enum_var' can't be set to the value of 'impossible'
 UNINSTALL PLUGIN example;
diff -Nrup a/plugin/audit_null/Makefile.am b/plugin/audit_null/Makefile.am
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/plugin/audit_null/Makefile.am	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,27 @@
+# Copyright (C) 2007 MySQL 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
+
+#Makefile.am example for a plugin
+
+pkglibdir=$(libdir)/mysql
+INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include
+#noinst_LTLIBRARIES= adt_null.la
+pkglib_LTLIBRARIES= adt_null.la
+adt_null_la_SOURCES= audit_null.c
+adt_null_la_LDFLAGS= -module -rpath $(pkglibdir)
+adt_null_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff -Nrup a/plugin/audit_null/audit_null.c b/plugin/audit_null/audit_null.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/plugin/audit_null/audit_null.c	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,135 @@
+/* Copyright (C) 2006-2007 MySQL 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 */
+
+#include <stdio.h>
+#include <mysql/plugin.h>
+
+#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__)  || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
+#define __attribute__(A)
+#endif
+
+static volatile int number_of_calls; /* for SHOW STATUS, see below */
+
+
+/*
+  Initialize the plugin at server start or plugin installation.
+
+  SYNOPSIS
+    null_audit_plugin_init()
+
+  DESCRIPTION
+    Does nothing.
+
+  RETURN VALUE
+    0                    success
+    1                    failure (cannot happen)
+*/
+
+static int null_audit_plugin_init(void *arg __attribute__((unused)))
+{
+  number_of_calls= 0;
+  return(0);
+}
+
+
+/*
+  Terminate the plugin at server shutdown or plugin deinstallation.
+
+  SYNOPSIS
+    null_audit_plugin_deinit()
+    Does nothing.
+
+  RETURN VALUE
+    0                    success
+    1                    failure (cannot happen)
+
+*/
+
+static int null_audit_plugin_deinit(void *arg __attribute__((unused)))
+{
+  printf("audit_null was invoked %u times\n", number_of_calls);
+  return(0);
+}
+
+
+/*
+  Foo
+
+  SYNOPSIS
+    null_notify()
+      thd                connection context
+
+  DESCRIPTION
+*/
+
+static void null_notify(MYSQL_THD thd __attribute__((unused)),
+                        const struct mysql_event *event
+                        __attribute__((unused)))
+{
+  /* prone to races, oh well */
+  number_of_calls++;
+}
+
+
+static unsigned long long null_audit_mask[]=
+{
+  (unsigned long long) -1
+};
+
+
+/*
+  Plugin type-specific descriptor
+*/
+
+static struct st_mysql_audit null_audit_descriptor=
+{
+  MYSQL_AUDIT_INTERFACE_VERSION,    /* interface version      */
+  null_audit_mask,                  /* class mask             */
+  NULL,                             /* release_thd function   */
+  null_notify                       /* notify function        */
+};
+
+/*
+  Plugin status variables for SHOW STATUS
+*/
+
+static struct st_mysql_show_var simple_status[]=
+{
+  {"null_audit_called", (char *)&number_of_calls, SHOW_INT},
+  {0,0,0}
+};
+
+
+/*
+  Plugin library descriptor
+*/
+
+mysql_declare_plugin(null_audit)
+{
+  MYSQL_AUDIT_PLUGIN,         /* type                            */
+  &null_audit_descriptor,     /* descriptor                      */
+  "NULL_AUDIT",               /* name                            */
+  "MySQL AB",                 /* author                          */
+  "Simple NULL Audit",        /* description                     */
+  PLUGIN_LICENSE_GPL,
+  null_audit_plugin_init,     /* init function (when loaded)     */
+  null_audit_plugin_deinit,   /* deinit function (when unloaded) */
+  0x0001,                     /* version                         */
+  simple_status,              /* status variables                */
+  NULL,                       /* system variables                */
+  NULL
+}
+mysql_declare_plugin_end;
+
diff -Nrup a/plugin/audit_null/plug.in b/plugin/audit_null/plug.in
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/plugin/audit_null/plug.in	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,3 @@
+MYSQL_PLUGIN(audit_null,         [NULL Audit Plug-in],
+        [Simple black-hole Audit example plug-in])
+MYSQL_PLUGIN_DYNAMIC(audit_null, [adt_null.la])
diff -Nrup a/sql/CMakeLists.txt b/sql/CMakeLists.txt
--- a/sql/CMakeLists.txt	2007-11-14 08:37:44 -08:00
+++ b/sql/CMakeLists.txt	2007-12-12 01:36:22 -08:00
@@ -73,7 +73,7 @@ ADD_EXECUTABLE(mysqld
                event_queue.cc event_db_repository.cc 
                sql_tablespace.cc events.cc ../sql-common/my_user.c 
                partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
-               rpl_rli.cc rpl_mi.cc sql_servers.cc
+               rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
                sql_connect.cc scheduler.cc 
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
diff -Nrup a/sql/Makefile.am b/sql/Makefile.am
--- a/sql/Makefile.am	2007-11-01 11:37:48 -07:00
+++ b/sql/Makefile.am	2007-12-12 01:36:22 -08:00
@@ -84,7 +84,7 @@ noinst_HEADERS =	item.h item_func.h item
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
 			probes.h \
-			contributors.h sql_servers.h
+			contributors.h sql_servers.h sql_audit.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -127,7 +127,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
                         event_queue.cc event_db_repository.cc events.cc \
 			sql_plugin.cc sql_binlog.cc \
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
-			sql_servers.cc
+			sql_servers.cc sql_audit.cc
 
 if HAVE_DTRACE
   mysqld_SOURCES += probes.d
diff -Nrup a/sql/event_queue.cc b/sql/event_queue.cc
--- a/sql/event_queue.cc	2007-08-25 01:43:10 -07:00
+++ b/sql/event_queue.cc	2007-12-12 01:36:22 -08:00
@@ -16,6 +16,7 @@
 #include "mysql_priv.h"
 #include "event_queue.h"
 #include "event_data_objects.h"
+#include "sql_audit.h"
 
 /**
   @addtogroup Event_Scheduler
@@ -547,6 +548,9 @@ Event_queue::get_top_for_execution_if_ti
       /* There are no events in the queue */
       next_activation_at= 0;
 
+      /* Release any held audit resources */
+      mysql_audit_release(thd);
+
       /* Wait on condition until signaled. Release LOCK_queue while waiting. */
       cond_wait(thd, NULL, queue_empty_msg, SCHED_FUNC, __LINE__);
 
@@ -566,6 +570,10 @@ Event_queue::get_top_for_execution_if_ti
       */
       struct timespec top_time;
       set_timespec(top_time, next_activation_at - thd->query_start());
+
+      /* Release any held audit resources */
+      mysql_audit_release(thd);
+
       cond_wait(thd, &top_time, queue_wait_msg, SCHED_FUNC, __LINE__);
 
       continue;
diff -Nrup a/sql/log.cc b/sql/log.cc
--- a/sql/log.cc	2007-11-14 02:01:42 -08:00
+++ b/sql/log.cc	2007-12-12 01:36:22 -08:00
@@ -21,6 +21,7 @@
 #include "sql_repl.h"
 #include "rpl_filter.h"
 #include "rpl_rli.h"
+#include "sql_audit.h"
 
 #include <my_dir.h>
 #include <stdarg.h>
@@ -975,6 +976,14 @@ bool LOGGER::general_log_write(THD *thd,
                                                           user_host_buff;
 
   current_time= my_time(0);
+
+  mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_LOG, 0, current_time,
+                      user_host_buff, user_host_len,
+                      command_name[(uint) command].str,
+                      command_name[(uint) command].length,
+                      query, query_length,
+                      thd->variables.character_set_client,0);
+                        
   while (*current_handler)
     error+= (*current_handler++)->
       log_general(thd, current_time, user_host_buff,
@@ -4376,7 +4385,8 @@ int vprint_msg_to_log(enum loglevel leve
   DBUG_RETURN(0);
 }
 #else /*!EMBEDDED_LIBRARY*/
-static void print_buffer_to_file(enum loglevel level, const char *buffer)
+static void print_buffer_to_file(enum loglevel level, int error_code,
+                                 const char *buffer, size_t buffer_length)
 {
   time_t skr;
   struct tm tm_tmp;
@@ -4387,6 +4397,7 @@ static void print_buffer_to_file(enum lo
   VOID(pthread_mutex_lock(&LOCK_error_log));
 
   skr= my_time(0);
+
   localtime_r(&skr, &tm_tmp);
   start=&tm_tmp;
 
@@ -4412,10 +4423,12 @@ int vprint_msg_to_log(enum loglevel leve
 {
   char   buff[1024];
   size_t length;
+  int error_code= errno;
   DBUG_ENTER("vprint_msg_to_log");
 
   length= my_vsnprintf(buff, sizeof(buff), format, args);
-  print_buffer_to_file(level, buff);
+
+  print_buffer_to_file(level, error_code, buff, length);
 
 #ifdef __NT__
   print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2007-11-22 11:45:19 -08:00
+++ b/sql/mysqld.cc	2007-12-12 01:36:22 -08:00
@@ -26,6 +26,7 @@
 #include "mysqld_suffix.h"
 #include "mysys_err.h"
 #include "events.h"
+#include "sql_audit.h"
 
 #include "../storage/myisam/ha_myisam.h"
 
@@ -1364,6 +1365,8 @@ static void clean_up_mutexes()
   (void) pthread_cond_destroy(&COND_thread_cache);
   (void) pthread_cond_destroy(&COND_flush_thread_cache);
   (void) pthread_cond_destroy(&COND_manager);
+
+  mysql_audit_finalize();
 }
 
 #endif /*EMBEDDED_LIBRARY*/
@@ -3252,6 +3255,7 @@ static void end_ssl()
 static int init_server_components()
 {
   DBUG_ENTER("init_server_components");
+
   /*
     We need to call each of these following functions to ensure that
     all things are initialized so that unireg_abort() doesn't fail
@@ -3746,6 +3750,10 @@ int main(int argc, char **argv)
   thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
 #else
   thr_kill_signal= SIGINT;
+#endif
+
+#ifndef EMBEDDED_LIBRARY
+  mysql_audit_initialize();
 #endif
 
   /*
diff -Nrup a/sql/protocol.cc b/sql/protocol.cc
--- a/sql/protocol.cc	2007-11-01 04:32:31 -07:00
+++ b/sql/protocol.cc	2007-12-12 01:36:23 -08:00
@@ -24,6 +24,7 @@
 
 #include "mysql_priv.h"
 #include "sp_rcontext.h"
+#include "sql_audit.h"
 #include <stdarg.h>
 
 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
@@ -132,6 +133,12 @@ void net_send_error(THD *thd, uint sql_e
 
   DBUG_ASSERT(!thd->spcont);
 
+  mysql_audit_general(thd,MYSQL_AUDIT_GENERAL_ERROR,sql_errno,my_time(0),
+                      0,0,err,err?strlen(err):0,
+                      thd->query,thd->query_length,
+                      thd->variables.character_set_client,
+                      thd->row_count);
+
   if (net && net->no_send_error)
   {
     thd->clear_error();
@@ -210,6 +217,12 @@ send_ok(THD *thd, ha_rows affected_rows,
   NET *net= &thd->net;
   uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
   DBUG_ENTER("send_ok");
+
+  mysql_audit_general(thd,MYSQL_AUDIT_GENERAL_RESULT,0,my_time(0),
+                      0,0,message,message?strlen(message):0,
+                      thd->query,thd->query_length,
+                      thd->variables.character_set_client,
+                      affected_rows);  
 
   if (net->no_send_ok || !net->vio)	// hack for re-parsing queries
   {
diff -Nrup a/sql/scheduler.cc b/sql/scheduler.cc
--- a/sql/scheduler.cc	2007-11-02 12:39:00 -07:00
+++ b/sql/scheduler.cc	2007-12-12 01:36:23 -08:00
@@ -22,6 +22,7 @@
 #endif
 
 #include <mysql_priv.h>
+#include "sql_audit.h"
 
 
 /*
@@ -396,6 +397,8 @@ static void libevent_connection_close(TH
 
   thd->killed= THD::KILL_CONNECTION;          // Avoid error messages
 
+  mysql_audit_release(thd);
+
   if (thd->net.vio->sd >= 0)                   // not already closed
   {
     end_connection(thd);
@@ -539,6 +542,8 @@ static bool libevent_needs_immediate_pro
   */
   if (thd->net.vio == 0 || thd->net.vio->read_pos < thd->net.vio->read_end)
     return TRUE;
+
+  mysql_audit_release(thd);
     
   /*
     Send to be queued for libevent.
diff -Nrup a/sql/set_var.cc b/sql/set_var.cc
--- a/sql/set_var.cc	2007-11-14 05:53:13 -08:00
+++ b/sql/set_var.cc	2007-12-12 01:36:23 -08:00
@@ -3031,6 +3031,24 @@ sys_var *intern_find_sys_var(const char 
 }
 
 
+sys_var *intern_find_sys_var(bool (*func)(sys_var *, void*), void *data)
+{
+  uint index;
+
+  /*
+    This function is only called from the sql_plugin.cc.
+    A lock on LOCK_system_variable_hash should be held
+  */
+  for (index= 0; index < system_variable_hash.records; index++)
+  {
+    sys_var *var= (sys_var*) hash_element(&system_variable_hash, index);
+    if (func(var, data))
+      return var;
+  }
+  return 0;
+}
+
+
 /*
   Execute update of all variables
 
diff -Nrup a/sql/sql_audit.cc b/sql/sql_audit.cc
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sql/sql_audit.cc	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,417 @@
+/* Copyright (C) 2007 MySQL 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 "mysql_priv.h"
+#include "sql_audit.h"
+
+extern int initialize_audit_plugin(st_plugin_int *plugin);
+extern int finalize_audit_plugin(st_plugin_int *plugin);
+
+#ifndef EMBEDDED_LIBRARY
+
+uint64 mysql_global_audit_mask;
+
+static pthread_mutex_t LOCK_audit_mask;
+
+static void event_class_dispatch(THD *thd, const struct mysql_event *event);
+
+typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap);
+
+/**
+  MYSQL_AUDIT_GENERAL_CLASS handler
+  
+  @param[in] thd
+  @param[in] event_subtype
+  @param[in] error_code
+  @param[in] ap
+  
+*/
+
+static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
+{
+  mysql_event_general event;
+  event.event_class= MYSQL_AUDIT_GENERAL_CLASS;
+  event.general_error_code= va_arg(ap, int);
+  event.general_thread_id= thd ? thd->thread_id : 0;
+  event.general_time= va_arg(ap, time_t);
+  event.general_user= va_arg(ap, const char *);
+  event.general_user_length= va_arg(ap, unsigned int);
+  event.general_command= va_arg(ap, const char *);
+  event.general_command_length= va_arg(ap, unsigned int);
+  event.general_query= va_arg(ap, const char *);
+  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_class_dispatch(thd, (const mysql_event*) &event);
+}
+
+
+static audit_handler_t audit_handlers[] =
+{
+  general_class_handler
+};
+
+static const uint audit_handlers_count=
+  (sizeof(audit_handlers) / sizeof(audit_handler_t));
+
+
+/**
+  Acquire and lock any additional audit plugins as required
+  
+  @param[in] thd
+  @param[in] plugin
+  @param[in] arg
+
+  @retval FALSE Always  
+*/
+
+static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
+{
+  uint event_class= *(uint*) arg;
+  uint64 event_class_mask= (1 << event_class);
+  st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
+
+  /* Check if this plugin is interested in the event */
+  if (!(data->class_mask[0] & event_class_mask))
+    return 0;
+  
+  /* Check if we need to initialize the array of acquired plugins */
+  if (unlikely(!thd->audit_class_plugins.buffer))
+  {
+    /* specify some reasonable initialization defaults */
+    my_init_dynamic_array(&thd->audit_class_plugins,
+                          sizeof(plugin_ref), 16, 16);
+  }
+  else
+  {
+    plugin_ref *plugins, *plugins_last;
+
+    plugins= (plugin_ref*) thd->audit_class_plugins.buffer;
+    plugins_last= plugins + thd->audit_class_plugins.elements;
+    for (; plugins < plugins_last; plugins++)
+    {
+      st_mysql_audit *data2= plugin_data(*plugins, struct st_mysql_audit *);
+
+      /* Check if we already have acquired this plugin */
+      if (data == data2)
+        return 0;
+    }
+  }
+  
+  /* lock the plugin and add it to the list */
+  plugin= my_plugin_lock(NULL, &plugin);
+  insert_dynamic(&thd->audit_class_plugins, (uchar*) &plugin);
+
+  return 0;
+}
+
+
+/**
+  Notify the audit system of an event
+  
+  @param[in] thd
+  @param[in] event_class
+  @param[in] event_subtype
+  @param[in] error_code
+
+*/
+
+void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...)
+{
+  va_list ap;
+  audit_handler_t *handlers= audit_handlers + event_class;
+  uint64 event_class_mask= (1 << event_class);
+  
+  DBUG_ASSERT(event_class < audit_handlers_count);
+
+  if (thd && thd->killed == THD::KILL_CONNECTION &&
+      !(thd->audit_class_mask & event_class_mask))
+    thd= NULL;
+
+  /*
+    Check to see if we have acquired the audit plugins for the
+    required audit event classes.
+  */
+  if (thd && !(thd->audit_class_mask & event_class_mask))
+  {
+    plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class);
+    thd->audit_class_mask|= event_class_mask;
+  }
+
+  va_start(ap, event_subtype);  
+  (*handlers)(thd, event_subtype, ap);
+  va_end(ap);
+}
+
+
+/**
+  Release any resources associated with the current thd.
+  
+  @param[in] thd
+
+*/
+
+void mysql_audit_release(THD *thd)
+{
+  plugin_ref *plugins, *plugins_last;
+  
+  if (!thd || !(thd->audit_class_plugins.elements))
+    return;
+  
+  plugins= (plugin_ref*) thd->audit_class_plugins.buffer;
+  plugins_last= plugins + thd->audit_class_plugins.elements;
+  for (; plugins < plugins_last; plugins++)
+  {
+    st_mysql_audit *data= plugin_data(*plugins, struct st_mysql_audit *);
+	
+    /* Check to see if the plugin has a release method */
+    if (!(data->release_thd))
+      continue;
+
+    /* Tell the plugin to release its resources */
+    data->release_thd(thd);
+  }
+
+  /* Now we actually unlock the plugins */  
+  plugin_unlock_list(NULL, (plugin_ref*) thd->audit_class_plugins.buffer,
+                     thd->audit_class_plugins.elements);
+  
+  /* Reset the state of thread values */
+  reset_dynamic(&thd->audit_class_plugins);
+  thd->audit_class_mask= 0;
+}
+
+
+/**
+  Initialize thd variables used by Audit
+  
+  @param[in] thd
+
+*/
+
+void mysql_audit_init_thd(THD *thd)
+{
+  bzero(&thd->audit_class_plugins, sizeof(thd->audit_class_plugins));
+  thd->audit_class_mask= 0;
+}
+
+
+/**
+  Free thd variables used by Audit
+  
+  @param[in] thd
+  @param[in] plugin
+  @param[in] arg
+
+  @retval FALSE Always  
+*/
+
+void mysql_audit_free_thd(THD *thd)
+{
+  mysql_audit_release(thd);
+  DBUG_ASSERT(thd->audit_class_plugins.elements == 0);
+  delete_dynamic(&thd->audit_class_plugins);
+}
+
+
+/**
+  Initialize Audit global variables
+*/
+
+void mysql_audit_initialize()
+{
+  pthread_mutex_init(&LOCK_audit_mask, MY_MUTEX_INIT_FAST);
+  mysql_global_audit_mask= 0;
+}
+
+
+/**
+  Finalize Audit global variables  
+*/
+
+void mysql_audit_finalize()
+{
+  pthread_mutex_destroy(&LOCK_audit_mask);
+}
+
+
+/**
+  Initialize an Audit plug-in
+  
+  @param[in] plugin
+
+  @retval FALSE  OK
+  @retval TRUE   There was an error.
+*/
+
+int initialize_audit_plugin(st_plugin_int *plugin)
+{
+  st_mysql_audit *data= (st_mysql_audit*) plugin->plugin->info;
+  
+  if (!data->class_mask || !data->event_notify ||
+      !data->class_mask[0])
+  {
+    sql_print_error("Plugin '%s' has invalid data.",
+                    plugin->name.str);
+    return 1;
+  }
+  
+  if (plugin->plugin->init && plugin->plugin->init(NULL))
+  {
+    sql_print_error("Plugin '%s' init function returned error.",
+                    plugin->name.str);
+    return 1;
+  }
+
+  /* Make the interface info more easily accessible */
+  plugin->data= plugin->plugin->info;
+  
+  /* Add the bits the plugin is interested in to the global mask */
+  pthread_mutex_lock(&LOCK_audit_mask);
+  mysql_global_audit_mask|= data->class_mask[0];
+  pthread_mutex_unlock(&LOCK_audit_mask);
+
+  return 0;
+}
+
+
+static my_bool calc_class_mask(THD *thd, plugin_ref plugin, void *arg)
+{
+  uint64 *event_class_mask_ptr= (uint64*) arg;
+  st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
+  if ((data= plugin_data(plugin, struct st_mysql_audit *)))
+    event_class_mask_ptr[0]|= data->class_mask[0];
+  return 0;
+}
+
+
+/**
+  Finalize an Audit plug-in
+  
+  @param[in] plugin
+
+  @retval FALSE  OK
+  @retval TRUE   There was an error.
+*/
+int finalize_audit_plugin(st_plugin_int *plugin)
+{
+  uint64 event_class_mask= 0;
+  
+  if (plugin->plugin->deinit && plugin->plugin->deinit(NULL))
+  {
+    DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
+                            plugin->name.str));
+    DBUG_EXECUTE("finalize_audit_plugin", return 1; );
+  }
+  
+  plugin->data= NULL;
+
+  /* Iterate through all the installed plugins to create new mask */
+  pthread_mutex_lock(&LOCK_audit_mask);
+  plugin_foreach(current_thd, calc_class_mask, MYSQL_AUDIT_PLUGIN,
+                 &event_class_mask);
+
+  /* Set the global audit mask */
+  mysql_global_audit_mask= event_class_mask;
+  pthread_mutex_unlock(&LOCK_audit_mask);
+
+  return 0;
+}
+
+
+static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg)
+{
+  const struct mysql_event *event= (const struct mysql_event *) arg;
+  uint64 event_class_mask= (1 << event->event_class);
+  st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
+
+  /* Check to see if the plugin is interested in this event */
+  if (!(data->class_mask[0] & event_class_mask))
+    return 0;
+
+  /* Actually notify the plugin */
+  data->event_notify(thd, event);
+
+  return 0;
+}
+
+
+/**
+  Distributes an audit event to plug-ins
+  
+  @param[in] thd
+  @param[in] event
+*/
+
+static void event_class_dispatch(THD *thd, const struct mysql_event *event)
+{
+  if (unlikely(!thd))
+  {
+    plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, (void*) event);
+  }
+  else
+  {
+    uint64 event_class_mask= (1 << event->event_class);  
+    plugin_ref *plugins, *plugins_last;
+
+    /* Use the cached set of audit plugins */
+    plugins= (plugin_ref*) thd->audit_class_plugins.buffer;
+    plugins_last= plugins + thd->audit_class_plugins.elements;
+    for (; plugins < plugins_last; plugins++)
+    {
+      st_mysql_audit *data= plugin_data(*plugins, struct st_mysql_audit *);
+
+      /* Check to see if the plugin is interested in this event */
+      if (!(data->class_mask[0] & event_class_mask))
+        continue;
+
+      /* Actually notify the plugin */
+      data->event_notify(thd, event);
+    }
+  }
+}
+
+
+#else /* EMBEDDED_LIBRARY */
+
+
+void mysql_audit_initialize()
+{
+}
+
+
+void mysql_audit_finalize()
+{
+}
+
+
+int initialize_audit_plugin(st_plugin_int *plugin)
+{
+  return 1;
+}
+
+
+int finalize_audit_plugin(st_plugin_int *plugin)
+{
+  return 0;
+}
+
+
+void mysql_audit_release(THD *thd)
+{
+}
+
+
+#endif /* EMBEDDED_LIBRARY */
diff -Nrup a/sql/sql_audit.h b/sql/sql_audit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sql/sql_audit.h	2007-12-12 01:36:24 -08:00
@@ -0,0 +1,49 @@
+/* Copyright (C) 2007 MySQL 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 */
+
+
+
+extern uint64 mysql_global_audit_mask;
+
+
+extern void mysql_audit_initialize();
+extern void mysql_audit_finalize();
+
+
+extern void mysql_audit_init_thd(THD *thd);
+extern void mysql_audit_free_thd(THD *thd);
+
+
+extern void mysql_audit_notify(THD *thd, uint event_class,
+                               uint event_subtype, ...);
+extern void mysql_audit_release(THD *thd);
+
+
+
+inline void mysql_audit_general(THD *thd, uint event_subtype,
+                                int error_code, time_t time,
+                                const char *user, uint userlen,
+                                const char *cmd, uint cmdlen,
+                                const char *query, uint querylen,
+                                CHARSET_INFO *clientcs,
+                                ha_rows rows)
+{
+#ifndef EMBEDDED_LIBRARY
+  if (mysql_global_audit_mask & MYSQL_AUDIT_GENERAL_CLASSMASK)
+    mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype,
+                       error_code, time, user, userlen, cmd, cmdlen,
+                       query, querylen, clientcs, rows);
+#endif
+}
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2007-11-22 11:45:21 -08:00
+++ b/sql/sql_class.cc	2007-12-12 01:36:23 -08:00
@@ -30,6 +30,7 @@
 #include "rpl_record.h"
 #include <my_bitmap.h>
 #include "log_event.h"
+#include "sql_audit.h"
 #include <m_ctype.h>
 #include <sys/stat.h>
 #include <thr_alarm.h>
@@ -428,6 +429,7 @@ THD::THD()
   dbug_sentry=THD_SENTRY_MAGIC;
 #endif
 #ifndef EMBEDDED_LIBRARY
+  mysql_audit_init_thd(this);
   net.vio=0;
 #endif
   client_capabilities= 0;                       // minimalistic client
@@ -768,6 +770,8 @@ THD::~THD()
 #ifndef EMBEDDED_LIBRARY
   if (rli_fake)
     delete rli_fake;
+
+  mysql_audit_free_thd(this);
 #endif
 
   free_root(&main_mem_root, MYF(0));
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h	2007-11-22 11:45:22 -08:00
+++ b/sql/sql_class.h	2007-12-12 01:36:23 -08:00
@@ -1588,6 +1588,11 @@ public:
   partition_info *work_part_info;
 #endif
 
+#ifndef EMBEDDED_LIBRARY
+  DYNAMIC_ARRAY audit_class_plugins;
+  uint64 audit_class_mask;
+#endif
+
   THD();
   ~THD();
 
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc	2007-11-22 11:45:22 -08:00
+++ b/sql/sql_insert.cc	2007-12-12 01:36:24 -08:00
@@ -61,6 +61,7 @@
 #include "sql_show.h"
 #include "slave.h"
 #include "rpl_mi.h"
+#include "sql_audit.h"
 
 #ifndef EMBEDDED_LIBRARY
 static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
@@ -2331,6 +2332,7 @@ pthread_handler_t handle_delayed_insert(
       di->thd.mysys_var->current_mutex= &di->mutex;
       di->thd.mysys_var->current_cond= &di->cond;
       THD_SET_PROC_INFO(& (di->thd), "Waiting for INSERT");
+      mysql_audit_release(thd);
 
       DBUG_PRINT("info",("Waiting for someone to insert rows"));
       while (!thd->killed)
@@ -2416,6 +2418,7 @@ pthread_handler_t handle_delayed_insert(
       di->table->file->ha_release_auto_increment();
       mysql_unlock_tables(thd, lock);
       di->group_count=0;
+      mysql_audit_release(thd);
       pthread_mutex_lock(&di->mutex);
     }
     if (di->tables_in_use)
diff -Nrup a/sql/sql_plugin.cc b/sql/sql_plugin.cc
--- a/sql/sql_plugin.cc	2007-11-21 12:19:04 -08:00
+++ b/sql/sql_plugin.cc	2007-12-12 01:36:24 -08:00
@@ -16,6 +16,9 @@
 #include "mysql_priv.h"
 #include <my_pthread.h>
 #include <my_getopt.h>
+
+#include <mysql/plugin.h>
+
 #define REPORT_TO_LOG  1
 #define REPORT_TO_USER 2
 
@@ -42,12 +45,16 @@ const LEX_STRING plugin_type_names[MYSQL
   { C_STRING_WITH_LEN("STORAGE ENGINE") },
   { C_STRING_WITH_LEN("FTPARSER") },
   { C_STRING_WITH_LEN("DAEMON") },
-  { C_STRING_WITH_LEN("INFORMATION SCHEMA") }
+  { C_STRING_WITH_LEN("INFORMATION SCHEMA") },
+  { C_STRING_WITH_LEN("AUDIT") }
 };
 
 extern int initialize_schema_table(st_plugin_int *plugin);
 extern int finalize_schema_table(st_plugin_int *plugin);
 
+extern int initialize_audit_plugin(st_plugin_int *plugin);
+extern int finalize_audit_plugin(st_plugin_int *plugin);
+
 /*
   The number of elements in both plugin_type_initialize and
   plugin_type_deinitialize should equal to the number of plugins
@@ -55,12 +62,14 @@ extern int finalize_schema_table(st_plug
 */
 plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
 {
-  0,ha_initialize_handlerton,0,0,initialize_schema_table
+  0,ha_initialize_handlerton,0,0,initialize_schema_table,
+  initialize_audit_plugin
 };
 
 plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
 {
-  0,ha_finalize_handlerton,0,0,finalize_schema_table
+  0,ha_finalize_handlerton,0,0,finalize_schema_table,
+  finalize_audit_plugin
 };
 
 #ifdef HAVE_DLOPEN
@@ -81,7 +90,8 @@ static int min_plugin_info_interface_ver
   MYSQL_HANDLERTON_INTERFACE_VERSION,
   MYSQL_FTPARSER_INTERFACE_VERSION,
   MYSQL_DAEMON_INTERFACE_VERSION,
-  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+  MYSQL_AUDIT_INTERFACE_VERSION
 };
 static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
 {
@@ -89,7 +99,8 @@ static int cur_plugin_info_interface_ver
   MYSQL_HANDLERTON_INTERFACE_VERSION,
   MYSQL_FTPARSER_INTERFACE_VERSION,
   MYSQL_DAEMON_INTERFACE_VERSION,
-  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+  MYSQL_AUDIT_INTERFACE_VERSION
 };
 
 static bool initialized= 0;
@@ -205,10 +216,12 @@ static plugin_ref intern_plugin_lock(LEX
                                      CALLER_INFO_PROTO);
 static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
 static void reap_plugins(void);
+static const char *find_sys_var_name(struct st_mysql_sys_var *plugin_var);
 
 
 /* declared in set_var.cc */
 extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error);
+extern sys_var *intern_find_sys_var(bool (*func)(sys_var *, void*), void *data);
 
 #ifdef EMBEDDED_LIBRARY
 /* declared in sql_base.cc */
@@ -330,6 +343,11 @@ static inline void free_plugin_mem(struc
     my_free((uchar*)p->plugins, MYF(MY_ALLOW_ZERO_PTR));
 }
 
+extern "C" char *mysqld_plugin_path(char *tgt, unsigned int tgt_size,
+                                    const char *name)
+{
+  return strxnmov(tgt, tgt_size - 1, opt_plugin_dir, "/", name, NullS);
+}
 
 static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
 {
@@ -346,7 +364,8 @@ static st_plugin_dl *plugin_dl_add(const
     plugin directory are used (to make this even remotely secure).
   */
   if (my_strchr(files_charset_info, dl->str, dl->str + dl->length, FN_LIBCHAR) ||
-      check_identifier_name((LEX_STRING *) dl) ||
+      check_string_char_length((LEX_STRING *) dl, "", NAME_CHAR_LEN,
+                               system_charset_info, 1) ||
       plugin_dir_len + dl->length + 1 >= FN_REFLEN)
   {
     if (report & REPORT_TO_USER)
@@ -364,7 +383,7 @@ static st_plugin_dl *plugin_dl_add(const
   bzero(&plugin_dl, sizeof(plugin_dl));
   /* Compile dll path */
   dlpathlen=
-    strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", dl->str, NullS) -
+    mysqld_plugin_path(dlpath, sizeof(dlpath), dl->str) -
     dlpath;
   plugin_dl.ref_count= 1;
   /* Open new dll handle */
@@ -1179,9 +1198,7 @@ int plugin_init(int *argc, char **argv, 
   /* Register all dynamic plugins */
   if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING))
   {
-    if (opt_plugin_load &&
-        plugin_load_list(&tmp_root, argc, argv, opt_plugin_load))
-      goto err;
+    plugin_load_list(&tmp_root, argc, argv, opt_plugin_load);
     if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE))
       plugin_load(&tmp_root, argc, argv);
   }
@@ -1310,27 +1327,23 @@ end:
 */
 static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
 {
+  THD thd;
   TABLE_LIST tables;
   TABLE *table;
   READ_RECORD read_record_info;
   int error;
-  THD *new_thd;
+  THD *new_thd= &thd;
 #ifdef EMBEDDED_LIBRARY
   bool table_exists;
 #endif /* EMBEDDED_LIBRARY */
   DBUG_ENTER("plugin_load");
 
-  if (!(new_thd= new THD))
-  {
-    sql_print_error("Can't allocate memory for plugin structures");
-    delete new_thd;
-    DBUG_VOID_RETURN;
-  }
   new_thd->thread_stack= (char*) &tables;
   new_thd->store_globals();
   lex_start(new_thd);
   new_thd->db= my_strdup("mysql", MYF(0));
   new_thd->db_length= 5;
+  bzero((char*) &thd.net, sizeof(thd.net));
   bzero((uchar*)&tables, sizeof(tables));
   tables.alias= tables.table_name= (char*)"plugin";
   tables.lock_type= TL_READ;
@@ -1388,7 +1401,6 @@ static void plugin_load(MEM_ROOT *tmp_ro
   new_thd->version--; // Force close to free memory
 end:
   close_thread_tables(new_thd);
-  delete new_thd;
   /* Remember that we don't have a THD */
   my_pthread_setspecific_ptr(THR_THD, 0);
   DBUG_VOID_RETURN;
@@ -1406,11 +1418,15 @@ static bool plugin_load_list(MEM_ROOT *t
   struct st_plugin_dl *plugin_dl;
   struct st_mysql_plugin *plugin;
   char *p= buffer;
+  bool result= FALSE;
   DBUG_ENTER("plugin_load_list");
   while (list)
   {
     if (p == buffer + sizeof(buffer) - 1)
+    {
+      sql_print_warning("plugin-load argument too long");
       break;
+    }
     switch ((*(p++)= *(list++))) {
     case '\0':
       list= NULL; /* terminate the loop */
@@ -1420,6 +1436,7 @@ static bool plugin_load_list(MEM_ROOT *t
 #endif
     case ';':
       name.str[name.length]= '\0';
+      pthread_mutex_lock(&LOCK_plugin);
       if (str != &dl)  // load all plugins in named module
       {
         dl= name;
@@ -1432,7 +1449,10 @@ static bool plugin_load_list(MEM_ROOT *t
 
             free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
             if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+            {
+              pthread_mutex_unlock(&LOCK_plugin);
               goto error;
+            }
           }
           plugin_dl_del(&dl); // reduce ref count
         }
@@ -1441,8 +1461,12 @@ static bool plugin_load_list(MEM_ROOT *t
       {
         free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE));
         if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG))
+        {
+          pthread_mutex_unlock(&LOCK_plugin);
           goto error;
+        }
       }
+      pthread_mutex_unlock(&LOCK_plugin);
       name.length= dl.length= 0;
       dl.str= NULL; name.str= p= buffer;
       str= &name;
@@ -1459,12 +1483,12 @@ static bool plugin_load_list(MEM_ROOT *t
       str->length++;
       continue;
     }
-  }
-  DBUG_RETURN(FALSE);
 error:
-  sql_print_error("Couldn't load plugin named '%s' with soname '%s'.",
-                  name.str, dl.str);
-  DBUG_RETURN(TRUE);
+    sql_print_warning("Couldn't load plugin named '%s' with soname '%s'.",
+                      name.str, dl.str);
+    result= TRUE;
+  }
+  DBUG_RETURN(result);
 }
 
 
@@ -1624,12 +1648,14 @@ bool mysql_install_plugin(THD *thd, cons
   if (! (table = open_ltable(thd, &tables, TL_WRITE, 0)))
     DBUG_RETURN(TRUE);
 
-  pthread_mutex_lock(&LOCK_plugin);
-  rw_wrlock(&LOCK_system_variables_hash);
   /* handle_options() assumes arg0 (program name) always exists */
   argv[0]= const_cast<char*>(""); // without a cast gcc emits a warning
   argv[1]= 0;
   argc= 1;
+
+  /* Attempt to load the plugin */
+  pthread_mutex_lock(&LOCK_plugin);
+  rw_wrlock(&LOCK_system_variables_hash);
   error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
   rw_unlock(&LOCK_system_variables_hash);
 
@@ -1647,8 +1673,7 @@ bool mysql_install_plugin(THD *thd, cons
   restore_record(table, s->default_values);
   table->field[0]->store(name->str, name->length, system_charset_info);
   table->field[1]->store(dl->str, dl->length, files_charset_info);
-  error= table->file->ha_write_row(table->record[0]);
-  if (error)
+  if ((error= table->file->ha_write_row(table->record[0])))
   {
     table->file->print_error(error, MYF(0));
     goto deinit;
@@ -1832,6 +1857,7 @@ typedef uchar *(*mysql_sys_var_ptr_p)(vo
   default variable data check and update functions
 ****************************************************************************/
 
+
 static int check_func_bool(THD *thd, struct st_mysql_sys_var *var,
                            void *save, st_mysql_value *value)
 {
@@ -1866,7 +1892,9 @@ static int check_func_bool(THD *thd, str
   *(int*)save= -result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  rw_rdlock(&LOCK_system_variables_hash);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), find_sys_var_name(var), strvalue);
+  rw_unlock(&LOCK_system_variables_hash);
   return 1;
 }
 
@@ -1965,7 +1993,9 @@ static int check_func_enum(THD *thd, str
   *(long*)save= result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  rw_rdlock(&LOCK_system_variables_hash);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), find_sys_var_name(var), strvalue);
+  rw_unlock(&LOCK_system_variables_hash);
   return 1;
 }
 
@@ -2015,7 +2045,9 @@ static int check_func_set(THD *thd, stru
   *(ulonglong*)save= result;
   return 0;
 err:
-  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue);
+  rw_rdlock(&LOCK_system_variables_hash);
+  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), find_sys_var_name(var), strvalue);
+  rw_unlock(&LOCK_system_variables_hash);
   return 1;
 }
 
@@ -2065,6 +2097,19 @@ static void update_func_str(THD *thd, st
   System Variables support
 ****************************************************************************/
 
+static bool check_is_plugin_var(sys_var *var_arg, void *arg)
+{
+  sys_var_pluginvar *var= var_arg->cast_pluginvar();
+  return var && ((void*) var->plugin_var == arg);
+}
+
+
+static const char *find_sys_var_name(struct st_mysql_sys_var *plugin_var)
+{
+  sys_var *var= intern_find_sys_var(check_is_plugin_var, plugin_var);
+  return var ? var->name : plugin_var->name;
+}
+
 
 sys_var *find_sys_var(THD *thd, const char *str, uint length)
 {
@@ -2944,7 +2989,8 @@ static int construct_options(MEM_ROOT *m
       DBUG_RETURN(-1);
     }
 
-    if (opt->flags & PLUGIN_VAR_NOCMDOPT)
+    if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL))
+                    == PLUGIN_VAR_NOCMDOPT)
       continue;
 
     if (!opt->name)
@@ -2954,7 +3000,7 @@ static int construct_options(MEM_ROOT *m
       DBUG_RETURN(-1);
     }
 
-    if (!(v= find_bookmark(name, opt->name, opt->flags)))
+    if (!(opt->flags & PLUGIN_VAR_THDLOCAL))
     {
       optnamelen= strlen(opt->name);
       optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2);
@@ -2962,7 +3008,22 @@ static int construct_options(MEM_ROOT *m
       optnamelen= namelen + optnamelen + 1;
     }
     else
-      optname= (char*) memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1);
+    {
+      if (!(v= find_bookmark(name, opt->name, opt->flags)))
+      {
+        sql_print_error("Thread local variable '%s' not allocated "
+                        "in plugin '%s'.", opt->name, plugin_name);
+    	DBUG_RETURN(-1);
+      }
+
+      *(int*)(opt + 1)= offset= v->offset;
+
+      if (opt->flags & PLUGIN_VAR_NOCMDOPT)
+        continue;
+
+      optname= (char*) memdup_root(mem_root, v->key + 1, 
+                                   (optnamelen= v->name_len) + 1);
+    }
 
     /* convert '_' to '-' */
     for (p= optname; *p; p++)
@@ -2974,20 +3035,13 @@ static int construct_options(MEM_ROOT *m
     options->app_type= opt;
     options->id= (options-1)->id + 1;
 
-    if (opt->flags & PLUGIN_VAR_THDLOCAL)
-      *(int*)(opt + 1)= offset= v->offset;
-
     plugin_opt_set_limits(options, opt);
 
-    if ((opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM &&
-        (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET)
-    {
-      if (opt->flags & PLUGIN_VAR_THDLOCAL)
-        options->value= options->u_max_value= (uchar**)
-          (global_system_variables.dynamic_variables_ptr + offset);
-      else
-        options->value= options->u_max_value= *(uchar***) (opt + 1);
-    }
+    if (opt->flags & PLUGIN_VAR_THDLOCAL)
+      options->value= options->u_max_value= (uchar**)
+        (global_system_variables.dynamic_variables_ptr + offset);
+    else
+      options->value= options->u_max_value= *(uchar***) (opt + 1);
 
     options[1]= options[0];
     options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8);
Thread
bk commit into 6.0 tree (antony:1.2699) WL#3771antony12 Dec
  • Re: bk commit into 6.0 tree (antony:1.2699) WL#3771Konstantin Osipov12 Dec