Commit fec70c97 authored by petr@mysql.com's avatar petr@mysql.com

WL#3153 "Split logs". Recommit with post-review fixes

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