mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
7a7c338a0b
1. Binlog commit by rotate (MDEV-32014) should not be used with Galera, yet while WSREP binlog emulation is active, the code path could lead into binlog_cache_data::write_prepare() in an invalid state, leading to errors in MTR. To fix, an extra check is added to ensure the binlog is actually active before calling write_prepare(). 2. If the #binlog_cache_files directory exists on a mariadbd run without opt_log_bin, the directory was treated as a table/database, leading to errors. To fix, on startup, if opt_log_bin is disabled and #binlog_cache_files exists (in the default log directory), the directory is deleted (and an informational message is provided in the error log) Reviewed By: ============ Andrei Elkin <andrei.elkin@mariadb.com>
141 lines
3.9 KiB
C++
141 lines
3.9 KiB
C++
#include "my_global.h"
|
|
#include "log_cache.h"
|
|
#include "handler.h"
|
|
#include "my_sys.h"
|
|
#include "mysql/psi/mysql_file.h"
|
|
#include "mysql/service_wsrep.h"
|
|
|
|
const char *BINLOG_CACHE_DIR= "#binlog_cache_files";
|
|
char binlog_cache_dir[FN_REFLEN];
|
|
extern uint32 binlog_cache_reserved_size();
|
|
|
|
bool binlog_cache_data::init_file_reserved_bytes()
|
|
{
|
|
// Session's cache file is not created, so created here.
|
|
if (cache_log.file == -1)
|
|
{
|
|
char name[FN_REFLEN];
|
|
|
|
/* Cache file is named with PREFIX + binlog_cache_data object's address */
|
|
snprintf(name, FN_REFLEN, "%s/%s_%llu", cache_log.dir, cache_log.prefix,
|
|
(ulonglong) this);
|
|
|
|
if ((cache_log.file=
|
|
mysql_file_open(0, name, O_CREAT | O_RDWR, MYF(MY_WME))) < 0)
|
|
{
|
|
sql_print_error("Failed to open binlog cache temporary file %s", name);
|
|
cache_log.error= -1;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_WSREP
|
|
/*
|
|
WSREP code accesses cache_log directly, so don't reserve space if WSREP is
|
|
on.
|
|
*/
|
|
if (unlikely(wsrep_on(current_thd)))
|
|
return false;
|
|
#endif
|
|
|
|
m_file_reserved_bytes= binlog_cache_reserved_size();
|
|
cache_log.pos_in_file= m_file_reserved_bytes;
|
|
cache_log.seek_not_done= 1;
|
|
return false;
|
|
}
|
|
|
|
void binlog_cache_data::detach_temp_file()
|
|
{
|
|
mysql_file_close(cache_log.file, MYF(0));
|
|
cache_log.file= -1;
|
|
reset();
|
|
}
|
|
|
|
extern void ignore_db_dirs_append(const char *dirname_arg);
|
|
|
|
bool init_binlog_cache_dir()
|
|
{
|
|
size_t length;
|
|
uint max_tmp_file_name_len=
|
|
2 /* prefix */ + 10 /* max len of thread_id */ + 1 /* underline */;
|
|
|
|
/*
|
|
Even if the binary log is disabled (and thereby we wouldn't use the binlog
|
|
cache), we need to try to build the directory name, so if it exists while
|
|
the binlog is off (e.g. due to a previous run of mariadbd, or an SST), we
|
|
can delete it.
|
|
*/
|
|
dirname_part(binlog_cache_dir,
|
|
opt_bin_log ? log_bin_basename : opt_log_basename, &length);
|
|
/*
|
|
Must ensure the full name of the tmp file is shorter than FN_REFLEN, to
|
|
avoid overflowing the name buffer in write and commit.
|
|
*/
|
|
if (length + strlen(BINLOG_CACHE_DIR) + max_tmp_file_name_len >= FN_REFLEN)
|
|
{
|
|
sql_print_error("Could not create binlog cache dir %s%s. It is too long.",
|
|
binlog_cache_dir, BINLOG_CACHE_DIR);
|
|
return true;
|
|
}
|
|
|
|
memcpy(binlog_cache_dir + length, BINLOG_CACHE_DIR,
|
|
strlen(BINLOG_CACHE_DIR));
|
|
binlog_cache_dir[length + strlen(BINLOG_CACHE_DIR)]= 0;
|
|
|
|
MY_DIR *dir_info= my_dir(binlog_cache_dir, MYF(0));
|
|
|
|
/*
|
|
If the binlog cache dir exists, yet binlogging is disabled, delete the
|
|
directory and skip the initialization logic.
|
|
*/
|
|
if (!opt_bin_log)
|
|
{
|
|
if (dir_info)
|
|
{
|
|
sql_print_information(
|
|
"Found binlog cache dir '%s', yet binary logging is "
|
|
"disabled. Deleting directory.",
|
|
binlog_cache_dir);
|
|
my_dirend(dir_info);
|
|
my_rmtree(binlog_cache_dir, MYF(0));
|
|
}
|
|
memset(binlog_cache_dir, 0, sizeof(binlog_cache_dir));
|
|
return false;
|
|
}
|
|
|
|
ignore_db_dirs_append(BINLOG_CACHE_DIR);
|
|
|
|
if (!dir_info)
|
|
{
|
|
/* Make a dir for binlog cache temp files if not exist. */
|
|
if (my_mkdir(binlog_cache_dir, 0777, MYF(0)) < 0)
|
|
{
|
|
sql_print_error("Could not create binlog cache dir %s.",
|
|
binlog_cache_dir);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* Try to delete all cache files in the directory. */
|
|
for (uint i= 0; i < dir_info->number_of_files; i++)
|
|
{
|
|
FILEINFO *file= dir_info->dir_entry + i;
|
|
|
|
if (strncmp(file->name, LOG_PREFIX, strlen(LOG_PREFIX)))
|
|
{
|
|
sql_print_warning("%s is in %s/, but it is not a binlog cache file",
|
|
file->name, BINLOG_CACHE_DIR);
|
|
continue;
|
|
}
|
|
|
|
char file_path[FN_REFLEN];
|
|
fn_format(file_path, file->name, binlog_cache_dir, "",
|
|
MYF(MY_REPLACE_DIR));
|
|
|
|
my_delete(file_path, MYF(0));
|
|
}
|
|
|
|
my_dirend(dir_info);
|
|
return false;
|
|
}
|