1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-34075: Binlog-in-engine: Some test and review fixes

Enable binlog_in_engine as a default suite.

Fix embedded and Windows build failures.

Use sql_print_(error|warning) over ib::error() and ib::warn().

Use small_vector<> for the innodb_binlog_oob_reader instead of a custom
implementation.

Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
This commit is contained in:
Kristian Nielsen
2025-01-17 16:55:09 +01:00
parent dd8ffe952d
commit 468c23d69b
6 changed files with 66 additions and 100 deletions

View File

@@ -180,6 +180,7 @@ my @DEFAULT_SUITES= qw(
atomic- atomic-
binlog- binlog-
binlog_encryption- binlog_encryption-
binlog_in_engine-
client- client-
csv- csv-
compat/oracle- compat/oracle-

View File

@@ -3375,7 +3375,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
goto err; goto err;
} }
if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg) || if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg) ||
fake_format_description_event(info, info->fdev, &info->errmsg, pos)) fake_format_description_event(info, info->fdev, &info->errmsg,
(uint32_t)pos))
{ {
info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG; info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err; goto err;

View File

@@ -184,18 +184,18 @@ fsp_binlog_open(const char *file_name, pfs_os_file_t fh,
restart. restart.
*/ */
if (!os_file_set_size(file_name, fh, binlog_size, false)) { if (!os_file_set_size(file_name, fh, binlog_size, false)) {
ib::warn() << "Failed to change the size of InnoDB binlog file " << sql_print_warning("Failed to change the size of InnoDB binlog file '%s' "
file_name << " from " << file_size << " to " << binlog_size << "from %zu to %zu bytes (error code: %d)", file_name,
" bytes (error code: " << errno << ")."; file_size, (size_t)binlog_size, errno);
} else { } else {
file_size= (size_t)binlog_size; file_size= (size_t)binlog_size;
} }
} }
if (file_size < 2*page_size) if (file_size < 2*page_size)
{ {
ib::warn() << "InnoDB binlog file number " << file_no << " is too short" sql_print_warning("InnoDB binlog file number %llu is too short (%zu bytes), "
" (" << file_size << " bytes), should be at least " << 2*page_size << "should be at least %u bytes",
" bytes."; file_no, file_size, 2*page_size);
os_file_close(fh); os_file_close(fh);
return nullptr; return nullptr;
} }
@@ -211,7 +211,7 @@ fsp_binlog_open(const char *file_name, pfs_os_file_t fh,
dberr_t err= os_file_read(IORequestRead, fh, page_buf, 0, page_size, nullptr); dberr_t err= os_file_read(IORequestRead, fh, page_buf, 0, page_size, nullptr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
ib::warn() << "Unable to read first page of file " << file_name; sql_print_warning("Unable to read first page of file '%s'", file_name);
aligned_free(page_buf); aligned_free(page_buf);
os_file_close(fh); os_file_close(fh);
return nullptr; return nullptr;
@@ -220,9 +220,8 @@ fsp_binlog_open(const char *file_name, pfs_os_file_t fh,
/* ToDo: Maybe use leaner page format for binlog tablespace? */ /* ToDo: Maybe use leaner page format for binlog tablespace? */
uint32_t id1= mach_read_from_4(FIL_PAGE_SPACE_ID + page_buf); uint32_t id1= mach_read_from_4(FIL_PAGE_SPACE_ID + page_buf);
if (id1 != space_id) { if (id1 != space_id) {
ib::warn() << "Binlog file " << file_name << sql_print_warning("Binlog file %s has inconsistent tablespace id %u "
" has inconsistent tablespace id " << id1 << "(expected %u)", file_name, id1, space_id);
" (expected " << space_id << ")";
aligned_free(page_buf); aligned_free(page_buf);
os_file_close(fh); os_file_close(fh);
return nullptr; return nullptr;
@@ -298,7 +297,7 @@ dberr_t fsp_binlog_tablespace_create(uint64_t file_no, fil_space_t **new_space)
/* We created the binlog file and now write it full of zeros */ /* We created the binlog file and now write it full of zeros */
if (!os_file_set_size(name, fh, if (!os_file_set_size(name, fh,
os_offset_t{size} << srv_page_size_shift)) { os_offset_t{size} << srv_page_size_shift)) {
ib::error() << "Unable to allocate " << name; sql_print_error("Unable to allocate file %s", name);
os_file_close(fh); os_file_close(fh);
os_file_delete(innodb_data_file_key, name); os_file_delete(innodb_data_file_key, name);
return DB_ERROR; return DB_ERROR;
@@ -625,8 +624,8 @@ int
binlog_chunk_reader::read_error_corruption(uint64_t file_no, uint64_t page_no, binlog_chunk_reader::read_error_corruption(uint64_t file_no, uint64_t page_no,
const char *msg) const char *msg)
{ {
ib::error() << "Corrupt binlog found on page " << page_no << sql_print_error("Corrupt binlog found on page %llu in binlog number %llu: "
" in binlog number " << file_no << ": " << msg; "%s", page_no, file_no, msg);
return -1; return -1;
} }

View File

@@ -26,6 +26,7 @@ InnoDB implementation of binlog.
#include "mtr0log.h" #include "mtr0log.h"
#include "fsp0fsp.h" #include "fsp0fsp.h"
#include "trx0trx.h" #include "trx0trx.h"
#include "small_vector.h"
#include "rpl_gtid_base.h" #include "rpl_gtid_base.h"
#include "handler.h" #include "handler.h"
@@ -159,16 +160,9 @@ class innodb_binlog_oob_reader {
a prior tree that must be traversed first. a prior tree that must be traversed first.
*/ */
bool is_leftmost; bool is_leftmost;
} init_stack[8], *stack; };
small_vector<stack_entry, 8>stack;
/*
If the stack_len is == sizeof(init_stack)/sizeof(init_stack[0]), then we
are using the embedded stack memory. Otherwise we are using a dynamically
allocated stack that must be freed.
*/
uint32_t stack_len;
/* Current top of stack. */
uint32_t stack_top;
/* State machine current state. */ /* State machine current state. */
enum oob_states state; enum oob_states state;
@@ -176,13 +170,12 @@ public:
innodb_binlog_oob_reader(); innodb_binlog_oob_reader();
~innodb_binlog_oob_reader(); ~innodb_binlog_oob_reader();
bool start_traversal(uint64_t file_no, uint64_t offset); void start_traversal(uint64_t file_no, uint64_t offset);
bool oob_traversal_done() { return stack_top == 0; } bool oob_traversal_done() { return stack.empty(); }
int read_data(binlog_chunk_reader *chunk_rd, uchar *buf, int max_len); int read_data(binlog_chunk_reader *chunk_rd, uchar *buf, int max_len);
private: private:
bool ensure_stack(uint32_t length); void push_state(enum oob_states state, uint64_t file_no, uint64_t offset,
bool push_state(enum oob_states state, uint64_t file_no, uint64_t offset,
bool is_leftmost); bool is_leftmost);
}; };
@@ -474,14 +467,14 @@ innodb_binlog_init(size_t binlog_size, const char *directory)
uint64_t pages= binlog_size >> srv_page_size_shift; uint64_t pages= binlog_size >> srv_page_size_shift;
if (UNIV_LIKELY(pages > (uint64_t)UINT32_MAX)) { if (UNIV_LIKELY(pages > (uint64_t)UINT32_MAX)) {
pages= UINT32_MAX; pages= UINT32_MAX;
ib::warn() << "Requested max_binlog_size is larger than the maximum " << sql_print_warning("Requested max_binlog_size is larger than the maximum "
"InnoDB tablespace size, truncated to " << "InnoDB tablespace size, truncated to %llu",
(pages << srv_page_size_shift) << "."; (pages << srv_page_size_shift));
} else if (pages < 2) { /* Minimum one data page and one index page. */ } else if (pages < 2) { /* Minimum one data page and one index page. */
pages= 2; pages= 2;
ib::warn() << "Requested max_binlog_size is smaller than the minimum " << sql_print_warning("Requested max_binlog_size is smaller than the minimum "
"size supported by InnoDB, truncated to " << "size supported by InnoDB, truncated to %llu",
(pages << srv_page_size_shift) << "."; (pages << srv_page_size_shift));
} }
innodb_binlog_size_in_pages= (uint32_t)pages; innodb_binlog_size_in_pages= (uint32_t)pages;
@@ -489,8 +482,8 @@ innodb_binlog_init(size_t binlog_size, const char *directory)
directory= "."; directory= ".";
else if (strlen(directory) + BINLOG_NAME_MAX_LEN > OS_FILE_MAX_PATH) else if (strlen(directory) + BINLOG_NAME_MAX_LEN > OS_FILE_MAX_PATH)
{ {
ib::error() << "Specified binlog directory path '" << directory << sql_print_error("Specified binlog directory path '%s' is too long",
"' is too long."; directory);
return true; return true;
} }
innodb_binlog_directory= directory; innodb_binlog_directory= directory;
@@ -582,7 +575,7 @@ find_pos_in_binlog(uint64_t file_no, size_t file_size, byte *page_buf,
OS_FILE_OPEN, OS_DATA_FILE, OS_FILE_OPEN, OS_DATA_FILE,
srv_read_only_mode, &ret); srv_read_only_mode, &ret);
if (!ret) { if (!ret) {
ib::warn() << "Unable to open file " << file_name; sql_print_warning("Unable to open file '%s'", file_name);
return -1; return -1;
} }
@@ -679,8 +672,8 @@ innodb_binlog_discover()
{ {
if (my_errno == ENOENT) if (my_errno == ENOENT)
return 0; return 0;
ib::error() << "Could not read the binlog directory '" << sql_print_error("Could not read the binlog directory '%s', error code %d",
innodb_binlog_directory << "', error code " << my_errno << "."; innodb_binlog_directory, my_errno);
return -1; return -1;
} }
@@ -715,9 +708,9 @@ innodb_binlog_discover()
if (res < 0) { if (res < 0) {
file_no= binlog_files.last_file_no; file_no= binlog_files.last_file_no;
active_binlog_file_no.store(file_no, std::memory_order_release); active_binlog_file_no.store(file_no, std::memory_order_release);
ib::warn() << "Binlog number " << binlog_files.last_file_no << sql_print_warning("Binlog number %llu could no be opened. Starting a new "
" could no be opened. Starting a new binlog file from number " << "binlog file from number %llu",
(file_no + 1) << "."; binlog_files.last_file_no,(file_no + 1));
return 0; return 0;
} }
@@ -747,9 +740,9 @@ innodb_binlog_discover()
active_binlog_space= space; active_binlog_space= space;
binlog_cur_page_no= page_no; binlog_cur_page_no= page_no;
binlog_cur_page_offset= pos_in_page; binlog_cur_page_offset= pos_in_page;
ib::warn() << "Binlog number " << binlog_files.prev_file_no sql_print_warning("Binlog number %llu could not be opened, starting "
<< " could not be opened, starting from binlog number " "from binlog number %llu instead",
<< file_no << " instead." ; binlog_files.prev_file_no, file_no);
return 1; return 1;
} }
file_no= binlog_files.prev_file_no; file_no= binlog_files.prev_file_no;
@@ -1161,8 +1154,8 @@ binlog_state_recover()
} }
if (diff_state_interval == 0 || diff_state_interval % srv_page_size != 0) if (diff_state_interval == 0 || diff_state_interval % srv_page_size != 0)
{ {
ib::warn() << "Invalid differential binlog state interval " << sql_print_warning("Invalid differential binlog state interval %llu found "
diff_state_interval << " found in binlog file, ignoring"; "in binlog file, ignoring", diff_state_interval);
current_binlog_state_interval= 0; /* Disable in this binlog file */ current_binlog_state_interval= 0; /* Disable in this binlog file */
} }
else else
@@ -1437,64 +1430,35 @@ innodb_free_oob(THD *thd, void *engine_data)
innodb_binlog_oob_reader::innodb_binlog_oob_reader() innodb_binlog_oob_reader::innodb_binlog_oob_reader()
: stack(init_stack), stack_len(sizeof(init_stack)/sizeof(init_stack[0])),
stack_top(0)
{ {
/* Nothing. */
} }
innodb_binlog_oob_reader::~innodb_binlog_oob_reader() innodb_binlog_oob_reader::~innodb_binlog_oob_reader()
{ {
if (stack_len > sizeof(init_stack)/sizeof(init_stack[0])) /* Nothing. */
ut_free(stack);
} }
bool void
innodb_binlog_oob_reader::ensure_stack(uint32_t needed_length)
{
uint32_t len= stack_len;
if (len >= needed_length)
return false;
do
len*= 2;
while (len < needed_length);
size_t needed= len*sizeof(stack_entry);
stack_entry *new_stack= (stack_entry *) ut_malloc(needed, mem_key_binlog);
if (!new_stack)
{
my_error(ER_OUTOFMEMORY, MYF(0), needed);
return true;
}
memcpy(new_stack, stack, stack_len*sizeof(stack_entry));
stack= new_stack;
stack_len= len;
return false;
}
bool
innodb_binlog_oob_reader::push_state(enum oob_states state, uint64_t file_no, innodb_binlog_oob_reader::push_state(enum oob_states state, uint64_t file_no,
uint64_t offset, bool is_leftmost) uint64_t offset, bool is_leftmost)
{ {
uint32_t idx= stack_top; stack_entry new_entry;
if (ensure_stack(idx + 1)) new_entry.state= state;
return true; new_entry.file_no= file_no;
stack[idx].state= state; new_entry.offset= offset;
stack[idx].file_no= file_no; new_entry.is_leftmost= is_leftmost;
stack[idx].offset= offset; stack.emplace_back(std::move(new_entry));
stack[idx].is_leftmost= is_leftmost;
stack_top= idx + 1;
return false;
} }
bool void
innodb_binlog_oob_reader::start_traversal(uint64_t file_no, uint64_t offset) innodb_binlog_oob_reader::start_traversal(uint64_t file_no, uint64_t offset)
{ {
stack_top= 0; stack.clear();
return push_state(ST_initial, file_no, offset, true); push_state(ST_initial, file_no, offset, true);
} }
@@ -1521,14 +1485,14 @@ innodb_binlog_oob_reader::read_data(binlog_chunk_reader *chunk_rd,
std::pair<uint64_t, const unsigned char *> v_and_p; std::pair<uint64_t, const unsigned char *> v_and_p;
int size; int size;
if (stack_top <= 0) if (stack.empty())
{ {
ut_ad(0 /* Should not call when no more oob data to read. */); ut_ad(0 /* Should not call when no more oob data to read. */);
return 0; return 0;
} }
again: again:
e= &(stack[stack_top - 1]); e= &(stack[stack.size() - 1]);
switch (e->state) switch (e->state)
{ {
case ST_initial: case ST_initial:
@@ -1632,8 +1596,8 @@ again:
if (chunk_rd->end_of_record()) if (chunk_rd->end_of_record())
{ {
/* This oob record done, pop the state. */ /* This oob record done, pop the state. */
ut_ad(stack_top > 0); ut_ad(!stack.empty());
--stack_top; stack.erase(stack.end() - 1, stack.end());
} }
return size; return size;
@@ -2157,8 +2121,8 @@ innodb_find_binlogs(uint64_t *out_first, uint64_t *out_last)
MY_DIR *dir= my_dir(innodb_binlog_directory, MYF(0)); MY_DIR *dir= my_dir(innodb_binlog_directory, MYF(0));
if (!dir) if (!dir)
{ {
ib::error() << "Could not read the binlog directory '" << sql_print_error("Could not read the binlog directory '%s', error code %d",
innodb_binlog_directory << "', error code " << my_errno << "."; innodb_binlog_directory, my_errno);
return true; return true;
} }
@@ -2181,12 +2145,12 @@ innodb_find_binlogs(uint64_t *out_first, uint64_t *out_last)
if (num_file_no == 0) if (num_file_no == 0)
{ {
ib::error() << "No binlog files found (deleted externally?)"; sql_print_error("No binlog files found (deleted externally?)");
return true; return true;
} }
if (num_file_no != last_file_no - first_file_no + 1) if (num_file_no != last_file_no - first_file_no + 1)
{ {
ib::error() << "Missing binlog files (deleted externally?)"; sql_print_error("Missing binlog files (deleted externally?)");
return true; return true;
} }
*out_first= first_file_no; *out_first= first_file_no;
@@ -2208,8 +2172,8 @@ innodb_reset_binlogs()
MY_DIR *dir= my_dir(innodb_binlog_directory, MYF(MY_WME)); MY_DIR *dir= my_dir(innodb_binlog_directory, MYF(MY_WME));
if (!dir) if (!dir)
{ {
ib::error() << "Could not read the binlog directory '" << sql_print_error("Could not read the binlog directory '%s', error code %d",
innodb_binlog_directory << "', error code " << my_errno << "."; innodb_binlog_directory, my_errno);
err= true; err= true;
} }
else else

View File

@@ -19,6 +19,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
/* A normally small vector, inspired by llvm::SmallVector */ /* A normally small vector, inspired by llvm::SmallVector */
#include "my_global.h" #include "my_global.h"
#include "my_valgrind.h"
#include <iterator> #include <iterator>
#include <memory> #include <memory>

View File

@@ -44,7 +44,7 @@ of the multiplication result:
#include <intrin.h> #include <intrin.h>
#pragma warning(pop) #pragma warning(pop)
#endif #endif
__forceinline unsigned int nlz (ulonglong x) __forceinline unsigned int nlz (unsigned long long x)
{ {
#if defined(_M_IX86) || defined(_M_X64) #if defined(_M_IX86) || defined(_M_X64)
unsigned long n; unsigned long n;
@@ -67,7 +67,7 @@ __forceinline unsigned int nlz (ulonglong x)
#endif #endif
} }
#else #else
inline unsigned int nlz (ulonglong x) inline unsigned int nlz (unsigned long long x)
{ {
static unsigned char table [48] = { static unsigned char table [48] = {
32, 6, 5, 0, 4, 12, 0, 20, 32, 6, 5, 0, 4, 12, 0, 20,