List:Commits« Previous MessageNext Message »
From:antony Date:March 12 2007 6:52pm
Subject:bk commit into 5.1 tree (acurtis:1.2466)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 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-03-12 10:52:25-07:00, acurtis@stripped +45 -0
  WL#3771
    "Error Logging plugins"
    Temporary commit of initial collapse of repository for review/examination
    Code incomplete - requires 2936 for command line and server variables.
    Code incomplete - does not yet reopen log files on flush
  ---
  Temporary commit for work in progress.
  Will be collapsed at a later date.
  ---
  Temporary commit for work in progress.
  Will be collapsed at a later date.
  ---
  Temporary commit for work in progress.
  Will be collapsed at a later date.
  ---
  Temporary commit for work in progress.
  Will be collapsed at a later date.
  ---
  Temporary commit for work in progress.
  Will be collapsed at a later date.

  include/mysql/plugin.h@stripped, 2007-03-12 10:52:19-07:00, acurtis@stripped +21 -1
    add declarations for logging plugin

  libmysqld/Makefile.am@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +1 -0
    add new files to build
    ---
    remove log_file.cc and log_table.cc from the makefile as it is now built by the
    plugin framework.

  libmysqld/lib_sql.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -6
    remove old logging code

  plugin/log_file/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +43 -0
    New BitKeeper file ``plugin/log_file/Makefile.am''

  plugin/log_file/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_file/log_file.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +330 -0
    New BitKeeper file ``sql/log_file.cc''

  plugin/log_file/log_file.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_file/plug.in@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +5 -0
    New BitKeeper file ``plugin/log_file/plug.in''

  plugin/log_file/plug.in@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_null/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +45 -0
    New BitKeeper file ``plugin/log_null/Makefile.am''

  plugin/log_null/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_null/log_null.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +165 -0
    New BitKeeper file ``plugin/log_null/log_null.cc''

  plugin/log_null/log_null.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_null/plug.in@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +5 -0
    New BitKeeper file ``plugin/log_null/plug.in''

  plugin/log_null/plug.in@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_syslog/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +45 -0
    New BitKeeper file ``plugin/log_syslog/Makefile.am''

  plugin/log_syslog/Makefile.am@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_syslog/log_syslog.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +177
-0
    New BitKeeper file ``plugin/log_syslog/log_syslog.cc''

  plugin/log_syslog/log_syslog.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  plugin/log_syslog/plug.in@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +5 -0
    New BitKeeper file ``plugin/log_syslog/plug.in''

  plugin/log_syslog/plug.in@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +0 -0

  plugin/log_table/Makefile.am@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +45 -0
    New BitKeeper file ``plugin/log_table/Makefile.am''
    ---
    new header file

  plugin/log_table/Makefile.am@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +0 -0

  plugin/log_table/log_insert.h@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +130 -0
    New BitKeeper file ``plugin/log_table/log_insert.h''

  plugin/log_table/log_insert.h@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +0 -0

  plugin/log_table/log_table.cc@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +431 -0
    New BitKeeper file ``sql/log_table.cc''
    ---
    remove tab characters.
    make it actually work.
    ---
    moved out class declaration into log_insert.h
    reduced some local variables

  plugin/log_table/log_table.cc@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +0 -0

  plugin/log_table/plug.in@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +5 -0
    New BitKeeper file ``plugin/log_table/plug.in''

  plugin/log_table/plug.in@stripped, 2007-03-12 10:52:22-07:00, acurtis@stripped +0 -0

  sql/Makefile.am@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +2 -0
    add sql_logger.cc to build
    ---
    add new files to build
    ---
    remove log_file.cc and log_table.cc from the makefile as it is now built by the
    plugin framework.

  sql/event_scheduler.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +16 -3
    use new logging code

  sql/handler.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -28
    remove old logging code

  sql/handler.h@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -33
    remove old logging code

  sql/lock.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -11
    remove old logging code

  sql/log.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -1412
    put the existing logging code under the new plugin-logger interface
    ---
    remove old logging code

  sql/log.h@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -217
    remove old logging code

  sql/mysql_priv.h@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +2 -27
    include sql_logger.h
    ---
    remove old logging code

  sql/mysqld.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +6 -80
    remove old logging code
    ---
    logger mutex initialization and destruction

  sql/set_var.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -227
    remove old logging code

  sql/set_var.h@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +0 -32
    remove old logging code

  sql/sp_head.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +2 -2
    remove old logging code

  sql/sql_base.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +7 -9
    remove old logging code

  sql/sql_class.cc@stripped, 2007-03-12 10:52:20-07:00, acurtis@stripped +3 -0
    initialize/finalize logger cache structure

  sql/sql_class.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +1 -0
    logger cache in thd

  sql/sql_delete.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -22
    remove old logging code

  sql/sql_logger.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +554 -0
    New BitKeeper file ``sql/sql_logger.cc''
    ---
    relocated logging functions from log.cc into here.
    new functions:
      my_vstrprintf()
      my_strprintf()   - appends a printf into a String object.
    ---
    remove unused variable.
    ---
    implement logger cache structure to minimize the amount of times that mutex locking
    occurs.

  sql/sql_logger.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  sql/sql_logger.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +82 -0
    New BitKeeper file ``sql/sql_logger.h''
    ---
    added additional 'data' member to logger struct
    relocated error logging declarations from mysql_priv.h
    ---
    implement logger cache structure to minimize the amount of times that mutex locking
    occurs.

  sql/sql_logger.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -0

  sql/sql_parse.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +22 -24
    removed old logging code
    use post_statement_log() istead of log_slow_statement()
    ---
    implement logger cache to minimize the amount of times that mutex locking occurs.

  sql/sql_plugin.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +91 -11
    add support for logging plugin.
    add additional lines so that future plugin types can be added only by adding lines
    without need to edit any existing lines of code.
    fix a typo.
    ---
    zero out the data member.
    ---
    notify on delete requested callback
    new functions: plugin_lockall() and plugin_unlockall()

  sql/sql_plugin.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +3 -0
    new functions: plugin_lockall() and plugin_unlockall()

  sql/sql_rename.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -99
    removed old logging code

  sql/sql_table.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +3 -68
    removed old logging code

  sql/table.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -6
    removed old logging code

  sql/table.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -6
    removed old logging code

  storage/csv/ha_tina.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -11
    removed old logging code

  storage/csv/ha_tina.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -4
    removed old logging code

  storage/myisam/ha_myisam.cc@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -30
    removed old logging code

  storage/myisam/ha_myisam.h@stripped, 2007-03-12 10:52:21-07:00, acurtis@stripped +0 -4
    removed old logging code

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	acurtis
# Host:	ltamd64.xiphis.org
# Root:	/home/antony/work2/mysql-5.1-logging.4

--- 1.174/sql/Makefile.am	2007-03-12 10:52:50 -07:00
+++ 1.175/sql/Makefile.am	2007-03-12 10:52:50 -07:00
@@ -69,6 +69,7 @@
 			sql_plugin.h authors.h \
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
+			sql_logger.h \
 			contributors.h sql_servers.h
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -109,6 +110,7 @@
                         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_logger.cc \
 			sql_servers.cc
 
 

--- 1.210/storage/myisam/ha_myisam.cc	2007-03-12 10:52:50 -07:00
+++ 1.211/storage/myisam/ha_myisam.cc	2007-03-12 10:52:50 -07:00
@@ -563,36 +563,6 @@
 #endif /* HAVE_REPLICATION */
 
 
-bool ha_myisam::check_if_locking_is_allowed(uint sql_command,
-                                            ulong type, TABLE *table,
-                                            uint count,
-                                            bool called_by_privileged_thread)
-{
-  /*
-    To be able to open and lock for reading system tables like 'mysql.proc',
-    when we already have some tables opened and locked, and avoid deadlocks
-    we have to disallow write-locking of these tables with any other tables.
-  */
-  if (table->s->system_table &&
-      table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE &&
-      count != 1)
-  {
-    my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table->s->db.str,
-             table->s->table_name.str);
-    return FALSE;
-  }
-
-  /*
-    Deny locking of the log tables, which is incompatible with
-    concurrent insert. Unless called from a logger THD (general_log_thd
-    or slow_log_thd) or by a privileged thread.
-  */
-  if (!called_by_privileged_thread)
-    return check_if_log_table_locking_is_allowed(sql_command, type, table);
-
-  return TRUE;
-}
-
 	/* Name is here without an extension */
 
 int ha_myisam::open(const char *name, int mode, uint test_if_locked)

--- 1.81/storage/myisam/ha_myisam.h	2007-03-12 10:52:50 -07:00
+++ 1.82/storage/myisam/ha_myisam.h	2007-03-12 10:52:50 -07:00
@@ -60,10 +60,6 @@
   uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; }
   uint checksum() const;
 
-  virtual bool check_if_locking_is_allowed(uint sql_command,
-                                           ulong type, TABLE *table,
-                                           uint count,
-                                           bool called_by_logger_thread);
   int open(const char *name, int mode, uint test_if_locked);
   int close(void);
   int write_row(byte * buf);

--- 1.297/sql/handler.cc	2007-03-12 10:52:50 -07:00
+++ 1.298/sql/handler.cc	2007-03-12 10:52:50 -07:00
@@ -1475,34 +1475,6 @@
 }
 
 
-bool handler::check_if_log_table_locking_is_allowed(uint sql_command,
-                                                    ulong type, TABLE *table)
-{
-  /*
-    Deny locking of the log tables, which is incompatible with
-    concurrent insert. The routine is not called if the table is
-    being locked from a logger THD (general_log_thd or slow_log_thd)
-    or from a privileged thread (see log.cc for details)
-  */
-  if (table->s->log_table &&
-      sql_command != SQLCOM_TRUNCATE &&
-      sql_command != SQLCOM_ALTER_TABLE &&
-      !(sql_command == SQLCOM_FLUSH &&
-        type & REFRESH_LOG) &&
-      (table->reginfo.lock_type >= TL_READ_NO_INSERT))
-  {
-    /*
-      The check  >= TL_READ_NO_INSERT denies all write locks
-      plus the only read lock (TL_READ_NO_INSERT itself)
-    */
-    table->reginfo.lock_type == TL_READ_NO_INSERT ?
-      my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) :
-        my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
-    return FALSE;
-  }
-  return TRUE;
-}
-
 /** @brief
   Open database-handler.
 

--- 1.252/sql/handler.h	2007-03-12 10:52:50 -07:00
+++ 1.253/sql/handler.h	2007-03-12 10:52:50 -07:00
@@ -967,39 +967,6 @@
   {
     cached_table_flags= table_flags();
   }
-  /*
-    Check whether a handler allows to lock the table.
-
-    SYNOPSIS
-      check_if_locking_is_allowed()
-        thd     Handler of the thread, trying to lock the table
-        table   Table handler to check
-        count   Number of locks already granted to the table
-        called_by_privileged_thread TRUE if called from a logger THD
-                                    (general_log_thd or slow_log_thd)
-                                    or by a privileged thread, which
-                                    has the right to lock log tables.
-
-    DESCRIPTION
-      Check whether a handler allows to lock the table. For instance,
-      MyISAM does not allow to lock mysql.proc along with other tables.
-      This limitation stems from the fact that MyISAM does not support
-      row-level locking and we have to add this limitation to avoid
-      deadlocks.
-
-    RETURN
-      TRUE      Locking is allowed
-      FALSE     Locking is not allowed. The error was thrown.
-  */
-  virtual bool check_if_locking_is_allowed(uint sql_command,
-                                           ulong type, TABLE *table,
-                                           uint count,
-                                           bool called_by_privileged_thread)
-  {
-    return TRUE;
-  }
-  bool check_if_log_table_locking_is_allowed(uint sql_command,
-                                             ulong type, TABLE *table);
   int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
   void adjust_next_insert_id_after_explicit_value(ulonglong nr);
   int update_auto_increment();

--- 1.103/sql/lock.cc	2007-03-12 10:52:50 -07:00
+++ 1.104/sql/lock.cc	2007-03-12 10:52:50 -07:00
@@ -699,17 +699,6 @@
       tables+=table_ptr[i]->file->lock_count();
       lock_count++;
     }
-    /*
-      Check if we can lock the table. For some tables we cannot do that
-      beacause of handler-specific locking issues.
-    */
-    if (!table_ptr[i]-> file->
-          check_if_locking_is_allowed(thd->lex->sql_command, thd->lex->type,
-                                      table_ptr[i], count,
-                                      (thd == logger.get_general_log_thd()) ||
-                                      (thd == logger.get_slow_log_thd()) ||
-                                      (thd == logger.get_privileged_thread())))
-      DBUG_RETURN(0);
   }
 
   /*

--- 1.257/sql/log.cc	2007-03-12 10:52:50 -07:00
+++ 1.258/sql/log.cc	2007-03-12 10:52:50 -07:00
@@ -48,8 +48,6 @@
 
 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
 
-LOGGER logger;
-
 MYSQL_BIN_LOG mysql_bin_log;
 ulong sync_binlog_counter= 0;
 
@@ -65,21 +63,8 @@
 static int binlog_rollback(handlerton *hton, THD *thd, bool all);
 static int binlog_prepare(handlerton *hton, THD *thd, bool all);
 
-sql_print_message_func sql_print_message_handlers[3] =
-{
-  sql_print_information,
-  sql_print_warning,
-  sql_print_error
-};
 
 
-char *make_default_log_name(char *buff,const char* log_ext)
-{
-  strmake(buff, glob_hostname, FN_REFLEN-5);
-  return fn_format(buff, buff, mysql_data_home, log_ext,
-                   MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
-}
-
 /*
   Helper class to hold a mutex for the duration of the
   block.
@@ -195,1150 +180,6 @@
 handlerton *binlog_hton;
 
 
-/* Check if a given table is opened log table */
-int check_if_log_table(uint db_len, const char *db, uint table_name_len,
-                       const char *table_name, uint check_if_opened)
-{
-  if (db_len == 5 &&
-      !(lower_case_table_names ?
-        my_strcasecmp(system_charset_info, db, "mysql") :
-        strcmp(db, "mysql")))
-  {
-    if (table_name_len == 11 && !(lower_case_table_names ?
-                                  my_strcasecmp(system_charset_info,
-                                                table_name, "general_log") :
-                                  strcmp(table_name, "general_log")) &&
-        (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL)))
-      return QUERY_LOG_GENERAL;
-    else
-      if (table_name_len == 8 && !(lower_case_table_names ?
-        my_strcasecmp(system_charset_info, table_name, "slow_log") :
-        strcmp(table_name, "slow_log")) &&
-          (!check_if_opened ||logger.is_log_table_enabled(QUERY_LOG_SLOW)))
-        return QUERY_LOG_SLOW;
-  }
-  return 0;
-}
-
-
-/*
-  Open log table of a given type (general or slow log)
-
-  SYNOPSIS
-    open_log_table()
-
-    log_table_type   type of the log table to open: QUERY_LOG_GENERAL
-                     or QUERY_LOG_SLOW
-
-  DESCRIPTION
-
-    The function opens a log table and marks it as such. Log tables are open
-    during the whole time, while server is running. Except for the moments
-    when they have to be reopened: during FLUSH LOGS and TRUNCATE. This
-    function is invoked directly only once during startup. All subsequent
-    calls happen through reopen_log_table(), which performs additional check.
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool Log_to_csv_event_handler::open_log_table(uint log_table_type)
-{
-  THD *log_thd, *curr= current_thd;
-  TABLE_LIST *table;
-  bool error= FALSE;
-  DBUG_ENTER("open_log_table");
-
-  switch (log_table_type) {
-  case QUERY_LOG_GENERAL:
-    log_thd= general_log_thd;
-    table= &general_log;
-    /* clean up table before reuse/initial usage */
-    bzero((char*) table, sizeof(TABLE_LIST));
-    table->alias= table->table_name= (char*) "general_log";
-    table->table_name_length= 11;
-    break;
-  case QUERY_LOG_SLOW:
-    log_thd= slow_log_thd;
-    table= &slow_log;
-    bzero((char*) table, sizeof(TABLE_LIST));
-    table->alias= table->table_name= (char*) "slow_log";
-    table->table_name_length= 8;
-    break;
-  default:
-    assert(0);                                  // Impossible
-  }
-
-  /*
-    This way we check that appropriate log thd was created ok during
-    initialization. We cannot check "is_log_tables_initialized" var, as
-    the very initialization is not finished until this function is
-    completed in the very first time.
-  */
-  if (!log_thd)
-  {
-    DBUG_PRINT("error",("Cannot initialize log tables"));
-    DBUG_RETURN(TRUE);
-  }
-
-  /*
-    Set THD's thread_stack. This is needed to perform stack overrun
-    check, which is done by some routines (e.g. open_table()).
-    In the case we are called by thread, which already has this parameter
-    set, we use this value. Otherwise we do a wild guess. This won't help
-    to correctly track the stack overrun in these exceptional cases (which
-    could probably happen only during startup and shutdown) but at least
-    lets us to pass asserts.
-    The problem stems from the fact that logger THDs are not real threads.
-  */
-  if (curr)
-    log_thd->thread_stack= curr->thread_stack;
-  else
-    log_thd->thread_stack= (char*) &log_thd;
-
-  log_thd->store_globals();
-
-  table->lock_type= TL_WRITE_CONCURRENT_INSERT;
-  table->db= log_thd->db;
-  table->db_length= log_thd->db_length;
-
-  if (simple_open_n_lock_tables(log_thd, table) ||
-      table->table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
-      table->table->file->ha_rnd_init(0))
-    error= TRUE;
-  else
-  {
-    table->table->use_all_columns();
-    table->table->locked_by_logger= TRUE;
-  }
-  /* restore thread settings */
-  if (curr)
-    curr->store_globals();
-  else
-  {
-    my_pthread_setspecific_ptr(THR_THD,  0);
-    my_pthread_setspecific_ptr(THR_MALLOC, 0);
-  }
-
-  /*
-    After a log table was opened, we should clear privileged thread
-    flag (which allows locking of a log table by a special thread, usually
-    the one who closed log tables temporarily).
-  */
-  privileged_thread= 0;
-  DBUG_RETURN(error);
-}
-
-
-Log_to_csv_event_handler::Log_to_csv_event_handler()
-{
-  /* init artificial THD's */
-  general_log_thd= new THD;
-  /* logger thread always works with mysql database */
-  general_log_thd->db= my_strdup("mysql", MYF(0));
-  general_log_thd->db_length= 5;
-  general_log.table= 0;
-
-  slow_log_thd= new THD;
-  /* logger thread always works with mysql database */
-  slow_log_thd->db= my_strdup("mysql", MYF(0));;
-  slow_log_thd->db_length= 5;
-  slow_log.table= 0;
-  /* no privileged thread exists at the moment */
-  privileged_thread= 0;
-}
-
-
-Log_to_csv_event_handler::~Log_to_csv_event_handler()
-{
-  /* now cleanup the tables */
-  if (general_log_thd)
-  {
-    delete general_log_thd;
-    general_log_thd= NULL;
-  }
-
-  if (slow_log_thd)
-  {
-    delete slow_log_thd;
-    slow_log_thd= NULL;
-  }
-}
-
-
-/*
-  Reopen log table of a given type
-
-  SYNOPSIS
-    reopen_log_table()
-
-    log_table_type   type of the log table to open: QUERY_LOG_GENERAL
-                     or QUERY_LOG_SLOW
-
-  DESCRIPTION
-
-    The function is a wrapper around open_log_table(). It is used during
-    FLUSH LOGS and TRUNCATE of the log tables (i.e. when we need to close
-    and reopen them). The difference is in the check of the
-    logger.is_log_tables_initialized var, which can't be done in
-    open_log_table(), as it makes no sense during startup.
-
-    NOTE: this code assumes that we have logger mutex locked
-
-  RETURN
-    FALSE - ok
-    TRUE - open_log_table() returned an error
-*/
-
-bool Log_to_csv_event_handler::reopen_log_table(uint log_table_type)
-{
-  /* don't open the log table, if it wasn't enabled during startup */
-  if (!logger.is_log_tables_initialized)
-    return FALSE;
-  return open_log_table(log_table_type);
-}
-
-
-void Log_to_csv_event_handler::cleanup()
-{
-  if (opt_log)
-    close_log_table(QUERY_LOG_GENERAL, FALSE);
-  if (opt_slow_log)
-    close_log_table(QUERY_LOG_SLOW, FALSE);
-  logger.is_log_tables_initialized= FALSE;
-}
-
-/* log event handlers */
-
-/*
-  Log command to the general log table
-
-  SYNOPSIS
-    log_general()
-
-    event_time        command start timestamp
-    user_host         the pointer to the string with user@host info
-    user_host_len     length of the user_host string. this is computed once
-                      and passed to all general log event handlers
-    thread_id         Id of the thread, issued a query
-    command_type      the type of the command being logged
-    command_type_len  the length of the string above
-    sql_text          the very text of the query being executed
-    sql_text_len      the length of sql_text string
-
-  DESCRIPTION
-
-   Log given command to the general log table
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool Log_to_csv_event_handler::
-  log_general(time_t event_time, const char *user_host,
-              uint user_host_len, int thread_id,
-              const char *command_type, uint command_type_len,
-              const char *sql_text, uint sql_text_len,
-              CHARSET_INFO *client_cs)
-{
-  TABLE *table= general_log.table;
-
-  /*
-    "INSERT INTO general_log" can generate warning sometimes.
-    Let's reset warnings from previous queries,
-    otherwise warning list can grow too much,
-    so thd->query gets spoiled as some point in time,
-    and mysql_parse() receives a broken query.
-    QQ: this problem needs to be studied in more details.
-    Probably it's better to suppress warnings in logging INSERTs at all.
-    Comment this line and run "cast.test" to see what's happening:
-  */
-  mysql_reset_errors(table->in_use, 1);
-
-  /* below should never happen */
-  if (unlikely(!logger.is_log_tables_initialized))
-    return FALSE;
-
-  /*
-    NOTE: we do not call restore_record() here, as all fields are
-    filled by the Logger (=> no need to load default ones).
-  */
-
-  /* Set current time. Required for CURRENT_TIMESTAMP to work */
-  general_log_thd->start_time= event_time;
-
-  /*
-    We do not set a value for table->field[0], as it will use
-    default value (which is CURRENT_TIMESTAMP).
-  */
-
-  /* check that all columns exist */
-  if (!table->field[1] || !table->field[2] || !table->field[3] ||
-      !table->field[4] || !table->field[5])
-    goto err;
-
-  /* do a write */
-  if (table->field[1]->store(user_host, user_host_len, client_cs) ||
-      table->field[2]->store((longlong) thread_id, TRUE) ||
-      table->field[3]->store((longlong) server_id, TRUE) ||
-      table->field[4]->store(command_type, command_type_len, client_cs) ||
-      table->field[5]->store(sql_text, sql_text_len, client_cs))
-    goto err;
-
-  /* mark tables as not null */
-  table->field[1]->set_notnull();
-  table->field[2]->set_notnull();
-  table->field[3]->set_notnull();
-  table->field[4]->set_notnull();
-  table->field[5]->set_notnull();
-
-  /* log table entries are not replicated at the moment */
-  tmp_disable_binlog(current_thd);
-
-  table->file->ha_write_row(table->record[0]);
-
-  reenable_binlog(current_thd);
-
-  return FALSE;
-err:
-  return TRUE;
-}
-
-
-/*
-  Log a query to the slow log table
-
-  SYNOPSIS
-    log_slow()
-    thd               THD of the query
-    current_time      current timestamp
-    query_start_arg   command start timestamp
-    user_host         the pointer to the string with user@host info
-    user_host_len     length of the user_host string. this is computed once
-                      and passed to all general log event handlers
-    query_time        Amount of time the query took to execute (in seconds)
-    lock_time         Amount of time the query was locked (in seconds)
-    is_command        The flag, which determines, whether the sql_text is a
-                      query or an administrator command (these are treated
-                      differently by the old logging routines)
-    sql_text          the very text of the query or administrator command
-                      processed
-    sql_text_len      the length of sql_text string
-
-  DESCRIPTION
-
-   Log a query to the slow log table
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool Log_to_csv_event_handler::
-  log_slow(THD *thd, time_t current_time, time_t query_start_arg,
-           const char *user_host, uint user_host_len,
-           longlong query_time, longlong lock_time, bool is_command,
-           const char *sql_text, uint sql_text_len)
-{
-  /* table variables */
-  TABLE *table= slow_log.table;
-  CHARSET_INFO *client_cs= thd->variables.character_set_client;
-
-  DBUG_ENTER("log_slow");
-
-  /* below should never happen */
-  if (unlikely(!logger.is_log_tables_initialized))
-    return FALSE;
-
-  /*
-     Set start time for CURRENT_TIMESTAMP to the start of the query.
-     This will be default value for the field[0]
-  */
-  slow_log_thd->start_time= query_start_arg;
-  restore_record(table, s->default_values);    // Get empty record
-
-  /*
-    We do not set a value for table->field[0], as it will use
-    default value.
-  */
-
-  if (!table->field[1] || !table->field[2] || !table->field[3] ||
-      !table->field[4] || !table->field[5] || !table->field[6] ||
-      !table->field[7] || !table->field[8] || !table->field[9] ||
-      !table->field[10])
-    goto err;
-
-  /* store the value */
-  if (table->field[1]->store(user_host, user_host_len, client_cs))
-    goto err;
-
-  if (query_start_arg)
-  {
-    /* fill in query_time field */
-    if (table->field[2]->store(query_time, TRUE))
-      goto err;
-    /* lock_time */
-    if (table->field[3]->store(lock_time, TRUE))
-      goto err;
-    /* rows_sent */
-    if (table->field[4]->store((longlong) thd->sent_row_count, TRUE))
-      goto err;
-    /* rows_examined */
-    if (table->field[5]->store((longlong) thd->examined_row_count, TRUE))
-      goto err;
-  }
-  else
-  {
-    table->field[2]->set_null();
-    table->field[3]->set_null();
-    table->field[4]->set_null();
-    table->field[5]->set_null();
-  }
-
-  /* fill database field */
-  if (thd->db)
-  {
-    if (table->field[6]->store(thd->db, thd->db_length, client_cs))
-      goto err;
-    table->field[6]->set_notnull();
-  }
-
-  if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
-  {
-    if (table->
-        field[7]->store((longlong)
-                        thd->first_successful_insert_id_in_prev_stmt_for_binlog,
-                        TRUE))
-      goto err;
-    table->field[7]->set_notnull();
-  }
-
-  /*
-    Set value if we do an insert on autoincrement column. Note that for
-    some engines (those for which get_auto_increment() does not leave a
-    table lock until the statement ends), this is just the first value and
-    the next ones used may not be contiguous to it.
-  */
-  if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
-  {
-    if (table->
-        field[8]->store((longlong)
-          thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(), TRUE))
-      goto err;
-    table->field[8]->set_notnull();
-  }
-
-  if (table->field[9]->store((longlong) server_id, TRUE))
-    goto err;
-  table->field[9]->set_notnull();
-
-  /* sql_text */
-  if (table->field[10]->store(sql_text,sql_text_len, client_cs))
-    goto err;
-
-  /* log table entries are not replicated at the moment */
-  tmp_disable_binlog(current_thd);
-
-  /* write the row */
-  table->file->ha_write_row(table->record[0]);
-
-  reenable_binlog(current_thd);
-
-  DBUG_RETURN(0);
-err:
-  DBUG_RETURN(1);
-}
-
-bool Log_to_csv_event_handler::
-  log_error(enum loglevel level, const char *format, va_list args)
-{
-  /* No log table is implemented */
-  DBUG_ASSERT(0);
-  return FALSE;
-}
-
-bool Log_to_file_event_handler::
-  log_error(enum loglevel level, const char *format,
-            va_list args)
-{
-  return vprint_msg_to_log(level, format, args);
-}
-
-void Log_to_file_event_handler::init_pthread_objects()
-{
-  mysql_log.init_pthread_objects();
-  mysql_slow_log.init_pthread_objects();
-}
-
-
-/* Wrapper around MYSQL_LOG::write() for slow log */
-
-bool Log_to_file_event_handler::
-  log_slow(THD *thd, time_t current_time, time_t query_start_arg,
-           const char *user_host, uint user_host_len,
-           longlong query_time, longlong lock_time, bool is_command,
-           const char *sql_text, uint sql_text_len)
-{
-  return mysql_slow_log.write(thd, current_time, query_start_arg,
-                              user_host, user_host_len,
-                              query_time, lock_time, is_command,
-                              sql_text, sql_text_len);
-}
-
-
-/*
-   Wrapper around MYSQL_LOG::write() for general log. We need it since we
-   want all log event handlers to have the same signature.
-*/
-
-bool Log_to_file_event_handler::
-  log_general(time_t event_time, const char *user_host,
-              uint user_host_len, int thread_id,
-              const char *command_type, uint command_type_len,
-              const char *sql_text, uint sql_text_len,
-              CHARSET_INFO *client_cs)
-{
-  return mysql_log.write(event_time, user_host, user_host_len,
-                         thread_id, command_type, command_type_len,
-                         sql_text, sql_text_len);
-}
-
-
-bool Log_to_file_event_handler::init()
-{
-  if (!is_initialized)
-  {
-    if (opt_slow_log)
-      mysql_slow_log.open_slow_log(sys_var_slow_log_path.value);
-
-    if (opt_log)
-      mysql_log.open_query_log(sys_var_general_log_path.value);
-
-    is_initialized= TRUE;
-  }
-
-  return FALSE;
-}
-
-
-void Log_to_file_event_handler::cleanup()
-{
-  mysql_log.cleanup();
-  mysql_slow_log.cleanup();
-}
-
-void Log_to_file_event_handler::flush()
-{
-  /* reopen log files */
-  if (opt_log)
-    mysql_log.reopen_file();
-  if (opt_slow_log)
-    mysql_slow_log.reopen_file();
-}
-
-/*
-  Log error with all enabled log event handlers
-
-  SYNOPSIS
-    error_log_print()
-
-    level             The level of the error significance: NOTE,
-                      WARNING or ERROR.
-    format            format string for the error message
-    args              list of arguments for the format string
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool LOGGER::error_log_print(enum loglevel level, const char *format,
-                             va_list args)
-{
-  bool error= FALSE;
-  Log_event_handler **current_handler= error_log_handler_list;
-
-  /* currently we don't need locking here as there is no error_log table */
-  while (*current_handler)
-    error= (*current_handler++)->log_error(level, format, args) || error;
-
-  return error;
-}
-
-
-void LOGGER::cleanup_base()
-{
-  DBUG_ASSERT(inited == 1);
-  (void) pthread_mutex_destroy(&LOCK_logger);
-  if (table_log_handler)
-  {
-    table_log_handler->cleanup();
-    delete table_log_handler;
-  }
-  if (file_log_handler)
-    file_log_handler->cleanup();
-}
-
-
-void LOGGER::cleanup_end()
-{
-  DBUG_ASSERT(inited == 1);
-  if (file_log_handler)
-    delete file_log_handler;
-}
-
-
-void LOGGER::close_log_table(uint log_table_type, bool lock_in_use)
-{
-  table_log_handler->close_log_table(log_table_type, lock_in_use);
-}
-
-
-/*
-  Perform basic log initialization: create file-based log handler and
-  init error log.
-*/
-void LOGGER::init_base()
-{
-  DBUG_ASSERT(inited == 0);
-  inited= 1;
-
-  /*
-    Here we create file log handler. We don't do it for the table log handler
-    here as it cannot be created so early. The reason is THD initialization,
-    which depends on the system variables (parsed later).
-  */
-  if (!file_log_handler)
-    file_log_handler= new Log_to_file_event_handler;
-
-  /* by default we use traditional error log */
-  init_error_log(LOG_FILE);
-
-  file_log_handler->init_pthread_objects();
-  (void) pthread_mutex_init(&LOCK_logger, MY_MUTEX_INIT_SLOW);
-}
-
-
-void LOGGER::init_log_tables()
-{
-  if (!table_log_handler)
-    table_log_handler= new Log_to_csv_event_handler;
-
-  if (!is_log_tables_initialized &&
-      !table_log_handler->init() && !file_log_handler->init())
-    is_log_tables_initialized= TRUE;
-}
-
-
-bool LOGGER::reopen_log_table(uint log_table_type)
-{
-  return table_log_handler->reopen_log_table(log_table_type);
-}
-
-bool LOGGER::reopen_log_tables()
-{
-    /*
-      we use | and not || here, to ensure that both reopen_log_table
-      are called, even if the first one fails
-    */
-    if ((opt_slow_log && logger.reopen_log_table(QUERY_LOG_SLOW)) |
-        (opt_log && logger.reopen_log_table(QUERY_LOG_GENERAL)))
-      return TRUE;
-    return FALSE;
-}
-
-
-void LOGGER::tmp_close_log_tables(THD *thd)
-{
-  table_log_handler->tmp_close_log_tables(thd);
-}
-
-bool LOGGER::flush_logs(THD *thd)
-{
-  int rc= 0;
-
-  /*
-    Now we lock logger, as nobody should be able to use logging routines while
-    log tables are closed
-  */
-  logger.lock();
-  if (logger.is_log_tables_initialized)
-    table_log_handler->tmp_close_log_tables(thd); // the locking happens here
-
-  /* reopen log files */
-  file_log_handler->flush();
-
-  /* reopen tables in the case they were enabled */
-  if (logger.is_log_tables_initialized)
-  {
-    if (reopen_log_tables())
-      rc= TRUE;
-  }
-  /* end of log flush */
-  logger.unlock();
-  return rc;
-}
-
-
-/*
-  Log slow query with all enabled log event handlers
-
-  SYNOPSIS
-    slow_log_print()
-
-    thd               THD of the query being logged
-    query             The query being logged
-    query_length      The length of the query string
-    query_start_arg   Query start timestamp
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
-                            time_t query_start_arg)
-{
-  bool error= FALSE;
-  Log_event_handler **current_handler= slow_log_handler_list;
-  bool is_command= FALSE;
-  char user_host_buff[MAX_USER_HOST_SIZE];
-
-  my_time_t current_time;
-  Security_context *sctx= thd->security_ctx;
-  uint user_host_len= 0;
-  longlong query_time= 0, lock_time= 0;
-
-  /*
-    Print the message to the buffer if we have slow log enabled
-  */
-
-  if (*slow_log_handler_list)
-  {
-    current_time= time(NULL);
-
-    /* do not log slow queries from replication threads */
-    if (thd->slave_thread)
-      return 0;
-
-    lock();
-    if (!opt_slow_log)
-    {
-      unlock();
-      return 0;
-    }
-
-    /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
-    user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
-                            sctx->priv_user ? sctx->priv_user : "", "[",
-                            sctx->user ? sctx->user : "", "] @ ",
-                            sctx->host ? sctx->host : "", " [",
-                            sctx->ip ? sctx->ip : "", "]", NullS) -
-      user_host_buff;
-
-    if (query_start_arg)
-    {
-      query_time= (longlong) (current_time - query_start_arg);
-      lock_time= (longlong) (thd->time_after_lock - query_start_arg);
-    }
-
-    if (!query)
-    {
-      is_command= TRUE;
-      query= command_name[thd->command].str;
-      query_length= command_name[thd->command].length;
-    }
-
-    while (*current_handler)
-      error= (*current_handler++)->log_slow(thd, current_time, query_start_arg,
-                                            user_host_buff, user_host_len,
-                                            query_time, lock_time, is_command,
-                                            query, query_length) || error;
-
-    unlock();
-  }
-  return error;
-}
-
-bool LOGGER::general_log_print(THD *thd, enum enum_server_command command,
-                               const char *format, va_list args)
-{
-  bool error= FALSE;
-  Log_event_handler **current_handler= general_log_handler_list;
-
-  /*
-    Print the message to the buffer if we have at least one log event handler
-    enabled and want to log this king of commands
-  */
-  if (*general_log_handler_list && (what_to_log & (1L << (uint)
command)))
-  {
-    char message_buff[MAX_LOG_BUFFER_SIZE];
-    char user_host_buff[MAX_USER_HOST_SIZE];
-    Security_context *sctx= thd->security_ctx;
-    ulong id;
-    uint message_buff_len= 0, user_host_len= 0;
-
-    if (thd)
-    {                                           /* Normal thread */
-      if ((thd->options & OPTION_LOG_OFF)
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-          && (sctx->master_access & SUPER_ACL)
-#endif
-         )
-      {
-        return 0;                         /* No logging */
-      }
-      id= thd->thread_id;
-    }
-    else
-      id=0;                                     /* Log from connect handler */
-
-    lock();
-    if (!opt_log)
-    {
-      unlock();
-      return 0;
-    }
-    time_t current_time= time(NULL);
-
-    user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
-                            sctx->priv_user ? sctx->priv_user : "", "[",
-                            sctx->user ? sctx->user : "", "] @ ",
-                            sctx->host ? sctx->host : "", " [",
-                            sctx->ip ? sctx->ip : "", "]", NullS) -
-                                                            user_host_buff;
-
-    /* prepare message */
-    if (format)
-      message_buff_len= my_vsnprintf(message_buff,
-                   sizeof(message_buff), format, args);
-    else
-      message_buff[0]= '\0';
-
-    while (*current_handler)
-      error+= (*current_handler++)->
-        log_general(current_time, user_host_buff,
-                   user_host_len, id,
-                   command_name[(uint) command].str,
-                   command_name[(uint) command].length,
-                   message_buff, message_buff_len,
-                   thd->variables.character_set_client) || error;
-    unlock();
-  }
-  return error;
-}
-
-void LOGGER::init_error_log(uint error_log_printer)
-{
-  if (error_log_printer & LOG_NONE)
-  {
-    error_log_handler_list[0]= 0;
-    return;
-  }
-
-  switch (error_log_printer) {
-  case LOG_FILE:
-    error_log_handler_list[0]= file_log_handler;
-    error_log_handler_list[1]= 0;
-    break;
-    /* these two are disabled for now */
-  case LOG_TABLE:
-    DBUG_ASSERT(0);
-    break;
-  case LOG_TABLE|LOG_FILE:
-    DBUG_ASSERT(0);
-    break;
-  }
-}
-
-void LOGGER::init_slow_log(uint slow_log_printer)
-{
-  if (slow_log_printer & LOG_NONE)
-  {
-    slow_log_handler_list[0]= 0;
-    return;
-  }
-
-  switch (slow_log_printer) {
-  case LOG_FILE:
-    slow_log_handler_list[0]= file_log_handler;
-    slow_log_handler_list[1]= 0;
-    break;
-  case LOG_TABLE:
-    slow_log_handler_list[0]= table_log_handler;
-    slow_log_handler_list[1]= 0;
-    break;
-  case LOG_TABLE|LOG_FILE:
-    slow_log_handler_list[0]= file_log_handler;
-    slow_log_handler_list[1]= table_log_handler;
-    slow_log_handler_list[2]= 0;
-    break;
-  }
-}
-
-void LOGGER::init_general_log(uint general_log_printer)
-{
-  if (general_log_printer & LOG_NONE)
-  {
-    general_log_handler_list[0]= 0;
-    return;
-  }
-
-  switch (general_log_printer) {
-  case LOG_FILE:
-    general_log_handler_list[0]= file_log_handler;
-    general_log_handler_list[1]= 0;
-    break;
-  case LOG_TABLE:
-    general_log_handler_list[0]= table_log_handler;
-    general_log_handler_list[1]= 0;
-    break;
-  case LOG_TABLE|LOG_FILE:
-    general_log_handler_list[0]= file_log_handler;
-    general_log_handler_list[1]= table_log_handler;
-    general_log_handler_list[2]= 0;
-    break;
-  }
-}
-
-
-bool LOGGER::activate_log_handler(THD* thd, uint log_type)
-{
-  bool res= 0;
-  lock();
-  switch (log_type) {
-  case QUERY_LOG_SLOW:
-    if (!opt_slow_log)
-    {
-      if ((res= reopen_log_table(log_type)))
-        goto err;
-      file_log_handler->get_mysql_slow_log()->
-        open_slow_log(sys_var_slow_log_path.value);
-      init_slow_log(log_output_options);
-      opt_slow_log= TRUE;
-    }
-    break;
-  case QUERY_LOG_GENERAL:
-    if (!opt_log)
-    {
-      if ((res= reopen_log_table(log_type)))
-        goto err;
-      file_log_handler->get_mysql_log()->
-        open_query_log(sys_var_general_log_path.value);
-      init_general_log(log_output_options);
-      opt_log= TRUE;
-    }
-    break;
-  default:
-    DBUG_ASSERT(0);
-  }
-err:
-  unlock();
-  return res;
-}
-
-
-void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
-{
-  TABLE_LIST *table_list;
-  my_bool *tmp_opt= 0;
-  MYSQL_LOG *file_log;
-  THD *log_thd;
-
-  switch (log_type) {
-  case QUERY_LOG_SLOW:
-    table_list= &table_log_handler->slow_log;
-    tmp_opt= &opt_slow_log;
-    file_log= file_log_handler->get_mysql_slow_log();
-    log_thd= table_log_handler->slow_log_thd;
-    break;
-  case QUERY_LOG_GENERAL:
-    table_list= &table_log_handler->general_log;
-    tmp_opt= &opt_log;
-    file_log= file_log_handler->get_mysql_log();
-    log_thd= table_log_handler->general_log_thd;
-    break;
-  default:
-    assert(0);                                  // Impossible
-  }
-
-  if (!(*tmp_opt))
-    return;
-
-  if (is_log_tables_initialized)
-    lock_and_wait_for_table_name(log_thd, table_list);
-  lock();
-
-  if (is_log_tables_initialized)
-  {
-    VOID(pthread_mutex_lock(&LOCK_open));
-    close_log_table(log_type, TRUE);
-    table_list->table= 0;
-    query_cache_invalidate3(log_thd, table_list, 0);
-    unlock_table_name(log_thd, table_list);
-    VOID(pthread_mutex_unlock(&LOCK_open));
-  }
-  file_log->close(0);
-  *tmp_opt= FALSE;
-  unlock();
-}
-
-
-/*
-  Close log tables temporarily. The thread which closed
-  them this way can lock them in any mode it needs.
-  NOTE: one should call logger.lock() before entering this
-  function.
-*/
-void Log_to_csv_event_handler::tmp_close_log_tables(THD *thd)
-{
-  TABLE_LIST close_slow_log, close_general_log;
-
-  /* fill lists, we will need to perform operations on tables */
-  bzero((char*) &close_slow_log, sizeof(TABLE_LIST));
-  close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log";
-  close_slow_log.table_name_length= 8;
-  close_slow_log.db= (char*) "mysql";
-  close_slow_log.db_length= 5;
-
-  bzero((char*) &close_general_log, sizeof(TABLE_LIST));
-  close_general_log.alias= close_general_log.table_name=(char*) "general_log";
-  close_general_log.table_name_length= 11;
-  close_general_log.db= (char*) "mysql";
-  close_general_log.db_length= 5;
-
-  privileged_thread= thd;
-
-  VOID(pthread_mutex_lock(&LOCK_open));
-  /*
-    NOTE: in fact, the first parameter used in query_cache_invalidate3()
-    could be any non-NULL THD, as the underlying code makes certain
-    assumptions about this.
-    Here we use one of the logger handler THD's. Simply because it
-    seems appropriate.
-  */
-  if (opt_log)
-  {
-    close_log_table(QUERY_LOG_GENERAL, TRUE);
-    query_cache_invalidate3(general_log_thd, &close_general_log, 0);
-  }
-  if (opt_slow_log)
-  {
-    close_log_table(QUERY_LOG_SLOW, TRUE);
-    query_cache_invalidate3(general_log_thd, &close_slow_log, 0);
-  }
-  VOID(pthread_mutex_unlock(&LOCK_open));
-}
-
-/* the parameters are unused for the log tables */
-bool Log_to_csv_event_handler::init()
-{
-  /*
-    we use | and not || here, to ensure that both open_log_table
-    are called, even if the first one fails
-  */
-  if ((opt_log && open_log_table(QUERY_LOG_GENERAL)) |
-      (opt_slow_log && open_log_table(QUERY_LOG_SLOW)))
-    return 1;
-  return 0;
-}
-
-int LOGGER::set_handlers(uint error_log_printer,
-                         uint slow_log_printer,
-                         uint general_log_printer)
-{
-  /* error log table is not supported yet */
-  DBUG_ASSERT(error_log_printer < LOG_TABLE);
-
-  lock();
-
-  if ((slow_log_printer & LOG_TABLE || general_log_printer & LOG_TABLE)
&&
-      !is_log_tables_initialized)
-  {
-    slow_log_printer= (slow_log_printer & ~LOG_TABLE) | LOG_FILE;
-    general_log_printer= (general_log_printer & ~LOG_TABLE) | LOG_FILE;
-
-    sql_print_error("Failed to initialize log tables. "
-                    "Falling back to the old-fashioned logs");
-  }
-
-  init_error_log(error_log_printer);
-  init_slow_log(slow_log_printer);
-  init_general_log(general_log_printer);
-
-  unlock();
-
-  return 0;
-}
-
-
-/*
-  Close log table of a given type (general or slow log)
-
-  SYNOPSIS
-    close_log_table()
-
-    log_table_type   type of the log table to close: QUERY_LOG_GENERAL
-                     or QUERY_LOG_SLOW
-    lock_in_use      Set to TRUE if the caller owns LOCK_open. FALSE otherwise.
-
-  DESCRIPTION
-
-    The function closes a log table. It is invoked (1) when we need to reopen
-    log tables (e.g. FLUSH LOGS or TRUNCATE on the log table is being
-    executed) or (2) during shutdown.
-*/
-
-void Log_to_csv_event_handler::
-  close_log_table(uint log_table_type, bool lock_in_use)
-{
-  THD *log_thd, *curr= current_thd;
-  TABLE_LIST *table;
-
-  if (!logger.is_log_table_enabled(log_table_type))
-    return;                                     /* do nothing */
-
-  switch (log_table_type) {
-  case QUERY_LOG_GENERAL:
-    log_thd= general_log_thd;
-    table= &general_log;
-    break;
-  case QUERY_LOG_SLOW:
-    log_thd= slow_log_thd;
-    table= &slow_log;
-    break;
-  default:
-    assert(0);                                  // Impossible
-  }
-
-  /*
-    Set thread stack start for the logger thread. See comment in
-    open_log_table() for details.
-  */
-  if (curr)
-    log_thd->thread_stack= curr->thread_stack;
-  else
-    log_thd->thread_stack= (char*) &log_thd;
-
-  /* close the table */
-  log_thd->store_globals();
-  table->table->file->ha_rnd_end();
-  /* discard logger mark before unlock*/
-  table->table->locked_by_logger= FALSE;
-  close_thread_tables(log_thd, lock_in_use);
-
-  if (curr)
-    curr->store_globals();
-  else
-  {
-    my_pthread_setspecific_ptr(THR_THD,  0);
-    my_pthread_setspecific_ptr(THR_MALLOC, 0);
-  }
-}
-
-
  /*
   Save position of binary log transaction cache.
 
@@ -3849,33 +2690,6 @@
 }
 
 
-int error_log_print(enum loglevel level, const char *format,
-                    va_list args)
-{
-  return logger.error_log_print(level, format, args);
-}
-
-
-bool slow_log_print(THD *thd, const char *query, uint query_length,
-                    time_t query_start_arg)
-{
-  return logger.slow_log_print(thd, query, query_length, query_start_arg);
-}
-
-
-bool general_log_print(THD *thd, enum enum_server_command command,
-                       const char *format, ...)
-{
-  va_list args;
-  uint error= 0;
-
-  va_start(args, format);
-  error= logger.general_log_print(thd, command, format, args);
-  va_end(args);
-
-  return error;
-}
-
 void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
 {
   if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
@@ -4223,236 +3037,10 @@
 } /* test_if_number */
 
 
-void print_buffer_to_file(enum loglevel level, const char *buffer)
-{
-  time_t skr;
-  struct tm tm_tmp;
-  struct tm *start;
-  DBUG_ENTER("print_buffer_to_file");
-  DBUG_PRINT("enter",("buffer: %s", buffer));
-
-  VOID(pthread_mutex_lock(&LOCK_error_log));
-
-  skr=time(NULL);
-  localtime_r(&skr, &tm_tmp);
-  start=&tm_tmp;
-
-  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
-          start->tm_year % 100,
-          start->tm_mon+1,
-          start->tm_mday,
-          start->tm_hour,
-          start->tm_min,
-          start->tm_sec,
-          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
-           "Warning" : "Note"),
-          buffer);
-
-  fflush(stderr);
-
-  VOID(pthread_mutex_unlock(&LOCK_error_log));
-  DBUG_VOID_RETURN;
-}
-
-
-void sql_perror(const char *message)
-{
-#ifdef HAVE_STRERROR
-  sql_print_error("%s: %s",message, strerror(errno));
-#else
-  perror(message);
-#endif
-}
-
-
-bool flush_error_log()
-{
-  bool result=0;
-  if (opt_error_log)
-  {
-    char err_renamed[FN_REFLEN], *end;
-    end= strmake(err_renamed,log_error_file,FN_REFLEN-4);
-    strmov(end, "-old");
-    VOID(pthread_mutex_lock(&LOCK_error_log));
-#ifdef __WIN__
-    char err_temp[FN_REFLEN+4];
-    /*
-     On Windows is necessary a temporary file for to rename
-     the current error file.
-    */
-    strxmov(err_temp, err_renamed,"-tmp",NullS);
-    (void) my_delete(err_temp, MYF(0)); 
-    if (freopen(err_temp,"a+",stdout))
-    {
-      freopen(err_temp,"a+",stderr);
-      (void) my_delete(err_renamed, MYF(0));
-      my_rename(log_error_file,err_renamed,MYF(0));
-      if (freopen(log_error_file,"a+",stdout))
-        freopen(log_error_file,"a+",stderr);
-      int fd, bytes;
-      char buf[IO_SIZE];
-      if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
-      {
-        while ((bytes = (int) my_read(fd, (byte*) buf, IO_SIZE, MYF(0))) > 0)
-             my_fwrite(stderr, (byte*) buf, bytes, MYF(0));
-        my_close(fd, MYF(0));
-      }
-      (void) my_delete(err_temp, MYF(0)); 
-    }
-    else
-     result= 1;
-#else
-   my_rename(log_error_file,err_renamed,MYF(0));
-   if (freopen(log_error_file,"a+",stdout))
-     freopen(log_error_file,"a+",stderr);
-   else
-     result= 1;
-#endif
-    VOID(pthread_mutex_unlock(&LOCK_error_log));
-  }
-   return result;
-}
-
 void MYSQL_BIN_LOG::signal_update()
 {
   DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
   pthread_cond_broadcast(&update_cond);
-  DBUG_VOID_RETURN;
-}
-
-#ifdef __NT__
-void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
-                                 uint length, int buffLen)
-{
-  HANDLE event;
-  char   *buffptr;
-  LPCSTR *buffmsgptr;
-  DBUG_ENTER("print_buffer_to_nt_eventlog");
-
-  buffptr= buff;
-  if (length > (uint)(buffLen-5))
-  {
-    char *newBuff= new char[length + 5];
-    strcpy(newBuff, buff);
-    buffptr= newBuff;
-  }
-  strmov(buffptr+length, "\r\n\r\n");
-  buffmsgptr= (LPCSTR*) &buffptr;               // Keep windows happy
-
-  setup_windows_event_source();
-  if ((event= RegisterEventSource(NULL,"MySQL")))
-  {
-    switch (level) {
-      case ERROR_LEVEL:
-        ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
-                    buffmsgptr, NULL);
-        break;
-      case WARNING_LEVEL:
-        ReportEvent(event, EVENTLOG_WARNING_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
-                    buffmsgptr, NULL);
-        break;
-      case INFORMATION_LEVEL:
-        ReportEvent(event, EVENTLOG_INFORMATION_TYPE, 0, MSG_DEFAULT, NULL, 1,
-                    0, buffmsgptr, NULL);
-        break;
-    }
-    DeregisterEventSource(event);
-  }
-
-  /* if we created a string buffer, then delete it */
-  if (buffptr != buff)
-    delete[] buffptr;
-
-  DBUG_VOID_RETURN;
-}
-#endif /* __NT__ */
-
-
-/*
-  Prints a printf style message to the error log and, under NT, to the
-  Windows event log.
-
-  SYNOPSIS
-    vprint_msg_to_log()
-    event_type             Type of event to write (Error, Warning, or Info)
-    format                 Printf style format of message
-    args                   va_list list of arguments for the message
-
-  NOTE
-
-  IMPLEMENTATION
-    This function prints the message into a buffer and then sends that buffer
-    to other functions to write that message to other logging sources.
-
-  RETURN VALUES
-    The function always returns 0. The return value is present in the
-    signature to be compatible with other logging routines, which could
-    return an error (e.g. logging to the log tables)
-*/
-
-#ifdef EMBEDDED_LIBRARY
-int vprint_msg_to_log(enum loglevel level __attribute__((unused)),
-                       const char *format __attribute__((unused)),
-                       va_list argsi __attribute__((unused)))
-{
-  DBUG_ENTER("vprint_msg_to_log");
-  DBUG_RETURN(0);
-}
-#else /*!EMBEDDED_LIBRARY*/
-int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
-{
-  char   buff[1024];
-  uint length;
-  DBUG_ENTER("vprint_msg_to_log");
-
-  /* "- 5" is because of print_buffer_to_nt_eventlog() */
-  length= my_vsnprintf(buff, sizeof(buff) - 5, format, args);
-  print_buffer_to_file(level, buff);
-
-#ifdef __NT__
-  print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
-#endif
-
-  DBUG_RETURN(0);
-}
-#endif /*EMBEDDED_LIBRARY*/
-
-
-void sql_print_error(const char *format, ...) 
-{
-  va_list args;
-  DBUG_ENTER("sql_print_error");
-
-  va_start(args, format);
-  error_log_print(ERROR_LEVEL, format, args);
-  va_end(args);
-
-  DBUG_VOID_RETURN;
-}
-
-
-void sql_print_warning(const char *format, ...) 
-{
-  va_list args;
-  DBUG_ENTER("sql_print_warning");
-
-  va_start(args, format);
-  error_log_print(WARNING_LEVEL, format, args);
-  va_end(args);
-
-  DBUG_VOID_RETURN;
-}
-
-
-void sql_print_information(const char *format, ...) 
-{
-  va_list args;
-  DBUG_ENTER("sql_print_information");
-
-  va_start(args, format);
-  error_log_print(INFORMATION_LEVEL, format, args);
-  va_end(args);
-
   DBUG_VOID_RETURN;
 }
 

--- 1.486/sql/mysql_priv.h	2007-03-12 10:52:50 -07:00
+++ 1.487/sql/mysql_priv.h	2007-03-12 10:52:50 -07:00
@@ -574,6 +574,7 @@
 #include "protocol.h"
 #include "sql_udf.h"
 #include "sql_partition.h"
+#include "sql_logger.h"
 
 class user_var_entry;
 class Security_context;
@@ -844,7 +845,7 @@
 bool do_command(THD *thd);
 bool dispatch_command(enum enum_server_command command, THD *thd,
 		      char* packet, uint packet_length);
-void log_slow_statement(THD *thd);
+void post_statement_log(THD *thd);
 bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
 bool compare_record(TABLE *table);
 bool append_file_to_dir(THD *thd, const char **filename_ptr, 
@@ -1257,7 +1258,6 @@
 void remove_db_from_cache(const char *db);
 void flush_tables();
 bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
-char *make_default_log_name(char *buff,const char* log_ext);
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 uint fast_alter_partition_table(THD *thd, TABLE *table,
@@ -1480,26 +1480,6 @@
 
 bool init_errmessage(void);
 #endif /* MYSQL_SERVER */
-void sql_perror(const char *message);
-
-
-int vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
-void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
-void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
-void sql_print_information(const char *format, ...)
-  ATTRIBUTE_FORMAT(printf, 1, 2);
-typedef void (*sql_print_message_func)(const char *format, ...)
-  ATTRIBUTE_FORMAT(printf, 1, 2);
-extern sql_print_message_func sql_print_message_handlers[];
-
-int error_log_print(enum loglevel level, const char *format,
-                    va_list args);
-
-bool slow_log_print(THD *thd, const char *query, uint query_length,
-                    time_t query_start_arg);
-
-bool general_log_print(THD *thd, enum enum_server_command command,
-                       const char *format,...);
 
 bool fn_format_relative_to_data_home(my_string to, const char *name,
 				     const char *dir, const char *extension);
@@ -1640,8 +1620,6 @@
 extern const char *log_output_str;
 
 extern MYSQL_BIN_LOG mysql_bin_log;
-extern LOGGER logger;
-extern TABLE_LIST general_log, slow_log;
 extern FILE *bootstrap_file;
 extern int bootstrap_error;
 extern FILE *stderror_file;
@@ -1899,9 +1877,6 @@
 		     LEX_STRING component);
 int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
                         LEX_STRING &name, user_var_entry **out_entry);
-/* log.cc */
-bool flush_error_log(void);
-
 /* sql_list.cc */
 void free_list(I_List <i_string_pair> *list);
 void free_list(I_List <i_string> *list);

--- 1.622/sql/mysqld.cc	2007-03-12 10:52:50 -07:00
+++ 1.623/sql/mysqld.cc	2007-03-12 10:52:50 -07:00
@@ -1167,6 +1167,7 @@
   DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
   wait_for_signal_thread_to_end();
   clean_up_mutexes();
+  logger_cache_done();
   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
   exit(exit_code); /* purecov: inspected */
 }
@@ -1179,8 +1180,6 @@
   if (cleanup_done++)
     return; /* purecov: inspected */
 
-  logger.cleanup_base();
-
   /*
     make sure that handlers finish up
     what they have that is dependent on the binlog
@@ -1235,8 +1234,6 @@
     free_defaults(defaults_argv);
   my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
-  my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
-  my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
   free_tmpdir(&mysql_tmpdir_list);
 #ifdef HAVE_REPLICATION
   my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
@@ -1270,7 +1267,6 @@
           MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
   DBUG_PRINT("quit", ("Error messages freed"));
   /* Tell main we are ready */
-  logger.cleanup_end();
   (void) pthread_mutex_lock(&LOCK_thread_count);
   DBUG_PRINT("quit", ("got thread count lock"));
   ready_to_exit=1;
@@ -2476,9 +2472,6 @@
 #ifdef EXTRA_DEBUG
       sql_print_information("Got signal %d to shutdown mysqld",sig);
 #endif
-      /* switch to the old log message processing */
-      logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
-                          opt_log ? LOG_FILE:LOG_NONE);
       DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
       if (!abort_loop)
       {
@@ -2506,9 +2499,6 @@
 			      REFRESH_THREADS | REFRESH_HOSTS),
 			     (TABLE_LIST*) 0, &not_used); // Flush logs
       }
-      /* reenable logs after the options were reloaded */
-      logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_TABLE:LOG_NONE,
-                          opt_log ? LOG_TABLE:LOG_NONE);
       break;
 #ifdef USE_ONE_SIGNAL_HAND
     case THR_SERVER_ALARM:
@@ -2693,7 +2683,6 @@
 static int init_common_variables(const char *conf_file_name, int argc,
 				 char **argv, const char **groups)
 {
-  char buff[FN_REFLEN];
   umask(((~my_umask) & 0666));
   my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
   tzset();			// Set tzname
@@ -2884,29 +2873,6 @@
   else
     sys_init_slave.value=my_strdup("",MYF(0));
 
-  /* check log options and issue warnings if needed */
-  if (opt_log && opt_logname && !(log_output_options & LOG_FILE)
&&
-      !(log_output_options & LOG_NONE))
-    sql_print_warning("Although a path was specified for the "
-                      "--log option, log tables are used. "
-                      "To enable logging to files use the --log-output option.");
-
-  if (opt_slow_log && opt_slow_logname && !(log_output_options &
LOG_FILE)
-      && !(log_output_options & LOG_NONE))
-    sql_print_warning("Although a path was specified for the "
-                      "--log-slow-queries option, log tables are used. "
-                      "To enable logging to files use the --log-output option.");
-
-  if (!opt_logname)
-    opt_logname= make_default_log_name(buff, ".log");
-  sys_var_general_log_path.value= my_strdup(opt_logname, MYF(0));
-  sys_var_general_log_path.value_length= strlen(opt_logname);
-
-  if (!opt_slow_logname)
-    opt_slow_logname= make_default_log_name(buff, "-slow.log");
-  sys_var_slow_log_path.value= my_strdup(opt_slow_logname, MYF(0));
-  sys_var_slow_log_path.value_length= strlen(opt_slow_logname);
-
   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
     return 1;
   if (my_database_names_init())
@@ -3332,44 +3298,6 @@
     unireg_abort(1);
   }
 
-#ifdef WITH_CSV_STORAGE_ENGINE
-  if (opt_bootstrap)
-    log_output_options= LOG_FILE;
-  else
-    logger.init_log_tables();
-
-  if (log_output_options & LOG_NONE)
-  {
-    /*
-      Issue a warining if there were specified additional options to the
-      log-output along with NONE. Probably this wasn't what user wanted.
-    */
-    if ((log_output_options & LOG_NONE) && (log_output_options &
~LOG_NONE))
-      sql_print_warning("There were other values specified to "
-                        "log-output besides NONE. Disabling slow "
-                        "and general logs anyway.");
-    logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
-  }
-  else
-  {
-    /* fall back to the log files if tables are not present */
-    if (have_csv_db == SHOW_OPTION_NO)
-    {
-      /* purecov: begin inspected */
-      sql_print_error("CSV engine is not present, falling back to the "
-                      "log files");
-      log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
-      /* purecov: end */
-    }
-
-    logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
-                        opt_log ? log_output_options:LOG_NONE);
-  }
-#else
-  logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
-                      opt_log ? LOG_FILE:LOG_NONE);
-#endif
-
   /*
     Check that the default storage engine is actually available.
   */
@@ -3574,12 +3502,6 @@
   MY_INIT(argv[0]);		// init my_sys library & pthreads
   /* nothing should come before this line ^^^ */
 
-  /*
-    Perform basic logger initialization logger. Should be called after
-    MY_INIT, as it initializes mutexes. Log tables are inited later.
-  */
-  logger.init_base();
-
 #ifdef _CUSTOMSTARTUPCONFIG_
   if (_cust_check_startup())
   {
@@ -3588,6 +3510,9 @@
   }
 #endif
 
+  /* Initialize error messaging */
+  logger_cache_init();
+
 #ifdef	__WIN__
   /*
     Before performing any socket operation (like retrieving hostname
@@ -3857,6 +3782,7 @@
   clean_up(1);
   wait_for_signal_thread_to_end();
   clean_up_mutexes();
+  logger_cache_done();
   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
 
   exit(0);
@@ -7879,7 +7805,7 @@
 {
   va_list args;
   va_start(args, format);
-  vprint_msg_to_log(level, format, args);
+  intern_error_log(NULL, 0, level, format, args);
   va_end(args);
 }
 

--- 1.378/sql/sql_base.cc	2007-03-12 10:52:50 -07:00
+++ 1.379/sql/sql_base.cc	2007-03-12 10:52:50 -07:00
@@ -845,7 +845,7 @@
     bool found=0;
     for (TABLE_LIST *table= tables; table; table= table->next_local)
     {
-      if ((!table->table || !table->table->s->log_table) &&
+      if (!table->table &&
           remove_table_from_cache(thd, table->db, table->table_name,
                                   RTFC_OWNED_BY_THD_FLAG))
 	found=1;
@@ -880,8 +880,7 @@
       for (uint idx=0 ; idx < open_cache.records ; idx++)
       {
 	TABLE *table=(TABLE*) hash_element(&open_cache,idx);
-	if (!table->s->log_table &&
-            ((table->s->version) < refresh_version &&
table->db_stat))
+	if ((table->s->version) < refresh_version && table->db_stat)
 	{
 	  found=1;
           DBUG_PRINT("signal", ("Waiting for COND_refresh"));
@@ -2015,7 +2014,7 @@
       Here we flush tables marked for flush. However we never flush log
       tables here. They are flushed only on FLUSH LOGS.
     */
-    if (table->s->version != refresh_version && !table->s->log_table)
+    if (table->s->version != refresh_version)
     {
       DBUG_PRINT("note",
                  ("Found table '%s.%s' with different refresh version",
@@ -2373,7 +2372,7 @@
       Reopen marked for flush. But close log tables. They are flushed only
       explicitly on FLUSH LOGS
     */
-    if (table->s->version != refresh_version && !table->s->log_table)
+    if (table->s->version != refresh_version)
     {
       found=1;
       if (table->db_stat)
@@ -2420,10 +2419,10 @@
          search= (TABLE*) hash_next(&open_cache, (byte*) key,
                                     key_length, &state))
     {
-      DBUG_PRINT("info", ("share: 0x%lx  locked_by_logger: %d "
+      DBUG_PRINT("info", ("share: 0x%lx  "
                           "locked_by_flush: %d  locked_by_name: %d "
                           "db_stat: %u  version: %lu",
-                          (ulong) search->s, search->locked_by_logger,
+                          (ulong) search->s,
                           search->locked_by_flush, search->locked_by_name,
                           search->db_stat,
                           search->s->version));
@@ -2438,8 +2437,7 @@
         However we fo not wait if we encountered a table, locked by the logger.
         Log tables are managed separately by logging routines.
       */
-      if (!search->locked_by_logger &&
-          (search->locked_by_name && wait_for_name_lock ||
+      if ((search->locked_by_name && wait_for_name_lock ||
            search->locked_by_flush ||
            (search->db_stat && search->s->version <
refresh_version)))
         DBUG_RETURN(1);

--- 1.315/sql/sql_class.cc	2007-03-12 10:52:50 -07:00
+++ 1.316/sql/sql_class.cc	2007-03-12 10:52:50 -07:00
@@ -220,6 +220,7 @@
   thread_stack= 0;
   db= 0;
   catalog= (char*)"std"; // the only catalog we have for now
+  bzero(&logger_cache, sizeof(logger_cache));
   main_security_ctx.init();
   security_ctx= &main_security_ctx;
   locked=some_tables_deleted=no_errors=password= 0;
@@ -465,6 +466,8 @@
     cleanup();
 
   ha_close_connection(this);
+
+  logger_cache_release(this);
 
   DBUG_PRINT("info", ("freeing security context"));
   main_security_ctx.destroy();

--- 1.340/sql/sql_class.h	2007-03-12 10:52:51 -07:00
+++ 1.341/sql/sql_class.h	2007-03-12 10:52:51 -07:00
@@ -865,6 +865,7 @@
   struct  system_variables variables;	// Changeable local variables
   struct  system_status_var status_var; // Per thread statistic vars
   struct  system_status_var *initial_status_var; /* used by show status */
+  struct  logger_cache logger_cache;	// used for error log plugins
   THR_LOCK_INFO lock_info;              // Locking info of this thread
   THR_LOCK_OWNER main_lock_id;          // To use for conventional queries
   THR_LOCK_OWNER *lock_id;              // If not main_lock_id, points to

--- 1.209/sql/sql_delete.cc	2007-03-12 10:52:51 -07:00
+++ 1.210/sql/sql_delete.cc	2007-03-12 10:52:51 -07:00
@@ -865,9 +865,7 @@
   char path[FN_REFLEN];
   TABLE *table;
   bool error;
-  uint closed_log_tables= 0, lock_logger= 0;
   uint path_length;
-  uint log_type;
   DBUG_ENTER("mysql_truncate");
 
   bzero((char*) &create_info,sizeof(create_info));
@@ -919,18 +917,6 @@
       DBUG_RETURN(TRUE);
   }
 
-  log_type= check_if_log_table(table_list->db_length, table_list->db,
-                               table_list->table_name_length,
-                               table_list->table_name, 1);
-  /* close log tables in use */
-  if (log_type)
-  {
-    lock_logger= 1;
-    logger.lock();
-    logger.close_log_table(log_type, FALSE);
-    closed_log_tables= closed_log_tables | log_type;
-  }
-
   // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
   // crashes, replacement works.  *(path + path_length - reg_ext_length)=
   // '\0';
@@ -961,14 +947,6 @@
     VOID(pthread_mutex_lock(&LOCK_open));
     unlock_table_name(thd, table_list);
     VOID(pthread_mutex_unlock(&LOCK_open));
-
-    if (opt_slow_log && (closed_log_tables & QUERY_LOG_SLOW))
-      logger.reopen_log_table(QUERY_LOG_SLOW);
-
-    if (opt_log && (closed_log_tables & QUERY_LOG_GENERAL))
-      logger.reopen_log_table(QUERY_LOG_GENERAL);
-    if (lock_logger)
-      logger.unlock();
   }
   else if (error)
   {

--- 1.629/sql/sql_parse.cc	2007-03-12 10:52:51 -07:00
+++ 1.630/sql/sql_parse.cc	2007-03-12 10:52:51 -07:00
@@ -607,6 +607,9 @@
 
   thd->clear_error();				// Clear error message
 
+  /* release cache of logger plugins if neccessary before blocking */
+  logger_cache_check(thd);
+
   net_new_transaction(net);
   if ((packet_length=my_net_read(net)) == packet_error)
   {
@@ -637,6 +640,9 @@
   /* Restore read timeout value */
   net_set_read_timeout(net, thd->variables.net_read_timeout);
 
+  /* prepare cache of logger plugins to minimize mutex locking */
+  logger_cache_prepare(thd);
+
   /*
     packet_length contains length of data, as it was stored in packet
     header. In case of malformed header, packet_length can be zero.
@@ -891,7 +897,7 @@
         close_thread_tables(thd);
       ulong length= (ulong)(packet_end - next_packet);
 
-      log_slow_statement(thd);
+      post_statement_log(thd);
 
       /* Remove garbage at start of query */
       while (my_isspace(thd->charset(), *next_packet) && length > 0)
@@ -1250,7 +1256,7 @@
   if (thd->net.report_error)
     net_send_error(thd);
 
-  log_slow_statement(thd);
+  post_statement_log(thd);
 
   thd->proc_info="cleaning up";
   VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
@@ -1266,10 +1272,11 @@
 }
 
 
-void log_slow_statement(THD *thd)
+void post_statement_log(THD *thd)
 {
   time_t start_of_query;
-  DBUG_ENTER("log_slow_statement");
+  ulong long_query_count;
+  DBUG_ENTER("post_statement_log");
 
   /*
     The following should never be true with our current code base,
@@ -1280,26 +1287,20 @@
     DBUG_VOID_RETURN;                           // Don't set time for sub stmt
 
   start_of_query= thd->start_time;
-  thd->end_time();				// Set start time
+  long_query_count= thd->status_var.long_query_count;
+
+  mysql_suffix_log(thd, start_of_query, WARNING_LEVEL,
+            	   "%.*b", thd->query_length, thd->query);
+
+  thd->end_time();
 
   /*
-    Do not log administrative statements unless the appropriate option is
-    set; do not log into slow log if reading from backup.
+    Ensure that even if we do have multiple slow logging, that
+	we only increment the long_query_count by one
   */
-  if (thd->enable_slow_log && !thd->user_time)
-  {
-    thd->proc_info="logging slow query";
+  if (long_query_count != thd->status_var.long_query_count)
+    thd->status_var.long_query_count= long_query_count + 1;
 
-    if ((ulong) (thd->start_time - thd->time_after_lock) >
-	thd->variables.long_query_time ||
-	((thd->server_status &
-	  (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
-	 (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES)))
-    {
-      thd->status_var.long_query_count++;
-      slow_log_print(thd, thd->query, thd->query_length, start_of_query);
-    }
-  }
   DBUG_VOID_RETURN;
 }
 
@@ -6068,12 +6069,9 @@
     pthread_mutex_unlock(&LOCK_active_mi);
 #endif
 
-    /* flush slow and general logs */
-    logger.flush_logs(thd);
-
     if (ha_flush_logs(NULL))
       result=1;
-    if (flush_error_log())
+    if (flush_error_log(thd))
       result=1;
   }
 #ifdef HAVE_QUERY_CACHE

--- 1.393/sql/sql_table.cc	2007-03-12 10:52:51 -07:00
+++ 1.394/sql/sql_table.cc	2007-03-12 10:52:51 -07:00
@@ -1636,15 +1636,6 @@
     table->db_type= NULL;
     if ((share= get_cached_table_share(table->db, table->table_name)))
       table->db_type= share->db_type;
-
-    /* Disable drop of enabled log tables */
-    if (share && share->log_table &&
-        check_if_log_table(table->db_length, table->db,
-                           table->table_name_length, table->table_name, 1))
-    {
-      my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
-      DBUG_RETURN(1);
-    }
   }
 
   if (!drop_temporary && lock_table_names(thd, tables))
@@ -4037,7 +4028,7 @@
   Item *item;
   Protocol *protocol= thd->protocol;
   LEX *lex= thd->lex;
-  int result_code, disable_logs= 0;
+  int result_code;
   DBUG_ENTER("mysql_admin_table");
 
   if (end_active_trans(thd))
@@ -4085,22 +4076,6 @@
       if (view_operator_func == NULL)
         table->required_type=FRMTYPE_TABLE;
 
-      /*
-        If we want to perform an admin operation on the log table
-        (E.g. rename) and lock_type >= TL_READ_NO_INSERT disable
-        log tables
-      */
-
-      if (check_if_log_table(table->db_length, table->db,
-                             table->table_name_length,
-                             table->table_name, 1) &&
-          lock_type >= TL_READ_NO_INSERT)
-      {
-        disable_logs= 1;
-        logger.lock();
-        logger.tmp_close_log_tables(thd);
-      }
-
       open_and_lock_tables(thd, table);
       thd->no_warnings_for_error= 0;
       table->next_global= save_next_global;
@@ -4188,8 +4163,7 @@
     }
 
     /* Close all instances of the table to allow repair to rename files */
-    if (lock_type == TL_WRITE && table->table->s->version &&
-        !table->table->s->log_table)
+    if (lock_type == TL_WRITE && table->table->s->version)
     {
       pthread_mutex_lock(&LOCK_open);
       const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
@@ -4393,7 +4367,7 @@
       /* in the below check we do not refresh the log tables */
       if (fatal_error)
         table->table->s->version=0;               // Force close of table
-      else if (open_for_modify && !table->table->s->log_table)
+      else if (open_for_modify)
       {
         if (table->table->s->tmp_table)
           table->table->file->info(HA_STATUS_CONST);
@@ -4416,24 +4390,11 @@
   }
 
   send_eof(thd);
-  if (disable_logs)
-  {
-    if (logger.reopen_log_tables())
-      my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
-    logger.unlock();
-  }
   DBUG_RETURN(FALSE);
 
  err:
   ha_autocommit_or_rollback(thd, 1);
   close_thread_tables(thd);			// Shouldn't be needed
-  /* enable logging back if needed */
-  if (disable_logs)
-  {
-    if (logger.reopen_log_tables())
-      my_error(ER_CANT_ACTIVATE_LOG, MYF(0));
-    logger.unlock();
-  }
   if (table)
     table->table=0;
   DBUG_RETURN(TRUE);
@@ -5337,32 +5298,6 @@
   LINT_INIT(index_drop_count);
   LINT_INIT(index_add_buffer);
   LINT_INIT(index_drop_buffer);
-
-  if (table_list && table_list->db && table_list->table_name)
-  {
-    int table_kind= 0;
-
-    table_kind= check_if_log_table(table_list->db_length, table_list->db,
-                                   table_list->table_name_length,
-                                   table_list->table_name, 0);
-
-    /* Disable alter of enabled log tables */
-    if (table_kind && logger.is_log_table_enabled(table_kind))
-    {
-      my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
-      DBUG_RETURN(TRUE);
-    }
-
-    /* Disable alter of log tables to unsupported engine */
-    if (table_kind &&
-        (lex_create_info->used_fields & HA_CREATE_USED_ENGINE) &&
-        (!lex_create_info->db_type || /* unknown engine */
-        !(lex_create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
-    {
-      my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
-      DBUG_RETURN(TRUE);
-    }
-  }
 
   thd->proc_info="init";
   if (!(create_info= copy_create_info(lex_create_info)))

--- 1.276/sql/table.cc	2007-03-12 10:52:51 -07:00
+++ 1.277/sql/table.cc	2007-03-12 10:52:51 -07:00
@@ -370,12 +370,6 @@
             my_strcasecmp(system_charset_info, share->table_name.str, "proc") :
             strcmp(share->table_name.str, "proc")))
         share->system_table= 1;
-      else
-      {
-        share->log_table= check_if_log_table(share->db.length, share->db.str,
-                                             share->table_name.length,
-                                             share->table_name.str, 0);
-      }
     }
     error_given= 1;
   }

--- 1.161/sql/table.h	2007-03-12 10:52:51 -07:00
+++ 1.162/sql/table.h	2007-03-12 10:52:51 -07:00
@@ -228,11 +228,6 @@
     locking of this table for writing. FALSE - otherwise.
   */
   bool system_table;
-  /*
-    This flag is set for the log tables. Used during FLUSH instances to skip
-    log tables, while closing tables (since logs must be always available)
-  */
-  bool log_table;
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   bool auto_partitioned;
   const uchar *partition_info;
@@ -414,7 +409,6 @@
   my_bool distinct,const_table,no_rows;
   my_bool key_read, no_keyread;
   my_bool locked_by_flush;
-  my_bool locked_by_logger;
   my_bool locked_by_name;
   my_bool fulltext_searched;
   my_bool no_cache;
--- New file ---
+++ plugin/log_file/Makefile.am	07/03/12 10:52:21
# 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

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_srcdir)/include -I$(top_builddir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
WRAPLIBS=

LDADD =

DEFS =                  @DEFS@ -DMYSQL_SERVER

noinst_HEADERS =	

EXTRA_LIBRARIES =	liblogfile.a
noinst_LIBRARIES =	@plugin_logfile_static_target@
liblogfile_a_CXXFLAGS=	$(AM_CFLAGS)
liblogfile_a_CFLAGS =	$(AM_CFLAGS)
liblogfile_a_SOURCES=	log_file.cc


EXTRA_DIST =		CMakeLists.txt plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%

--- New file ---
+++ plugin/log_file/log_file.cc	07/03/12 10:52:21
/* 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 <stdarg.h>
#include <mysql/plugin.h>


struct log_data
{
  int err_fd, gen_fd, slo_fd;
  time_t gen_last_time, slo_last_time;
  LEX_STRING general_log_path, slow_log_path;
};


static int file_prefix_log(THD *thd, void *data, time_t start_time,
						   enum loglevel log_level,
						   enum enum_server_command command,
						   const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  CHARSET_INFO *client_cs= thd->variables.character_set_client;
  const LEX_STRING *cmdstr= &command_name[(uint) command];
  char strbuff[STRING_BUFFER_USUAL_SIZE];
  String str(strbuff, sizeof(strbuff), client_cs);
  int error= 0;
  DBUG_ENTER("file_prefix_log");

  str.length(0);
  
  if (!start_time || start_time != log->gen_last_time)
  {
	struct tm start;
	
	if (!start_time)
      start_time= time(NULL);

    log->gen_last_time= start_time;
    localtime_r(&start_time, &start);

    my_strprintf(&str,"%02d%02d%02d %2d:%02d:%02d",
                 start.tm_year % 100, start.tm_mon + 1,
                 start.tm_mday, start.tm_hour,
                 start.tm_min, start.tm_sec);
  }
  else
    str.append( C_STRING_WITH_LEN("\t\t") );

  /* command_type, thread_id */
  my_strprintf(&str, "%5ld ", (long) thread_id);

  str.append(cmdstr->str, cmdstr->length);

  str.append('\t');

  my_vstrprintf(&str, format, args);

  str.append(C_STRING_WITH_LEN("\n"));
  
  /*
    file has been opened as O_APPEND so the following write will
	append to end of log file and arbitration is performed by the 
	operating system.
  */
  error= my_write(log->gen_fd, (byte*)str.ptr(), str.length(),
  				  MYF(MY_WME | MY_NABP));

  if (!error)
    my_sync(log->gen_fd, MYF(MY_WME));

  DBUG_RETURN(error);
}


static int file_suffix_log(THD *thd, void *data, time_t start_time,
						   enum loglevel log_level,
						   enum enum_server_command command,
						   const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  ulong long_query_time= thd->variables.long_query_time;
  int error= 0;
  bool slow_query= FALSE;
  time_t now= time(NULL);
  DBUG_ENTER("file_suffix_log");

  /* If LOCK TABLES is in effect, we log nothing */
  if (!thd || thd->locked_tables)
    DBUG_RETURN(0);

  if (long_query_time < (ulong) (now - thd->time_after_lock))
    slow_query= TRUE;
	
  if ((specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES) &&
      (thd->server_status & 
	   (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)))
    slow_query= TRUE;

  if (!thd->enable_slow_log || thd->user_time)
    slow_query= FALSE;

  if (slow_query)
  {
	CHARSET_INFO *client_cs= thd->variables.character_set_client;
	const LEX_STRING *cmdstr= &command_name[(uint) command];
	char strbuff[STRING_BUFFER_USUAL_SIZE];
	String str(strbuff, sizeof(strbuff), client_cs);

    thd->status_var.long_query_count++;
	
	str.length(0);

	if (!start_time || start_time != log->slo_last_time)
	{
	  struct tm start;

      if (!start_time)
        start_time= time(NULL);

      log->slo_last_time= start_time;
      localtime_r(&start_time, &start);

      my_strprintf(&str, "%02d%02d%02d %2d:%02d:%02d",
                   start.tm_year % 100, start.tm_mon + 1,
                   start.tm_mday, start.tm_hour,
                   start.tm_min, start.tm_sec);
	}
	else
      str.append(C_STRING_WITH_LEN("\t\t"));

	/* command_type, thread_id */
	my_strprintf(&str, "%5ld ", (long) thread_id);

	str.append(cmdstr->str, cmdstr->length);

	str.append('\t');

	my_vstrprintf(&str, format, args);

	str.append(C_STRING_WITH_LEN("\n"));
	
	error= my_write(log->slo_fd, str.ptr(), str.length(), MYF(MY_WME));

	if (!error)
      my_sync(log->slo_fd, MYF(MY_WME));
  }

  DBUG_RETURN(error);
}


static int file_error_log(THD *thd, void *data, time_t start_time,
						  enum loglevel log_level,
						  enum enum_server_command command,
						  const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  char strbuff[STRING_BUFFER_USUAL_SIZE];
  String str(strbuff, sizeof(strbuff), system_charset_info);
  struct tm tm_tmp;
  struct tm *start;
  int error;
  DBUG_ENTER("error_log");

  str.length(0);

  localtime_r(&start_time, &tm_tmp);
  start=&tm_tmp;

  my_strprintf(&str, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
          start->tm_year % 100,
          start->tm_mon+1,
          start->tm_mday,
          start->tm_hour,
          start->tm_min,
          start->tm_sec,
          (log_level == ERROR_LEVEL ? "ERROR" : log_level == WARNING_LEVEL ?
           "Warning" : "Note"),
          str.c_ptr_quick());

  my_vstrprintf(&str, format, args);

  str.append(C_STRING_WITH_LEN("\n"));

  error= my_write(log->err_fd, str.ptr(), str.length(), MYF(MY_WME));

  if (!error)
    my_sync(log->err_fd, MYF(MY_WME));

  return error;
}


static char *make_default_log_name(char *buff, const char* log_ext)
{
  strmake(buff, glob_hostname, FN_REFLEN-5);
  return fn_format(buff, buff, mysql_data_home, log_ext,
                   MYF(MY_UNPACK_FILENAME|MY_APPEND_EXT));
}


static int logger_init(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  char buff[FN_REFLEN];
  log_data *data;
  int error= ENOMEM;
  
  if (!(data= (log_data *) my_malloc(sizeof(log_data), 
  									 MYF(MY_WME | MY_ZEROFILL))))
    goto fail;
	
  data->err_fd= data->gen_fd= data->slo_fd= -1;

  if (opt_log)
  {
    char *logname;

	if (!(logname= opt_logname) || !*logname)
      logname= make_default_log_name(buff, ".log");

	data->general_log_path.str= my_strdup(logname, MYF(MY_WME | MY_FAE));
	data->general_log_path.length= strlen(logname);
	
	data->gen_fd= my_open(logname, O_WRONLY|O_CREAT|O_APPEND, MYF(MY_WME));

    if (data->gen_fd == -1)
	  sql_print_warning("Unable to open general log file for appending.");
  }
  
  if (opt_slow_log)
  {
    char *logname;

	if (!(logname= opt_slow_logname) || !*logname)
      logname= make_default_log_name(buff, ".log");

	data->slow_log_path.str= my_strdup(logname, MYF(0));
	data->slow_log_path.length= strlen(logname);

	data->slo_fd= my_open(logname, O_WRONLY|O_CREAT|O_APPEND, MYF(MY_WME));

    if (data->slo_fd == -1)
	  sql_print_warning("Unable to open slow query log file for appending.");
  }

  /* we don't yet do err logging in this plugin. */

  if (data->gen_fd != -1)
    logger->prefix_log= file_prefix_log;
  if (data->slo_fd != -1)
    logger->suffix_log= file_suffix_log;
  if (data->err_fd != -1)
    logger->error_log= file_error_log;
  
  logger->data= data;
  error= 0;

fail:
  if (error && data)
  {
    if (data->err_fd >= 0)
	  my_close(data->err_fd, MYF(0));
    if (data->gen_fd >= 0)
	  my_close(data->gen_fd, MYF(0));
    if (data->slo_fd >= 0)
	  my_close(data->slo_fd, MYF(0));
	my_free((gptr) data->general_log_path.str, MYF(MY_ALLOW_ZERO_PTR));
	my_free((gptr) data->slow_log_path.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }

  return error;
}


static int logger_fini(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data= (log_data *) logger->data;

  if (data)
  {
    if (data->err_fd >= 0)
	  my_close(data->err_fd, MYF(0));
    if (data->gen_fd >= 0)
	  my_close(data->gen_fd, MYF(0));
    if (data->slo_fd >= 0)
	  my_close(data->slo_fd, MYF(0));
	my_free((gptr) data->general_log_path.str, MYF(MY_ALLOW_ZERO_PTR));
	my_free((gptr) data->slow_log_path.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }

  return 0;
}


struct st_mysql_logging log_file=
{ MYSQL_LOGGING_INTERFACE_VERSION };

mysql_declare_plugin(logfile)
{
  MYSQL_LOGGING_PLUGIN,
  &log_file,
  "LogFile",
  "MySQL AB",
  "Logs to a file",
  PLUGIN_LICENSE_GPL,
  logger_init, /* Plugin Init */
  logger_fini, /* Plugin Deinit */
  0x0100 /* 1.0 */,
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
}
mysql_declare_plugin_end;

--- New file ---
+++ plugin/log_file/plug.in	07/03/12 10:52:21
MYSQL_PLUGIN(logfile, [Text File Log Plugin],
 [This plugin writes the general log and the slow query log as a text file.])
MYSQL_PLUGIN_STATIC(logfile,   [liblogfile.a])
MYSQL_PLUGIN_MANDATORY(logfile)  dnl Default
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(logfile, [log_file.cc])

--- New file ---
+++ plugin/log_null/Makefile.am	07/03/12 10:52:21
# 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

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_builddir)/include \
			-I$(top_srcdir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
LDADD =

DEFS =			@DEFS@ -DMYSQL_SERVER
noinst_HEADERS	  =	

EXTRA_LTLIBRARIES =	log_null.la
pkglib_LTLIBRARIES =	@plugin_lognull_shared_target@
log_null_la_LDFLAGS =	-module -rpath $(MYSQLLIBdir)
log_null_la_CXXFLAGS =	$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
log_null_la_SOURCES =	log_null.cc 

EXTRA_LIBRARIES =	liblognull.a
noinst_LIBRARIES =	@plugin_lognull_static_target@
liblognull_a_CXXFLAGS =	$(AM_CFLAGS)
liblognull_a_SOURCES =	log_null.cc

EXTRA_DIST =		CMakeLists.txt plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%

--- New file ---
+++ plugin/log_null/log_null.cc	07/03/12 10:52:21
/* 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 <stdarg.h>
#include <mysql/plugin.h>

struct log_data
{
  int err_count;
  int pre_count;
  int suf_count;
  int flush_count;
};


static int null_prefix_log(THD *thd, void *data, time_t start_time,
                           enum loglevel log_level,
                           enum enum_server_command command,
                           const char *format, va_list args)
{
  log_data *log= (log_data*) data;

  /*
    This is called before a statement has been executed.
  */
  
  log->pre_count++;
  
  return 0;
}


static int null_suffix_log(THD *thd, void *data, time_t start_time,
                           enum loglevel log_level,
                           enum enum_server_command command,
                           const char *format, va_list args)
{
  log_data *log= (log_data*) data;

  /*
    This is called after a statement has been executed.
  */
  
  log->suf_count++;
  
  return 0;
}


static int null_error_log(THD *thd, void *data, time_t start_time,
                          enum loglevel log_level,
                          enum enum_server_command command,
                          const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  
  /*
    When an error message is emitted by mysqld, it will
    be seen here.
  */
  
  log->err_count++;
  
  return 0;
}


static my_bool null_flush_logs(THD *thd, void *data)
{
  log_data *log= (log_data*) data;
  
  /*
    Called when FLUSH is encountered.
    This is where if you have any open file handles, 
    you may want to close and reopen them.
  */
  
  log->flush_count++;
  
  return 0;
}



static int logger_init(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data;
  int error= ENOMEM;

  if (!(data= (log_data *) my_malloc(sizeof(log_data),
                                     MYF(MY_WME | MY_ZEROFILL))))
    goto fail;

  /*
    Set up your data structures.
    
    Install whatever interests you.
  */
  
  logger->prefix_log= null_prefix_log;
  logger->suffix_log= null_suffix_log;
  logger->error_log= null_error_log;
  logger->flush_logs= null_flush_logs;

  logger->data= data;

  error= 0;

fail:
  if (error && data)
  {
    my_free((gptr) data, MYF(MY_WME));
  }
  
  return error;
}


static int logger_fini(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data= (log_data *) logger->data;

  if (data)
  {
    my_free((gptr) data, MYF(MY_WME));
  }

  return 0;
}


struct st_mysql_logging log_null=
{ MYSQL_LOGGING_INTERFACE_VERSION };

mysql_declare_plugin(lognull)
{
  MYSQL_LOGGING_PLUGIN,
  &log_null,
  "LogNull",
  "MySQL AB",
  "Logging to nowhere",
  PLUGIN_LICENSE_GPL,
  logger_init, /* Plugin Init */
  logger_fini, /* Plugin Deinit */
  0x0100 /* 1.0 */,
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
}
mysql_declare_plugin_end;

--- New file ---
+++ plugin/log_null/plug.in	07/03/12 10:52:21
MYSQL_PLUGIN(lognull, [Null Log Plugin],
 [This Log plugin does not do anything useful.])
MYSQL_PLUGIN_DYNAMIC(lognull,  [log_null.la])
MYSQL_PLUGIN_STATIC(lognull,   [liblognull.a])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(lognull, [log_null.cc])

--- New file ---
+++ plugin/log_syslog/Makefile.am	07/03/12 10:52:21
# 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

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_builddir)/include \
			-I$(top_srcdir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
LDADD =

DEFS =			@DEFS@ -DMYSQL_SERVER
noinst_HEADERS	  =	

EXTRA_LTLIBRARIES =	log_syslog.la
pkglib_LTLIBRARIES =	@plugin_logsyslog_shared_target@
log_syslog_la_LDFLAGS =	-module -rpath $(MYSQLLIBdir)
log_syslog_la_CXXFLAGS =$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
log_syslog_la_SOURCES =	log_syslog.cc 

EXTRA_LIBRARIES =	liblogsyslog.a
noinst_LIBRARIES =	@plugin_logsyslog_static_target@
liblogsyslog_a_CXXFLAGS =$(AM_CFLAGS)
liblogsyslog_a_SOURCES =log_syslog.cc

EXTRA_DIST =		CMakeLists.txt plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%

--- New file ---
+++ plugin/log_syslog/log_syslog.cc	07/03/12 10:52:21
/* 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 <stdarg.h>
#ifndef __NT__
#include <syslog.h>
#endif
#include <mysql/plugin.h>

/*
  Experimental Syslog Error Log Plugin - may harm kittens.
*/

struct log_data
{
  const char *ident;
  int option;
  int facility;
#ifdef __NT__
  HANDLE event;
#endif /*__NT__*/
};


static int error_log(THD *thd, void *data, time_t start_time,
                     enum loglevel log_level, enum enum_server_command command,
                     const char *format, va_list args)
{
  log_data *log= (log_data*) data;
#ifdef __NT__
  HANDLE event;
  LPCSTR *buffmsgptr;
  WORD wType;
  
  switch (log_level) {
  case ERROR_LEVEL:
    wType= EVENTLOG_ERROR_TYPE;
    break;
  case WARNING_LEVEL:
    wType= EVENTLOG_WARNING_TYPE;
    break;
  case INFORMATION_LEVEL:
  default:
    wType= EVENTLOG_INFORMATION_TYPE;
    break;
  }

  if (data->event)
  {
    char *fmt= (char *) my_alloca(strlen(format) + 5);
    char buff[STRING_BUFFER_USUAL_SIZE];
    String str(buff, sizeof(buff), system_charset_info);

    strxmov(fmt, format, "\r\n\r\n", NullS);

    str.length(0);
    my_vstrprintf(&str, fmt, args);

    my_afree(fmt);

    buffmsgptr= (LPCSTR*) str.c_ptr_quick();	// Keep windows happy

    ReportEvent(event, wType, 0, MSG_DEFAULT, NULL, 1, 0,
                buffmsgptr, NULL);
  }
#else
  int priority;

  switch (log_level) {
  case ERROR_LEVEL:
    priority= log->facility | LOG_ERR;
    break;
  case WARNING_LEVEL:
    priority= log->facility | LOG_WARNING;
    break;
  case INFORMATION_LEVEL:
  default:
    priority= log->facility | LOG_INFO;
    break;
  }
  
  vsyslog(priority, format, args);
#endif /*__NT__*/

  return 0;
}


static int logger_init(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data;
  int error= ENOMEM;
  
  LEX_STRING d= { C_STRING_WITH_LEN("mysql") };

  if (!(data= (log_data *) my_malloc(sizeof(log_data), MYF(MY_WME))) ||
      !(data->ident= (char *) my_memdup(d.str, d.length, MYF(MY_WME))))
    goto fail;

  data->option= LOG_PERROR | LOG_PID;
  data->facility= LOG_LOCAL0;

#ifdef __NT__
  data->event= RegisterEventSource(NULL, data->ident)
#else
  openlog(data->ident, data->option, data->facility);
#endif /*__NT__*/

  logger->error_log= error_log;
  logger->data= data;
  error= 0;

fail:
  if (error && data)
  {
    my_free((gptr) data->ident, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }

  return error;
}


static int logger_fini(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data= (log_data *) logger->data;

  if (data)
  {
#ifdef __NT__
    DeregisterEventSource(data->event);
#else
    closelog();
#endif /*__NT__*/

    my_free((gptr) data->ident, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }

  return 0;
}


struct st_mysql_logging log_syslog=
{ MYSQL_LOGGING_INTERFACE_VERSION };

mysql_declare_plugin(logsyslog)
{
  MYSQL_LOGGING_PLUGIN,
  &log_syslog,
  "LogSyslog",
  "MySQL AB",
  "Logs errors to the system logger facility",
  PLUGIN_LICENSE_GPL,
  logger_init, /* Plugin Init */
  logger_fini, /* Plugin Deinit */
  0x0100 /* 1.0 */,
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
}
mysql_declare_plugin_end;

--- New file ---
+++ plugin/log_syslog/plug.in	07/03/12 10:52:22
MYSQL_PLUGIN(logsyslog, [Syslog Log Plugin],
 [This plugin writes the error log to the system logging facility.])
MYSQL_PLUGIN_DYNAMIC(logsyslog,  [log_syslog.la])
MYSQL_PLUGIN_STATIC(logsyslog,   [liblogsyslog.a])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(logsyslog, [log_syslog.cc])

--- New file ---
+++ plugin/log_table/Makefile.am	07/03/12 10:52:22
# 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

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_builddir)/include \
			-I$(top_srcdir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
LDADD =

DEFS =			@DEFS@ -DMYSQL_SERVER
noinst_HEADERS	  =	log_insert.h

EXTRA_LTLIBRARIES =	log_table.la
pkglib_LTLIBRARIES =	@plugin_logtable_shared_target@
log_table_la_LDFLAGS =	-module -rpath $(MYSQLLIBdir)
log_table_la_CXXFLAGS =	$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
log_table_la_SOURCES =	log_table.cc 

EXTRA_LIBRARIES =	liblogtable.a
noinst_LIBRARIES =	@plugin_logtable_static_target@
liblogtable_a_CXXFLAGS =$(AM_CFLAGS)
liblogtable_a_SOURCES =	log_table.cc

EXTRA_DIST =		CMakeLists.txt plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%

--- New file ---
+++ plugin/log_table/log_insert.h	07/03/12 10:52:22
/* 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 */

/*
  A utility class to make inserting into tables quick and easy.
*/
class LogQuickInsert
{
  Name_resolution_context *ctx;
  my_bool save_report_error;
  my_bool save_nosend_error;
  bool save_isfatal_error;
  TABLE_LIST table_list[1], *leaves;
  TABLE *table;
  COPY_INFO info;
  List<Item> fields;
  Field *field;
  LEX lex, *oldlex;
  THD *thd;
  int error;
public:
  LogQuickInsert(THD *athd, LEX_STRING *db, LEX_STRING *table_name)
  : save_report_error(athd->net.report_error),
    save_nosend_error(athd->net.no_send_error),
    save_isfatal_error(athd->is_fatal_error),
    thd(athd), oldlex(athd->lex), leaves(0), 
    table(NULL), ctx(NULL), error(1), lex()
  {
    bzero((char*)&info, sizeof(info));
    bzero((char*)&table_list, sizeof(table_list));

    info.ignore= 1;
    info.handle_duplicates= DUP_ERROR;

    table_list[0].db= db->str;
    table_list[0].db_length= db->length;
    table_list[0].table_name= table_name->str;
    table_list[0].table_name_length= table_name->length;
    table_list[0].lock_type= TL_WRITE_CONCURRENT_INSERT;
    table_list[0].alias= table_list[0].table_name;
  }

  ~LogQuickInsert()
  {
    if (table && (error || thd->net.report_error))
      table->file->ha_release_auto_increment();
    close_thread_tables(thd);

    thd->net.report_error= save_report_error;
    thd->net.no_send_error= save_nosend_error;
    thd->is_fatal_error= save_isfatal_error;
    thd->lex= oldlex;
  }

  bool open_table()
  {
    thd->lex= &lex;

    mysql_init_query(thd, (uchar*) "", 0);

    thd->net.report_error= 0;
    thd->net.no_send_error= 1;
    thd->is_fatal_error= 0;

    if (open_and_lock_tables(thd, table_list) || thd->is_fatal_error)
      return true;

    thd->lex->select_lex.context.table_list=
      thd->lex->select_lex.context.first_name_resolution_table= &table_list[0];

    if (setup_tables(thd, &thd->lex->select_lex.context,
                     &thd->lex->select_lex.top_join_list,
                     table_list, &leaves, FALSE))
      return true;

    ctx= &thd->lex->select_lex.context;
    return false;
  }

  bool is_transactional()
  {
    return table_list->table->file->has_transactions();
  }

  Item_field *push_field(const char *field_name)
  {
    Item_field *item;
    DBUG_ASSERT(ctx);
    fields.push_back(item= new Item_field(ctx, NullS, NullS, field_name));
    return item;
  }

  bool check_fields()
  {
    TABLE *t= table_list->table;

    if (setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0) ||
        check_that_all_fields_are_given_values(thd, t, table_list))
      return true;

    table= t;
    table->mark_columns_needed_for_insert();
    return false;
  }

  void reset_record()
  {
    DBUG_ASSERT(table);
    restore_record(table, s->default_values);
    error= 0;
  }

  int write()
  {
    DBUG_ASSERT(table && !error);
    return error= write_record(thd, table, &info);
  }
};

--- New file ---
+++ plugin/log_table/log_table.cc	07/03/12 10:52:22
/* 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 "log_insert.h"
#include <stdarg.h>
#include <mysql/plugin.h>

/*
  Logs to tables: mysql.general_log and mysql.slow_log
  
  It should be flexible enough to handle any storage engine
  and does not require columns to be in a specific order,
  as long as all the expected columns are present.
  
  LIMITATIONS:
  When LOCK TABLES is in effect, this plugin will not
  log anything. Logging to transactional tables make
  the logging tables a party to the current transaction
  so log rows may be 'rolled back'.
  
  Some future solution such as logging to a temporary
  in-memory table or structure and then spooling the
  logs out when safe, perhaps from an alternate thread.
  
*/


struct log_data
{
  bool gen_bad, slo_bad;
  bool gen_warn_trans, slo_warn_trans;
  LEX_STRING gen_db, gen_table;
  LEX_STRING slo_db, slo_table;
};


static String *my_print_user_host_info(THD *thd, String *str)
{
  Security_context *sctx= thd->security_ctx;

  /* append user_host value: the format is "%s[%s] @ %s [%s]" */
  return my_strprintf(str, "%s[%s] @ %s [%s]",
  					  sctx->priv_user ? sctx->priv_user : "",
					  sctx->user ? sctx->user : "",
					  sctx->host ? sctx->host : "",
					  sctx->ip ? sctx->ip : "");
}


static int table_prefix_log(THD *thd, void *data, time_t start_time,
                            enum loglevel log_level,
                            enum enum_server_command command,
                            const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  CHARSET_INFO *client_cs= thd->variables.character_set_client;
  const LEX_STRING *cmdstr= &command_name[(uint) command];
  char user_buff[STRING_BUFFER_USUAL_SIZE];
  char arg_buff[STRING_BUFFER_USUAL_SIZE];
  String user(user_buff, sizeof(user_buff), client_cs);
  String arg(arg_buff, sizeof(arg_buff), client_cs);
  TIME ltime;

  /* If LOCK TABLES is in effect, we log nothing */
  if (!thd || thd->locked_tables || log->gen_bad)
    return 0;

  /* build the required values to emit */
  user.length(0);
  my_print_user_host_info(thd, &user);

  arg.length(0);
  my_vstrprintf(&arg, format, args);

  if (!start_time)
    start_time= time(NULL);
  thd->variables.time_zone->gmt_sec_to_TIME(&ltime, (my_time_t) start_time);

  /* prepare to insert into the general log table */
  LogQuickInsert quick(thd, &log->gen_db, &log->gen_table);
  Item_field *item[6];
  Field *field;
  int error= 1;
  
  if (quick.open_table())
    goto fail;

  if (!log->gen_warn_trans && quick.is_transactional())
  {
    log->gen_warn_trans= TRUE;
    sql_print_warning("Logging general log to transactional table '%s.%s' "
                      "may have unexpected behaviour",
                      log->gen_db.str, log->gen_table.str);
  }

  item[0]= quick.push_field("event_time");
  item[1]= quick.push_field("user_host");
  item[2]= quick.push_field("thread_id");
  item[3]= quick.push_field("server_id");
  item[4]= quick.push_field("command_type");
  item[5]= quick.push_field("argument");

  if (quick.check_fields())
    goto fail;

  quick.reset_record();

  (field= item[0]->field)->set_notnull();
  field->store_time(&ltime, MYSQL_TIMESTAMP_DATETIME);

  (field= item[1]->field)->set_notnull();
  field->store(user.c_ptr_quick(), user.length(), client_cs);

  (field= item[2]->field)->set_notnull();
  field->store((longlong) thd->thread_id, TRUE);

  (field= item[3]->field)->set_notnull();
  field->store((longlong) server_id, TRUE);

  (field= item[4]->field)->set_notnull();
  field->store(cmdstr->str, cmdstr->length, client_cs);

  (field= item[5]->field)->set_notnull();
  field->store(arg.c_ptr_quick(), arg.length(), client_cs);

  error= quick.write();

fail:  
  if (error || thd->net.report_error)
  {
    log->gen_bad= 1;
    sql_print_warning("failed to insert to general log table");
  }

  return error;
}


static int table_suffix_log(THD *thd, void *data, time_t start_time,
                            enum loglevel log_level,
                            enum enum_server_command command,
                            const char *format, va_list args)
{
  log_data *log= (log_data*) data;
  CHARSET_INFO *client_cs= thd->variables.character_set_client;
  ulong long_query_time;
  bool slow_query= FALSE;
  longlong sent_row_count, examined_row_count;
  longlong last_insert_id, insert_id;
  bool have_last_insert_id, have_insert_id;
  char user_buff[STRING_BUFFER_USUAL_SIZE];
  char query_buff[STRING_BUFFER_USUAL_SIZE];
  String user(user_buff, sizeof(user_buff), client_cs);
  String qstr(query_buff, sizeof(query_buff), client_cs);
  time_t now= time(NULL);
  char *query;
  uint query_length;
  TIME ltime;

  /* If LOCK TABLES is in effect, we log nothing */
  if (!thd || thd->locked_tables || log->slo_bad)
    return 0;

  /* we need to test if this is a slow query */

  long_query_time= thd->variables.long_query_time;

  if (long_query_time < (ulong) (now - thd->time_after_lock))
    slow_query= TRUE;
	
  if ((specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES) &&
      (thd->server_status & 
       (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)))
    slow_query= TRUE;

  if (!thd->enable_slow_log || thd->user_time)
    slow_query= FALSE;

  if (!slow_query)
    return 0;

  /* increment the long_query_count, we found one */
  thd->status_var.long_query_count++;

  /* prepare the values which we will emit */
  sent_row_count= thd->sent_row_count;
  examined_row_count= thd->examined_row_count;
  have_last_insert_id= 
    thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt;  
  last_insert_id= (longlong)
    thd->first_successful_insert_id_in_prev_stmt_for_binlog;
  insert_id= (have_insert_id=
        thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
    ? (longlong) thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum()
    : 0;
	
  user.length(0);
  my_print_user_host_info(thd, &user);

  if (!format)
  {
    query= command_name[thd->command].str;
    query_length= command_name[thd->command].length;
  }
  else
  {
    qstr.length(0);
    my_vstrprintf(&qstr, format, args);
    query= qstr.c_ptr_quick();
    query_length= qstr.length();
  }

  if (!start_time)
    thd->variables.time_zone->gmt_sec_to_TIME(&ltime, (my_time_t) time(NULL));
  else
    thd->variables.time_zone->gmt_sec_to_TIME(&ltime, (my_time_t) start_time);

  /* prepare to insert into the slow query table */
  LogQuickInsert quick(thd, &log->slo_db, &log->slo_table);
  Item_field *item[11];
  Field *field;
  int error= 1;

  if (quick.open_table())
    goto fail;

  if (!log->slo_warn_trans && quick.is_transactional())
  {
    log->gen_warn_trans= TRUE;
    sql_print_warning("Logging slow queries to transactional table '%s.%s' "
                      "may have unexpected behaviour",
                      log->slo_db.str, log->slo_table.str);
  }

  item[0]= quick.push_field("start_time");
  item[1]= quick.push_field("user_host");
  item[2]= quick.push_field("query_time");
  item[3]= quick.push_field("lock_time");
  item[4]= quick.push_field("rows_sent");
  item[5]= quick.push_field("rows_examined");
  item[6]= quick.push_field("db");
  item[7]= quick.push_field("last_insert_id");
  item[8]= quick.push_field("insert_id");
  item[9]= quick.push_field("server_id");
  item[10]= quick.push_field("sql_text");

  if (quick.check_fields())
    goto fail;

  quick.reset_record();

  (field= item[0]->field)->set_notnull();
  field->store_time(&ltime, MYSQL_TIMESTAMP_DATETIME);

  (field= item[1]->field)->set_notnull();
  field->store(user.c_ptr_quick(), user.length(), client_cs);

  if (start_time)
  {	  
    longlong query_time, lock_time;

    query_time= (longlong) (now - start_time);
    lock_time= (longlong) (thd->time_after_lock - start_time);

    (field= item[2]->field)->set_notnull();
    field->store(query_time, TRUE);
	
    (field= item[3]->field)->set_notnull();
    field->store(lock_time, TRUE);
	
    (field= item[4]->field)->set_notnull();
    field->store(sent_row_count, TRUE);
	
    (field= item[5]->field)->set_notnull();
    field->store(examined_row_count, TRUE);
  }
  else
  {
    item[2]->field->set_null();
    item[3]->field->set_null();
    item[4]->field->set_null();
    item[5]->field->set_null();
  }

  if (thd->db)
  {
    (field= item[6]->field)->set_notnull();
    field->store(thd->db, thd->db_length, client_cs);
  }
  else
    item[6]->field->set_null();

  if (have_last_insert_id)
  {
    (field= item[7]->field)->set_notnull();
    field->store(last_insert_id);
  }
  else
    item[7]->field->set_null();

  if (have_insert_id)
  {
    (field= item[8]->field)->set_notnull();
    field->store(insert_id);
  }
  else
    item[8]->field->set_null();

  (field= item[9]->field)->set_notnull();
  field->store((longlong) server_id);
	
  (field= item[10]->field)->set_notnull();
  field->store(query, query_length, client_cs);

  error= quick.write();

fail:  
  if (error || thd->net.report_error)
  {
    log->slo_bad= 1;
    sql_print_warning("failed to insert to slow query log table");
  }
  
  return error;
}


static int logger_init(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data;
  int error= ENOMEM;

  /* For now, these values are hard coded */
  
  LEX_STRING db= { C_STRING_WITH_LEN("mysql") };
  LEX_STRING gen= { C_STRING_WITH_LEN("general_log") };
  LEX_STRING slo= { C_STRING_WITH_LEN("slow_log") };

  if (!(data= (log_data *) my_malloc(sizeof(log_data),
                                     MYF(MY_WME | MY_ZEROFILL))))
    goto fail;

  if (opt_log && (data->gen_db.str= my_strdup(db.str, MYF(MY_WME))))
  {
    data->gen_db.length= db.length;

    if ((data->gen_table.str= my_strdup(gen.str, MYF(MY_WME))))
      data->gen_table.length= gen.length;
  }

  if (opt_slow_log && (data->slo_db.str= my_strdup(db.str, MYF(MY_WME))))
  {
    data->slo_db.length= db.length;

    if ((data->slo_table.str= my_strdup(slo.str, MYF(MY_WME))))
      data->slo_table.length= slo.length;
  }

  if (data->gen_db.str && data->gen_table.str)
    logger->prefix_log= table_prefix_log;
  if (data->slo_db.str && data->slo_table.str)
    logger->suffix_log= table_suffix_log;
  logger->data= data;

  error= 0;

fail:
  if (error && data)
  {
    my_free((gptr) data->gen_db.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->gen_table.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->slo_db.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->slo_table.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }
  
  return error;
}


static int logger_fini(void *p)
{
  mysql_logger *logger= (mysql_logger *) p;
  log_data *data= (log_data *) logger->data;

  if (data)
  {
    my_free((gptr) data->gen_db.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->gen_table.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->slo_db.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data->slo_table.str, MYF(MY_ALLOW_ZERO_PTR));
    my_free((gptr) data, MYF(MY_WME));
  }

  return 0;
}


struct st_mysql_logging log_table=
{ MYSQL_LOGGING_INTERFACE_VERSION };

mysql_declare_plugin(logtable)
{
  MYSQL_LOGGING_PLUGIN,
  &log_table,
  "LogTable",
  "MySQL AB",
  "Logging to a table",
  PLUGIN_LICENSE_GPL,
  logger_init, /* Plugin Init */
  logger_fini, /* Plugin Deinit */
  0x0100 /* 1.0 */,
  NULL,                       /* status variables                */
  NULL,                       /* system variables                */
  NULL                        /* config options                  */
}
mysql_declare_plugin_end;

--- New file ---
+++ plugin/log_table/plug.in	07/03/12 10:52:22
MYSQL_PLUGIN(logtable, [Table Log Plugin],
 [This plugin writes the general log and the slow query log into a table.])
MYSQL_PLUGIN_DYNAMIC(logtable,  [log_table.la])
MYSQL_PLUGIN_STATIC(logtable,   [liblogtable.a])
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(logtable, [log_table.cc])

--- New file ---
+++ sql/sql_logger.cc	07/03/12 10:52:21
/* 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 <stdarg.h>
#include <mysql/plugin.h>

/*
  New plugin-based logging framework.
  
  TODO:
    Variables to set what plugins are to be used for logging so that
	plugin_foreach() is not required. This will remove mutex overhead.

*/


struct logger_emit_st
{
  mysql_logger_func mysql_logger::*offset;
  time_t start_time;
  enum loglevel log_level;
  enum enum_server_command command;
  const char *format;
  va_list args;
  int errorbits, handlecount;  
};


static rw_lock_t THR_LOCK_logger;
static uint version, version_head;


static void stderr_log(THD *thd, time_t start_time,
					   enum loglevel log_level, 
					   enum enum_server_command command,
					   const char *format, va_list args);


static my_bool call_log(THD *thd, mysql_logger *logger, logger_emit_st *emit)
{
  mysql_logger_func logfunc;
  va_list args;
  DBUG_ENTER("call_log");
  
  if ((logfunc= logger->*(emit->offset)))
  {
    va_copy(args, emit->args);
    emit->errorbits|= logfunc(thd, logger->data, emit->start_time, 
                              emit->log_level, emit->command,
                              emit->format, args);
    va_end(args);
	emit->handlecount++;
  }
  DBUG_RETURN(0);
}


static my_bool call_log(THD *thd, st_plugin_int *plugin, void *data)
{
  return call_log(thd, (mysql_logger *) plugin->data, (logger_emit_st *) data);
}


static my_bool flush_log(THD *thd, st_plugin_int *plugin, void *data)
{
  mysql_logger *logger= (mysql_logger *) plugin->data;
  DBUG_ENTER("flush_log");
  
  if (logger->flush_logs)
    DBUG_RETURN(logger->flush_logs(thd, logger->data));

  DBUG_RETURN(0);
}


static int intern_log(THD *thd, time_t start_time, enum loglevel log_level,
					  mysql_logger_func mysql_logger::*function,
					  const char *format, va_list args)
{
  logger_emit_st data;
  
  va_copy(data.args, args);
  
  data.offset= function;
  data.start_time= start_time;
  data.log_level= log_level;
  data.command= thd ? thd->command : (enum_server_command) 0;
  data.format= format;
  data.errorbits= 0;
  data.handlecount= 0;
  
  if (thd && thd->logger_cache.version)
  {
    st_plugin_int **log= thd->logger_cache.loggers, *logger;
    while ((logger= *log++))
      call_log(thd, (mysql_logger *)logger->data, &data);
  }
  else
    plugin_foreach(thd, call_log, MYSQL_LOGGING_PLUGIN, &data);
  
  va_end(data.args);
  
  return data.errorbits ? TRUE : FALSE;
}


int mysql_prefix_log(THD *thd, time_t start_time, enum loglevel log_level,
			    const char *format, ...)
{
  int error;
  va_list args;
  DBUG_ENTER("mysql_prefix_log");
  
  va_start(args, format);
  
  error= intern_log(thd, start_time, log_level, &mysql_logger::prefix_log,
                    format, args);
  va_end(args);
  DBUG_RETURN(error);
}


int mysql_suffix_log(THD *thd, time_t start_time, enum loglevel log_level,
				const char *format, ...)
{
  int error;
  va_list args;
  DBUG_ENTER("mysql_suffix_log");
  
  va_start(args, format);
  
  error= intern_log(thd, start_time, log_level, &mysql_logger::suffix_log,
                    format, args);
  va_end(args);
  DBUG_RETURN(error);
}


int intern_error_log(THD *thd, time_t start_time, enum loglevel log_level,
			 		 const char *format, va_list args)
{
  int error;
  va_list arg_copy;
  DBUG_ENTER("mysql_error_log");
  
  va_copy(arg_copy, args);
  
  stderr_log(thd, start_time, log_level,
  			 thd ? thd->command : (enum_server_command) 0,
			 format, arg_copy);

  va_end(arg_copy);
  
  error= intern_log(thd, start_time, log_level, &mysql_logger::error_log,
                    format, args);

  DBUG_RETURN(error);
}


int mysql_error_log(THD *thd, time_t start_time, enum loglevel log_level,
				const char *format, ...)
{
  va_list args;
  int error;
  
  va_start(args, format);

  error= intern_error_log(thd, start_time, log_level, format, args);
  
  va_end(args);
  return error;
}


bool general_log_print(THD *thd, enum enum_server_command command,
                       const char *format,...)
{
  int error;
  va_list args;
  DBUG_ENTER("general_log_print");
  
  va_start(args, format);

  error= intern_log(thd, thd->start_time, INFORMATION_LEVEL,
  					&mysql_logger::prefix_log, format, args);
  va_end(args);
  
  DBUG_RETURN(error);
}


void sql_print_error(const char *format, ...) 
{
  va_list args;
  DBUG_ENTER("sql_print_error");

  va_start(args, format);
  intern_error_log(NULL, time(NULL), ERROR_LEVEL, format, args);
  va_end(args);

  DBUG_VOID_RETURN;
}


void sql_print_warning(const char *format, ...) 
{
  va_list args;
  DBUG_ENTER("sql_print_warning");

  va_start(args, format);
  intern_error_log(NULL, time(NULL), WARNING_LEVEL, format, args);
  va_end(args);

  DBUG_VOID_RETURN;
}


void sql_print_information(const char *format, ...) 
{
  va_list args;
  DBUG_ENTER("sql_print_information");

  va_start(args, format);
  intern_error_log(NULL, time(NULL), INFORMATION_LEVEL, format, args);
  va_end(args);

  DBUG_VOID_RETURN;
}


static void stderr_log(THD *thd, time_t start_time,
					   enum loglevel log_level, 
					   enum enum_server_command command,
					   const char *format, va_list args)
{
#ifndef EMBEDDED_LIBRARY

  char strbuff[STRING_BUFFER_USUAL_SIZE];
  String str(strbuff, sizeof(strbuff), system_charset_info);
  struct tm tm_tmp;
  struct tm *start;
  DBUG_ENTER("error_log");

  str.length(0);
  my_vstrprintf(&str, format, args);

  localtime_r(&start_time, &tm_tmp);
  start=&tm_tmp;

  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
          start->tm_year % 100,
          start->tm_mon+1,
          start->tm_mday,
          start->tm_hour,
          start->tm_min,
          start->tm_sec,
          (log_level == ERROR_LEVEL ? "ERROR" : log_level == WARNING_LEVEL ?
           "Warning" : "Note"),
          str.c_ptr_quick());

  fflush(stderr);
  DBUG_VOID_RETURN;
#endif /* EMBEDDED_LIBRARY */
}


bool flush_error_log(THD *thd)
{
  bool result= FALSE;
  DBUG_ENTER("flush_error_log");

  if (thd && thd->logger_cache.version)
  {
    st_plugin_int **log= thd->logger_cache.loggers, *plugin;
    while ((plugin= *log++))
      flush_log(thd, plugin, NULL);
  }
  else
    result= plugin_foreach(thd, flush_log, MYSQL_LOGGING_PLUGIN, NULL);

  DBUG_RETURN(result);
}


void sql_perror(const char *message)
{
#ifdef HAVE_STRERROR
  sql_print_error("%s: %s",message, strerror(errno));
#else
  perror(message);
#endif
}


void logger_cache_prepare(THD *thd)
{
  rw_rdlock(&THR_LOCK_logger);
  if (thd->logger_cache.version != version)
  {
    if (thd->logger_cache.version)
      plugin_unlockall(thd->logger_cache.loggers);
    thd->logger_cache.loggers= plugin_lockall(MYSQL_LOGGING_PLUGIN);
    thd->logger_cache.version= version_head;
  }  
  rw_unlock(&THR_LOCK_logger);
}


void logger_cache_check(THD *thd)
{
  if (thd->logger_cache.version != version)
    logger_cache_release(thd);
}


void logger_cache_release(THD *thd)
{
  plugin_unlockall(thd->logger_cache.loggers);
  thd->logger_cache.loggers= NULL;    
  thd->logger_cache.version= 0;
}


void logger_cache_notify(void)
{
  rw_wrlock(&THR_LOCK_logger);
  version++;
  rw_unlock(&THR_LOCK_logger);
}

void logger_cache_init(void)
{
  my_rwlock_init(&THR_LOCK_logger, NULL);
  version= 0;
  version_head= 0;
}

void logger_cache_done(void)
{
  rwlock_destroy(&THR_LOCK_logger);
  version= 0;
}


/* Plugin Initialization and finalization */
int initialize_logger(st_plugin_int *plugin)
{
  mysql_logger *logger= NULL;
  int error= 1;
  DBUG_ENTER("initialize_logger");
  
  if (!(logger= (mysql_logger *) (plugin->data= 
  			    my_malloc(sizeof(mysql_logger), MYF(MY_WME | MY_ZEROFILL)))))
    goto err;
  
    /* Historical Requirement */
  plugin->data= logger; // shortcut for the future
  if (plugin->plugin->init)
  {
    if ((error= plugin->plugin->init(logger)))
    {
      sql_print_error("Plugin '%s' init function returned error.",
                      plugin->name.str);
      goto err;
    }
  }

  rw_wrlock(&THR_LOCK_logger);
  version++;
  version_head= version;
  rw_unlock(&THR_LOCK_logger);

  DBUG_RETURN(0);
err:
  my_free((gptr)logger, MYF(MY_ALLOW_ZERO_PTR));
  DBUG_RETURN(error);
}


int finalize_logger(st_plugin_int *plugin)
{
  mysql_logger *logger;
  int error= 0;
  DBUG_ENTER("finalize_logger");
  
  if ((logger= (mysql_logger *) plugin->data) &&
      plugin->plugin->deinit)
  {
    error= plugin->plugin->deinit(logger);
	my_free((gptr)logger, MYF(0));

    rw_wrlock(&THR_LOCK_logger);
    version++;
    version_head= version;
    rw_unlock(&THR_LOCK_logger);
  }

  DBUG_RETURN(error);
}

/*
  Limited snprintf() implementations

  SYNOPSIS
    my_vstrprintf()
    to		Store result here
    fmt		printf format
    ap		Arguments

  IMPLEMENTION:
    Supports following formats:
    %#[l]d
    %#[l]u
    %#[l]x
    %#.#b 	Local format; note first # is ignored and second is REQUIRED
    %#.#s	Note first # is ignored
    
  RETURN
    string result
*/

String *my_vstrprintf(String *str, const char* fmt, va_list ap)
{
  uint length, width, pre_zero, have_long;
  
  if (!fmt)
    return str;

  for (; *fmt ; fmt++)
  {
    if (*fmt != '%')
    {
	  str->append(*fmt);	/* Copy ordinary char */
      continue;
    }
    fmt++;					/* skip '%' */
    /* Read max fill size (only used with %d and %u) */
    if (*fmt == '-')
      fmt++;
    length= width= pre_zero= have_long= 0;
    if (*fmt == '*')
    {
      fmt++;
      length= va_arg(ap, int);
    }
    else
      for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
      {
        length= length * 10 + (uint)(*fmt - '0');
        if (!length)
          pre_zero= 1;			/* first digit was 0 */
      }
    if (*fmt == '.')
    {
      fmt++;
      if (*fmt == '*')
      {
        fmt++;
        width= va_arg(ap, int);
      }
      else
        for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
          width= width * 10 + (uint)(*fmt - '0');
    }
    else
      width= ~0;
    if (*fmt == 'l')
    {
      fmt++;
      have_long= 1;
    }
    if (*fmt == 's')				/* String parameter */
    {
      reg2 char	*par = va_arg(ap, char *);
      uint plen;
      if (!par) par = (char*)"(null)";
      plen = (uint) strlen(par);
      set_if_smaller(plen,width);
	  str->append(par, plen);
      continue;
    }
    else if (*fmt == 'b')				/* Buffer parameter */
    {
      char *par = va_arg(ap, char *);
      str->append(par, abs(width));
      continue;
    }
    else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x')	/* Integer parameter */
    {
      register long larg;
      uint res_length;
      char *store_end;
      char buff[32];

      if (have_long)
        larg = va_arg(ap, long);
      else
        if (*fmt == 'd')
          larg = va_arg(ap, int);
        else
          larg= (long) (uint) va_arg(ap, int);
      if (*fmt == 'd')
	    store_end= int10_to_str(larg, buff, -10);
      else
        if (*fmt== 'u')
          store_end= int10_to_str(larg, buff, 10);
        else
          store_end= int2str(larg, buff, 16, 0);
      res_length= (uint) (store_end - buff);
      /* If %#d syntax was used, we have to pre-zero/pre-space the string */
      str->append_with_prefill(buff, res_length, length, pre_zero ? '0' : ' ');
      continue;
    }
    else if (*fmt == 'c')                       /* Character parameter */
    {
      register int larg;
      larg = va_arg(ap, int);
      str->append((char) larg);
      continue;
    }

    /* We come here on '%%', unknown code or too long parameter */
    str->append('%');				/* % used as % or unknown code */
  }
  return str;
}

String *my_strprintf(String *str, const char* fmt, ...)
{
  String *result;
  va_list ap;
  
  va_start(ap, fmt);
  
  result= my_vstrprintf(str, fmt, ap);
  
  va_end(ap);
  
  return result;
}

--- New file ---
+++ sql/sql_logger.h	07/03/12 10:52:21
/* 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 */


typedef int (*mysql_logger_func)(THD *thd, void *data, time_t start_time,
								 enum loglevel log_level,
								 enum enum_server_command command,
								 const char *format, va_list args);

struct mysql_logger
{
  void *data;
  mysql_logger_func prefix_log;
  mysql_logger_func suffix_log;
  mysql_logger_func error_log;
  my_bool (*flush_logs)(THD *thd, void *data);
};


struct logger_cache
{
  uint version;
  struct st_plugin_int **loggers;
};

#ifdef __cplusplus
extern "C" {
#endif

int mysql_prefix_log(THD *thd, time_t start_time, enum loglevel log_level,
			    const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5);
int mysql_suffix_log(THD *thd, time_t start_time, enum loglevel log_level,
				const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5);
int mysql_error_log(THD *thd, time_t start_time, enum loglevel log_level,
				const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5);

void sql_perror(const char *message);

void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void sql_print_information(const char *format, ...)
  ATTRIBUTE_FORMAT(printf, 1, 2);

#ifdef __cplusplus
};
#endif

bool general_log_print(THD *thd, enum enum_server_command command,
                       const char *format,...) ATTRIBUTE_FORMAT(printf, 3, 4);

String *my_vstrprintf(String *str, const char *fmt, va_list args);
String *my_strprintf(String *str, const char *fmt, ...);

bool flush_error_log(THD *thd);

int intern_error_log(THD *thd, time_t start_time, enum loglevel log_level,
			 		 const char *format, va_list args);


void logger_cache_prepare(THD *thd);
void logger_cache_check(THD *thd);
void logger_cache_release(THD *thd);
void logger_cache_notify(void);
void logger_cache_init(void);
void logger_cache_done(void);


/* init/deinit used by sql_plugin.cc */
int initialize_logger(st_plugin_int *plugin);
int finalize_logger(st_plugin_int *plugin);


--- 1.32/sql/event_scheduler.cc	2007-03-12 10:52:51 -07:00
+++ 1.33/sql/event_scheduler.cc	2007-03-12 10:52:51 -07:00
@@ -90,9 +90,22 @@
     err_msg.append(prefix);
     err_msg.append(err->msg, strlen(err->msg), system_charset_info);
     err_msg.append("]");
-    DBUG_ASSERT(err->level < 3);
-    (sql_print_message_handlers[err->level])("%*s", err_msg.length(),
-                                              err_msg.c_ptr());
+    switch (err->level) {
+    case MYSQL_ERROR::WARN_LEVEL_NOTE:
+      mysql_error_log(thd, time(NULL), INFORMATION_LEVEL,
+                      "%*s", err_msg.length(), err_msg.c_ptr_quick());
+      continue;
+    case MYSQL_ERROR::WARN_LEVEL_WARN:
+      mysql_error_log(thd, time(NULL), WARNING_LEVEL,
+                      "%*s", err_msg.length(), err_msg.c_ptr_quick());
+      continue;
+    case MYSQL_ERROR::WARN_LEVEL_ERROR:
+      mysql_error_log(thd, time(NULL), ERROR_LEVEL,
+                      "%*s", err_msg.length(), err_msg.c_ptr_quick());
+      continue;
+    default:
+      DBUG_ASSERT(0);
+    }
   }
   DBUG_VOID_RETURN;
 }

--- 1.75/storage/csv/ha_tina.cc	2007-03-12 10:52:51 -07:00
+++ 1.76/storage/csv/ha_tina.cc	2007-03-12 10:52:51 -07:00
@@ -785,17 +785,6 @@
 }
 
 
-bool ha_tina::check_if_locking_is_allowed(uint sql_command,
-                                          ulong type, TABLE *table,
-                                          uint count,
-                                          bool called_by_privileged_thread)
-{
-  if (!called_by_privileged_thread)
-    return check_if_log_table_locking_is_allowed(sql_command, type, table);
-
-  return TRUE;
-}
-
 /*
   Open a database file. Keep in mind that tables are caches, so
   this will not be called for every request. Any sort of positions

--- 1.27/storage/csv/ha_tina.h	2007-03-12 10:52:51 -07:00
+++ 1.28/storage/csv/ha_tina.h	2007-03-12 10:52:51 -07:00
@@ -126,10 +126,6 @@
   */
   ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; }
 
-  virtual bool check_if_locking_is_allowed(uint sql_command,
-                                           ulong type, TABLE *table,
-                                           uint count,
-                                           bool called_by_logger_thread);
   int open(const char *name, int mode, uint open_options);
   int close(void);
   int write_row(byte * buf);

--- 1.22/sql/log.h	2007-03-12 10:52:51 -07:00
+++ 1.23/sql/log.h	2007-03-12 10:52:51 -07:00
@@ -384,223 +384,6 @@
   inline uint32 get_open_count() { return open_count; }
 };
 
-class Log_event_handler
-{
-public:
-  Log_event_handler() {}
-  virtual bool init()= 0;
-  virtual void cleanup()= 0;
-
-  virtual bool log_slow(THD *thd, time_t current_time,
-                        time_t query_start_arg, const char *user_host,
-                        uint user_host_len, longlong query_time,
-                        longlong lock_time, bool is_command,
-                        const char *sql_text, uint sql_text_len)= 0;
-  virtual bool log_error(enum loglevel level, const char *format,
-                         va_list args)= 0;
-  virtual bool log_general(time_t event_time, const char *user_host,
-                           uint user_host_len, int thread_id,
-                           const char *command_type, uint command_type_len,
-                           const char *sql_text, uint sql_text_len,
-                           CHARSET_INFO *client_cs)= 0;
-  virtual ~Log_event_handler() {}
-};
-
-
-int check_if_log_table(uint db_len, const char *db, uint table_name_len,
-                       const char *table_name, uint check_if_opened);
-
-class Log_to_csv_event_handler: public Log_event_handler
-{
-  /*
-    We create artificial THD for each of the logs. This is to avoid
-    locking issues: we don't want locks on the log tables reside in the
-    THD's of the query. The reason is the locking order and duration.
-  */
-  THD *general_log_thd, *slow_log_thd;
-  /*
-    This is for the thread, which called tmp_close_log_tables. The thread
-    will be allowed to write-lock the log tables (as it explicitly disabled
-    logging). This is used for such operations as REPAIR, which require
-    exclusive lock on the log tables.
-    NOTE: there can be only one priviliged thread, as one should
-    lock logger with logger.lock() before calling tmp_close_log_tables().
-    So no other thread could get privileged status at the same time.
-  */
-  THD *privileged_thread;
-  friend class LOGGER;
-  TABLE_LIST general_log, slow_log;
-
-private:
-  bool open_log_table(uint log_type);
-
-public:
-  Log_to_csv_event_handler();
-  ~Log_to_csv_event_handler();
-  virtual bool init();
-  virtual void cleanup();
-
-  virtual bool log_slow(THD *thd, time_t current_time,
-                        time_t query_start_arg, const char *user_host,
-                        uint user_host_len, longlong query_time,
-                        longlong lock_time, bool is_command,
-                        const char *sql_text, uint sql_text_len);
-  virtual bool log_error(enum loglevel level, const char *format,
-                         va_list args);
-  virtual bool log_general(time_t event_time, const char *user_host,
-                           uint user_host_len, int thread_id,
-                           const char *command_type, uint command_type_len,
-                           const char *sql_text, uint sql_text_len,
-                            CHARSET_INFO *client_cs);
-  void tmp_close_log_tables(THD *thd);
-  void close_log_table(uint log_type, bool lock_in_use);
-  bool reopen_log_table(uint log_type);
-  THD* get_privileged_thread()
-  {
-    return privileged_thread;
-  }
-};
-
-
-/* type of the log table */
-#define QUERY_LOG_SLOW 1
-#define QUERY_LOG_GENERAL 2
-
-class Log_to_file_event_handler: public Log_event_handler
-{
-  MYSQL_QUERY_LOG mysql_log;
-  MYSQL_QUERY_LOG mysql_slow_log;
-  bool is_initialized;
-public:
-  Log_to_file_event_handler(): is_initialized(FALSE)
-  {}
-  virtual bool init();
-  virtual void cleanup();
-
-  virtual bool log_slow(THD *thd, time_t current_time,
-                        time_t query_start_arg, const char *user_host,
-                        uint user_host_len, longlong query_time,
-                        longlong lock_time, bool is_command,
-                        const char *sql_text, uint sql_text_len);
-  virtual bool log_error(enum loglevel level, const char *format,
-                         va_list args);
-  virtual bool log_general(time_t event_time, const char *user_host,
-                           uint user_host_len, int thread_id,
-                           const char *command_type, uint command_type_len,
-                           const char *sql_text, uint sql_text_len,
-                           CHARSET_INFO *client_cs);
-  void flush();
-  void init_pthread_objects();
-  MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; }
-  MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; }
-};
-
-
-/* Class which manages slow, general and error log event handlers */
-class LOGGER
-{
-  pthread_mutex_t LOCK_logger;
-  /* flag to check whether logger mutex is initialized */
-  uint inited;
-
-  /* available log handlers */
-  Log_to_csv_event_handler *table_log_handler;
-  Log_to_file_event_handler *file_log_handler;
-
-  /* NULL-terminated arrays of log handlers */
-  Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
-  Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
-  Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1];
-
-public:
-
-  bool is_log_tables_initialized;
-
-  LOGGER() : inited(0), table_log_handler(NULL),
-             file_log_handler(NULL), is_log_tables_initialized(FALSE)
-  {}
-  void lock() { (void) pthread_mutex_lock(&LOCK_logger); }
-  void unlock() { (void) pthread_mutex_unlock(&LOCK_logger); }
-  void tmp_close_log_tables(THD *thd);
-  bool is_log_table_enabled(uint log_table_type)
-  {
-    switch (log_table_type) {
-    case QUERY_LOG_SLOW:
-      return table_log_handler && table_log_handler->slow_log.table != 0;
-    case QUERY_LOG_GENERAL:
-      return table_log_handler && table_log_handler->general_log.table != 0;
-    default:
-      DBUG_ASSERT(0);
-      return FALSE;                             /* make compiler happy */
-    }
-  }
-  /*
-    We want to initialize all log mutexes as soon as possible,
-    but we cannot do it in constructor, as safe_mutex relies on
-    initialization, performed by MY_INIT(). This why this is done in
-    this function.
-  */
-  void init_base();
-  void init_log_tables();
-  bool flush_logs(THD *thd);
-  THD *get_general_log_thd()
-  {
-    if (table_log_handler)
-      return (THD *) table_log_handler->general_log_thd;
-    else
-      return NULL;
-  }
-  THD *get_slow_log_thd()
-  {
-    if (table_log_handler)
-      return (THD *) table_log_handler->slow_log_thd;
-    else
-      return NULL;
-  }
-  /* Perform basic logger cleanup. this will leave e.g. error log open. */
-  void cleanup_base();
-  /* Free memory. Nothing could be logged after this function is called */
-  void cleanup_end();
-  bool error_log_print(enum loglevel level, const char *format,
-                      va_list args);
-  bool slow_log_print(THD *thd, const char *query, uint query_length,
-                      time_t query_start_arg);
-  bool general_log_print(THD *thd,enum enum_server_command command,
-                         const char *format, va_list args);
-
-  void close_log_table(uint log_type, bool lock_in_use);
-  bool reopen_log_table(uint log_type);
-  bool reopen_log_tables();
-
-  /* we use this function to setup all enabled log event handlers */
-  int set_handlers(uint error_log_printer,
-                   uint slow_log_printer,
-                   uint general_log_printer);
-  void init_error_log(uint error_log_printer);
-  void init_slow_log(uint slow_log_printer);
-  void init_general_log(uint general_log_printer);
-  void deactivate_log_handler(THD* thd, uint log_type);
-  bool activate_log_handler(THD* thd, uint log_type);
-  MYSQL_QUERY_LOG *get_slow_log_file_handler()
-  { 
-    if (file_log_handler)
-      return file_log_handler->get_mysql_slow_log();
-    return NULL;
-  }
-  MYSQL_QUERY_LOG *get_log_file_handler()
-  { 
-    if (file_log_handler)
-      return file_log_handler->get_mysql_log();
-    return NULL;
-  }
-  THD* get_privileged_thread()
-  {
-    if (table_log_handler)
-      return table_log_handler->get_privileged_thread();
-    else
-      return NULL;
-  }
-};
 
 enum enum_binlog_format {
   BINLOG_FORMAT_STMT= 0, // statement-based

--- 1.43/sql/sql_rename.cc	2007-03-12 10:52:51 -07:00
+++ 1.44/sql/sql_rename.cc	2007-03-12 10:52:51 -07:00
@@ -35,9 +35,6 @@
 {
   bool error= 1;
   TABLE_LIST *ren_table= 0;
-  int to_table;
-  char *rename_log_table[2]= {NULL, NULL};
-  int disable_logs= 0;
   DBUG_ENTER("mysql_rename_tables");
 
   /*
@@ -55,95 +52,6 @@
   if (wait_if_global_read_lock(thd,0,1))
     DBUG_RETURN(1);
 
-  if (logger.is_log_table_enabled(QUERY_LOG_GENERAL) ||
-      logger.is_log_table_enabled(QUERY_LOG_SLOW))
-  {
-
-    /*
-      Rules for rename of a log table:
-
-      IF   1. Log tables are enabled
-      AND  2. Rename operates on the log table and nothing is being
-              renamed to the log table.
-      DO   3. Throw an error message.
-      ELSE 4. Perform rename.
-    */
-
-    for (to_table= 0, ren_table= table_list; ren_table;
-         to_table= 1 - to_table, ren_table= ren_table->next_local)
-    {
-      int log_table_rename= 0;
-
-      if ((log_table_rename=
-           check_if_log_table(ren_table->db_length, ren_table->db,
-                              ren_table->table_name_length,
-                              ren_table->table_name, 1)))
-      {
-        /*
-          Log table encoutered we will need to disable and lock logs
-          for duration of rename.
-        */
-        disable_logs= TRUE;
-
-        /*
-          as we use log_table_rename as an array index, we need it to start
-          with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2.
-          So, we shift the value to start with 0;
-        */
-        log_table_rename--;
-        if (rename_log_table[log_table_rename])
-        {
-          if (to_table)
-            rename_log_table[log_table_rename]= NULL;
-          else
-          {
-            /*
-              Two renames of "log_table TO" w/o rename "TO log_table" in
-              between.
-            */
-            my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name,
-                     ren_table->table_name);
-            DBUG_RETURN(1);
-          }
-        }
-        else
-        {
-          if (to_table)
-          {
-            /*
-              Attempt to rename a table TO log_table w/o renaming
-              log_table TO some table.
-            */
-            my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name,
-                     ren_table->table_name);
-            DBUG_RETURN(1);
-          }
-          else
-          {
-            /* save the name of the log table to report an error */
-            rename_log_table[log_table_rename]= ren_table->table_name;
-          }
-        }
-      }
-    }
-    if (rename_log_table[0] || rename_log_table[1])
-    {
-      if (rename_log_table[0])
-        my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[0],
-                 rename_log_table[0]);
-      else
-        my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[1],
-                 rename_log_table[1]);
-      DBUG_RETURN(1);
-    }
-
-    if (disable_logs)
-    {
-      logger.lock();
-      logger.tmp_close_log_tables(thd);
-    }
-  }
-
   VOID(pthread_mutex_lock(&LOCK_open));
   if (lock_table_names(thd, table_list))
     goto err;
@@ -187,13 +95,6 @@
 
 err:
   pthread_mutex_unlock(&LOCK_open);
-  /* enable logging back if needed */
-  if (disable_logs)
-  {
-    if (logger.reopen_log_tables())
-      error= TRUE;
-    logger.unlock();
-  }
   start_waiting_global_read_lock(thd);
   DBUG_RETURN(error);
 }

--- 1.217/sql/set_var.cc	2007-03-12 10:52:51 -07:00
+++ 1.218/sql/set_var.cc	2007-03-12 10:52:51 -07:00
@@ -153,11 +153,6 @@
 static byte *get_error_count(THD *thd);
 static byte *get_warning_count(THD *thd);
 static byte *get_tmpdir(THD *thd);
-static int  sys_check_log_path(THD *thd,  set_var *var);
-static bool sys_update_general_log_path(THD *thd, set_var * var);
-static void sys_default_general_log_path(THD *thd, enum_var_type type);
-static bool sys_update_slow_log_path(THD *thd, set_var * var);
-static void sys_default_slow_log_path(THD *thd, enum_var_type type);
 
 /*
   Variable definition list
@@ -678,22 +673,6 @@
 /* Global read-only variable describing server license */
 sys_var_const_str		sys_license("license", STRINGIFY_ARG(LICENSE));
 
-/* Global variables which enable|disable logging */
-sys_var_log_state sys_var_general_log("general_log", &opt_log,
-                                      QUERY_LOG_GENERAL);
-sys_var_log_state sys_var_slow_query_log("slow_query_log", &opt_slow_log,
-                                         QUERY_LOG_SLOW);
-sys_var_str sys_var_general_log_path("general_log_file", sys_check_log_path,
-				     sys_update_general_log_path,
-				     sys_default_general_log_path,
-				     opt_logname);
-sys_var_str sys_var_slow_log_path("slow_query_log_file", sys_check_log_path,
-				  sys_update_slow_log_path, 
-				  sys_default_slow_log_path,
-				  opt_slow_logname);
-sys_var_log_output sys_var_log_output_state("log_output", &log_output_options,
-					    &log_output_typelib, 0);
-
 #ifdef HAVE_REPLICATION
 static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff)
 {
@@ -783,8 +762,6 @@
   {"ft_min_word_len",         (char*) &ft_min_word_len,             SHOW_LONG},
   {"ft_query_expansion_limit",(char*) &ft_query_expansion_limit,    SHOW_LONG},
   {"ft_stopword_file",        (char*) &ft_stopword_file,            SHOW_CHAR_PTR},
-  {sys_var_general_log.name, (char*) &opt_log,                      SHOW_MY_BOOL},
-  {sys_var_general_log_path.name, (char*) &sys_var_general_log_path,  SHOW_SYS},
   {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len,  SHOW_SYS},
   {sys_have_compress.name,    (char*) &have_compress,               SHOW_HAVE},
   {sys_have_crypt.name,       (char*) &have_crypt,                  SHOW_HAVE},
@@ -859,7 +836,6 @@
   {"log_bin",                 (char*) &opt_bin_log,                 SHOW_BOOL},
   {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS},
   {"log_error",               (char*) log_error_file,               SHOW_CHAR},
-  {sys_var_log_output_state.name, (char*) &sys_var_log_output_state, SHOW_SYS},
   {sys_log_queries_not_using_indexes.name,
     (char*) &sys_log_queries_not_using_indexes, SHOW_SYS},
 #ifdef HAVE_REPLICATION
@@ -984,8 +960,6 @@
   {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries,   SHOW_SYS},
 #endif
   {sys_slow_launch_time.name, (char*) &sys_slow_launch_time,        SHOW_SYS},
-  {sys_var_slow_query_log.name, (char*) &opt_slow_log,              SHOW_MY_BOOL},
-  {sys_var_slow_log_path.name, (char*) &sys_var_slow_log_path,      SHOW_SYS},
 #ifdef HAVE_SYS_UN_H
   {"socket",                  (char*) &mysqld_unix_port,             SHOW_CHAR_PTR},
 #endif
@@ -2520,207 +2494,6 @@
 end:
   pthread_mutex_unlock(&LOCK_global_system_variables);
   return error;
-}
-
-
-bool sys_var_log_state::update(THD *thd, set_var *var)
-{
-  bool res= 0;
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  if (!var->save_result.ulong_value)
-    logger.deactivate_log_handler(thd, log_type);
-  else
-  {
-    if ((res= logger.activate_log_handler(thd, log_type)))
-    {
-      my_error(ER_CANT_ACTIVATE_LOG, MYF(0),
-               log_type == QUERY_LOG_GENERAL ? "general" :
-               "slow query");
-      goto err;
-    }
-  }
-err:
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-  return res;
-}
-
-void sys_var_log_state::set_default(THD *thd, enum_var_type type)
-{
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  logger.deactivate_log_handler(thd, log_type);
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-}
-
-
-static int  sys_check_log_path(THD *thd,  set_var *var)
-{
-  char path[FN_REFLEN];
-  MY_STAT f_stat;
-  const char *var_path= var->value->str_value.ptr();
-  bzero(&f_stat, sizeof(MY_STAT));
-
-  (void) unpack_filename(path, var_path);
-  if (my_stat(path, &f_stat, MYF(0)))
-  {
-    /* Check if argument is a file and we have 'write' permission */
-    if (!MY_S_ISREG(f_stat.st_mode) ||
-        !(f_stat.st_mode & MY_S_IWRITE))
-      return -1;
-  }
-  else
-  {
-    /*
-      Check if directory exists and 
-      we have permission to create file & write to file
-    */
-    (void) dirname_part(path, var_path);
-    if (my_access(path, (F_OK|W_OK)))
-      return -1;
-  }
-  return 0;
-}
-
-
-bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
-			     set_var *var, const char *log_ext,
-			     bool log_state, uint log_type)
-{
-  MYSQL_QUERY_LOG *file_log;
-  char buff[FN_REFLEN];
-  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
-  bool result= 0;
-  uint str_length= (var ? var->value->str_value.length() : 0);
-
-  switch (log_type) {
-  case QUERY_LOG_SLOW:
-    file_log= logger.get_slow_log_file_handler();
-    break;
-  case QUERY_LOG_GENERAL:
-    file_log= logger.get_log_file_handler();
-    break;
-  default:
-    assert(0);                                  // Impossible
-  }
-
-  if (!old_value)
-  {
-    old_value= make_default_log_name(buff, log_ext);
-    str_length= strlen(old_value);
-  }
-  if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
-  {
-    result= 1;
-    goto err;
-  }
-
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  logger.lock();
-
-  if (file_log && log_state)
-    file_log->close(0);
-  old_value= var_str->value;
-  var_str->value= res;
-  var_str->value_length= str_length;
-  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
-  if (file_log && log_state)
-  {
-    switch (log_type) {
-    case QUERY_LOG_SLOW:
-      file_log->open_slow_log(sys_var_general_log_path.value);
-      break;
-    case QUERY_LOG_GENERAL:
-      file_log->open_query_log(sys_var_general_log_path.value);
-      break;
-    default:
-      DBUG_ASSERT(0);
-    }
-  }
-
-  logger.unlock();
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-
-err:
-  return result;
-}
-
-
-static bool sys_update_general_log_path(THD *thd, set_var * var)
-{
-  return update_sys_var_str_path(thd, &sys_var_general_log_path, 
-				 var, ".log", opt_log, QUERY_LOG_GENERAL);
-}
-
-
-static void sys_default_general_log_path(THD *thd, enum_var_type type)
-{
-  (void) update_sys_var_str_path(thd, &sys_var_general_log_path,
-				 0, ".log", opt_log, QUERY_LOG_GENERAL);
-}
-
-
-static bool sys_update_slow_log_path(THD *thd, set_var * var)
-{
-  return update_sys_var_str_path(thd, &sys_var_slow_log_path,
-				 var, "-slow.log", opt_slow_log,
-                                 QUERY_LOG_SLOW);
-}
-
-
-static void sys_default_slow_log_path(THD *thd, enum_var_type type)
-{
-  (void) update_sys_var_str_path(thd, &sys_var_slow_log_path,
-				 0, "-slow.log", opt_slow_log,
-                                 QUERY_LOG_SLOW);
-}
-
-
-bool sys_var_log_output::update(THD *thd, set_var *var)
-{
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  logger.lock();
-  logger.init_slow_log(var->save_result.ulong_value);
-  logger.init_general_log(var->save_result.ulong_value);
-  *value= var->save_result.ulong_value;
-  logger.unlock();
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-  return 0;
-}
-
-
-void sys_var_log_output::set_default(THD *thd, enum_var_type type)
-{
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  logger.lock();
-  logger.init_slow_log(LOG_TABLE);
-  logger.init_general_log(LOG_TABLE);
-  *value= LOG_TABLE;
-  logger.unlock();
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-}
-
-
-byte *sys_var_log_output::value_ptr(THD *thd, enum_var_type type,
-                                    LEX_STRING *base)
-{
-  char buff[256];
-  String tmp(buff, sizeof(buff), &my_charset_latin1);
-  ulong length;
-  ulong val= *value;
-
-  tmp.length(0);
-  for (uint i= 0; val; val>>= 1, i++)
-  {
-    if (val & 1)
-    {
-      tmp.append(log_output_typelib.type_names[i],
-                 log_output_typelib.type_lengths[i]);
-      tmp.append(',');
-    }
-  }
-
-  if ((length= tmp.length()))
-    length--;
-  return (byte*) thd->strmake(tmp.ptr(), length);
 }
 
 

--- 1.102/sql/set_var.h	2007-03-12 10:52:51 -07:00
+++ 1.103/sql/set_var.h	2007-03-12 10:52:51 -07:00
@@ -775,38 +775,6 @@
 };
 
 
-class sys_var_log_state :public sys_var_bool_ptr
-{
-  uint log_type;
-public:
-  sys_var_log_state(const char *name_arg, my_bool *value_arg, uint log_type_arg)
-    :sys_var_bool_ptr(name_arg, value_arg), log_type(log_type_arg) {}
-  bool update(THD *thd, set_var *var);
-  void set_default(THD *thd, enum_var_type type);
-};
-
-
-class sys_var_log_output :public sys_var
-{
-  ulong *value;
-  TYPELIB *enum_names;
-public:
-  sys_var_log_output(const char *name_arg, ulong *value_arg,
-                     TYPELIB *typelib, sys_after_update_func func)
-    :sys_var(name_arg,func), value(value_arg), enum_names(typelib)
-  {}
-  bool check(THD *thd, set_var *var)
-  {
-    return check_set(thd, var, enum_names);
-  }
-  bool update(THD *thd, set_var *var);
-  byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
-  bool check_update_type(Item_result type) { return 0; }
-  void set_default(THD *thd, enum_var_type type);
-  SHOW_TYPE show_type() { return SHOW_CHAR; }
-};
-
-
 /* Variable that you can only read from */
 
 class sys_var_readonly: public sys_var

--- 1.26/include/mysql/plugin.h	2007-03-12 10:52:51 -07:00
+++ 1.27/include/mysql/plugin.h	2007-03-12 10:52:51 -07:00
@@ -30,7 +30,8 @@
 #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_LOGGING_PLUGIN         5	/* query log 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
@@ -344,6 +345,25 @@
 */
 
 struct st_mysql_information_schema
+{
+  int interface_version;
+};
+
+
+/*************************************************************************
+  API for Logging plugins. (MYSQL_LOGGING_PLUGIN)
+*/
+
+/* THDs of different MySQL releases are incompatible */
+#define MYSQL_LOGGING_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)
+
+/*
+  The real API is in the sql/sql_logger.h
+  Here we define only the descriptor structure, that is referred from
+  st_mysql_plugin.
+*/
+
+struct st_mysql_logging
 {
   int interface_version;
 };

--- 1.44/sql/sql_plugin.cc	2007-03-12 10:52:51 -07:00
+++ 1.45/sql/sql_plugin.cc	2007-03-12 10:52:51 -07:00
@@ -23,16 +23,20 @@
 char *opt_plugin_dir_ptr;
 char opt_plugin_dir[FN_REFLEN];
 /*
-  When you ad a new plugin type, add both a string and make sure that the 
+  When you add a new plugin type, add both a string and make sure that the 
   init and deinit array are correctly updated.
+  The final entry is unused and is present only to ensure that addional
+  lines may be added without requiring the previous line to be edited.
 */
-const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
 {
   { C_STRING_WITH_LEN("UDF") },
   { 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("LOGGING") },
+  { NULL, 0 }
 };
 
 extern int initialize_schema_table(st_plugin_int *plugin);
@@ -42,15 +46,28 @@
   The number of elements in both plugin_type_initialize and 
   plugin_type_deinitialize should equal to the number of plugins
   defined.
+  The final entry is unused and is present only to ensure that addional
+  lines may be added without requiring the previous line to be edited.
 */  
-plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
 {
-  0,ha_initialize_handlerton,0,0,initialize_schema_table
+  0,ha_initialize_handlerton,0,0,initialize_schema_table,
+  initialize_logger,
+  NULL
 };
 
-plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
 {
-  0,ha_finalize_handlerton,0,0,finalize_schema_table
+  0,ha_finalize_handlerton,0,0,finalize_schema_table,
+  finalize_logger,
+  NULL
+};
+
+plugin_type_notify plugin_type_notifydel[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
+{
+  0,0,0,0,0,
+  logger_cache_notify,
+  NULL
 };
 
 #ifdef HAVE_DLOPEN
@@ -64,22 +81,28 @@
 
 /* Note that 'int version' must be the first field of every plugin
    sub-structure (plugin->info).
+  The final entry is unused and is present only to ensure that addional
+  lines may be added without requiring the previous line to be edited.
 */
-static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
 {
   0x0000,
   MYSQL_HANDLERTON_INTERFACE_VERSION,
   MYSQL_FTPARSER_INTERFACE_VERSION,
   MYSQL_DAEMON_INTERFACE_VERSION,
-  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+  MYSQL_LOGGING_INTERFACE_VERSION,
+  0
 };
-static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM+1]=
 {
   0x0000, /* UDF: not implemented */
   MYSQL_HANDLERTON_INTERFACE_VERSION,
   MYSQL_FTPARSER_INTERFACE_VERSION,
   MYSQL_DAEMON_INTERFACE_VERSION,
-  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
+  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
+  MYSQL_LOGGING_INTERFACE_VERSION,
+  0
 };
 
 static DYNAMIC_ARRAY plugin_dl_array;
@@ -411,6 +434,35 @@
 }
 
 
+struct st_plugin_int **plugin_lockall(int type)
+{
+  struct st_plugin_int **plugins, **list;
+  struct st_plugin_int *plugin;
+  HASH *hash= plugin_hash+ type;
+  uint idx, total;
+  DBUG_ENTER("plugin_lockall");
+  rw_wrlock(&THR_LOCK_plugin);
+  total= hash->records;
+  if ((plugins= (struct st_plugin_int **) my_malloc(sizeof(void*)*(total+1),
+                                                    MYF(MY_WME))))
+  {
+    list= plugins;
+    for (idx= 0; idx < total; idx++)
+    {
+      plugin= (struct st_plugin_int *) hash_element(hash, idx);
+      if (plugin->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED))
+      {
+        plugin->ref_count++;
+        *list++= plugin;
+      }
+    }
+  }
+  rw_unlock(&THR_LOCK_plugin);
+  *list= NULL;
+  DBUG_RETURN(plugins);
+}
+
+
 static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
 {
   uint i;
@@ -477,6 +529,7 @@
       tmp.name.length= name_len;
       tmp.ref_count= 0;
       tmp.state= PLUGIN_IS_UNINITIALIZED;
+	  tmp.data= NULL;
       if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
         goto err;
       plugin_array_version++;
@@ -581,6 +634,30 @@
 }
 
 
+void plugin_unlockall(struct st_plugin_int **plugins)
+{
+  struct st_plugin_int *plugin, **list;
+  DBUG_ENTER("plugin_unlockall");
+  if ((list= plugins))
+  {
+    rw_wrlock(&THR_LOCK_plugin);
+	while ((plugin= *list++))
+	{
+      DBUG_ASSERT(plugin && plugin->ref_count);
+      plugin->ref_count--;
+      if (plugin->state == PLUGIN_IS_DELETED && ! plugin->ref_count)
+      {
+        plugin_deinitialize(plugin);
+        plugin_del(plugin);
+      }
+    }
+    rw_unlock(&THR_LOCK_plugin);
+	my_free((gptr) plugins, MYF(0));
+  }
+  DBUG_VOID_RETURN;
+}
+
+
 static int plugin_initialize(struct st_plugin_int *plugin)
 {
   DBUG_ENTER("plugin_initialize");
@@ -732,6 +809,7 @@
   tmp.name.str= (char *)plugin->name;
   tmp.name.length= strlen(plugin->name);
   tmp.state= PLUGIN_IS_UNINITIALIZED;
+  tmp.data= NULL;
 
   /* Cannot be unloaded */
   tmp.ref_count= 1;
@@ -933,6 +1011,8 @@
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
                  "Plugin is busy and will be uninstalled on shutdown");
     plugin->state= PLUGIN_IS_DELETED;
+	if (plugin_type_notifydel[plugin->plugin->type])
+	  plugin_type_notifydel[plugin->plugin->type]();
   }
   else
   {

--- 1.13/sql/sql_plugin.h	2007-03-12 10:52:51 -07:00
+++ 1.14/sql/sql_plugin.h	2007-03-12 10:52:51 -07:00
@@ -66,6 +66,7 @@
 };
 
 typedef int (*plugin_type_init)(struct st_plugin_int *);
+typedef void (*plugin_type_notify)(void);
 
 extern char *opt_plugin_dir_ptr;
 extern char opt_plugin_dir[FN_REFLEN];
@@ -75,6 +76,8 @@
 extern my_bool plugin_is_ready(const LEX_STRING *name, int type);
 extern st_plugin_int *plugin_lock(const LEX_STRING *name, int type);
 extern void plugin_unlock(struct st_plugin_int *plugin);
+extern st_plugin_int **plugin_lockall(int type);
+extern void plugin_unlockall(struct st_plugin_int **plugin);
 extern my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING
*dl);
 extern my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name);
 

--- 1.109/libmysqld/Makefile.am	2007-03-12 10:52:51 -07:00
+++ 1.110/libmysqld/Makefile.am	2007-03-12 10:52:51 -07:00
@@ -74,6 +74,7 @@
 	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_logger.cc \
 	sql_servers.cc
 
 libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)

--- 1.132/libmysqld/lib_sql.cc	2007-03-12 10:52:51 -07:00
+++ 1.133/libmysqld/lib_sql.cc	2007-03-12 10:52:51 -07:00
@@ -470,12 +470,6 @@
 
   my_progname= (char *)"mysql_embedded";
 
-  /*
-    Perform basic logger initialization logger. Should be called after
-    MY_INIT, as it initializes mutexes. Log tables are inited later.
-  */
-  logger.init_base();
-
   if (init_common_variables("my", *argcp, *argvp, (const char **)groups))
   {
     mysql_server_end();

--- 1.252/sql/sp_head.cc	2007-03-12 10:52:51 -07:00
+++ 1.253/sql/sp_head.cc	2007-03-12 10:52:51 -07:00
@@ -2522,9 +2522,9 @@
 					  thd->query, thd->query_length) <= 0)
     {
       res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
-      if (!res && unlikely(thd->enable_slow_log))
-        log_slow_statement(thd);
       query_cache_end_of_result(thd);
+	  if (!res)
+	    post_statement_log(thd);
     }
     else
       *nextp= m_ip+1;
Thread
bk commit into 5.1 tree (acurtis:1.2466)antony12 Mar