diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index ac4b67928b1dc9458569c87b744a8ebddbbd31e3..637388dc441d0347c662422ad3a9fe7780b58e64 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -428,7 +428,7 @@ static void ndbcluster_binlog_wait(THD *thd)
 }
 
 /*
- Called from MYSQL_LOG::reset_logs in log.cc when binlog is emptied
+ Called from MYSQL_BIN_LOG::reset_logs in log.cc when binlog is emptied
 */
 static int ndbcluster_reset_logs(THD *thd)
 {
@@ -452,7 +452,7 @@ static int ndbcluster_reset_logs(THD *thd)
 }
 
 /*
-  Called from MYSQL_LOG::purge_logs in log.cc when the binlog "file"
+  Called from MYSQL_BIN_LOG::purge_logs in log.cc when the binlog "file"
   is removed
 */
 
diff --git a/sql/log.cc b/sql/log.cc
index e9a5011db4dfa9921465a6d8feb946b49256bd5e..d1c33afcda7a5673cb5fb41d7fc770a41984311f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -42,7 +42,7 @@ extern char *opt_logname, *opt_slow_logname;
 
 LOGGER logger;
 
-MYSQL_LOG mysql_bin_log;
+MYSQL_BIN_LOG mysql_bin_log;
 ulong sync_binlog_counter= 0;
 
 static bool test_if_number(const char *str,
@@ -557,9 +557,8 @@ void Log_to_file_event_handler::cleanup()
 
 void Log_to_file_event_handler::flush()
 {
-  /* reopen log files */
-  mysql_log.new_file(1);
-  mysql_slow_log.new_file(1);
+  mysql_log.reopen_file();
+  mysql_slow_log.reopen_file();
 }
 
 /*
@@ -1054,7 +1053,7 @@ void Log_to_csv_event_handler::
 
 /*
   this function is mostly a placeholder.
-  conceptually, binlog initialization (now mostly done in MYSQL_LOG::open)
+  conceptually, binlog initialization (now mostly done in MYSQL_BIN_LOG::open)
   should be moved here.
 */
 
@@ -1128,7 +1127,7 @@ static int binlog_prepare(THD *thd, bool all)
     do nothing.
     just pretend we can do 2pc, so that MySQL won't
     switch to 1pc.
-    real work will be done in MYSQL_LOG::log()
+    real work will be done in MYSQL_BIN_LOG::log()
   */
   return 0;
 }
@@ -1144,7 +1143,7 @@ static int binlog_commit(THD *thd, bool all)
 
   if (trx_data->empty())
   {
-    // we're here because trans_log was flushed in MYSQL_LOG::log()
+    // we're here because trans_log was flushed in MYSQL_BIN_LOG::log()
     DBUG_RETURN(0);
   }
   Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
@@ -1382,12 +1381,125 @@ static int find_uniq_filename(char *name)
 }
 
 
+void MYSQL_LOG::init(enum_log_type log_type_arg,
+                    enum cache_type io_cache_type_arg)
+{
+  DBUG_ENTER("MYSQL_LOG::init");
+  log_type= log_type_arg;
+  io_cache_type= io_cache_type_arg;
+  DBUG_PRINT("info",("log_type: %d", log_type));
+  DBUG_VOID_RETURN;
+}
+
+
+/*
+  Open a (new) log file.
+
+  SYNOPSIS
+    open()
+
+    log_name            The name of the log to open
+    log_type_arg        The type of the log. E.g. LOG_NORMAL
+    new_name            The new name for the logfile. This is only needed
+                        when the method is used to open the binlog file.
+    io_cache_type_arg   The type of the IO_CACHE to use for this log file
+
+  DESCRIPTION
+    Open the logfile, init IO_CACHE and write startup messages
+    (in case of general and slow query logs).
+
+  RETURN VALUES
+    0   ok
+    1   error
+*/
+
+bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
+                     const char *new_name, enum cache_type io_cache_type_arg)
+{
+  char buff[FN_REFLEN];
+  File file= -1;
+  int open_flags= O_CREAT | O_BINARY;
+  DBUG_ENTER("MYSQL_LOG::open");
+  DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
+
+  write_error= 0;
+
+  init(log_type_arg, io_cache_type_arg);
+
+  if (!(name= my_strdup(log_name, MYF(MY_WME))))
+  {
+    name= (char *)log_name; // for the error message
+    goto err;
+  }
+
+  if (new_name)
+    strmov(log_file_name, new_name);
+  else if (generate_new_name(log_file_name, name))
+    goto err;
+
+  if (io_cache_type == SEQ_READ_APPEND)
+    open_flags |= O_RDWR | O_APPEND;
+  else
+    open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
+
+  db[0]= 0;
+
+  if ((file= my_open(log_file_name, open_flags,
+                     MYF(MY_WME | ME_WAITTANG))) < 0 ||
+      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
+                    my_tell(file, MYF(MY_WME)), 0,
+                    MYF(MY_WME | MY_NABP |
+                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
+    goto err;
+
+  switch (log_type) {
+  case LOG_NORMAL:
+  {
+    char *end;
+    int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. "
+#ifdef EMBEDDED_LIBRARY
+		        "embedded library\n", my_progname, server_version
+#elif __NT__
+			"started with:\nTCP Port: %d, Named Pipe: %s\n",
+			my_progname, server_version, mysqld_port,
+                        mysqld_unix_port
+#else
+			"started with:\nTcp port: %d  Unix socket: %s\n",
+			my_progname, server_version, mysqld_port,
+                        mysqld_unix_port
+#endif
+                       );
+    end= strnmov(buff + len, "Time                 Id Command    Argument\n",
+                 sizeof(buff) - len);
+    if (my_b_write(&log_file, (byte*) buff, (uint) (end-buff)) ||
+	flush_io_cache(&log_file))
+      goto err;
+    break;
+  }
+  case LOG_CLOSED:				// Impossible
+  case LOG_TO_BE_OPENED:
+    DBUG_ASSERT(1);
+    break;
+  }
+
+  DBUG_RETURN(0);
+
+err:
+  sql_print_error("Could not use %s for logging (error %d). \
+Turning logging off for the whole duration of the MySQL server process. \
+To turn it on again: fix the cause, \
+shutdown the MySQL server and restart it.", name, errno);
+  if (file >= 0)
+    my_close(file, MYF(0));
+  end_io_cache(&log_file);
+  safeFree(name);
+  log_type= LOG_CLOSED;
+  DBUG_RETURN(1);
+}
+
 MYSQL_LOG::MYSQL_LOG()
-  :bytes_written(0), last_time(0), query_start(0), name(0),
-   prepared_xids(0), log_type(LOG_CLOSED), file_id(1), open_count(1),
-   write_error(FALSE), inited(FALSE), need_start_event(TRUE),
-   m_table_map_version(0),
-   description_event_for_exec(0), description_event_for_queue(0)
+  : name(0),  log_type(LOG_CLOSED), write_error(FALSE),
+    inited(FALSE), last_time(0)
 {
   /*
     We don't want to initialize LOCK_Log here as such initialization depends on
@@ -1395,9 +1507,54 @@ MYSQL_LOG::MYSQL_LOG()
     called only in main(). Doing initialization here would make it happen
     before main().
   */
-  index_file_name[0] = 0;
-  bzero((char*) &log_file,sizeof(log_file));
-  bzero((char*) &index_file, sizeof(index_file));
+  bzero((char*) &log_file, sizeof(log_file));
+}
+
+void MYSQL_LOG::init_pthread_objects()
+{
+  DBUG_ASSERT(inited == 0);
+  inited= 1;
+  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
+}
+
+/*
+  Close the log file
+
+  SYNOPSIS
+    close()
+    exiting     Bitmask. For the slow and general logs the only used bit is
+                LOG_CLOSE_TO_BE_OPENED. This is used if we intend to call
+                open at once after close.
+
+  NOTES
+    One can do an open on the object at once after doing a close.
+    The internal structures are not freed until cleanup() is called
+*/
+
+void MYSQL_LOG::close(uint exiting)
+{					// One can't set log_type here!
+  DBUG_ENTER("MYSQL_LOG::close");
+  DBUG_PRINT("enter",("exiting: %d", (int) exiting));
+  if (log_type != LOG_CLOSED && log_type != LOG_TO_BE_OPENED)
+  {
+    end_io_cache(&log_file);
+
+    if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error)
+    {
+      write_error= 1;
+      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+    }
+
+    if (my_close(log_file.file, MYF(MY_WME)) && ! write_error)
+    {
+      write_error= 1;
+      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+    }
+  }
+
+  log_type= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
+  safeFree(name);
+  DBUG_VOID_RETURN;
 }
 
 /* this is called only once */
@@ -1408,17 +1565,57 @@ void MYSQL_LOG::cleanup()
   if (inited)
   {
     inited= 0;
-    close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
-    delete description_event_for_queue;
-    delete description_event_for_exec;
     (void) pthread_mutex_destroy(&LOCK_log);
-    (void) pthread_mutex_destroy(&LOCK_index);
-    (void) pthread_cond_destroy(&update_cond);
+    close(0);
   }
   DBUG_VOID_RETURN;
 }
 
 
+/*
+  Reopen the log file
+
+  SYNOPSIS
+    reopen_file()
+
+  DESCRIPTION
+    Reopen the log file. The method is used during FLUSH LOGS
+    and locks LOCK_log mutex
+*/
+
+
+void MYSQL_LOG::reopen_file()
+{
+  enum_log_type save_log_type;
+  char *save_name;
+
+  DBUG_ENTER("MYSQL_LOG::reopen_file");
+  if (!is_open())
+  {
+    DBUG_PRINT("info",("log is closed"));
+    DBUG_VOID_RETURN;
+  }
+
+  pthread_mutex_lock(&LOCK_log);
+
+  save_name= name;
+  save_log_type= log_type;
+  name= 0;				// Don't free name
+  close(LOG_CLOSE_TO_BE_OPENED);
+
+  /*
+     Note that at this point, log_type != LOG_CLOSED (important for is_open()).
+  */
+
+  open(save_name, save_log_type, 0, io_cache_type);
+  my_free(save_name, MYF(0));
+
+  pthread_mutex_unlock(&LOCK_log);
+
+  DBUG_VOID_RETURN;
+}
+
+
 int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
 {
   fn_format(new_name,log_name,mysql_data_home,"",4);
@@ -1437,33 +1634,245 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
 }
 
 
-void MYSQL_LOG::init(enum_log_type log_type_arg,
-		     enum cache_type io_cache_type_arg,
-		     bool no_auto_events_arg,
-                     ulong max_size_arg)
+/*
+  Write a command to traditional general log file
+
+  SYNOPSIS
+    write()
+
+    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 to normal (not rotable) log file
+
+  RETURN
+    FASE - OK
+    TRUE - error occured
+*/
+
+bool MYSQL_GENERAL_LOG::write(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)
 {
-  DBUG_ENTER("MYSQL_LOG::init");
-  log_type = log_type_arg;
-  io_cache_type = io_cache_type_arg;
-  no_auto_events = no_auto_events_arg;
-  max_size=max_size_arg;
-  DBUG_PRINT("info",("log_type: %d max_size: %lu", log_type, max_size));
-  DBUG_VOID_RETURN;
+  char buff[32];
+  uint length= 0;
+  char time_buff[MAX_TIME_SIZE];
+  struct tm start;
+  uint time_buff_len= 0;
+
+  /* Test if someone closed between the is_open test and lock */
+  if (is_open())
+  {
+    /* Note that my_b_write() assumes it knows the length for this */
+      if (event_time != last_time)
+      {
+        last_time= event_time;
+
+        localtime_r(&event_time, &start);
+
+        time_buff_len= my_snprintf(time_buff, MAX_TIME_SIZE,
+                                   "%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);
+
+        if (my_b_write(&log_file, (byte*) &time_buff, time_buff_len))
+          goto err;
+      }
+      else
+        if (my_b_write(&log_file, (byte*) "\t\t" ,2) < 0)
+          goto err;
+
+    /* command_type, thread_id */
+    length= my_snprintf(buff, 32, "%5ld ", thread_id);
+
+    if (my_b_write(&log_file, (byte*) buff, length))
+      goto err;
+
+    if (my_b_write(&log_file, (byte*) command_type, command_type_len))
+      goto err;
+
+    if (my_b_write(&log_file, (byte*) "\t", 1))
+      goto err;
+
+    /* sql_text */
+    if (my_b_write(&log_file, (byte*) sql_text, sql_text_len))
+      goto err;
+
+    if (my_b_write(&log_file, (byte*) "\n", 1) ||
+        flush_io_cache(&log_file))
+      goto err;
+  }
+
+  return FALSE;
+err:
+
+  if (!write_error)
+  {
+    write_error= 1;
+    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+  }
+  return TRUE;
 }
 
 
-void MYSQL_LOG::init_pthread_objects()
+/*
+  Log a query to the traditional slow log file
+
+  SYNOPSIS
+    write()
+
+    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.
+    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 file.
+
+  RETURN
+    FALSE - OK
+    TRUE - error occured
+*/
+
+bool MYSQL_SLOW_LOG::write(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)
 {
-  DBUG_ASSERT(inited == 0);
-  inited= 1;
-  (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
-  (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
-  (void) pthread_cond_init(&update_cond, 0);
+  bool error= 0;
+  DBUG_ENTER("MYSQL_SLOW_LOG::write");
+
+  if (!is_open())
+    DBUG_RETURN(0);
+
+  if (is_open())
+  {						// Safety agains reopen
+    int tmp_errno= 0;
+    char buff[80], *end;
+    uint buff_len;
+    end= buff;
+
+    if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
+    {
+      Security_context *sctx= thd->security_ctx;
+      if (current_time != last_time)
+      {
+        last_time= current_time;
+        struct tm start;
+        localtime_r(&current_time, &start);
+
+        buff_len= my_snprintf(buff, sizeof buff,
+                              "# Time: %02d%02d%02d %2d:%02d:%02d\n",
+                              start.tm_year % 100, start.tm_mon + 1,
+                              start.tm_mday, start.tm_hour,
+                              start.tm_min, start.tm_sec);
+
+        /* Note that my_b_write() assumes it knows the length for this */
+        if (my_b_write(&log_file, (byte*) buff, buff_len))
+          tmp_errno= errno;
+      }
+      if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1)
+          != sizeof("# User@Host: ") - 1)
+        tmp_errno= errno;
+      if (my_b_printf(&log_file, user_host, user_host_len) != user_host_len)
+        tmp_errno= errno;
+      if (my_b_write(&log_file, (byte*) "\n", 1))
+        tmp_errno= errno;
+    }
+    /* For slow query log */
+    if (my_b_printf(&log_file,
+                    "# Query_time: %lu  Lock_time: %lu"
+                    " Rows_sent: %lu  Rows_examined: %lu\n",
+                    (ulong) query_time, (ulong) lock_time,
+                    (ulong) thd->sent_row_count,
+                    (ulong) thd->examined_row_count) == (uint) -1)
+      tmp_errno= errno;
+    if (thd->db && strcmp(thd->db, db))
+    {						// Database changed
+      if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
+        tmp_errno= errno;
+      strmov(db,thd->db);
+    }
+    if (thd->last_insert_id_used)
+    {
+      end=strmov(end, ",last_insert_id=");
+      end=longlong10_to_str((longlong) thd->current_insert_id, end, -10);
+    }
+    // Save value if we do an insert.
+    if (thd->insert_id_used)
+    {
+      if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
+      {
+        end=strmov(end,",insert_id=");
+        end=longlong10_to_str((longlong) thd->last_insert_id, end, -10);
+      }
+    }
+
+    /*
+      This info used to show up randomly, depending on whether the query
+      checked the query start time or not. now we always write current
+      timestamp to the slow log
+    */
+    end= strmov(end, ",timestamp=");
+    end= int10_to_str((long) current_time, end, 10);
+
+    if (end != buff)
+    {
+      *end++=';';
+      *end='\n';
+      if (my_b_write(&log_file, (byte*) "SET ", 4) ||
+          my_b_write(&log_file, (byte*) buff + 1, (uint) (end-buff)))
+        tmp_errno= errno;
+    }
+    if (is_command)
+    {
+      end= strxmov(buff, "# administrator command: ", NullS);
+      buff_len= (ulong) (end - buff);
+      my_b_write(&log_file, (byte*) buff, buff_len);
+    }
+    if (my_b_write(&log_file, (byte*) sql_text, sql_text_len) ||
+        my_b_write(&log_file, (byte*) ";\n",2) ||
+        flush_io_cache(&log_file))
+      tmp_errno= errno;
+    if (tmp_errno)
+    {
+      error= 1;
+      if (! write_error)
+      {
+        write_error= 1;
+        sql_print_error(ER(ER_ERROR_ON_WRITE), name, error);
+      }
+    }
+  }
+  DBUG_RETURN(error);
 }
 
+
 const char *MYSQL_LOG::generate_name(const char *log_name,
-                                     const char *suffix,
-                                     bool strip_ext, char *buff)
+                                      const char *suffix,
+                                      bool strip_ext, char *buff)
 {
   if (!log_name || !log_name[0])
   {
@@ -1471,22 +1880,78 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
       TODO: The following should be using fn_format();  We just need to
       first change fn_format() to cut the file name if it's too long.
     */
-    strmake(buff,glob_hostname,FN_REFLEN-5);
-    strmov(fn_ext(buff),suffix);
+    strmake(buff, glob_hostname, FN_REFLEN - 5);
+    strmov(fn_ext(buff), suffix);
     return (const char *)buff;
   }
   // get rid of extension if the log is binary to avoid problems
   if (strip_ext)
   {
-    char *p = fn_ext(log_name);
-    uint length=(uint) (p-log_name);
-    strmake(buff,log_name,min(length,FN_REFLEN));
+    char *p= fn_ext(log_name);
+    uint length= (uint) (p - log_name);
+    strmake(buff, log_name, min(length, FN_REFLEN));
     return (const char*)buff;
   }
   return log_name;
 }
 
-bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
+
+MYSQL_BIN_LOG::MYSQL_BIN_LOG()
+  :bytes_written(0), prepared_xids(0), file_id(1), open_count(1),
+   need_start_event(TRUE), m_table_map_version(0),
+   description_event_for_exec(0), description_event_for_queue(0)
+{
+  /*
+    We don't want to initialize locks here as such initialization depends on
+    safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is
+    called only in main(). Doing initialization here would make it happen
+    before main().
+  */
+  index_file_name[0] = 0;
+  bzero((char*) &index_file, sizeof(index_file));
+}
+
+/* this is called only once */
+
+void MYSQL_BIN_LOG::cleanup()
+{
+  DBUG_ENTER("cleanup");
+  if (inited)
+  {
+    inited= 0;
+    close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT);
+    delete description_event_for_queue;
+    delete description_event_for_exec;
+    (void) pthread_mutex_destroy(&LOCK_log);
+    (void) pthread_mutex_destroy(&LOCK_index);
+    (void) pthread_cond_destroy(&update_cond);
+  }
+  DBUG_VOID_RETURN;
+}
+
+
+/* Init binlog-specific vars */
+void MYSQL_BIN_LOG::init(bool no_auto_events_arg, ulong max_size_arg)
+{
+  DBUG_ENTER("MYSQL_BIN_LOG::init");
+  no_auto_events= no_auto_events_arg;
+  max_size= max_size_arg;
+  DBUG_PRINT("info",("max_size: %lu", max_size));
+  DBUG_VOID_RETURN;
+}
+
+
+void MYSQL_BIN_LOG::init_pthread_objects()
+{
+  DBUG_ASSERT(inited == 0);
+  inited= 1;
+  (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
+  (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
+  (void) pthread_cond_init(&update_cond, 0);
+}
+
+
+bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
                                 const char *log_name)
 {
   File index_file_nr= -1;
@@ -1523,10 +1988,10 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
 
 
 /*
-  Open a (new) log file.
+  Open a (new) binlog file.
 
   DESCRIPTION
-  - If binary logs, also open the index file and register the new
+  - Open the log file and the index file. Register the new
     file name in it
   - When calling this when the file is in use, you must have a locks
     on LOCK_log and LOCK_index.
@@ -1536,94 +2001,33 @@ bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
     1	error
 */
 
-bool MYSQL_LOG::open(const char *log_name,
-                     enum_log_type log_type_arg,
-                     const char *new_name,
-                     enum cache_type io_cache_type_arg,
-                     bool no_auto_events_arg,
-                     ulong max_size_arg,
-                     bool null_created_arg)
+bool MYSQL_BIN_LOG::open(const char *log_name,
+                         enum_log_type log_type_arg,
+                         const char *new_name,
+                         enum cache_type io_cache_type_arg,
+                         bool no_auto_events_arg,
+                         ulong max_size_arg,
+                         bool null_created_arg)
 {
   char buff[FN_REFLEN];
   File file= -1;
   int open_flags = O_CREAT | O_BINARY;
-  DBUG_ENTER("MYSQL_LOG::open");
+  DBUG_ENTER("MYSQL_BIN_LOG::open");
   DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
 
-  last_time=query_start=0;
+  last_time= 0;
   write_error=0;
 
-  init(log_type_arg,io_cache_type_arg,no_auto_events_arg,max_size_arg);
+  /* open the main log file */
+  if (MYSQL_LOG::open(log_name, log_type_arg, new_name, io_cache_type_arg))
+    DBUG_RETURN(1);                            /* all warnings issued */
 
-  if (!(name=my_strdup(log_name,MYF(MY_WME))))
-  {
-    name= (char *)log_name; // for the error message
-    goto err;
-  }
-  if (new_name)
-    strmov(log_file_name,new_name);
-  else if (generate_new_name(log_file_name, name))
-    goto err;
+  init(no_auto_events_arg, max_size_arg);
 
-  if (io_cache_type == SEQ_READ_APPEND)
-    open_flags |= O_RDWR | O_APPEND;
-  else
-    open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
-
-  db[0]=0;
   open_count++;
-  if ((file=my_open(log_file_name,open_flags,
-		    MYF(MY_WME | ME_WAITTANG))) < 0 ||
-      init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
-		    my_tell(file,MYF(MY_WME)), 0, 
-                    MYF(MY_WME | MY_NABP |
-                        ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
-    goto err;
 
-  switch (log_type) {
-  case LOG_NORMAL:
-  {
-    char *end;
-    int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. "
-#ifdef EMBEDDED_LIBRARY
-		        "embedded library\n", my_progname, server_version
-#elif __NT__
-			"started with:\nTCP Port: %d, Named Pipe: %s\n",
-			my_progname, server_version, mysqld_port, mysqld_unix_port
-#else
-			"started with:\nTcp port: %d  Unix socket: %s\n",
-			my_progname,server_version,mysqld_port,mysqld_unix_port
-#endif
-                       );
-    end=strnmov(buff+len,"Time                 Id Command    Argument\n",
-                sizeof(buff)-len);
-    if (my_b_write(&log_file, (byte*) buff,(uint) (end-buff)) ||
-	flush_io_cache(&log_file))
-      goto err;
-    break;
-  }
-  case LOG_NEW:
-  {
-    uint len;
-    time_t skr=time(NULL);
-    struct tm tm_tmp;
-
-    localtime_r(&skr,&tm_tmp);
-    len= my_snprintf(buff,sizeof(buff),
-		     "# %s, Version: %s at %02d%02d%02d %2d:%02d:%02d\n",
-		     my_progname,server_version,
-		     tm_tmp.tm_year % 100,
-		     tm_tmp.tm_mon+1,
-		     tm_tmp.tm_mday,
-		     tm_tmp.tm_hour,
-		     tm_tmp.tm_min,
-		     tm_tmp.tm_sec);
-    if (my_b_write(&log_file, (byte*) buff, len) ||
-	flush_io_cache(&log_file))
-      goto err;
-    break;
-  }
-  case LOG_BIN:
+  DBUG_ASSERT(log_type == LOG_BIN);
+
   {
     bool write_file_name_to_index_file=0;
 
@@ -1714,12 +2118,6 @@ bool MYSQL_LOG::open(const char *log_name,
           my_sync(index_file.file, MYF(MY_WME)))
 	goto err;
     }
-    break;
-  }
-  case LOG_CLOSED:				// Impossible
-  case LOG_TO_BE_OPENED:
-    DBUG_ASSERT(1);
-    break;
   }
   DBUG_RETURN(0);
 
@@ -1738,7 +2136,7 @@ shutdown the MySQL server and restart it.", name, errno);
 }
 
 
-int MYSQL_LOG::get_current_log(LOG_INFO* linfo)
+int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo)
 {
   pthread_mutex_lock(&LOCK_log);
   strmake(linfo->log_file_name, log_file_name, sizeof(linfo->log_file_name)-1);
@@ -1825,7 +2223,7 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
     LOG_INFO_IO		Got IO error while reading file
 */
 
-int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
+int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
 			    bool need_lock)
 {
   int error= 0;
@@ -1899,7 +2297,7 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
     LOG_INFO_IO		Got IO error while reading file
 */
 
-int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
+int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
 {
   int error= 0;
   uint length;
@@ -1947,7 +2345,7 @@ int MYSQL_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
     1   error
 */
 
-bool MYSQL_LOG::reset_logs(THD* thd)
+bool MYSQL_BIN_LOG::reset_logs(THD* thd)
 {
   LOG_INFO linfo;
   bool error=0;
@@ -2047,7 +2445,7 @@ bool MYSQL_LOG::reset_logs(THD* thd)
 
 #ifdef HAVE_REPLICATION
 
-int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) 
+int MYSQL_BIN_LOG::purge_first_log(struct st_relay_log_info* rli, bool included) 
 {
   int error;
   DBUG_ENTER("purge_first_log");
@@ -2123,7 +2521,7 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
   Update log index_file
 */
 
-int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
+int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
 {
   if (copy_up_file_and_fill(&index_file, log_info->index_file_start_offset))
     return LOG_INFO_IO;
@@ -2156,7 +2554,7 @@ int MYSQL_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads)
     LOG_INFO_EOF		to_log not found
 */
 
-int MYSQL_LOG::purge_logs(const char *to_log, 
+int MYSQL_BIN_LOG::purge_logs(const char *to_log, 
                           bool included,
                           bool need_mutex, 
                           bool need_update_threads, 
@@ -2242,7 +2640,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
     LOG_INFO_PURGE_NO_ROTATE	Binary file that can't be rotated
 */
 
-int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
+int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
 {
   int error;
   LOG_INFO log_info;
@@ -2301,7 +2699,7 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
     If file name will be longer then FN_REFLEN it will be truncated
 */
 
-void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
+void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident)
 {
   uint dir_len = dirname_length(log_file_name); 
   if (dir_len > FN_REFLEN)
@@ -2315,29 +2713,49 @@ void MYSQL_LOG::make_log_name(char* buf, const char* log_ident)
   Check if we are writing/reading to the given log file
 */
 
-bool MYSQL_LOG::is_active(const char *log_file_name_arg)
+bool MYSQL_BIN_LOG::is_active(const char *log_file_name_arg)
 {
   return !strcmp(log_file_name, log_file_name_arg);
 }
 
 
+/*
+  Wrappers around new_file_impl to avoid using argument
+  to control locking. The argument 1) less readable 2) breaks
+  incapsulation 3) allows external access to the class without
+  a lock (which is not possible with private new_file_without_locking
+  method).
+*/
+
+void MYSQL_BIN_LOG::new_file()
+{
+  new_file_impl(1);
+}
+
+
+void MYSQL_BIN_LOG::new_file_without_locking()
+{
+  new_file_impl(0);
+}
+
+
 /*
   Start writing to a new log file or reopen the old file
 
   SYNOPSIS
-    new_file()
+    new_file_impl()
     need_lock		Set to 1 if caller has not locked LOCK_log
 
   NOTE
     The new file name is stored last in the index file
 */
 
-void MYSQL_LOG::new_file(bool need_lock)
+void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
 {
   char new_name[FN_REFLEN], *new_name_ptr, *old_name;
   enum_log_type save_log_type;
 
-  DBUG_ENTER("MYSQL_LOG::new_file");
+  DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
   if (!is_open())
   {
     DBUG_PRINT("info",("log is closed"));
@@ -2433,11 +2851,11 @@ void MYSQL_LOG::new_file(bool need_lock)
 }
 
 
-bool MYSQL_LOG::append(Log_event* ev)
+bool MYSQL_BIN_LOG::append(Log_event* ev)
 {
   bool error = 0;
   pthread_mutex_lock(&LOCK_log);
-  DBUG_ENTER("MYSQL_LOG::append");
+  DBUG_ENTER("MYSQL_BIN_LOG::append");
 
   DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
   /*
@@ -2452,7 +2870,7 @@ bool MYSQL_LOG::append(Log_event* ev)
   bytes_written+= ev->data_written;
   DBUG_PRINT("info",("max_size: %lu",max_size));
   if ((uint) my_b_append_tell(&log_file) > max_size)
-    new_file(0);
+    new_file_without_locking();
 
 err:
   pthread_mutex_unlock(&LOCK_log);
@@ -2461,10 +2879,10 @@ bool MYSQL_LOG::append(Log_event* ev)
 }
 
 
-bool MYSQL_LOG::appendv(const char* buf, uint len,...)
+bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...)
 {
   bool error= 0;
-  DBUG_ENTER("MYSQL_LOG::appendv");
+  DBUG_ENTER("MYSQL_BIN_LOG::appendv");
   va_list(args);
   va_start(args,len);
 
@@ -2482,7 +2900,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
   } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
   DBUG_PRINT("info",("max_size: %lu",max_size));
   if ((uint) my_b_append_tell(&log_file) > max_size)
-    new_file(0);
+    new_file_without_locking();
 
 err:
   if (!error)
@@ -2491,99 +2909,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
 }
 
 
-/*
-  Write a command to traditional general log file
-
-  SYNOPSIS
-    write()
-
-    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 to normal (not rotable) log file
-
-  RETURN
-    FASE - OK
-    TRUE - error occured
-*/
-
-bool MYSQL_LOG::write(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)
-{
-  char buff[32];
-  uint length= 0;
-  char time_buff[MAX_TIME_SIZE];
-  struct tm start;
-  uint time_buff_len= 0;
-
-  /* Test if someone closed between the is_open test and lock */
-  if (is_open())
-  {
-    /* Note that my_b_write() assumes it knows the length for this */
-      if (event_time != last_time)
-      {
-        last_time= event_time;
-
-        localtime_r(&event_time, &start);
-
-        time_buff_len= my_snprintf(time_buff, MAX_TIME_SIZE,
-                                   "%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);
-
-        if (my_b_write(&log_file, (byte*) &time_buff, time_buff_len))
-          goto err;
-      }
-      else
-        if (my_b_write(&log_file, (byte*) "\t\t" ,2) < 0)
-          goto err;
-
-    /* command_type, thread_id */
-    length= my_snprintf(buff, 32, "%5ld ", thread_id);
-
-    if (my_b_write(&log_file, (byte*) buff, length))
-      goto err;
-
-    if (my_b_write(&log_file, (byte*) command_type, command_type_len))
-      goto err;
-
-    if (my_b_write(&log_file, (byte*) "\t", 1))
-      goto err;
-
-    /* sql_text */
-    if (my_b_write(&log_file, (byte*) sql_text, sql_text_len))
-      goto err;
-
-    if (my_b_write(&log_file, (byte*) "\n", 1) ||
-        flush_io_cache(&log_file))
-      goto err;
-  }
-
-  return FALSE;
-err:
-
-  if (!write_error)
-  {
-    write_error= 1;
-    sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
-  }
-  return TRUE;
-}
-
-
-bool MYSQL_LOG::flush_and_sync()
+bool MYSQL_BIN_LOG::flush_and_sync()
 {
   int err=0, fd=log_file.file;
   safe_mutex_assert_owner(&LOCK_log);
@@ -2597,7 +2923,7 @@ bool MYSQL_LOG::flush_and_sync()
   return err;
 }
 
-void MYSQL_LOG::start_union_events(THD *thd)
+void MYSQL_BIN_LOG::start_union_events(THD *thd)
 {
   DBUG_ASSERT(!thd->binlog_evt_union.do_union);
   thd->binlog_evt_union.do_union= TRUE;
@@ -2606,13 +2932,13 @@ void MYSQL_LOG::start_union_events(THD *thd)
   thd->binlog_evt_union.first_query_id= thd->query_id;
 }
 
-void MYSQL_LOG::stop_union_events(THD *thd)
+void MYSQL_BIN_LOG::stop_union_events(THD *thd)
 {
   DBUG_ASSERT(thd->binlog_evt_union.do_union);
   thd->binlog_evt_union.do_union= FALSE;
 }
 
-bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
+bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
 {
   return (thd->binlog_evt_union.do_union && 
           query_id_param >= thd->binlog_evt_union.first_query_id);
@@ -2716,9 +3042,10 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev)
   (either cached binlog if transaction, or disk binlog). Sets a new pending
   event.
 */
-int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
+int MYSQL_BIN_LOG::
+  flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
 {
-  DBUG_ENTER("MYSQL_LOG::flush_and_set_pending_rows_event(event)");
+  DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
   DBUG_ASSERT(thd->current_stmt_binlog_row_based && mysql_bin_log.is_open());
   DBUG_PRINT("enter", ("event=%p", event));
 
@@ -2801,11 +3128,11 @@ int MYSQL_LOG::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event)
   Write an event to the binary log
 */
 
-bool MYSQL_LOG::write(Log_event *event_info)
+bool MYSQL_BIN_LOG::write(Log_event *event_info)
 {
   THD *thd= event_info->thd;
   bool error= 1;
-  DBUG_ENTER("MYSQL_LOG::write(Log_event *)");
+  DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)");
 
   if (thd->binlog_evt_union.do_union)
   {
@@ -3014,14 +3341,14 @@ bool general_log_print(THD *thd, enum enum_server_command command,
   return error;
 }
 
-void MYSQL_LOG::rotate_and_purge(uint flags)
+void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
 {
   if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
     pthread_mutex_lock(&LOCK_log);
   if ((flags & RP_FORCE_ROTATE) ||
       (my_b_tell(&log_file) >= (my_off_t) max_size))
   {
-    new_file(0);
+    new_file_without_locking();
 #ifdef HAVE_REPLICATION
     if (expire_logs_days)
     {
@@ -3035,7 +3362,7 @@ void MYSQL_LOG::rotate_and_purge(uint flags)
     pthread_mutex_unlock(&LOCK_log);
 }
 
-uint MYSQL_LOG::next_file_id()
+uint MYSQL_BIN_LOG::next_file_id()
 {
   uint res;
   pthread_mutex_lock(&LOCK_log);
@@ -3066,9 +3393,9 @@ uint MYSQL_LOG::next_file_id()
       that the same updates are run on the slave.
 */
 
-bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
+bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
 {
-  DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)");
+  DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
   VOID(pthread_mutex_lock(&LOCK_log));
 
   if (likely(is_open()))                       // Should always be true
@@ -3163,148 +3490,6 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
 }
 
 
-/*
-  Log a query to the traditional slow log file
-
-  SYNOPSIS
-    write()
-
-    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.
-    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 file.
-
-  RETURN
-    FALSE - OK
-    TRUE - error occured
-*/
-
-bool MYSQL_LOG::write(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)
-{
-  bool error= 0;
-  DBUG_ENTER("MYSQL_LOG::write");
-
-  if (!is_open())
-    DBUG_RETURN(0);
-
-  if (is_open())
-  {						// Safety agains reopen
-    int tmp_errno= 0;
-    char buff[80], *end;
-    uint buff_len;
-    end= buff;
-
-    if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
-    {
-      Security_context *sctx= thd->security_ctx;
-      if (current_time != last_time)
-      {
-        last_time= current_time;
-        struct tm start;
-        localtime_r(&current_time, &start);
-
-        buff_len= my_snprintf(buff, sizeof buff,
-                              "# Time: %02d%02d%02d %2d:%02d:%02d\n",
-                              start.tm_year % 100, start.tm_mon + 1,
-                              start.tm_mday, start.tm_hour,
-                              start.tm_min, start.tm_sec);
-
-        /* Note that my_b_write() assumes it knows the length for this */
-        if (my_b_write(&log_file, (byte*) buff, buff_len))
-          tmp_errno=errno;
-      }
-      if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1))
-        tmp_errno=errno;
-      if (my_b_printf(&log_file, user_host, user_host_len))
-        tmp_errno=errno;
-      if (my_b_write(&log_file, (byte*) "\n", 1))
-        tmp_errno=errno;
-    }
-    /* For slow query log */
-    if (my_b_printf(&log_file,
-                    "# Query_time: %lu  Lock_time: %lu"
-                    " Rows_sent: %lu  Rows_examined: %lu\n",
-                    (ulong) query_time, (ulong) lock_time,
-                    (ulong) thd->sent_row_count,
-                    (ulong) thd->examined_row_count) == (uint) -1)
-      tmp_errno=errno;
-    if (thd->db && strcmp(thd->db,db))
-    {						// Database changed
-      if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
-        tmp_errno=errno;
-      strmov(db,thd->db);
-    }
-    if (thd->last_insert_id_used)
-    {
-      end=strmov(end,",last_insert_id=");
-      end=longlong10_to_str((longlong) thd->current_insert_id,end,-10);
-    }
-    // Save value if we do an insert.
-    if (thd->insert_id_used)
-    {
-      if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
-      {
-        end=strmov(end,",insert_id=");
-        end=longlong10_to_str((longlong) thd->last_insert_id,end,-10);
-      }
-    }
-
-    /*
-      This info used to show up randomly, depending on whether the query
-      checked the query start time or not. now we always write current
-      timestamp to the slow log
-    */
-    end= strmov(end, ",timestamp=");
-    end= int10_to_str((long) current_time, end, 10);
-
-    if (end != buff)
-    {
-      *end++=';';
-      *end='\n';
-      if (my_b_write(&log_file, (byte*) "SET ",4) ||
-          my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)))
-        tmp_errno=errno;
-    }
-    if (is_command)
-    {
-      end= strxmov(buff, "# administrator command: ", NullS);
-      buff_len= (ulong) (end - buff);
-      my_b_write(&log_file, (byte*) buff, buff_len);
-    }
-    if (my_b_write(&log_file, (byte*) sql_text, sql_text_len) ||
-        my_b_write(&log_file, (byte*) ";\n",2) ||
-        flush_io_cache(&log_file))
-      tmp_errno=errno;
-    if (tmp_errno)
-    {
-      error=1;
-      if (! write_error)
-      {
-        write_error=1;
-        sql_print_error(ER(ER_ERROR_ON_WRITE),name,error);
-      }
-    }
-  }
-  DBUG_RETURN(error);
-}
-
-
 /*
   Wait until we get a signal that the binary log has been updated
 
@@ -3321,7 +3506,7 @@ bool MYSQL_LOG::write(THD *thd, time_t current_time, time_t query_start_arg,
     THD::enter_cond() (see NOTES in sql_class.h).
 */
 
-void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
+void MYSQL_BIN_LOG::wait_for_update(THD* thd, bool is_slave)
 {
   const char *old_msg;
   DBUG_ENTER("wait_for_update");
@@ -3354,9 +3539,9 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
     The internal structures are not freed until cleanup() is called
 */
 
-void MYSQL_LOG::close(uint exiting)
+void MYSQL_BIN_LOG::close(uint exiting)
 {					// One can't set log_type here!
-  DBUG_ENTER("MYSQL_LOG::close");
+  DBUG_ENTER("MYSQL_BIN_LOG::close");
   DBUG_PRINT("enter",("exiting: %d", (int) exiting));
   if (log_type != LOG_CLOSED && log_type != LOG_TO_BE_OPENED)
   {
@@ -3370,7 +3555,6 @@ void MYSQL_LOG::close(uint exiting)
       signal_update();
     }
 #endif /* HAVE_REPLICATION */
-    end_io_cache(&log_file);
 
     /* don't pwrite in a file opened with O_APPEND - it doesn't work */
     if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
@@ -3380,16 +3564,8 @@ void MYSQL_LOG::close(uint exiting)
       my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
     }
 
-    if (my_sync(log_file.file,MYF(MY_WME)) && ! write_error)
-    {
-      write_error=1;
-      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
-    }
-    if (my_close(log_file.file,MYF(MY_WME)) && ! write_error)
-    {
-      write_error=1;
-      sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
-    }
+    /* this will cleanup IO_CACHE, sync and close the file */
+    MYSQL_LOG::close(exiting);
   }
 
   /*
@@ -3412,7 +3588,7 @@ void MYSQL_LOG::close(uint exiting)
 }
 
 
-void MYSQL_LOG::set_max_size(ulong max_size_arg)
+void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg)
 {
   /*
     We need to take locks, otherwise this may happen:
@@ -3421,7 +3597,7 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg)
     uses the old_max_size argument, so max_size_arg has been overwritten and
     it's like if the SET command was never run.
   */
-  DBUG_ENTER("MYSQL_LOG::set_max_size");
+  DBUG_ENTER("MYSQL_BIN_LOG::set_max_size");
   pthread_mutex_lock(&LOCK_log);
   if (is_open())
     max_size= max_size_arg;
@@ -3570,9 +3746,9 @@ bool flush_error_log()
    return result;
 }
 
-void MYSQL_LOG::signal_update()
+void MYSQL_BIN_LOG::signal_update()
 {
-  DBUG_ENTER("MYSQL_LOG::signal_update");
+  DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
   pthread_cond_broadcast(&update_cond);
   DBUG_VOID_RETURN;
 }
@@ -4175,7 +4351,7 @@ int TC_LOG::using_heuristic_recover()
 }
 
 /****** transaction coordinator log for 2pc - binlog() based solution ******/
-#define TC_LOG_BINLOG MYSQL_LOG
+#define TC_LOG_BINLOG MYSQL_BIN_LOG
 
 /*
   TODO keep in-memory list of prepared transactions
diff --git a/sql/log.h b/sql/log.h
index 03d5466e5496af8241ca4c5a82c292c6b67eb770..589932dcac040d24b336b326e5071f7cf84724c1 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -147,33 +147,89 @@ typedef struct st_log_info
 class Log_event;
 class Rows_log_event;
 
-enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN};
+enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_BIN};
 
 /*
-  TODO split MYSQL_LOG into base MYSQL_LOG and
-  MYSQL_QUERY_LOG, MYSQL_SLOW_LOG, MYSQL_BIN_LOG
-  most of the code from MYSQL_LOG should be in the MYSQL_BIN_LOG
-  only (TC_LOG included)
-
   TODO use mmap instead of IO_CACHE for binlog
   (mmap+fsync is two times faster than write+fsync)
 */
 
-class MYSQL_LOG: public TC_LOG
+class MYSQL_LOG
+{
+public:
+  MYSQL_LOG();
+  void init_pthread_objects();
+  void cleanup();
+  void reopen_file();
+  bool open(const char *log_name,
+            enum_log_type log_type,
+            const char *new_name,
+            enum cache_type io_cache_type_arg);
+  void init(enum_log_type log_type_arg,
+            enum cache_type io_cache_type_arg);
+  void close(uint exiting);
+  inline bool is_open() { return log_type != LOG_CLOSED; }
+  const char *generate_name(const char *log_name, const char *suffix,
+                            bool strip_ext, char *buff);
+  int generate_new_name(char *new_name, const char *log_name);
+ protected:
+  /* LOCK_log is inited by init_pthread_objects() */
+  pthread_mutex_t LOCK_log;
+  char *name;
+  char log_file_name[FN_REFLEN];
+  char time_buff[20], db[NAME_LEN + 1];
+  bool write_error, inited;
+  IO_CACHE log_file;
+  volatile enum_log_type log_type;
+  enum cache_type io_cache_type;
+  time_t last_time;
+
+  friend class Log_event;
+};
+
+class MYSQL_GENERAL_LOG: public MYSQL_LOG
+{
+public:
+  MYSQL_GENERAL_LOG() {}  /* get rid of gcc warning */
+  bool write(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);
+  bool open_query_log(const char *log_name)
+  {
+    char buf[FN_REFLEN];
+    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
+                WRITE_CACHE);
+  }
+};
+
+class MYSQL_SLOW_LOG: public MYSQL_LOG
+{
+public:
+  MYSQL_SLOW_LOG() {}  /* get rid of gcc warning */
+  bool write(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);
+  bool open_slow_log(const char *log_name)
+  {
+    char buf[FN_REFLEN];
+    return open(generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0,
+                WRITE_CACHE);
+  }
+};
+
+class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
 {
  private:
   /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
-  pthread_mutex_t LOCK_log, LOCK_index;
+  pthread_mutex_t LOCK_index;
   pthread_mutex_t LOCK_prep_xids;
   pthread_cond_t  COND_prep_xids;
   pthread_cond_t update_cond;
   ulonglong bytes_written;
-  time_t last_time,query_start;
-  IO_CACHE log_file;
   IO_CACHE index_file;
-  char *name;
-  char time_buff[20],db[NAME_LEN+1];
-  char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
+  char index_file_name[FN_REFLEN];
   /*
      The max size before rotation (usable only if log_type == LOG_BIN: binary
      logs and relay logs).
@@ -186,13 +242,10 @@ class MYSQL_LOG: public TC_LOG
   */
   ulong max_size;
   ulong prepared_xids; /* for tc log - number of xids to remember */
-  volatile enum_log_type log_type;
-  enum cache_type io_cache_type;
   // current file sequence number for load data infile binary logging
   uint file_id;
   uint open_count;				// For replication
   int readers_count;
-  bool write_error, inited;
   bool need_start_event;
   /*
     no_auto_events means we don't want any of these automatic events :
@@ -202,13 +255,20 @@ class MYSQL_LOG: public TC_LOG
     In 5.0 it's 0 for relay logs too!
   */
   bool no_auto_events;
-  friend class Log_event;
 
   ulonglong m_table_map_version;
 
   int write_to_file(IO_CACHE *cache);
+  /*
+    This is used to start writing to a new log file. The difference from
+    new_file() is locking. new_file_without_locking() does not acquire
+    LOCK_log.
+  */
+  void new_file_without_locking();
+  void new_file_impl(bool need_lock);
 
 public:
+  MYSQL_LOG::generate_name;
   /*
     These describe the log's format. This is used only for relay logs.
     _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
@@ -220,9 +280,9 @@ class MYSQL_LOG: public TC_LOG
   Format_description_log_event *description_event_for_exec,
     *description_event_for_queue;
 
-  MYSQL_LOG();
+  MYSQL_BIN_LOG();
   /*
-    note that there's no destructor ~MYSQL_LOG() !
+    note that there's no destructor ~MYSQL_BIN_LOG() !
     The reason is that we don't want it to be automatically called
     on exit() - but only during the correct shutdown process
   */
@@ -264,9 +324,7 @@ class MYSQL_LOG: public TC_LOG
   void signal_update();
   void wait_for_update(THD* thd, bool master_or_slave);
   void set_need_start_event() { need_start_event = 1; }
-  void init(enum_log_type log_type_arg,
-	    enum cache_type io_cache_type_arg,
-	    bool no_auto_events_arg, ulong max_size);
+  void init(bool no_auto_events_arg, ulong max_size);
   void init_pthread_objects();
   void cleanup();
   bool open(const char *log_name,
@@ -275,35 +333,10 @@ class MYSQL_LOG: public TC_LOG
 	    enum cache_type io_cache_type_arg,
 	    bool no_auto_events_arg, ulong max_size,
             bool null_created);
-  const char *generate_name(const char *log_name, const char *suffix,
-                            bool strip_ext, char *buff);
-  /* simplified open_xxx wrappers for the gigantic open above */
-  bool open_query_log(const char *log_name)
-  {
-    char buf[FN_REFLEN];
-    return open(generate_name(log_name, ".log", 0, buf),
-                LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
-  }
-  bool open_slow_log(const char *log_name)
-  {
-    char buf[FN_REFLEN];
-    return open(generate_name(log_name, "-slow.log", 0, buf),
-                LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
-  }
   bool open_index_file(const char *index_file_name_arg,
                        const char *log_name);
-  void new_file(bool need_lock);
-  /* log a command to the old-fashioned general log */
-  bool write(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);
-
-  /* log a query to the old-fashioned slow query log */
-  bool write(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);
+  /* Use this to start writing a new log file */
+  void new_file();
 
   bool write(Log_event* event_info); // binary log write
   bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
@@ -319,7 +352,6 @@ class MYSQL_LOG: public TC_LOG
   bool appendv(const char* buf,uint len,...);
   bool append(Log_event* ev);
 
-  int generate_new_name(char *new_name,const char *old_name);
   void make_log_name(char* buf, const char* log_ident);
   bool is_active(const char* log_file_name);
   int update_log_index(LOG_INFO* linfo, bool need_update_threads);
@@ -416,7 +448,8 @@ class Log_to_csv_event_handler: public Log_event_handler
 
 class Log_to_file_event_handler: public Log_event_handler
 {
-  MYSQL_LOG mysql_log, mysql_slow_log;
+  MYSQL_GENERAL_LOG mysql_log;
+  MYSQL_SLOW_LOG mysql_slow_log;
   bool is_initialized;
 public:
   Log_to_file_event_handler(): is_initialized(FALSE)
diff --git a/sql/log_event.h b/sql/log_event.h
index b24686514e3b57643d09822348d7beb3a981b334..b94d94c8513a49aafd3981c167ed768bddc65643 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -470,7 +470,7 @@ enum Int_event_type
 
 #ifndef MYSQL_CLIENT
 class String;
-class MYSQL_LOG;
+class MYSQL_BIN_LOG;
 class THD;
 #endif
 
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 749a968a5afbb1ef9f5812cd332ef089cbdb8b71..2f7450e6261a4b0d33e8d1bb004a4884c9c9f8e7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1525,7 +1525,7 @@ extern char *default_tz_name;
 extern my_bool opt_large_pages;
 extern uint opt_large_page_size;
 
-extern MYSQL_LOG mysql_bin_log;
+extern MYSQL_BIN_LOG mysql_bin_log;
 extern LOGGER logger;
 extern TABLE_LIST general_log, slow_log;
 extern FILE *bootstrap_file;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 7d89b67b5838840ec30b66359636fa1d1af9da4f..dec1cb81a4c607f216098c63dff8bf5620bd6c05 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2610,10 +2610,10 @@ static int init_common_variables(const char *conf_file_name, int argc,
   global_system_variables.time_zone= my_tz_SYSTEM;
   
   /*
-    Init mutexes for the global MYSQL_LOG objects.
+    Init mutexes for the global MYSQL_BIN_LOG objects.
     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
-    global MYSQL_LOGs in their constructors, because then they would be inited
-    before MY_INIT(). So we do it here.
+    global MYSQL_BIN_LOGs in their constructors, because then they would be
+    inited before MY_INIT(). So we do it here.
   */
   mysql_bin_log.init_pthread_objects();
 
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index 265f5f61213780c69281f3444c7555dbecfd72d4..ec0add4165f67a9a8eb98b9e599e508bc76f99a2 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -25,7 +25,7 @@
 
 /* inline since it's called below */
 inline
-injector::transaction::transaction(MYSQL_LOG *log, THD *thd)
+injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
   : m_state(START_STATE), m_thd(thd)
 {
   /* 
diff --git a/sql/rpl_injector.h b/sql/rpl_injector.h
index 14d5cca9b6cb2e4ec9f426cc8f57dcd2b25617be..3b0857e0833aa7b0c68ec90e56d46fb38952721b 100644
--- a/sql/rpl_injector.h
+++ b/sql/rpl_injector.h
@@ -26,7 +26,7 @@
 
 /* Forward declarations */
 class handler;
-class MYSQL_LOG;
+class MYSQL_BIN_LOG;
 class st_table;
 
 typedef st_table TABLE;
@@ -219,7 +219,7 @@ class injector
 
     private:
       /* Only the injector may construct these object */
-      transaction(MYSQL_LOG *, THD *);
+      transaction(MYSQL_BIN_LOG *, THD *);
 
       void swap(transaction& o) {
         /* std::swap(m_start_pos, o.m_start_pos); */
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index cacae1aa4c2696d77dc62c8cf531deb848aa9d37..5fb0f85d8fe77661a7577c68e443d2b56cae9250 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -69,7 +69,7 @@ typedef struct st_relay_log_info
     Protected with internal locks.
     Must get data_lock when resetting the logs.
   */
-  MYSQL_LOG relay_log;
+  MYSQL_BIN_LOG relay_log;
   LOG_INFO linfo;
   IO_CACHE cache_buf,*cur_log;
 
diff --git a/sql/slave.cc b/sql/slave.cc
index 4ab9e951813498af909b9ead005c4a5bd8cdeff4..4ed78ea2de19188f78a0df98e81d1bd8761122b3 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -4570,7 +4570,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli)
       When the relay log is created when the I/O thread starts, easy: the
       master will send the description event and we will queue it.
       But if the relay log is created by new_file(): then the solution is:
-      MYSQL_LOG::open() will write the buffered description event.
+      MYSQL_BIN_LOG::open() will write the buffered description event.
     */
     if ((ev=Log_event::read_log_event(cur_log,0,
                                       rli->relay_log.description_event_for_exec)))
@@ -4832,7 +4832,8 @@ event(errno: %d  cur_log->error: %d)",
   Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
   because of size is simpler because when we do it we already have all relevant
   locks; here we don't, so this function is mainly taking locks). 
-  Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void).
+  Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
+  is void).
 */
 
 void rotate_relay_log(MASTER_INFO* mi)
@@ -4854,7 +4855,7 @@ void rotate_relay_log(MASTER_INFO* mi)
   }
 
   /* If the relay log is closed, new_file() will do nothing. */
-  rli->relay_log.new_file(1);
+  rli->relay_log.new_file();
 
   /*
     We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
diff --git a/sql/slave.h b/sql/slave.h
index 0b77d7f7c4f0785df7a7877e2bd1e3c9fed384e6..053358dc686ec03867bb876606c58c182fb8ff74 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -73,7 +73,7 @@
   run_lock protects all information about the run state: slave_running, and the
   existence of the I/O thread (to stop/start it, you need this mutex).
   data_lock protects some moving members of the struct: counters (log name,
-  position) and relay log (MYSQL_LOG object).
+  position) and relay log (MYSQL_BIN_LOG object).
 
   In RELAY_LOG_INFO: run_lock, data_lock
   see MASTER_INFO
@@ -81,7 +81,7 @@
   Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
   must acquire LOCK_active_mi first.
 
-  In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log
+  In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log
   LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
   (so that you have to update the .index file).
 */