1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge with 5.2

This commit is contained in:
Michael Widenius
2011-03-09 15:47:59 +02:00
1617 changed files with 25609 additions and 41019 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
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
@ -1908,10 +1908,11 @@ static int find_uniq_filename(char *name)
*end='.';
length= (size_t) (end-start+1);
if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
if ((DBUG_EVALUATE_IF("error_unique_log_filename", 1,
!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))))
{ // This shouldn't happen
strmov(end,".1"); // use name+1
DBUG_RETURN(0);
DBUG_RETURN(1);
}
file_info= dir_info->dir_entry;
for (i=dir_info->number_off_files ; i-- ; file_info++)
@ -1925,8 +1926,7 @@ static int find_uniq_filename(char *name)
my_dirend(dir_info);
*end++='.';
sprintf(end,"%06ld",max_found+1);
DBUG_RETURN(0);
DBUG_RETURN((sprintf(end,"%06ld",max_found+1) < 0));
}
@ -2138,6 +2138,8 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
{
if (find_uniq_filename(new_name))
{
my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE),
MYF(ME_FATALERROR), log_name);
sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
return 1;
}
@ -2659,6 +2661,23 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
sync_purge_index_file() ||
DBUG_EVALUATE_IF("fault_injection_registering_index", 1, 0))
{
/**
TODO: although this was introduced to appease valgrind
when injecting emulated faults using fault_injection_registering_index
it may be good to consider what actually happens when
open_purge_index_file succeeds but register or sync fails.
Perhaps we might need the code below in MYSQL_LOG_BIN::cleanup
for "real life" purposes as well?
*/
DBUG_EXECUTE_IF("fault_injection_registering_index", {
if (my_b_inited(&purge_index_file))
{
end_io_cache(&purge_index_file);
my_close(purge_index_file.file, MYF(0));
}
});
sql_print_error("MSYQL_BIN_LOG::open failed to sync the index file.");
DBUG_RETURN(1);
}
@ -3099,7 +3118,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
}
/* Start logging with a new file */
close(LOG_CLOSE_INDEX);
close(LOG_CLOSE_INDEX | LOG_CLOSE_TO_BE_OPENED);
if ((error= my_delete_allow_opened(index_file_name, MYF(0)))) // Reset (open will update)
{
if (my_errno == ENOENT)
@ -3128,7 +3147,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
if (!thd->slave_thread)
need_start_event=1;
if (!open_index_file(index_file_name, 0, FALSE))
open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE);
if ((error= open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE)))
goto err;
my_free((uchar*) save_name, MYF(0));
err:
@ -3790,17 +3810,23 @@ bool MYSQL_BIN_LOG::is_active(const char *log_file_name_arg)
incapsulation 3) allows external access to the class without
a lock (which is not possible with private new_file_without_locking
method).
@retval
nonzero - error
*/
void MYSQL_BIN_LOG::new_file()
int MYSQL_BIN_LOG::new_file()
{
new_file_impl(1);
return new_file_impl(1);
}
void MYSQL_BIN_LOG::new_file_without_locking()
/*
@retval
nonzero - error
*/
int MYSQL_BIN_LOG::new_file_without_locking()
{
new_file_impl(0);
return new_file_impl(0);
}
@ -3809,19 +3835,23 @@ void MYSQL_BIN_LOG::new_file_without_locking()
@param need_lock Set to 1 if caller has not locked LOCK_log
@retval
nonzero - error
@note
The new file name is stored last in the index file
*/
void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
{
char new_name[FN_REFLEN], *new_name_ptr, *old_name;
int error= 0, close_on_error= FALSE;
char new_name[FN_REFLEN], *new_name_ptr, *old_name, *file_to_open;
DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
if (!is_open())
{
DBUG_PRINT("info",("log is closed"));
DBUG_VOID_RETURN;
DBUG_RETURN(error);
}
if (need_lock)
@ -3859,7 +3889,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
We have to do this here and not in open as we want to store the
new file name in the current binary log file.
*/
if (generate_new_name(new_name, name))
if ((error= generate_new_name(new_name, name)))
goto end;
new_name_ptr=new_name;
@ -3873,7 +3903,14 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
*/
Rotate_log_event r(new_name+dirname_length(new_name),
0, LOG_EVENT_OFFSET, is_relay_log ? Rotate_log_event::RELAY_LOG : 0);
r.write(&log_file);
if(DBUG_EVALUATE_IF("fault_injection_new_file_rotate_event", (error=close_on_error=TRUE), FALSE) ||
(error= r.write(&log_file)))
{
DBUG_EXECUTE_IF("fault_injection_new_file_rotate_event", errno=2;);
close_on_error= TRUE;
my_printf_error(ER_ERROR_ON_WRITE, ER(ER_CANT_OPEN_FILE), MYF(ME_FATALERROR), name, errno);
goto end;
}
bytes_written += r.data_written;
}
/*
@ -3901,17 +3938,56 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
*/
/* reopen index binlog file, BUG#34582 */
if (!open_index_file(index_file_name, 0, FALSE))
open(old_name, log_type, new_name_ptr,
io_cache_type, no_auto_events, max_size, 1, FALSE);
file_to_open= index_file_name;
error= open_index_file(index_file_name, 0, FALSE);
if (!error)
{
/* reopen the binary log file. */
file_to_open= new_name_ptr;
error= open(old_name, log_type, new_name_ptr, io_cache_type,
no_auto_events, max_size, 1, FALSE);
}
/* handle reopening errors */
if (error)
{
my_printf_error(ER_CANT_OPEN_FILE, ER(ER_CANT_OPEN_FILE),
MYF(ME_FATALERROR), file_to_open, error);
close_on_error= TRUE;
}
my_free(old_name,MYF(0));
end:
if (error && close_on_error /* rotate or reopen failed */)
{
/*
Close whatever was left opened.
We are keeping the behavior as it exists today, ie,
we disable logging and move on (see: BUG#51014).
TODO: as part of WL#1790 consider other approaches:
- kill mysql (safety);
- try multiple locations for opening a log file;
- switch server to protected/readonly mode
- ...
*/
close(LOG_CLOSE_INDEX);
sql_print_error("Could not open %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.",
new_name_ptr, errno);
}
if (need_lock)
pthread_mutex_unlock(&LOCK_log);
pthread_mutex_unlock(&LOCK_index);
DBUG_VOID_RETURN;
DBUG_RETURN(error);
}
@ -3934,8 +4010,7 @@ bool MYSQL_BIN_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_without_locking();
error= new_file_without_locking();
err:
pthread_mutex_unlock(&LOCK_log);
signal_update(); // Safe as we don't call close
@ -3964,8 +4039,7 @@ bool MYSQL_BIN_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_without_locking();
error= new_file_without_locking();
err:
if (!error)
signal_update();
@ -4314,7 +4388,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
if (!error)
{
signal_update();
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
}
@ -4512,7 +4586,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
if (flush_and_sync())
goto err;
signal_update();
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
if ((error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED)))
goto err;
}
error=0;
@ -4595,8 +4671,19 @@ bool general_log_write(THD *thd, enum enum_server_command command,
return FALSE;
}
void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
/**
@note
If rotation fails, for instance the server was unable
to create a new log file, we still try to write an
incident event to the current log.
@retval
nonzero - error
*/
int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
{
int error= 0;
DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
#ifdef HAVE_REPLICATION
bool check_purge= false;
#endif
@ -4605,26 +4692,38 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
if ((flags & RP_FORCE_ROTATE) ||
(my_b_tell(&log_file) >= (my_off_t) max_size))
{
new_file_without_locking();
if ((error= new_file_without_locking()))
/**
Be conservative... There are possible lost events (eg,
failing to log the Execute_load_query_log_event
on a LOAD DATA while using a non-transactional
table)!
We give it a shot and try to write an incident event anyway
to the current log.
*/
if (!write_incident(current_thd, FALSE))
flush_and_sync();
#ifdef HAVE_REPLICATION
check_purge= true;
#endif
}
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
pthread_mutex_unlock(&LOCK_log);
#ifdef HAVE_REPLICATION
/*
NOTE: Run purge_logs wo/ holding LOCK_log
as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
*/
if (check_purge && expire_logs_days)
if (!error && check_purge && expire_logs_days)
{
time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
if (purge_time >= 0)
purge_logs_before_date(purge_time);
}
#endif
DBUG_RETURN(error);
}
uint MYSQL_BIN_LOG::next_file_id()
@ -4816,6 +4915,10 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
{
uint error= 0;
DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
if (!is_open())
DBUG_RETURN(error);
LEX_STRING const write_error_msg=
{ C_STRING_WITH_LEN("error writing to the binary log") };
Incident incident= INCIDENT_LOST_EVENTS;
@ -4829,7 +4932,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
if (!error && !(error= flush_and_sync()))
{
signal_update();
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
}
pthread_mutex_unlock(&LOCK_log);
}
@ -4948,7 +5051,8 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
pthread_mutex_unlock(&LOCK_prep_xids);
}
else
rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
if (rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED))
goto err;
}
VOID(pthread_mutex_unlock(&LOCK_log));
@ -5144,80 +5248,26 @@ void sql_perror(const char *message)
}
#ifdef __WIN__
/*
Change the file associated with two output streams. Used to
redirect stdout and stderr to a file. The streams are reopened
only for appending (writing at end of file).
*/
extern "C" my_bool reopen_fstreams(const char *filename,
FILE *outstream, FILE *errstream)
{
int handle_fd;
int err_fd, out_fd;
HANDLE osfh;
if (outstream && !my_freopen(filename, "a", outstream))
return TRUE;
DBUG_ASSERT(filename && errstream);
// Services don't have stdout/stderr on Windows, so _fileno returns -1.
err_fd= _fileno(errstream);
if (err_fd < 0)
{
if (!freopen(filename, "a+", errstream))
return TRUE;
if (errstream && !my_freopen(filename, "a", errstream))
return TRUE;
/* The error stream must be unbuffered. */
if (errstream)
setbuf(errstream, NULL);
err_fd= _fileno(errstream);
}
if (outstream)
{
out_fd= _fileno(outstream);
if (out_fd < 0)
{
if (!freopen(filename, "a+", outstream))
return TRUE;
out_fd= _fileno(outstream);
}
}
if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
return TRUE;
if ((handle_fd= _open_osfhandle((intptr_t)osfh,
_O_APPEND | _O_TEXT)) == -1)
{
CloseHandle(osfh);
return TRUE;
}
if (_dup2(handle_fd, err_fd) < 0)
{
CloseHandle(osfh);
return TRUE;
}
if (outstream && _dup2(handle_fd, out_fd) < 0)
{
CloseHandle(osfh);
return TRUE;
}
_close(handle_fd);
return FALSE;
}
#else
extern "C" my_bool reopen_fstreams(const char *filename,
FILE *outstream, FILE *errstream)
{
if (outstream && !freopen(filename, "a+", outstream))
return TRUE;
if (errstream && !freopen(filename, "a+", errstream))
return TRUE;
return FALSE;
}
#endif
/*
@ -5784,7 +5834,7 @@ int TC_LOG_MMAP::sync()
cookie points directly to the memory where xid was logged.
*/
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
{
PAGE *p=pages+(cookie/tc_log_page_size);
my_xid *x=(my_xid *)(data+cookie);
@ -5802,6 +5852,7 @@ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
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);
return 0;
}
void TC_LOG_MMAP::close()
@ -6043,8 +6094,9 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid)
DBUG_RETURN(!binlog_end_trans(thd, trx_data, &xle, TRUE));
}
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
{
DBUG_ENTER("TC_LOG_BINLOG::unlog");
pthread_mutex_lock(&LOCK_prep_xids);
DBUG_ASSERT(prepared_xids > 0);
if (--prepared_xids == 0) {
@ -6052,7 +6104,7 @@ void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
pthread_cond_signal(&COND_prep_xids);
}
pthread_mutex_unlock(&LOCK_prep_xids);
rotate_and_purge(0); // as ::write() did not rotate
DBUG_RETURN(rotate_and_purge(0)); // as ::write() did not rotate
}
int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)