summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
authorAlexander Nozdrin <alik@sun.com>2010-01-18 23:19:19 +0300
committerAlexander Nozdrin <alik@sun.com>2010-01-18 23:19:19 +0300
commitdedfdb490ba528ddf3f9155a4fb6f0b3728df149 (patch)
treed38210df12297fa40d9edbf59cbb72329a4ccad4 /sql/log.cc
parent7917f0852f57ff0fecb80f561eccd674a4e1866d (diff)
parentdccf2acceab7a3ed125c0d9c11330fe5f6898a1f (diff)
downloadmariadb-git-dedfdb490ba528ddf3f9155a4fb6f0b3728df149.tar.gz
Manual merge from mysql-next-mr.
Conflicts: - sql/sql_plugin.cc
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc1536
1 files changed, 873 insertions, 663 deletions
diff --git a/sql/log.cc b/sql/log.cc
index dd5a041290a..7d5d5f9e176 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
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
@@ -138,18 +138,22 @@ sql_print_message_func sql_print_message_handlers[3] =
sql_print_error
};
-
/**
- Create the name of the default general log file
-
+ Create the name of the log specified.
+
+ This method forms a new path + file name for the
+ log specified in @c name.
+
@param[IN] buff Location for building new string.
- @param[IN] log_ext The extension for the file (e.g .log)
- @returns Pointer to a new string containing the name
+ @param[IN] name Name of the log file.
+ @param[IN] log_ext The extension for the log (e.g. .log).
+
+ @returns Pointer to new string containing the name.
*/
-char *make_default_log_name(char *buff,const char* log_ext)
+char *make_log_name(char *buff, const char *name, const char* log_ext)
{
- strmake(buff, default_logfile_name, FN_REFLEN-5);
- return fn_format(buff, buff, mysql_data_home, log_ext,
+ strmake(buff, name, FN_REFLEN-5);
+ return fn_format(buff, buff, mysql_real_data_home, log_ext,
MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
}
@@ -164,24 +168,24 @@ char *make_default_log_name(char *buff,const char* log_ext)
class Mutex_sentry
{
public:
- Mutex_sentry(pthread_mutex_t *mutex)
+ Mutex_sentry(mysql_mutex_t *mutex)
: m_mutex(mutex)
{
if (m_mutex)
- pthread_mutex_lock(mutex);
+ mysql_mutex_lock(mutex);
}
~Mutex_sentry()
{
if (m_mutex)
- pthread_mutex_unlock(m_mutex);
+ mysql_mutex_unlock(m_mutex);
#ifndef DBUG_OFF
m_mutex= 0;
#endif
}
private:
- pthread_mutex_t *m_mutex;
+ mysql_mutex_t *m_mutex;
// It's not allowed to copy this object in any way
Mutex_sentry(Mutex_sentry const&);
@@ -189,115 +193,155 @@ private:
};
/*
- Helper class to store binary log transaction data.
+ Helper classes to store non-transactional and transactional data
+ before copying it to the binary log.
*/
-class binlog_trx_data {
+class binlog_cache_data
+{
public:
- binlog_trx_data()
- : at_least_one_stmt_committed(0), incident(FALSE), m_pending(0),
- before_stmt_pos(MY_OFF_T_UNDEF)
+ binlog_cache_data(): m_pending(0), before_stmt_pos (MY_OFF_T_UNDEF),
+ incident(FALSE)
{
- trans_log.end_of_file= max_binlog_cache_size;
+ cache_log.end_of_file= max_binlog_cache_size;
}
- ~binlog_trx_data()
+ ~binlog_cache_data()
{
- DBUG_ASSERT(pending() == NULL);
- close_cached_file(&trans_log);
+ DBUG_ASSERT(empty());
+ close_cached_file(&cache_log);
}
- my_off_t position() const {
- return my_b_tell(&trans_log);
+ bool empty() const
+ {
+ return pending() == NULL && my_b_tell(&cache_log) == 0;
}
- bool empty() const
+ Rows_log_event *pending() const
{
- return pending() == NULL && my_b_tell(&trans_log) == 0;
+ return m_pending;
}
- /*
- Truncate the transaction cache to a certain position. This
- includes deleting the pending event.
- */
- void truncate(my_off_t pos)
+ void set_pending(Rows_log_event *const pending)
{
- DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
- DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos));
- if (pending())
- {
- delete pending();
- }
- set_pending(0);
- reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0);
- trans_log.end_of_file= max_binlog_cache_size;
- if (pos < before_stmt_pos)
- before_stmt_pos= MY_OFF_T_UNDEF;
+ m_pending= pending;
+ }
- /*
- The only valid positions that can be truncated to are at the
- beginning of a statement. We are relying on this fact to be able
- to set the at_least_one_stmt_committed flag correctly. In other word, if
- we are truncating to the beginning of the transaction cache,
- there will be no statements in the cache, otherwhise, we will
- have at least one statement in the transaction cache.
- */
- at_least_one_stmt_committed= (pos > 0);
+ void set_incident(void)
+ {
+ incident= TRUE;
+ }
+
+ bool has_incident(void)
+ {
+ return(incident);
}
- /*
- Reset the entire contents of the transaction cache, emptying it
- completely.
- */
- void reset() {
- if (!empty())
- truncate(0);
- before_stmt_pos= MY_OFF_T_UNDEF;
+ void reset()
+ {
+ truncate(0);
incident= FALSE;
- trans_log.end_of_file= max_binlog_cache_size;
+ before_stmt_pos= MY_OFF_T_UNDEF;
+ cache_log.end_of_file= max_binlog_cache_size;
DBUG_ASSERT(empty());
}
- Rows_log_event *pending() const
+ my_off_t get_byte_position() const
{
- return m_pending;
+ return my_b_tell(&cache_log);
}
- void set_pending(Rows_log_event *const pending)
+ my_off_t get_prev_position()
{
- m_pending= pending;
+ return(before_stmt_pos);
}
- IO_CACHE trans_log; // The transaction cache
-
- void set_incident(void)
+ void set_prev_position(my_off_t pos)
{
- incident= TRUE;
+ before_stmt_pos= pos;
}
- bool has_incident(void)
+ void restore_prev_position()
{
- return(incident);
+ truncate(before_stmt_pos);
}
- /**
- Boolean that is true if there is at least one statement in the
- transaction cache.
+ void restore_savepoint(my_off_t pos)
+ {
+ truncate(pos);
+ if (pos < before_stmt_pos)
+ before_stmt_pos= MY_OFF_T_UNDEF;
+ }
+
+ /*
+ Cache to store data before copying it to the binary log.
*/
- bool at_least_one_stmt_committed;
- bool incident;
+ IO_CACHE cache_log;
private:
/*
- Pending binrows event. This event is the event where the rows are
- currently written.
+ Pending binrows event. This event is the event where the rows are currently
+ written.
*/
Rows_log_event *m_pending;
-public:
/*
Binlog position before the start of the current statement.
*/
my_off_t before_stmt_pos;
+
+ /*
+ This indicates that some events did not get into the cache and most likely
+ it is corrupted.
+ */
+ bool incident;
+
+ /*
+ It truncates the cache to a certain position. This includes deleting the
+ pending event.
+ */
+ void truncate(my_off_t pos)
+ {
+ DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos));
+ if (pending())
+ {
+ delete pending();
+ set_pending(0);
+ }
+ reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, 0);
+ cache_log.end_of_file= max_binlog_cache_size;
+ }
+
+ binlog_cache_data& operator=(const binlog_cache_data& info);
+ binlog_cache_data(const binlog_cache_data& info);
+};
+
+class binlog_cache_mngr {
+public:
+ binlog_cache_mngr() {}
+
+ void reset_cache(binlog_cache_data* cache_data)
+ {
+ cache_data->reset();
+ }
+
+ binlog_cache_data* get_binlog_cache_data(bool is_transactional)
+ {
+ return (is_transactional ? &trx_cache : &stmt_cache);
+ }
+
+ IO_CACHE* get_binlog_cache_log(bool is_transactional)
+ {
+ return (is_transactional ? &trx_cache.cache_log : &stmt_cache.cache_log);
+ }
+
+ binlog_cache_data stmt_cache;
+
+ binlog_cache_data trx_cache;
+
+private:
+
+ binlog_cache_mngr& operator=(const binlog_cache_mngr& info);
+ binlog_cache_mngr(const binlog_cache_mngr& info);
};
handlerton *binlog_hton;
@@ -420,8 +464,8 @@ bool Log_to_csv_event_handler::
*/
save_time_zone_used= thd->time_zone_used;
- save_thd_options= thd->options;
- thd->options&= ~OPTION_BIN_LOG;
+ save_thd_options= thd->variables.option_bits;
+ thd->variables.option_bits&= ~OPTION_BIN_LOG;
bzero(& table_list, sizeof(TABLE_LIST));
table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str;
@@ -433,7 +477,7 @@ bool Log_to_csv_event_handler::
table_list.db_length= MYSQL_SCHEMA_NAME.length;
/*
- 1) open_performance_schema_table generates an error of the
+ 1) open_log_table generates an error of the
table can not be opened or is corrupted.
2) "INSERT INTO general_log" can generate warning sometimes.
@@ -446,8 +490,7 @@ bool Log_to_csv_event_handler::
thd->push_internal_handler(& error_handler);
need_pop= TRUE;
- if (!(table= open_performance_schema_table(thd, & table_list,
- & open_tables_backup)))
+ if (!(table= open_log_table(thd, &table_list, &open_tables_backup)))
goto err;
need_close= TRUE;
@@ -527,9 +570,9 @@ err:
if (need_pop)
thd->pop_internal_handler();
if (need_close)
- close_performance_schema_table(thd, & open_tables_backup);
+ close_log_table(thd, &open_tables_backup);
- thd->options= save_thd_options;
+ thd->variables.option_bits= save_thd_options;
thd->time_zone_used= save_time_zone_used;
return result;
}
@@ -597,8 +640,7 @@ bool Log_to_csv_event_handler::
table_list.db= MYSQL_SCHEMA_NAME.str;
table_list.db_length= MYSQL_SCHEMA_NAME.length;
- if (!(table= open_performance_schema_table(thd, & table_list,
- & open_tables_backup)))
+ if (!(table= open_log_table(thd, &table_list, &open_tables_backup)))
goto err;
need_close= TRUE;
@@ -723,7 +765,7 @@ err:
table->file->ha_release_auto_increment();
}
if (need_close)
- close_performance_schema_table(thd, & open_tables_backup);
+ close_log_table(thd, &open_tables_backup);
thd->time_zone_used= save_time_zone_used;
DBUG_RETURN(result);
}
@@ -757,12 +799,11 @@ int Log_to_csv_event_handler::
table_list.db= MYSQL_SCHEMA_NAME.str;
table_list.db_length= MYSQL_SCHEMA_NAME.length;
- table= open_performance_schema_table(thd, & table_list,
- & open_tables_backup);
+ table= open_log_table(thd, &table_list, &open_tables_backup);
if (table)
{
result= 0;
- close_performance_schema_table(thd, & open_tables_backup);
+ close_log_table(thd, &open_tables_backup);
}
else
result= 1;
@@ -838,10 +879,10 @@ 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);
+ mysql_slow_log.open_slow_log(opt_slow_logname);
if (opt_log)
- mysql_log.open_query_log(sys_var_general_log_path.value);
+ mysql_log.open_query_log(opt_logname);
is_initialized= TRUE;
}
@@ -898,7 +939,7 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format,
void LOGGER::cleanup_base()
{
DBUG_ASSERT(inited == 1);
- rwlock_destroy(&LOCK_logger);
+ mysql_rwlock_destroy(&LOCK_logger);
if (table_log_handler)
{
table_log_handler->cleanup();
@@ -943,7 +984,7 @@ void LOGGER::init_base()
init_error_log(LOG_FILE);
file_log_handler->init_pthread_objects();
- my_rwlock_init(&LOCK_logger, NULL);
+ mysql_rwlock_init(key_rwlock_LOCK_logger, &LOCK_logger);
}
@@ -977,6 +1018,54 @@ bool LOGGER::flush_logs(THD *thd)
}
+/**
+ Close and reopen the slow log (with locks).
+
+ @returns FALSE.
+*/
+bool LOGGER::flush_slow_log()
+{
+ /*
+ Now we lock logger, as nobody should be able to use logging routines while
+ log tables are closed
+ */
+ logger.lock_exclusive();
+
+ /* Reopen slow log file */
+ if (opt_slow_log)
+ file_log_handler->get_mysql_slow_log()->reopen_file();
+
+ /* End of log flush */
+ logger.unlock();
+
+ return 0;
+}
+
+
+/**
+ Close and reopen the general log (with locks).
+
+ @returns FALSE.
+*/
+bool LOGGER::flush_general_log()
+{
+ /*
+ Now we lock logger, as nobody should be able to use logging routines while
+ log tables are closed
+ */
+ logger.lock_exclusive();
+
+ /* Reopen general log file */
+ if (opt_log)
+ file_log_handler->get_mysql_log()->reopen_file();
+
+ /* End of log flush */
+ logger.unlock();
+
+ return 0;
+}
+
+
/*
Log slow query with all enabled log event handlers
@@ -1202,7 +1291,7 @@ bool LOGGER::activate_log_handler(THD* thd, uint log_type)
{
file_log= file_log_handler->get_mysql_slow_log();
- file_log->open_slow_log(sys_var_slow_log_path.value);
+ file_log->open_slow_log(opt_slow_logname);
if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW))
{
/* Error printed by open table in activate_log() */
@@ -1221,7 +1310,7 @@ bool LOGGER::activate_log_handler(THD* thd, uint log_type)
{
file_log= file_log_handler->get_mysql_log();
- file_log->open_query_log(sys_var_general_log_path.value);
+ file_log->open_query_log(opt_logname);
if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL))
{
/* Error printed by open table in activate_log() */
@@ -1305,26 +1394,6 @@ int LOGGER::set_handlers(uint error_log_printer,
return 0;
}
-/**
- This function checks if a transactional talbe was updated by the
- current statement.
-
- @param thd The client thread that executed the current statement.
- @return
- @c true if a transactional table was updated, @false otherwise.
-*/
-static bool stmt_has_updated_trans_table(THD *thd)
-{
- Ha_trx_info *ha_info;
-
- for (ha_info= thd->transaction.stmt.ha_list; ha_info && ha_info->is_started(); ha_info= ha_info->next())
- {
- if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton)
- return (TRUE);
- }
- return (FALSE);
-}
-
/*
Save position of binary log transaction cache.
@@ -1347,10 +1416,10 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos)
DBUG_ASSERT(pos != NULL);
if (thd_get_ha_data(thd, binlog_hton) == NULL)
thd->binlog_setup_trx_data();
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
DBUG_ASSERT(mysql_bin_log.is_open());
- *pos= trx_data->position();
+ *pos= cache_mngr->trx_cache.get_byte_position();
DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
DBUG_VOID_RETURN;
}
@@ -1381,9 +1450,9 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos)
/* Only true if binlog_trans_log_savepos() wasn't called before */
DBUG_ASSERT(pos != ~(my_off_t) 0);
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
- trx_data->truncate(pos);
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ cache_mngr->trx_cache.restore_savepoint(pos);
DBUG_VOID_RETURN;
}
@@ -1412,115 +1481,127 @@ int binlog_init(void *p)
static int binlog_close_connection(handlerton *hton, THD *thd)
{
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
- DBUG_ASSERT(trx_data->empty());
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ DBUG_ASSERT(cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty());
thd_set_ha_data(thd, binlog_hton, NULL);
- trx_data->~binlog_trx_data();
- my_free((uchar*)trx_data, MYF(0));
+ cache_mngr->~binlog_cache_mngr();
+ my_free((uchar*)cache_mngr, MYF(0));
return 0;
}
-/*
- End a transaction.
+/**
+ This function flushes a transactional cache upon commit/rollback.
- SYNOPSIS
- binlog_end_trans()
+ @param thd The thread whose transaction should be flushed
+ @param cache_mngr Pointer to the cache data to be flushed
+ @param end_ev The end event either commit/rollback.
- thd The thread whose transaction should be ended
- trx_data Pointer to the transaction data to use
- end_ev The end event to use, or NULL
- all True if the entire transaction should be ended, false if
- only the statement transaction should be ended.
+ @return
+ nonzero if an error pops up when flushing the transactional cache.
+*/
+static int
+binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr,
+ Log_event *end_ev)
+{
+ DBUG_ENTER("binlog_flush_trx_cache");
+ int error=0;
+ IO_CACHE *cache_log= &cache_mngr->trx_cache.cache_log;
- DESCRIPTION
+ /*
+ This function handles transactional changes and as such
+ this flag equals to true.
+ */
+ bool const is_transactional= TRUE;
- End the currently open transaction. The transaction can be either
- a real transaction (if 'all' is true) or a statement transaction
- (if 'all' is false).
+ if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
+ DBUG_RETURN(1);
+ /*
+ Doing a commit or a rollback including non-transactional tables,
+ i.e., ending a transaction where we might write the transaction
+ cache to the binary log.
+
+ We can always end the statement when ending a transaction since
+ transactions are not allowed inside stored functions. If they
+ were, we would have to ensure that we're not ending a statement
+ inside a stored function.
+ */
+ error= mysql_bin_log.write(thd, &cache_mngr->trx_cache.cache_log, end_ev,
+ cache_mngr->trx_cache.has_incident());
+ cache_mngr->reset_cache(&cache_mngr->trx_cache);
- If 'end_ev' is NULL, the transaction is a rollback of only
- transactional tables, so the transaction cache will be truncated
- to either just before the last opened statement transaction (if
- 'all' is false), or reset completely (if 'all' is true).
- */
+ /*
+ We need to step the table map version after writing the
+ transaction cache to disk.
+ */
+ mysql_bin_log.update_table_map_version();
+ statistic_increment(binlog_cache_use, &LOCK_status);
+ if (cache_log->disk_writes != 0)
+ {
+ statistic_increment(binlog_cache_disk_use, &LOCK_status);
+ cache_log->disk_writes= 0;
+ }
+
+ DBUG_ASSERT(cache_mngr->trx_cache.empty());
+ DBUG_RETURN(error);
+}
+
+/**
+ This function truncates the transactional cache upon committing or rolling
+ back either a transaction or a statement.
+
+ @param thd The thread whose transaction should be flushed
+ @param cache_mngr Pointer to the cache data to be flushed
+ @param all @c true means truncate the transaction, otherwise the
+ statement must be truncated.
+
+ @return
+ nonzero if an error pops up when truncating the transactional cache.
+*/
static int
-binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
- Log_event *end_ev, bool all)
+binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all)
{
- DBUG_ENTER("binlog_end_trans");
+ DBUG_ENTER("binlog_truncate_trx_cache");
int error=0;
- IO_CACHE *trans_log= &trx_data->trans_log;
- DBUG_PRINT("enter", ("transaction: %s end_ev: 0x%lx",
- all ? "all" : "stmt", (long) end_ev));
- DBUG_PRINT("info", ("thd->options={ %s%s}",
- FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
- FLAGSTR(thd->options, OPTION_BEGIN)));
+ /*
+ This function handles transactional changes and as such this flag
+ equals to true.
+ */
+ bool const is_transactional= TRUE;
+ DBUG_PRINT("info", ("thd->options={ %s%s}, transaction: %s",
+ FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
+ FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
+ all ? "all" : "stmt"));
/*
- NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
- only transactional tables. If the transaction contain changes to
- any non-transactiona tables, we need write the transaction and log
- a ROLLBACK last.
+ If rolling back an entire transaction or a single statement not
+ inside a transaction, we reset the transaction cache.
*/
- if (end_ev != NULL)
+ thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
+ if (all || !thd->in_multi_stmt_transaction())
{
- if (thd->binlog_flush_pending_rows_event(TRUE))
- DBUG_RETURN(1);
- /*
- Doing a commit or a rollback including non-transactional tables,
- i.e., ending a transaction where we might write the transaction
- cache to the binary log.
-
- We can always end the statement when ending a transaction since
- transactions are not allowed inside stored functions. If they
- were, we would have to ensure that we're not ending a statement
- inside a stored function.
- */
- error= mysql_bin_log.write(thd, &trx_data->trans_log, end_ev,
- trx_data->has_incident());
- trx_data->reset();
+ if (cache_mngr->trx_cache.has_incident())
+ error= mysql_bin_log.write_incident(thd, TRUE);
- /*
- We need to step the table map version after writing the
- transaction cache to disk.
- */
- mysql_bin_log.update_table_map_version();
- statistic_increment(binlog_cache_use, &LOCK_status);
- if (trans_log->disk_writes != 0)
- {
- statistic_increment(binlog_cache_disk_use, &LOCK_status);
- trans_log->disk_writes= 0;
- }
+ cache_mngr->reset_cache(&cache_mngr->trx_cache);
+
+ thd->clear_binlog_table_maps();
}
+ /*
+ If rolling back a statement in a transaction, we truncate the
+ transaction cache to remove the statement.
+ */
else
- {
- /*
- If rolling back an entire transaction or a single statement not
- inside a transaction, we reset the transaction cache.
-
- If rolling back a statement in a transaction, we truncate the
- transaction cache to remove the statement.
- */
- thd->binlog_remove_pending_rows_event(TRUE);
- if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
- {
- if (trx_data->has_incident())
- error= mysql_bin_log.write_incident(thd, TRUE);
- trx_data->reset();
- }
- else // ...statement
- trx_data->truncate(trx_data->before_stmt_pos);
+ cache_mngr->trx_cache.restore_prev_position();
- /*
- We need to step the table map version on a rollback to ensure
- that a new table map event is generated instead of the one that
- was written to the thrown-away transaction cache.
- */
- mysql_bin_log.update_table_map_version();
- }
+ /*
+ We need to step the table map version on a rollback to ensure that a new
+ table map event is generated instead of the one that was written to the
+ thrown-away transaction cache.
+ */
+ mysql_bin_log.update_table_map_version();
- DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL);
+ DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL);
DBUG_RETURN(error);
}
@@ -1536,10 +1617,56 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all)
}
/**
+ This function flushes the non-transactional to the binary log upon
+ committing or rolling back a statement.
+
+ @param thd The thread whose transaction should be flushed
+ @param cache_mngr Pointer to the cache data to be flushed
+
+ @return
+ nonzero if an error pops up when flushing the non-transactional cache.
+*/
+static int
+binlog_flush_stmt_cache(THD *thd, binlog_cache_mngr *cache_mngr)
+{
+ int error= 0;
+ DBUG_ENTER("binlog_flush_stmt_cache");
+ /*
+ If we are flushing the statement cache, it means that the changes get
+ through otherwise the cache is empty and this routine should not be called.
+ */
+ DBUG_ASSERT(cache_mngr->stmt_cache.has_incident() == FALSE);
+ /*
+ This function handles non-transactional changes and as such this flag equals
+ to false.
+ */
+ bool const is_transactional= FALSE;
+ IO_CACHE *cache_log= &cache_mngr->stmt_cache.cache_log;
+ thd->binlog_flush_pending_rows_event(TRUE, is_transactional);
+ Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
+ if ((error= mysql_bin_log.write(thd, cache_log, &qev,
+ cache_mngr->stmt_cache.has_incident())))
+ DBUG_RETURN(error);
+ cache_mngr->reset_cache(&cache_mngr->stmt_cache);
+
+ /*
+ We need to step the table map version after writing the
+ transaction cache to disk.
+ */
+ mysql_bin_log.update_table_map_version();
+ statistic_increment(binlog_cache_use, &LOCK_status);
+ if (cache_log->disk_writes != 0)
+ {
+ statistic_increment(binlog_cache_disk_use, &LOCK_status);
+ cache_log->disk_writes= 0;
+ }
+ DBUG_RETURN(error);
+}
+
+/**
This function is called once after each statement.
- It has the responsibility to flush the transaction cache to the
- binlog file on commits.
+ It has the responsibility to flush the caches to the binary log on commits.
@param hton The binlog handlerton.
@param thd The client thread that executes the transaction.
@@ -1552,57 +1679,53 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
{
int error= 0;
DBUG_ENTER("binlog_commit");
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ bool const in_transaction= thd->in_multi_stmt_transaction();
+
+ DBUG_PRINT("debug",
+ ("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
+ all,
+ YESNO(in_transaction),
+ YESNO(thd->transaction.all.modified_non_trans_table),
+ YESNO(thd->transaction.stmt.modified_non_trans_table)));
- if (trx_data->empty())
+ if (!cache_mngr->stmt_cache.empty())
{
- // we're here because trans_log was flushed in MYSQL_BIN_LOG::log_xid()
- trx_data->reset();
+ binlog_flush_stmt_cache(thd, cache_mngr);
+ }
+
+ if (cache_mngr->trx_cache.empty())
+ {
+ /*
+ we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
+ */
+ cache_mngr->reset_cache(&cache_mngr->trx_cache);
DBUG_RETURN(0);
}
/*
We commit the transaction if:
-
- We are not in a transaction and committing a statement, or
-
- - We are in a transaction and a full transaction is committed
-
- Otherwise, we accumulate the statement
+ - We are in a transaction and a full transaction is committed.
+ Otherwise, we accumulate the changes.
*/
- ulonglong const in_transaction=
- thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
- DBUG_PRINT("debug",
- ("all: %d, empty: %s, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
- all,
- YESNO(trx_data->empty()),
- YESNO(in_transaction),
- YESNO(thd->transaction.all.modified_non_trans_table),
- YESNO(thd->transaction.stmt.modified_non_trans_table)));
- if (!in_transaction || all ||
- (!all && !trx_data->at_least_one_stmt_committed &&
- !stmt_has_updated_trans_table(thd) &&
- thd->transaction.stmt.modified_non_trans_table))
+ if (!in_transaction || all)
{
- Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, 0);
- error= binlog_end_trans(thd, trx_data, &qev, all);
+ Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0);
+ error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
}
- trx_data->at_least_one_stmt_committed = my_b_tell(&trx_data->trans_log) > 0;
-
+ /*
+ This is part of the stmt rollback.
+ */
if (!all)
- trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit
+ cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
DBUG_RETURN(error);
}
/**
- This function is called when a transaction involving a transactional
- table is rolled back.
-
- It has the responsibility to flush the transaction cache to the
- binlog file. However, if the transaction does not involve
- non-transactional tables, nothing needs to be logged.
+ This function is called when a transaction or a statement is rolled back.
@param hton The binlog handlerton.
@param thd The client thread that executes the transaction.
@@ -1615,18 +1738,38 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
{
DBUG_ENTER("binlog_rollback");
int error=0;
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
-
- if (trx_data->empty()) {
- trx_data->reset();
- DBUG_RETURN(0);
- }
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
YESNO(all),
YESNO(thd->transaction.all.modified_non_trans_table),
YESNO(thd->transaction.stmt.modified_non_trans_table)));
+
+ /*
+ If an incident event is set we do not flush the content of the statement
+ cache because it may be corrupted.
+ */
+ if (cache_mngr->stmt_cache.has_incident())
+ {
+ mysql_bin_log.write_incident(thd, TRUE);
+ cache_mngr->reset_cache(&cache_mngr->stmt_cache);
+ }
+ else if (!cache_mngr->stmt_cache.empty())
+ {
+ binlog_flush_stmt_cache(thd, cache_mngr);
+ }
+
+ if (cache_mngr->trx_cache.empty())
+ {
+ /*
+ we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid()
+ */
+ cache_mngr->reset_cache(&cache_mngr->trx_cache);
+ DBUG_RETURN(0);
+ }
+
+
if (mysql_bin_log.check_write_error(thd))
{
/*
@@ -1637,52 +1780,46 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
*/
DBUG_ASSERT(!all);
/*
- We reach this point if either only transactional tables were modified or
- the effect of a statement that did not get into the binlog needs to be
- rolled back. In the latter case, if a statement changed non-transactional
- tables or had the OPTION_KEEP_LOG associated, we write an incident event
- to the binlog in order to stop slaves and notify users that some changes
- on the master did not get into the binlog and slaves will be inconsistent.
- On the other hand, if a statement is transactional, we just safely roll it
- back.
+ We reach this point if the effect of a statement did not properly get into
+ a cache and need to be rolled back.
*/
- if ((thd->transaction.stmt.modified_non_trans_table ||
- (thd->options & OPTION_KEEP_LOG)) &&
- mysql_bin_log.check_write_error(thd))
- trx_data->set_incident();
- error= binlog_end_trans(thd, trx_data, 0, all);
+ error= binlog_truncate_trx_cache(thd, cache_mngr, all);
}
else
- {
- /*
- We flush the cache with a rollback, wrapped in a beging/rollback if:
- . aborting a transaction that modified a non-transactional table;
+ {
+ /*
+ We flush the cache wrapped in a beging/rollback if:
+ . aborting a transcation that modified a non-transactional table or;
. aborting a statement that modified both transactional and
- non-transactional tables but which is not in the boundaries of any
- transaction or there was no early change;
+ non-transctional tables but which is not in the boundaries of any
+ transaction;
. the OPTION_KEEP_LOG is activate.
*/
- if ((all && thd->transaction.all.modified_non_trans_table) ||
+ if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
+ ((all && thd->transaction.all.modified_non_trans_table) ||
(!all && thd->transaction.stmt.modified_non_trans_table &&
- !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) ||
- (!all && thd->transaction.stmt.modified_non_trans_table &&
- !trx_data->at_least_one_stmt_committed &&
- thd->current_stmt_binlog_row_based) ||
- ((thd->options & OPTION_KEEP_LOG)))
+ !thd->in_multi_stmt_transaction()) ||
+ (thd->variables.option_bits & OPTION_KEEP_LOG)))
{
- Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);
- error= binlog_end_trans(thd, trx_data, &qev, all);
+ Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0);
+ error= binlog_flush_trx_cache(thd, cache_mngr, &qev);
}
/*
Otherwise, we simply truncate the cache as there is no change on
non-transactional tables as follows.
*/
- else if ((all && !thd->transaction.all.modified_non_trans_table) ||
- (!all && !thd->transaction.stmt.modified_non_trans_table))
- error= binlog_end_trans(thd, trx_data, 0, all);
+ else if (all || (!all &&
+ (!thd->transaction.stmt.modified_non_trans_table ||
+ !thd->in_multi_stmt_transaction() ||
+ thd->variables.binlog_format != BINLOG_FORMAT_STMT)))
+ error= binlog_truncate_trx_cache(thd, cache_mngr, all);
}
+
+ /*
+ This is part of the stmt rollback.
+ */
if (!all)
- trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback
+ cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
DBUG_RETURN(error);
}
@@ -1758,7 +1895,8 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int const error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query(), thd->query_length(), TRUE, FALSE, errcode);
+ thd->query(), thd->query_length(), TRUE, FALSE, FALSE,
+ errcode);
DBUG_RETURN(error);
}
@@ -1772,12 +1910,13 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
from the SAVEPOINT command.
*/
if (unlikely(thd->transaction.all.modified_non_trans_table ||
- (thd->options & OPTION_KEEP_LOG)))
+ (thd->variables.option_bits & OPTION_KEEP_LOG)))
{
int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
int error=
thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query(), thd->query_length(), TRUE, FALSE, errcode);
+ thd->query(), thd->query_length(), TRUE, FALSE, FALSE,
+ errcode);
DBUG_RETURN(error);
}
binlog_trans_log_truncate(thd, *(my_off_t*)sv);
@@ -1811,8 +1950,9 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
File file;
DBUG_ENTER("open_binlog");
- if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE,
- MYF(MY_WME))) < 0)
+ if ((file= mysql_file_open(key_file_binlog,
+ log_file_name, O_RDONLY | O_BINARY | O_SHARE,
+ MYF(MY_WME))) < 0)
{
sql_print_error("Failed to open log (file '%s', errno %d)",
log_file_name, my_errno);
@@ -1834,7 +1974,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg)
err:
if (file >= 0)
{
- my_close(file,MYF(0));
+ mysql_file_close(file, MYF(0));
end_io_cache(log);
}
DBUG_RETURN(-1);
@@ -1948,7 +2088,7 @@ updating the index files.", max_found);
*/
if (((strlen(ext_buf) + (end - name)) >= FN_REFLEN))
{
- sql_print_error("Log filename too large: %s%s (%lu). \
+ sql_print_error("Log filename too large: %s%s (%zu). \
Please fix this by archiving old logs and updating the \
index files.", name, ext_buf, (strlen(ext_buf) + (end - name)));
error= 1;
@@ -2044,10 +2184,11 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
db[0]= 0;
- if ((file= my_open(log_file_name, open_flags,
- MYF(MY_WME | ME_WAITTANG))) < 0 ||
+ if ((file= mysql_file_open(key_file_MYSQL_LOG,
+ 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,
+ mysql_file_tell(file, MYF(MY_WME)), 0,
MYF(MY_WME | MY_NABP |
((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
goto err;
@@ -2085,7 +2226,7 @@ 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));
+ mysql_file_close(file, MYF(0));
end_io_cache(&log_file);
safeFree(name);
log_state= LOG_CLOSED;
@@ -2109,7 +2250,7 @@ void MYSQL_LOG::init_pthread_objects()
{
DBUG_ASSERT(inited == 0);
inited= 1;
- (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW);
+ mysql_mutex_init(key_LOG_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW);
}
/*
@@ -2134,13 +2275,13 @@ void MYSQL_LOG::close(uint exiting)
{
end_io_cache(&log_file);
- if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error)
+ if (mysql_file_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)
+ if (mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
@@ -2160,7 +2301,7 @@ void MYSQL_LOG::cleanup()
if (inited)
{
inited= 0;
- (void) pthread_mutex_destroy(&LOCK_log);
+ mysql_mutex_destroy(&LOCK_log);
close(0);
}
DBUG_VOID_RETURN;
@@ -2215,7 +2356,7 @@ void MYSQL_QUERY_LOG::reopen_file()
DBUG_VOID_RETURN;
}
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
save_name= name;
name= 0; // Don't free name
@@ -2228,7 +2369,7 @@ void MYSQL_QUERY_LOG::reopen_file()
open(save_name, log_type, 0, io_cache_type);
my_free(save_name, MYF(0));
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_VOID_RETURN;
}
@@ -2270,7 +2411,7 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host,
struct tm start;
uint time_buff_len= 0;
- (void) pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
/* Test if someone closed between the is_open test and lock */
if (is_open())
@@ -2319,7 +2460,7 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host,
goto err;
}
- (void) pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
return FALSE;
err:
@@ -2328,7 +2469,7 @@ err:
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
- (void) pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
return TRUE;
}
@@ -2371,11 +2512,11 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
bool error= 0;
DBUG_ENTER("MYSQL_QUERY_LOG::write");
- (void) pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
if (!is_open())
{
- (void) pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(0);
}
@@ -2484,7 +2625,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
}
}
}
- (void) pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
}
@@ -2546,9 +2687,9 @@ void MYSQL_BIN_LOG::cleanup()
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);
+ mysql_mutex_destroy(&LOCK_log);
+ mysql_mutex_destroy(&LOCK_index);
+ mysql_cond_destroy(&update_cond);
}
DBUG_VOID_RETURN;
}
@@ -2569,9 +2710,9 @@ 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);
+ mysql_mutex_init(key_LOG_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW);
+ mysql_mutex_init(key_BINLOG_LOCK_index, &LOCK_index, MY_MUTEX_INIT_SLOW);
+ mysql_cond_init(key_BINLOG_update_cond, &update_cond, 0);
}
@@ -2594,23 +2735,25 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
}
fn_format(index_file_name, index_file_name_arg, mysql_data_home,
".index", opt);
- if ((index_file_nr= my_open(index_file_name,
- O_RDWR | O_CREAT | O_BINARY ,
- MYF(MY_WME))) < 0 ||
- my_sync(index_file_nr, MYF(MY_WME)) ||
+ if ((index_file_nr= mysql_file_open(key_file_binlog_index,
+ index_file_name,
+ O_RDWR | O_CREAT | O_BINARY,
+ MYF(MY_WME))) < 0 ||
+ mysql_file_sync(index_file_nr, MYF(MY_WME)) ||
init_io_cache(&index_file, index_file_nr,
IO_SIZE, WRITE_CACHE,
- my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)),
- 0, MYF(MY_WME | MY_WAIT_IF_FULL)) ||
+ mysql_file_seek(index_file_nr, 0L, MY_SEEK_END, MYF(0)),
+ 0, MYF(MY_WME | MY_WAIT_IF_FULL)) ||
DBUG_EVALUATE_IF("fault_injection_openning_index", 1, 0))
{
/*
TODO: all operations creating/deleting the index file or a log, should
call my_sync_dir() or my_sync_dir_by_file() to be durable.
- TODO: file creation should be done with my_create() not my_open().
+ TODO: file creation should be done with mysql_file_create()
+ not mysql_file_open().
*/
if (index_file_nr >= 0)
- my_close(index_file_nr,MYF(0));
+ mysql_file_close(index_file_nr, MYF(0));
return TRUE;
}
@@ -2774,7 +2917,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
bytes_written+= description_event_for_queue->data_written;
}
if (flush_io_cache(&log_file) ||
- my_sync(log_file.file, MYF(MY_WME)))
+ mysql_file_sync(log_file.file, MYF(MY_WME)))
goto err;
if (write_file_name_to_index_file)
@@ -2795,7 +2938,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
strlen(log_file_name)) ||
my_b_write(&index_file, (uchar*) "\n", 1) ||
flush_io_cache(&index_file) ||
- my_sync(index_file.file, MYF(MY_WME)))
+ mysql_file_sync(index_file.file, MYF(MY_WME)))
goto err;
#ifdef HAVE_REPLICATION
@@ -2822,7 +2965,7 @@ 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));
+ mysql_file_close(file, MYF(0));
end_io_cache(&log_file);
end_io_cache(&index_file);
safeFree(name);
@@ -2833,9 +2976,9 @@ shutdown the MySQL server and restart it.", name, errno);
int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo)
{
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
int ret = raw_get_current_log(linfo);
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
return ret;
}
@@ -2875,19 +3018,20 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset)
for (;; offset+= bytes_read)
{
- (void) my_seek(file, offset, MY_SEEK_SET, MYF(0));
- if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME)))
+ mysql_file_seek(file, offset, MY_SEEK_SET, MYF(0));
+ if ((bytes_read= (int) mysql_file_read(file, io_buf, sizeof(io_buf),
+ MYF(MY_WME)))
< 0)
goto err;
if (!bytes_read)
break; // end of file
- (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
- if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
+ mysql_file_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0));
+ if (mysql_file_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP)))
goto err;
}
/* The following will either truncate the file or fill the end with \n' */
- if (my_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) ||
- my_sync(file, MYF(MY_WME)))
+ if (mysql_file_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) ||
+ mysql_file_sync(file, MYF(MY_WME)))
goto err;
/* Reset data in old index cache */
@@ -2936,8 +3080,8 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
move from under our feet
*/
if (need_lock)
- pthread_mutex_lock(&LOCK_index);
- safe_mutex_assert_owner(&LOCK_index);
+ mysql_mutex_lock(&LOCK_index);
+ mysql_mutex_assert_owner(&LOCK_index);
/* As the file is flushed, we can't get an error here */
(void) reinit_io_cache(&index_file, READ_CACHE, (my_off_t) 0, 0, 0);
@@ -2971,7 +3115,7 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
}
if (need_lock)
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
@@ -3007,8 +3151,8 @@ int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
char *fname= linfo->log_file_name;
if (need_lock)
- pthread_mutex_lock(&LOCK_index);
- safe_mutex_assert_owner(&LOCK_index);
+ mysql_mutex_lock(&LOCK_index);
+ mysql_mutex_assert_owner(&LOCK_index);
/* As the file is flushed, we can't get an error here */
(void) reinit_io_cache(&index_file, READ_CACHE, linfo->index_file_offset, 0,
@@ -3025,7 +3169,7 @@ int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock)
err:
if (need_lock)
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_index);
return error;
}
@@ -3060,8 +3204,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
We need to get both locks to be sure that no one is trying to
write to the index log file.
*/
- pthread_mutex_lock(&LOCK_log);
- pthread_mutex_lock(&LOCK_index);
+ mysql_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_index);
/*
The following mutex is needed to ensure that no threads call
@@ -3069,7 +3213,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
thread. If the transaction involved MyISAM tables, it should go
into binlog even on rollback.
*/
- pthread_mutex_lock(&LOCK_thread_count);
+ mysql_mutex_lock(&LOCK_thread_count);
/* Save variables so that we can reopen the log */
save_name=name;
@@ -3162,9 +3306,9 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
err:
if (error == 1)
name= const_cast<char*>(save_name);
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_mutex_unlock(&LOCK_index);
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_thread_count);
+ mysql_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
}
@@ -3218,7 +3362,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
DBUG_ASSERT(rli->slave_running == 1);
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
- pthread_mutex_lock(&LOCK_index);
+ mysql_mutex_lock(&LOCK_index);
to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0));
/*
@@ -3262,19 +3406,19 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
DBUG_EXECUTE_IF("crash_before_purge_logs", abort(););
- pthread_mutex_lock(&rli->log_space_lock);
+ mysql_mutex_lock(&rli->log_space_lock);
rli->relay_log.purge_logs(to_purge_if_included, included,
0, 0, &rli->log_space_total);
// Tell the I/O thread to take the relay_log_space_limit into account
rli->ignore_log_space_limit= 0;
- pthread_mutex_unlock(&rli->log_space_lock);
+ mysql_mutex_unlock(&rli->log_space_lock);
/*
Ok to broadcast after the critical region as there is no risk of
the mutex being destroyed by this thread later - this helps save
context switches
*/
- pthread_cond_broadcast(&rli->log_space_cond);
+ mysql_cond_broadcast(&rli->log_space_cond);
/*
* Need to update the log pos because purge logs has been called
@@ -3296,7 +3440,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
err:
my_free(to_purge_if_included, MYF(0));
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
@@ -3336,7 +3480,7 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads
LOG_INFO_EOF to_log not found
LOG_INFO_EMFILE too many files opened
LOG_INFO_FATAL if any other than ENOENT error from
- my_stat() or my_delete()
+ mysql_file_stat() or mysql_file_delete()
*/
int MYSQL_BIN_LOG::purge_logs(const char *to_log,
@@ -3353,7 +3497,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
DBUG_PRINT("info",("to_log= %s",to_log));
if (need_mutex)
- pthread_mutex_lock(&LOCK_index);
+ mysql_mutex_lock(&LOCK_index);
if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
{
sql_print_error("MYSQL_BIN_LOG::purge_logs was called with file %s not "
@@ -3416,7 +3560,7 @@ err:
DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", abort(););
if (need_mutex)
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
@@ -3555,7 +3699,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
/* Get rid of the trailing '\n' */
log_info.log_file_name[length-1]= 0;
- if (!my_stat(log_info.log_file_name, &s, MYF(0)))
+ if (!mysql_file_stat(key_file_binlog, log_info.log_file_name, &s, MYF(0)))
{
if (my_errno == ENOENT)
{
@@ -3569,7 +3713,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
log_info.log_file_name);
}
- sql_print_information("Failed to execute my_stat on file '%s'",
+ sql_print_information("Failed to execute mysql_file_stat on file '%s'",
log_info.log_file_name);
my_errno= 0;
}
@@ -3707,7 +3851,7 @@ err:
@retval
LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated
LOG_INFO_FATAL if any other than ENOENT error from
- my_stat() or my_delete()
+ mysql_file_stat() or mysql_file_delete()
*/
int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
@@ -3720,7 +3864,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
DBUG_ENTER("purge_logs_before_date");
- pthread_mutex_lock(&LOCK_index);
+ mysql_mutex_lock(&LOCK_index);
to_log[0]= 0;
if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
@@ -3730,7 +3874,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
!is_active(log_info.log_file_name) &&
!log_in_use(log_info.log_file_name))
{
- if (!my_stat(log_info.log_file_name, &stat_area, MYF(0)))
+ if (!mysql_file_stat(key_file_binlog,
+ log_info.log_file_name, &stat_area, MYF(0)))
{
if (my_errno == ENOENT)
{
@@ -3779,7 +3924,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0);
err:
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
#endif /* HAVE_REPLICATION */
@@ -3855,11 +4000,11 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
}
if (need_lock)
- pthread_mutex_lock(&LOCK_log);
- pthread_mutex_lock(&LOCK_index);
+ mysql_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_index);
- safe_mutex_assert_owner(&LOCK_log);
- safe_mutex_assert_owner(&LOCK_index);
+ mysql_mutex_assert_owner(&LOCK_log);
+ mysql_mutex_assert_owner(&LOCK_index);
/*
if binlog is used as tc log, be sure all xids are "unlogged",
@@ -3873,12 +4018,12 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
if (prepared_xids)
{
tc_log_page_waits++;
- pthread_mutex_lock(&LOCK_prep_xids);
+ mysql_mutex_lock(&LOCK_prep_xids);
while (prepared_xids) {
DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
- pthread_cond_wait(&COND_prep_xids, &LOCK_prep_xids);
+ mysql_cond_wait(&COND_prep_xids, &LOCK_prep_xids);
}
- pthread_mutex_unlock(&LOCK_prep_xids);
+ mysql_mutex_unlock(&LOCK_prep_xids);
}
/* Reuse old name if not binlog and not update log */
@@ -3938,8 +4083,8 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
end:
if (need_lock)
- pthread_mutex_unlock(&LOCK_log);
- pthread_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_index);
DBUG_VOID_RETURN;
}
@@ -3948,7 +4093,7 @@ end:
bool MYSQL_BIN_LOG::append(Log_event* ev)
{
bool error = 0;
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
DBUG_ENTER("MYSQL_BIN_LOG::append");
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
@@ -3969,7 +4114,7 @@ bool MYSQL_BIN_LOG::append(Log_event* ev)
new_file_without_locking();
err:
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
signal_update(); // Safe as we don't call close
DBUG_RETURN(error);
}
@@ -3984,7 +4129,7 @@ bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...)
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
- safe_mutex_assert_owner(&LOCK_log);
+ mysql_mutex_assert_owner(&LOCK_log);
do
{
if (my_b_append(&log_file,(uchar*) buf,len))
@@ -4011,14 +4156,14 @@ bool MYSQL_BIN_LOG::flush_and_sync(bool *synced)
int err=0, fd=log_file.file;
if (synced)
*synced= 0;
- safe_mutex_assert_owner(&LOCK_log);
+ mysql_mutex_assert_owner(&LOCK_log);
if (flush_io_cache(&log_file))
return 1;
uint sync_period= get_sync_period();
if (sync_period && ++sync_counter >= sync_period)
{
sync_counter= 0;
- err=my_sync(fd, MYF(MY_WME));
+ err= mysql_file_sync(fd, MYF(MY_WME));
if (synced)
*synced= 1;
}
@@ -4055,27 +4200,67 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
int THD::binlog_setup_trx_data()
{
DBUG_ENTER("THD::binlog_setup_trx_data");
- binlog_trx_data *trx_data=
- (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
- if (trx_data)
+ if (cache_mngr)
DBUG_RETURN(0); // Already set up
- trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL));
- if (!trx_data ||
- open_cached_file(&trx_data->trans_log, mysql_tmpdir,
+ cache_mngr= (binlog_cache_mngr*) my_malloc(sizeof(binlog_cache_mngr), MYF(MY_ZEROFILL));
+ if (!cache_mngr ||
+ open_cached_file(&cache_mngr->stmt_cache.cache_log, mysql_tmpdir,
+ LOG_PREFIX, binlog_cache_size, MYF(MY_WME)) ||
+ open_cached_file(&cache_mngr->trx_cache.cache_log, mysql_tmpdir,
LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
{
- my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((uchar*)cache_mngr, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(1); // Didn't manage to set it up
}
- thd_set_ha_data(this, binlog_hton, trx_data);
+ thd_set_ha_data(this, binlog_hton, cache_mngr);
- trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data;
+ cache_mngr= new (thd_get_ha_data(this, binlog_hton)) binlog_cache_mngr;
DBUG_RETURN(0);
}
+/**
+ This function checks if a transactional talbe was updated by the
+ current transaction.
+
+ @param thd The client thread that executed the current statement.
+ @return
+ @c true if a transactional table was updated, @false otherwise.
+*/
+bool
+trans_has_updated_trans_table(THD* thd)
+{
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ return (cache_mngr ? my_b_tell (&cache_mngr->trx_cache.cache_log) : 0);
+}
+
+/**
+ This function checks if a transactional talbe was updated by the
+ current statement.
+
+ @param thd The client thread that executed the current statement.
+ @return
+ @c true if a transactional table was updated, @false otherwise.
+*/
+bool
+stmt_has_updated_trans_table(THD *thd)
+{
+ Ha_trx_info *ha_info;
+
+ for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next())
+ {
+ if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton)
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
/*
Function to start a statement and optionally a transaction for the
binary log.
@@ -4089,11 +4274,10 @@ int THD::binlog_setup_trx_data()
- Start a transaction if not in autocommit mode or if a BEGIN
statement has been seen.
- - Start a statement transaction to allow us to truncate the binary
- log.
+ - Start a statement transaction to allow us to truncate the cache.
- Save the currrent binlog position so that we can roll back the
- statement by truncating the transaction log.
+ statement by truncating the cache.
We only update the saved position if the old one was undefined,
the reason is that there are some cases (e.g., for CREATE-SELECT)
@@ -4107,18 +4291,18 @@ int THD::binlog_setup_trx_data()
void
THD::binlog_start_trans_and_stmt()
{
- binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
+ binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
DBUG_ENTER("binlog_start_trans_and_stmt");
- DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu",
- (long) trx_data,
- (trx_data ? (ulong) trx_data->before_stmt_pos :
+ DBUG_PRINT("enter", ("cache_mngr: %p cache_mngr->trx_cache.get_prev_position(): %lu",
+ cache_mngr,
+ (cache_mngr ? (ulong) cache_mngr->trx_cache.get_prev_position() :
(ulong) 0)));
- if (trx_data == NULL ||
- trx_data->before_stmt_pos == MY_OFF_T_UNDEF)
+ if (cache_mngr == NULL ||
+ cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
{
this->binlog_set_stmt_begin();
- if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
+ if (variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
trans_register_ha(this, TRUE, binlog_hton);
trans_register_ha(this, FALSE, binlog_hton);
/*
@@ -4136,27 +4320,35 @@ THD::binlog_start_trans_and_stmt()
}
void THD::binlog_set_stmt_begin() {
- binlog_trx_data *trx_data=
- (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
/*
- The call to binlog_trans_log_savepos() might create the trx_data
+ The call to binlog_trans_log_savepos() might create the cache_mngr
structure, if it didn't exist before, so we save the position
into an auto variable and then write it into the transaction
- data for the binary log (i.e., trx_data).
+ data for the binary log (i.e., cache_mngr).
*/
my_off_t pos= 0;
binlog_trans_log_savepos(this, &pos);
- trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
- trx_data->before_stmt_pos= pos;
+ cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
+ cache_mngr->trx_cache.set_prev_position(pos);
}
-/*
- Write a table map to the binary log.
- */
-
-int THD::binlog_write_table_map(TABLE *table, bool is_trans)
+/**
+ This function writes a table map to the binary log.
+ Note that in order to keep the signature uniform with related methods,
+ we use a redundant parameter to indicate whether a transactional table
+ was changed or not.
+
+ @param table a pointer to the table.
+ @param is_transactional @c true indicates a transactional table,
+ otherwise @c false a non-transactional.
+ @return
+ nonzero if an error pops up when writing the table map event.
+*/
+int THD::binlog_write_table_map(TABLE *table, bool is_transactional)
{
int error;
DBUG_ENTER("THD::binlog_write_table_map");
@@ -4165,19 +4357,21 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
table->s->table_map_id));
/* Pre-conditions */
- DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
+ DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
- Table_map_log_event::flag_set const
- flags= Table_map_log_event::TM_NO_FLAGS;
-
Table_map_log_event
- the_event(this, table, table->s->table_map_id, is_trans, flags);
+ the_event(this, table, table->s->table_map_id, is_transactional);
- if (is_trans && binlog_table_maps == 0)
+ if (binlog_table_maps == 0)
binlog_start_trans_and_stmt();
- if ((error= mysql_bin_log.write(&the_event)))
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
+
+ IO_CACHE *file= cache_mngr->get_binlog_cache_log(is_transactional);
+
+ if ((error= the_event.write(file)))
DBUG_RETURN(error);
binlog_table_maps++;
@@ -4185,144 +4379,163 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans)
DBUG_RETURN(0);
}
+/**
+ This function retrieves a pending row event from a cache which is
+ specified through the parameter @c is_transactional. Respectively, when it
+ is @c true, the pending event is returned from the transactional cache.
+ Otherwise from the non-transactional cache.
+
+ @param is_transactional @c true indicates a transactional cache,
+ otherwise @c false a non-transactional.
+ @return
+ The row event if any.
+*/
Rows_log_event*
-THD::binlog_get_pending_rows_event() const
+THD::binlog_get_pending_rows_event(bool is_transactional) const
{
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
+ Rows_log_event* rows= NULL;
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
+
/*
- This is less than ideal, but here's the story: If there is no
- trx_data, prepare_pending_rows_event() has never been called
- (since the trx_data is set up there). In that case, we just return
- NULL.
+ This is less than ideal, but here's the story: If there is no cache_mngr,
+ prepare_pending_rows_event() has never been called (since the cache_mngr
+ is set up there). In that case, we just return NULL.
*/
- return trx_data ? trx_data->pending() : NULL;
+ if (cache_mngr)
+ {
+ binlog_cache_data *cache_data=
+ cache_mngr->get_binlog_cache_data(is_transactional);
+
+ rows= cache_data->pending();
+ }
+ return (rows);
}
+/**
+ This function stores a pending row event into a cache which is specified
+ through the parameter @c is_transactional. Respectively, when it is @c
+ true, the pending event is stored into the transactional cache. Otherwise
+ into the non-transactional cache.
+
+ @param evt a pointer to the row event.
+ @param is_transactional @c true indicates a transactional cache,
+ otherwise @c false a non-transactional.
+*/
void
-THD::binlog_set_pending_rows_event(Rows_log_event* ev)
+THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional)
{
if (thd_get_ha_data(this, binlog_hton) == NULL)
binlog_setup_trx_data();
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(this, binlog_hton);
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
- DBUG_ASSERT(trx_data);
- trx_data->set_pending(ev);
+ DBUG_ASSERT(cache_mngr);
+
+ binlog_cache_data *cache_data=
+ cache_mngr->get_binlog_cache_data(is_transactional);
+
+ cache_data->set_pending(ev);
}
/**
- Remove the pending rows event, discarding any outstanding rows.
-
- If there is no pending rows event available, this is effectively a
+ This function removes the pending rows event, discarding any outstanding
+ rows. If there is no pending rows event available, this is effectively a
no-op.
- */
+
+ @param thd a pointer to the user thread.
+ @param is_transactional @c true indicates a transactional cache,
+ otherwise @c false a non-transactional.
+*/
int
-MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd)
+MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd, bool is_transactional)
{
DBUG_ENTER("MYSQL_BIN_LOG::remove_pending_rows_event");
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
- DBUG_ASSERT(trx_data);
+ DBUG_ASSERT(cache_mngr);
- if (Rows_log_event* pending= trx_data->pending())
+ binlog_cache_data *cache_data=
+ cache_mngr->get_binlog_cache_data(is_transactional);
+
+ if (Rows_log_event* pending= cache_data->pending())
{
delete pending;
- trx_data->set_pending(NULL);
+ cache_data->set_pending(NULL);
}
DBUG_RETURN(0);
}
/*
- Moves the last bunch of rows from the pending Rows event to the binlog
- (either cached binlog if transaction, or disk binlog). Sets a new pending
- event.
+ Moves the last bunch of rows from the pending Rows event to a cache (either
+ transactional cache if is_transaction is @c true, or the non-transactional
+ cache otherwise. Sets a new pending event.
+
+ @param thd a pointer to the user thread.
+ @param evt a pointer to the row event.
+ @param is_transactional @c true indicates a transactional cache,
+ otherwise @c false a non-transactional.
*/
int
MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
- Rows_log_event* event)
+ Rows_log_event* event,
+ bool is_transactional)
{
DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
DBUG_ASSERT(mysql_bin_log.is_open());
DBUG_PRINT("enter", ("event: 0x%lx", (long) event));
int error= 0;
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+ DBUG_ASSERT(cache_mngr);
- DBUG_ASSERT(trx_data);
+ binlog_cache_data *cache_data=
+ cache_mngr->get_binlog_cache_data(is_transactional);
- DBUG_PRINT("info", ("trx_data->pending(): 0x%lx", (long) trx_data->pending()));
+ DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long) cache_data->pending()));
- if (Rows_log_event* pending= trx_data->pending())
+ if (Rows_log_event* pending= cache_data->pending())
{
- IO_CACHE *file= &log_file;
-
- /*
- Decide if we should write to the log file directly or to the
- transaction log.
- */
- if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log))
- file= &trx_data->trans_log;
-
- /*
- If we are writing to the log file directly, we could avoid
- locking the log. This does not work since we need to step the
- m_table_map_version below, and that change has to be protected
- by the LOCK_log mutex.
- */
- pthread_mutex_lock(&LOCK_log);
+ IO_CACHE *file= &cache_data->cache_log;
/*
- Write pending event to log file or transaction cache
+ Write pending event to the cache.
*/
if (pending->write(file))
{
- pthread_mutex_unlock(&LOCK_log);
set_write_error(thd);
+ if (check_write_error(thd) && cache_data &&
+ thd->transaction.stmt.modified_non_trans_table)
+ cache_data->set_incident();
DBUG_RETURN(1);
}
/*
We step the table map version if we are writing an event
- representing the end of a statement. We do this regardless of
- wheather we write to the transaction cache or to directly to the
- file.
-
- In an ideal world, we could avoid stepping the table map version
- if we were writing to a transaction cache, since we could then
- reuse the table map that was written earlier in the transaction
- cache. This does not work since STMT_END_F implies closing all
- table mappings on the slave side.
+ representing the end of a statement.
+ In an ideal world, we could avoid stepping the table map version,
+ since we could then reuse the table map that was written earlier
+ in the cache. This does not work since STMT_END_F implies closing
+ all table mappings on the slave side.
+
TODO: Find a solution so that table maps does not have to be
written several times within a transaction.
- */
+ */
if (pending->get_flags(Rows_log_event::STMT_END_F))
++m_table_map_version;
delete pending;
-
- if (file == &log_file)
- {
- error= flush_and_sync(0);
- if (!error)
- {
- signal_update();
- rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
- }
- }
-
- pthread_mutex_unlock(&LOCK_log);
}
- thd->binlog_set_pending_rows_event(event);
+ thd->binlog_set_pending_rows_event(event, is_transactional);
DBUG_RETURN(error);
}
@@ -4336,6 +4549,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
THD *thd= event_info->thd;
bool error= 1;
DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)");
+ binlog_cache_data *cache_data= 0;
if (thd->binlog_evt_union.do_union)
{
@@ -4344,27 +4558,22 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
We will log the function call to the binary log on function exit
*/
thd->binlog_evt_union.unioned_events= TRUE;
- thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt;
+ thd->binlog_evt_union.unioned_events_trans |=
+ event_info->use_trans_cache();
DBUG_RETURN(0);
}
/*
- Flush the pending rows event to the transaction cache or to the
- log file. Since this function potentially aquire the LOCK_log
- mutex, we do this before aquiring the LOCK_log mutex in this
- function.
-
We only end the statement if we are in a top-level statement. If
we are inside a stored function, we do not end the statement since
this will close all tables on the slave.
*/
bool const end_stmt=
thd->prelocked_mode && thd->lex->requires_prelocking();
- if (thd->binlog_flush_pending_rows_event(end_stmt))
+ if (thd->binlog_flush_pending_rows_event(end_stmt,
+ event_info->use_trans_cache()))
DBUG_RETURN(error);
- pthread_mutex_lock(&LOCK_log);
-
/*
In most cases this is only called if 'is_open()' is true; in fact this is
mostly called if is_open() *was* true a few instructions before, but it
@@ -4372,7 +4581,6 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
*/
if (likely(is_open()))
{
- IO_CACHE *file= &log_file;
#ifdef HAVE_REPLICATION
/*
In the future we need to add to the following if tests like
@@ -4380,68 +4588,71 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
binlog_[wild_]{do|ignore}_table?" (WL#1049)"
*/
const char *local_db= event_info->get_db();
- if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
- (!binlog_filter->db_ok(local_db)))
- {
- pthread_mutex_unlock(&LOCK_log);
+ if ((thd && !(thd->variables.option_bits & OPTION_BIN_LOG)) ||
+ !binlog_filter->db_ok(local_db))
DBUG_RETURN(0);
- }
#endif /* HAVE_REPLICATION */
- /*
- Should we write to the binlog cache or to the binlog on disk?
- Write to the binlog cache if:
- - it is already not empty (meaning we're in a transaction; note that the
- present event could be about a non-transactional table, but still we need
- to write to the binlog cache in that case to handle updates to mixed
- trans/non-trans table types the best possible in binlogging)
- - or if the event asks for it (cache_stmt == TRUE).
- */
- if (opt_using_transactions && thd)
+ IO_CACHE *file= NULL;
+
+ if (event_info->use_direct_logging())
+ {
+ file= &log_file;
+ mysql_mutex_lock(&LOCK_log);
+ }
+ else
{
if (thd->binlog_setup_trx_data())
goto err;
- binlog_trx_data *const trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
- IO_CACHE *trans_log= &trx_data->trans_log;
- my_off_t trans_log_pos= my_b_tell(trans_log);
- if (event_info->get_cache_stmt() || trans_log_pos != 0 ||
- stmt_has_updated_trans_table(thd))
+ binlog_cache_mngr *const cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+
+ /*
+ If we are about to use write rows, we just need to check the type of
+ the event (either transactional or non-transactional) in order to
+ choose the cache.
+ */
+ if (thd->is_current_stmt_binlog_format_row())
{
- DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
- event_info->get_cache_stmt(),
- (ulong) trans_log_pos));
- thd->binlog_start_trans_and_stmt();
- file= trans_log;
+ file= cache_mngr->get_binlog_cache_log(event_info->use_trans_cache());
+ cache_data= cache_mngr->get_binlog_cache_data(event_info->use_trans_cache());
}
/*
- TODO as Mats suggested, for all the cases above where we write to
- trans_log, it sounds unnecessary to lock LOCK_log. We should rather
- test first if we want to write to trans_log, and if not, lock
- LOCK_log.
+ However, if we are about to write statements we need to consider other
+ things. We use the non-transactional cache when:
+
+ . the transactional cache is empty which means that there were no
+ early statement on behalf of the transaction.
+ . the respective event is tagged as non-transactional.
*/
- }
+ else if (cache_mngr->trx_cache.empty() &&
+ !event_info->use_trans_cache())
+ {
+ file= &cache_mngr->stmt_cache.cache_log;
+ cache_data= &cache_mngr->stmt_cache;
+ }
+ else
+ {
+ file= &cache_mngr->trx_cache.cache_log;
+ cache_data= &cache_mngr->trx_cache;
+ }
+ thd->binlog_start_trans_and_stmt();
+ }
DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
/*
- No check for auto events flag here - this write method should
- never be called if auto-events are enabled
- */
-
- /*
- 1. Write first log events which describe the 'run environment'
- of the SQL command
- */
+ No check for auto events flag here - this write method should
+ never be called if auto-events are enabled.
- /*
- If row-based binlogging, Insert_id, Rand and other kind of "setting
- context" events are not needed.
+ Write first log events which describe the 'run environment'
+ of the SQL command. If row-based binlogging, Insert_id, Rand
+ and other kind of "setting context" events are not needed.
*/
if (thd)
{
- if (!thd->current_stmt_binlog_row_based)
+ if (!thd->is_current_stmt_binlog_format_row())
{
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
{
@@ -4487,39 +4698,48 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
}
/*
- Write the SQL command
- */
-
- if (event_info->write(file) ||
+ Write the event.
+ */
+ if (event_info->write(file) ||
DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0))
goto err;
- if (file == &log_file) // we are writing to the real log (disk)
+ error= 0;
+
+err:
+ if (event_info->use_direct_logging())
{
- bool synced= 0;
- if (flush_and_sync(&synced))
- goto err;
+ if (!error)
+ {
+ bool synced;
+ if ((error= flush_and_sync(&synced)))
+ goto unlock;
- if (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 err;
+ 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;
+ }
+ signal_update();
+ rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
-
- signal_update();
- rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+unlock:
+ mysql_mutex_unlock(&LOCK_log);
}
- error=0;
-err:
if (error)
+ {
set_write_error(thd);
+ if (check_write_error(thd) && cache_data &&
+ thd->transaction.stmt.modified_non_trans_table)
+ cache_data->set_incident();
+ }
}
if (event_info->flags & LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F)
++m_table_map_version;
- pthread_mutex_unlock(&LOCK_log);
DBUG_RETURN(error);
}
@@ -4549,7 +4769,7 @@ bool LOGGER::log_command(THD *thd, enum enum_server_command command)
*/
if (*general_log_handler_list && (what_to_log & (1L << (uint) command)))
{
- if ((thd->options & OPTION_LOG_OFF)
+ if ((thd->variables.option_bits & OPTION_LOG_OFF)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
&& (sctx->master_access & SUPER_ACL)
#endif
@@ -4599,7 +4819,7 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
bool check_purge= false;
#endif
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
if ((flags & RP_FORCE_ROTATE) ||
(my_b_tell(&log_file) >= (my_off_t) max_size))
{
@@ -4609,7 +4829,7 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
#endif
}
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
#ifdef HAVE_REPLICATION
/*
@@ -4628,9 +4848,9 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
uint MYSQL_BIN_LOG::next_file_id()
{
uint res;
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
res = file_id++;
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
return res;
}
@@ -4642,7 +4862,7 @@ uint MYSQL_BIN_LOG::next_file_id()
write_cache()
cache Cache to write to the binary log
lock_log True if the LOCK_log mutex should be aquired, false otherwise
- sync_log True if the log should be flushed and sync:ed
+ sync_log True if the log should be flushed and synced
DESCRIPTION
Write the contents of the cache to the binary log. The cache will
@@ -4814,7 +5034,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
Incident incident= INCIDENT_LOST_EVENTS;
Incident_log_event ev(thd, incident, write_error_msg);
if (lock)
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
error= ev.write(&log_file);
if (lock)
{
@@ -4823,7 +5043,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
signal_update();
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
}
DBUG_RETURN(error);
}
@@ -4856,10 +5076,7 @@ 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 *)");
- pthread_mutex_lock(&LOCK_log);
-
- /* NULL would represent nothing to replicate after ROLLBACK */
- DBUG_ASSERT(commit_event != NULL);
+ mysql_mutex_lock(&LOCK_log);
DBUG_ASSERT(is_open());
if (likely(is_open())) // Should always be true
@@ -4875,19 +5092,9 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
transaction is either a BEGIN..COMMIT block or a single
statement in autocommit mode.
*/
- Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, TRUE, 0);
-
- /*
- Now this Query_log_event has artificial log_pos 0. It must be
- adjusted to reflect the real position in the log. Not doing it
- would confuse the slave: it would prevent this one from
- knowing where he is in the master's binlog, which would result
- in wrong positions being shown to the user, MASTER_POS_WAIT
- undue waiting etc.
- */
+ Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, TRUE, 0);
if (qinfo.write(&log_file))
goto err;
-
DBUG_EXECUTE_IF("crash_before_writing_xid",
{
if ((write_error= write_cache(cache, false, true)))
@@ -4938,14 +5145,14 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
*/
if (commit_event && commit_event->get_type_code() == XID_EVENT)
{
- pthread_mutex_lock(&LOCK_prep_xids);
+ mysql_mutex_lock(&LOCK_prep_xids);
prepared_xids++;
- pthread_mutex_unlock(&LOCK_prep_xids);
+ mysql_mutex_unlock(&LOCK_prep_xids);
}
else
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(0);
@@ -4955,7 +5162,7 @@ err:
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_RETURN(1);
}
@@ -4977,10 +5184,10 @@ void MYSQL_BIN_LOG::wait_for_update_relay_log(THD* thd)
DBUG_ENTER("wait_for_update_relay_log");
old_msg= thd->enter_cond(&update_cond, &LOCK_log,
- "Slave has read all relay log; "
+ "Slave has read all relay log; "
"waiting for the slave I/O "
"thread to update it" );
- pthread_cond_wait(&update_cond, &LOCK_log);
+ mysql_cond_wait(&update_cond, &LOCK_log);
thd->exit_cond(old_msg);
DBUG_VOID_RETURN;
}
@@ -5011,10 +5218,10 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd,
"Master has sent all binlog to slave; "
"waiting for binlog to be updated");
if (!timeout)
- pthread_cond_wait(&update_cond, &LOCK_log);
+ mysql_cond_wait(&update_cond, &LOCK_log);
else
- ret= pthread_cond_timedwait(&update_cond, &LOCK_log,
- const_cast<struct timespec *>(timeout));
+ ret= mysql_cond_timedwait(&update_cond, &LOCK_log,
+ const_cast<struct timespec *>(timeout));
DBUG_RETURN(ret);
}
@@ -5054,16 +5261,16 @@ void MYSQL_BIN_LOG::close(uint exiting)
if (log_file.type == WRITE_CACHE && log_type == LOG_BIN)
{
my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET;
- my_off_t org_position= my_tell(log_file.file, MYF(0));
+ my_off_t org_position= mysql_file_tell(log_file.file, MYF(0));
uchar flags= 0; // clearing LOG_EVENT_BINLOG_IN_USE_F
- my_pwrite(log_file.file, &flags, 1, offset, MYF(0));
+ mysql_file_pwrite(log_file.file, &flags, 1, offset, MYF(0));
/*
Restore position so that anything we have in the IO_cache is written
to the correct position.
- We need the seek here, as my_pwrite() is not guaranteed to keep the
+ We need the seek here, as mysql_file_pwrite() is not guaranteed to keep the
original position on system that doesn't support pwrite().
*/
- my_seek(log_file.file, org_position, MY_SEEK_SET, MYF(0));
+ mysql_file_seek(log_file.file, org_position, MY_SEEK_SET, MYF(0));
}
/* this will cleanup IO_CACHE, sync and close the file */
@@ -5078,7 +5285,7 @@ void MYSQL_BIN_LOG::close(uint exiting)
if ((exiting & LOG_CLOSE_INDEX) && my_b_inited(&index_file))
{
end_io_cache(&index_file);
- if (my_close(index_file.file, MYF(0)) < 0 && ! write_error)
+ if (mysql_file_close(index_file.file, MYF(0)) < 0 && ! write_error)
{
write_error= 1;
sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno);
@@ -5100,10 +5307,10 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg)
it's like if the SET command was never run.
*/
DBUG_ENTER("MYSQL_BIN_LOG::set_max_size");
- pthread_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_log);
if (is_open())
max_size= max_size_arg;
- pthread_mutex_unlock(&LOCK_log);
+ mysql_mutex_unlock(&LOCK_log);
DBUG_VOID_RETURN;
}
@@ -5175,7 +5382,7 @@ bool flush_error_log()
char err_renamed[FN_REFLEN], *end;
end= strmake(err_renamed,log_error_file,FN_REFLEN-5);
strmov(end, "-old");
- pthread_mutex_lock(&LOCK_error_log);
+ mysql_mutex_lock(&LOCK_error_log);
#ifdef __WIN__
char err_temp[FN_REFLEN+5];
/*
@@ -5183,7 +5390,7 @@ bool flush_error_log()
the current error file.
*/
strxmov(err_temp, err_renamed,"-tmp",NullS);
- (void) my_delete(err_temp, MYF(0));
+ my_delete(err_temp, MYF(0));
if (freopen(err_temp,"a+",stdout))
{
int fd;
@@ -5192,27 +5399,27 @@ bool flush_error_log()
freopen(err_temp,"a+",stderr);
setbuf(stderr, NULL);
- (void) my_delete(err_renamed, MYF(0));
- my_rename(log_error_file,err_renamed,MYF(0));
+ 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);
setbuf(stderr, NULL);
}
- if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
+ if ((fd= my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
{
- while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
+ while ((bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) &&
bytes != MY_FILE_ERROR)
my_fwrite(stderr, buf, bytes, MYF(0));
- my_close(fd, MYF(0));
+ mysql_file_close(fd, MYF(0));
}
- (void) my_delete(err_temp, MYF(0));
+ my_delete(err_temp, MYF(0));
}
else
result= 1;
#else
- my_rename(log_error_file,err_renamed,MYF(0));
+ my_rename(log_error_file, err_renamed, MYF(0));
if (freopen(log_error_file,"a+",stdout))
{
FILE *reopen;
@@ -5222,7 +5429,7 @@ bool flush_error_log()
else
result= 1;
#endif
- pthread_mutex_unlock(&LOCK_error_log);
+ mysql_mutex_unlock(&LOCK_error_log);
}
return result;
}
@@ -5231,7 +5438,7 @@ void MYSQL_BIN_LOG::signal_update()
{
DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
signal_cnt++;
- pthread_cond_broadcast(&update_cond);
+ mysql_cond_broadcast(&update_cond);
DBUG_VOID_RETURN;
}
@@ -5297,7 +5504,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
DBUG_ENTER("print_buffer_to_file");
DBUG_PRINT("enter",("buffer: %s", buffer));
- pthread_mutex_lock(&LOCK_error_log);
+ mysql_mutex_lock(&LOCK_error_log);
skr= my_time(0);
localtime_r(&skr, &tm_tmp);
@@ -5316,7 +5523,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer)
fflush(stderr);
- pthread_mutex_unlock(&LOCK_error_log);
+ mysql_mutex_unlock(&LOCK_error_log);
DBUG_VOID_RETURN;
}
@@ -5440,17 +5647,18 @@ int TC_LOG_MMAP::open(const char *opt_name)
DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
- if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0)
+ if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0)
{
if (my_errno != ENOENT)
goto err;
if (using_heuristic_recover())
return 1;
- if ((fd= my_create(logname, CREATE_MODE, O_RDWR, MYF(MY_WME))) < 0)
+ if ((fd= mysql_file_create(key_file_tclog, logname, CREATE_MODE,
+ O_RDWR, MYF(MY_WME))) < 0)
goto err;
inited=1;
file_length= opt_tc_log_size;
- if (my_chsize(fd, file_length, 0, MYF(MY_WME)))
+ if (mysql_file_chsize(fd, file_length, 0, MYF(MY_WME)))
goto err;
}
else
@@ -5464,7 +5672,7 @@ int TC_LOG_MMAP::open(const char *opt_name)
"--tc-heuristic-recover is used");
goto err;
}
- file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
+ file_length= mysql_file_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
goto err;
}
@@ -5488,8 +5696,8 @@ int TC_LOG_MMAP::open(const char *opt_name)
pg->next=pg+1;
pg->waiters=0;
pg->state=POOL;
- pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST);
- pthread_cond_init (&pg->cond, 0);
+ mysql_mutex_init(key_PAGE_lock, &pg->lock, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_PAGE_cond, &pg->cond, 0);
pg->start=(my_xid *)(data + i*tc_log_page_size);
pg->end=(my_xid *)(pg->start + tc_log_page_size);
pg->size=pg->free=tc_log_page_size/sizeof(my_xid);
@@ -5508,11 +5716,11 @@ int TC_LOG_MMAP::open(const char *opt_name)
my_msync(fd, data, tc_log_page_size, MS_SYNC);
inited=5;
- pthread_mutex_init(&LOCK_sync, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_active, MY_MUTEX_INIT_FAST);
- pthread_mutex_init(&LOCK_pool, MY_MUTEX_INIT_FAST);
- pthread_cond_init(&COND_active, 0);
- pthread_cond_init(&COND_pool, 0);
+ mysql_mutex_init(key_LOCK_sync, &LOCK_sync, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_active, &LOCK_active, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_pool, &LOCK_pool, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_active, &COND_active, 0);
+ mysql_cond_init(key_COND_pool, &COND_pool, 0);
inited=6;
@@ -5546,7 +5754,7 @@ void TC_LOG_MMAP::get_active_from_pool()
int best_free;
if (syncing)
- pthread_mutex_lock(&LOCK_pool);
+ mysql_mutex_lock(&LOCK_pool);
do
{
@@ -5579,7 +5787,7 @@ void TC_LOG_MMAP::get_active_from_pool()
pool_last=*best_p;
if (syncing)
- pthread_mutex_unlock(&LOCK_pool);
+ mysql_mutex_unlock(&LOCK_pool);
}
/**
@@ -5594,7 +5802,7 @@ int TC_LOG_MMAP::overflow()
let's check the behaviour of tc_log_page_waits first
*/
tc_log_page_waits++;
- pthread_cond_wait(&COND_pool, &LOCK_pool);
+ mysql_cond_wait(&COND_pool, &LOCK_pool);
return 1; // always return 1
}
@@ -5631,7 +5839,7 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
PAGE *p;
ulong cookie;
- pthread_mutex_lock(&LOCK_active);
+ mysql_mutex_lock(&LOCK_active);
/*
if active page is full - just wait...
@@ -5641,14 +5849,14 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
unlog() does not signal COND_active.
*/
while (unlikely(active && active->free == 0))
- pthread_cond_wait(&COND_active, &LOCK_active);
+ mysql_cond_wait(&COND_active, &LOCK_active);
/* no active page ? take one from the pool */
if (active == 0)
get_active_from_pool();
p=active;
- pthread_mutex_lock(&p->lock);
+ mysql_mutex_lock(&p->lock);
/* searching for an empty slot */
while (*p->ptr)
@@ -5664,9 +5872,9 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
p->state= DIRTY;
/* to sync or not to sync - this is the question */
- pthread_mutex_unlock(&LOCK_active);
- pthread_mutex_lock(&LOCK_sync);
- pthread_mutex_unlock(&p->lock);
+ mysql_mutex_unlock(&LOCK_active);
+ mysql_mutex_lock(&LOCK_sync);
+ mysql_mutex_unlock(&p->lock);
if (syncing)
{ // somebody's syncing. let's wait
@@ -5676,24 +5884,24 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
as p->state may be not DIRTY when we come here
*/
while (p->state == DIRTY && syncing)
- pthread_cond_wait(&p->cond, &LOCK_sync);
+ mysql_cond_wait(&p->cond, &LOCK_sync);
p->waiters--;
err= p->state == ERROR;
if (p->state != DIRTY) // page was synced
{
if (p->waiters == 0)
- pthread_cond_signal(&COND_pool); // in case somebody's waiting
- pthread_mutex_unlock(&LOCK_sync);
+ mysql_cond_signal(&COND_pool); // in case somebody's waiting
+ mysql_mutex_unlock(&LOCK_sync);
goto done; // we're done
}
} // page was not synced! do it now
DBUG_ASSERT(active == p && syncing == 0);
- pthread_mutex_lock(&LOCK_active);
+ mysql_mutex_lock(&LOCK_active);
syncing=p; // place is vacant - take it
active=0; // page is not active anymore
- pthread_cond_broadcast(&COND_active); // in case somebody's waiting
- pthread_mutex_unlock(&LOCK_active);
- pthread_mutex_unlock(&LOCK_sync);
+ mysql_cond_broadcast(&COND_active); // in case somebody's waiting
+ mysql_mutex_unlock(&LOCK_active);
+ mysql_mutex_unlock(&LOCK_sync);
err= sync();
done:
@@ -5713,20 +5921,20 @@ int TC_LOG_MMAP::sync()
err= my_msync(fd, syncing->start, 1, MS_SYNC);
/* page is synced. let's move it to the pool */
- pthread_mutex_lock(&LOCK_pool);
+ mysql_mutex_lock(&LOCK_pool);
pool_last->next=syncing;
pool_last=syncing;
syncing->next=0;
syncing->state= err ? ERROR : POOL;
- pthread_cond_broadcast(&syncing->cond); // signal "sync done"
- pthread_cond_signal(&COND_pool); // in case somebody's waiting
- pthread_mutex_unlock(&LOCK_pool);
+ mysql_cond_broadcast(&syncing->cond); // signal "sync done"
+ mysql_cond_signal(&COND_pool); // in case somebody's waiting
+ mysql_mutex_unlock(&LOCK_pool);
/* marking 'syncing' slot free */
- pthread_mutex_lock(&LOCK_sync);
+ mysql_mutex_lock(&LOCK_sync);
syncing=0;
- pthread_cond_signal(&active->cond); // wake up a new syncer
- pthread_mutex_unlock(&LOCK_sync);
+ mysql_cond_signal(&active->cond); // wake up a new syncer
+ mysql_mutex_unlock(&LOCK_sync);
return err;
}
@@ -5744,15 +5952,15 @@ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
DBUG_ASSERT(x >= p->start && x < p->end);
*x=0;
- pthread_mutex_lock(&p->lock);
+ mysql_mutex_lock(&p->lock);
p->free++;
DBUG_ASSERT(p->free <= p->size);
set_if_smaller(p->ptr, x);
if (p->free == p->size) // the page is completely empty
statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
if (p->waiters == 0) // the page is in pool and ready to rock
- pthread_cond_signal(&COND_pool); // ping ... for overflow()
- pthread_mutex_unlock(&p->lock);
+ mysql_cond_signal(&COND_pool); // ping ... for overflow()
+ mysql_mutex_unlock(&p->lock);
}
void TC_LOG_MMAP::close()
@@ -5760,29 +5968,29 @@ void TC_LOG_MMAP::close()
uint i;
switch (inited) {
case 6:
- pthread_mutex_destroy(&LOCK_sync);
- pthread_mutex_destroy(&LOCK_active);
- pthread_mutex_destroy(&LOCK_pool);
- pthread_cond_destroy(&COND_pool);
+ mysql_mutex_destroy(&LOCK_sync);
+ mysql_mutex_destroy(&LOCK_active);
+ mysql_mutex_destroy(&LOCK_pool);
+ mysql_cond_destroy(&COND_pool);
case 5:
- data[0]='A'; // garble the first (signature) byte, in case my_delete fails
+ data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails
case 4:
for (i=0; i < npages; i++)
{
if (pages[i].ptr == 0)
break;
- pthread_mutex_destroy(&pages[i].lock);
- pthread_cond_destroy(&pages[i].cond);
+ mysql_mutex_destroy(&pages[i].lock);
+ mysql_cond_destroy(&pages[i].cond);
}
case 3:
my_free((uchar*)pages, MYF(0));
case 2:
my_munmap((char*)data, (size_t)file_length);
case 1:
- my_close(fd, MYF(0));
+ mysql_file_close(fd, MYF(0));
}
if (inited>=5) // cannot do in the switch because of Windows
- my_delete(logname, MYF(MY_WME));
+ mysql_file_delete(key_file_tclog, logname, MYF(MY_WME));
inited=0;
}
@@ -5887,8 +6095,9 @@ int TC_LOG_BINLOG::open(const char *opt_name)
DBUG_ASSERT(total_ha_2pc > 1);
DBUG_ASSERT(opt_name && opt_name[0]);
- pthread_mutex_init(&LOCK_prep_xids, MY_MUTEX_INIT_FAST);
- pthread_cond_init (&COND_prep_xids, 0);
+ mysql_mutex_init(key_BINLOG_LOCK_prep_xids,
+ &LOCK_prep_xids, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_BINLOG_COND_prep_xids, &COND_prep_xids, 0);
if (!my_b_inited(&index_file))
{
@@ -5954,7 +6163,7 @@ int TC_LOG_BINLOG::open(const char *opt_name)
delete ev;
end_io_cache(&log);
- my_close(file, MYF(MY_WME));
+ mysql_file_close(file, MYF(MY_WME));
if (error)
goto err;
@@ -5968,8 +6177,8 @@ err:
void TC_LOG_BINLOG::close()
{
DBUG_ASSERT(prepared_xids==0);
- pthread_mutex_destroy(&LOCK_prep_xids);
- pthread_cond_destroy (&COND_prep_xids);
+ mysql_mutex_destroy(&LOCK_prep_xids);
+ mysql_cond_destroy(&COND_prep_xids);
}
/**
@@ -5985,24 +6194,25 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
{
DBUG_ENTER("TC_LOG_BINLOG::log");
Xid_log_event xle(thd, xid);
- binlog_trx_data *trx_data=
- (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
/*
We always commit the entire transaction when writing an XID. Also
note that the return value is inverted.
*/
- DBUG_RETURN(!binlog_end_trans(thd, trx_data, &xle, TRUE));
+ DBUG_RETURN(!binlog_flush_stmt_cache(thd, cache_mngr) &&
+ !binlog_flush_trx_cache(thd, cache_mngr, &xle));
}
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
{
- pthread_mutex_lock(&LOCK_prep_xids);
+ mysql_mutex_lock(&LOCK_prep_xids);
DBUG_ASSERT(prepared_xids > 0);
if (--prepared_xids == 0) {
DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
- pthread_cond_signal(&COND_prep_xids);
+ mysql_cond_signal(&COND_prep_xids);
}
- pthread_mutex_unlock(&LOCK_prep_xids);
+ mysql_mutex_unlock(&LOCK_prep_xids);
rotate_and_purge(0); // as ::write() did not rotate
}