summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc131
1 files changed, 97 insertions, 34 deletions
diff --git a/sql/log.cc b/sql/log.cc
index c6b41447d6a..77ba7aa6283 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -49,7 +49,7 @@
#include "sql_plugin.h"
#include "rpl_handler.h"
-
+#include "debug_sync.h"
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_TIME_SIZE 32
@@ -5002,19 +5002,29 @@ err:
{
bool synced;
if ((error= flush_and_sync(&synced)))
- goto unlock;
-
- if ((error= RUN_HOOK(binlog_storage, after_flush,
+ {
+ mysql_mutex_unlock(&LOCK_log);
+ }
+ else if ((error= RUN_HOOK(binlog_storage, after_flush,
(thd, log_file_name, file->pos_in_file, synced))))
{
sql_print_error("Failed to run 'after_flush' hooks");
- goto unlock;
+ mysql_mutex_unlock(&LOCK_log);
+ }
+ else
+ {
+ bool check_purge;
+ signal_update();
+ error= rotate(false, &check_purge);
+ mysql_mutex_unlock(&LOCK_log);
+ if (!error && check_purge)
+ purge();
}
- signal_update();
- rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
-unlock:
- mysql_mutex_unlock(&LOCK_log);
+ else
+ {
+ mysql_mutex_unlock(&LOCK_log);
+ }
}
if (error)
@@ -5100,25 +5110,29 @@ bool general_log_write(THD *thd, enum enum_server_command command,
}
/**
+ The method executes rotation when LOCK_log is already acquired
+ by the caller.
+
+ @param force_rotate caller can request the log rotation
+ @param check_purge is set to true if rotation took place
+
@note
If rotation fails, for instance the server was unable
to create a new log file, we still try to write an
incident event to the current log.
@retval
- nonzero - error
+ nonzero - error in rotating routine.
*/
-int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
+int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
{
int error= 0;
- DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
-#ifdef HAVE_REPLICATION
- bool check_purge= false;
-#endif
- if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
- mysql_mutex_lock(&LOCK_log);
- if ((flags & RP_FORCE_ROTATE) ||
- (my_b_tell(&log_file) >= (my_off_t) max_size))
+ DBUG_ENTER("MYSQL_BIN_LOG::rotate");
+
+ //todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log);
+ *check_purge= false;
+
+ if (force_rotate || (my_b_tell(&log_file) >= (my_off_t) max_size))
{
if ((error= new_file_without_locking()))
/**
@@ -5133,24 +5147,59 @@ int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
if (!write_incident(current_thd, FALSE))
flush_and_sync(0);
-#ifdef HAVE_REPLICATION
- check_purge= true;
-#endif
+ *check_purge= true;
}
- if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
- mysql_mutex_unlock(&LOCK_log);
+ DBUG_RETURN(error);
+}
+
+/**
+ The method executes logs purging routine.
+
+ @retval
+ nonzero - error in rotating routine.
+*/
+void MYSQL_BIN_LOG::purge()
+{
#ifdef HAVE_REPLICATION
- /*
- NOTE: Run purge_logs wo/ holding LOCK_log
- as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
- */
- if (!error && check_purge && expire_logs_days)
+ if (expire_logs_days)
{
+ DEBUG_SYNC(current_thd, "at_purge_logs_before_date");
time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
if (purge_time >= 0)
+ {
purge_logs_before_date(purge_time);
+ }
}
#endif
+}
+
+/**
+ The method is a shortcut of @c rotate() and @c purge().
+ LOCK_log is acquired prior to rotate and is released after it.
+
+ @param force_rotate caller can request the log rotation
+
+ @retval
+ nonzero - error in rotating routine.
+*/
+int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate)
+{
+ int error= 0;
+ DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
+ bool check_purge= false;
+
+ //todo: fix the macro def and restore safe_mutex_assert_not_owner(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
+ error= rotate(force_rotate, &check_purge);
+ /*
+ NOTE: Run purge_logs wo/ holding LOCK_log because it does not need
+ the mutex. Otherwise causes various deadlocks.
+ */
+ mysql_mutex_unlock(&LOCK_log);
+
+ if (!error && check_purge)
+ purge();
+
DBUG_RETURN(error);
}
@@ -5352,10 +5401,17 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
{
if (!error && !(error= flush_and_sync(0)))
{
+ bool check_purge= false;
signal_update();
- error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+ error= rotate(false, &check_purge);
+ mysql_mutex_unlock(&LOCK_log);
+ if (!error && check_purge)
+ purge();
+ }
+ else
+ {
+ mysql_mutex_unlock(&LOCK_log);
}
- mysql_mutex_unlock(&LOCK_log);
}
DBUG_RETURN(error);
}
@@ -5388,11 +5444,13 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
bool incident)
{
DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
- mysql_mutex_lock(&LOCK_log);
DBUG_ASSERT(is_open());
if (likely(is_open())) // Should always be true
{
+ bool check_purge;
+
+ mysql_mutex_lock(&LOCK_log);
/*
We only bother to write to the binary log if there is anything
to write.
@@ -5460,12 +5518,17 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
mysql_mutex_lock(&LOCK_prep_xids);
prepared_xids++;
mysql_mutex_unlock(&LOCK_prep_xids);
+ mysql_mutex_unlock(&LOCK_log);
}
else
- if (rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED))
+ {
+ if (rotate(false, &check_purge))
goto err;
+ mysql_mutex_unlock(&LOCK_log);
+ if (check_purge)
+ purge();
+ }
}
- mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(0);