Commit 23685378 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-14425 preparation: Simplify redo log upgrade

recv_log_recover_pre_10_2(): Merged from
recv_find_max_checkpoint_0(), recv_log_format_0_recover().
parent a4ab54d7
......@@ -1321,86 +1321,119 @@ static bool redo_file_sizes_are_correct()
return false;
}
/** Find the latest checkpoint in the format-0 log header.
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@return error code or DB_SUCCESS */
static MY_ATTRIBUTE((warn_unused_result))
dberr_t
recv_find_max_checkpoint_0(ulint* max_field)
/** Determine if a redo log from before MariaDB 10.2.2 is clean.
@return error code
@retval DB_SUCCESS if the redo log is clean
@retval DB_CORRUPTION if the redo log is corrupted
@retval DB_ERROR if the redo log is not empty */
static dberr_t recv_log_recover_pre_10_2()
{
ib_uint64_t max_no = 0;
ib_uint64_t checkpoint_no;
byte* buf = log_sys.checkpoint_buf;
uint64_t max_no= 0;
uint64_t checkpoint_no;
byte *buf= log_sys.buf;
ut_ad(log_sys.log.format == 0);
if (!redo_file_sizes_are_correct())
return DB_CORRUPTION;
/** Offset of the first checkpoint checksum */
constexpr uint CHECKSUM_1= 288;
/** Offset of the second checkpoint checksum */
constexpr uint CHECKSUM_2= CHECKSUM_1 + 4;
/** the checkpoint LSN field */
constexpr uint CHECKPOINT_LSN= 8;
/** Most significant bits of the checkpoint offset */
constexpr uint OFFS_HI= CHECKSUM_2 + 12;
/** Least significant bits of the checkpoint offset */
constexpr uint OFFS_LO= 16;
lsn_t lsn= 0;
for (ulint field= LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1)
{
log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE});
if (!redo_file_sizes_are_correct()) {
return DB_CORRUPTION;
}
if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1)) !=
mach_read_from_4(buf + CHECKSUM_1) ||
static_cast<uint32_t>(ut_fold_binary(buf + CHECKPOINT_LSN,
CHECKSUM_2 - CHECKPOINT_LSN)) !=
mach_read_from_4(buf + CHECKSUM_2))
{
DBUG_LOG("ib_log", "invalid pre-10.2.2 checkpoint " << field);
continue;
}
ut_ad(log_sys.log.format == 0);
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
/** Offset of the first checkpoint checksum */
static const uint CHECKSUM_1 = 288;
/** Offset of the second checkpoint checksum */
static const uint CHECKSUM_2 = CHECKSUM_1 + 4;
/** Most significant bits of the checkpoint offset */
static const uint OFFSET_HIGH32 = CHECKSUM_2 + 12;
/** Least significant bits of the checkpoint offset */
static const uint OFFSET_LOW32 = 16;
if (!log_crypt_101_read_checkpoint(buf))
{
ib::error() << "Decrypting checkpoint failed";
continue;
}
bool found = false;
DBUG_PRINT("ib_log", ("checkpoint " UINT64PF " at " LSN_PF " found",
checkpoint_no,
mach_read_from_8(buf + LOG_CHECKPOINT_LSN)));
for (ulint field = LOG_CHECKPOINT_1; field <= LOG_CHECKPOINT_2;
field += LOG_CHECKPOINT_2 - LOG_CHECKPOINT_1) {
log_sys.log.read(field, {buf, OS_FILE_LOG_BLOCK_SIZE});
if (checkpoint_no >= max_no)
{
max_no= checkpoint_no;
lsn= mach_read_from_8(buf + CHECKPOINT_LSN);
log_sys.log.set_lsn(lsn);
log_sys.log.set_lsn_offset(lsn_t{mach_read_from_4(buf + OFFS_HI)} << 32 |
mach_read_from_4(buf + OFFS_LO));
}
}
if (static_cast<uint32_t>(ut_fold_binary(buf, CHECKSUM_1))
!= mach_read_from_4(buf + CHECKSUM_1)
|| static_cast<uint32_t>(
ut_fold_binary(buf + LOG_CHECKPOINT_LSN,
CHECKSUM_2 - LOG_CHECKPOINT_LSN))
!= mach_read_from_4(buf + CHECKSUM_2)) {
DBUG_LOG("ib_log",
"invalid pre-10.2.2 checkpoint " << field);
continue;
}
if (!lsn)
{
ib::error() << "Upgrade after a crash is not supported."
" This redo log was created before MariaDB 10.2.2,"
" and we did not find a valid checkpoint."
" Please follow the instructions at"
" https://mariadb.com/kb/en/library/upgrading/";
return DB_ERROR;
}
checkpoint_no = mach_read_from_8(
buf + LOG_CHECKPOINT_NO);
log_sys.set_lsn(lsn);
log_sys.set_flushed_lsn(lsn);
const lsn_t source_offset= log_sys.log.calc_lsn_offset_old(lsn);
if (!log_crypt_101_read_checkpoint(buf)) {
ib::error() << "Decrypting checkpoint failed";
continue;
}
static constexpr char NO_UPGRADE_RECOVERY_MSG[]=
"Upgrade after a crash is not supported."
" This redo log was created before MariaDB 10.2.2";
DBUG_PRINT("ib_log",
("checkpoint " UINT64PF " at " LSN_PF " found",
checkpoint_no,
mach_read_from_8(buf + LOG_CHECKPOINT_LSN)));
recv_sys.read(source_offset & ~511, {buf, 512});
if (checkpoint_no >= max_no) {
found = true;
*max_field = field;
max_no = checkpoint_no;
if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf) &&
!log_crypt_101_read_block(buf, lsn))
{
ib::error() << NO_UPGRADE_RECOVERY_MSG << ", and it appears corrupted.";
return DB_CORRUPTION;
}
log_sys.log.set_lsn(mach_read_from_8(
buf + LOG_CHECKPOINT_LSN));
log_sys.log.set_lsn_offset(
lsn_t(mach_read_from_4(buf + OFFSET_HIGH32))
<< 32
| mach_read_from_4(buf + OFFSET_LOW32));
}
}
if (mach_read_from_2(buf + 4) == (source_offset & 511))
{
/* Mark the redo log for upgrading. */
srv_log_file_size= 0;
recv_sys.parse_start_lsn= recv_sys.recovered_lsn= recv_sys.scanned_lsn=
recv_sys.mlog_checkpoint_lsn = lsn;
log_sys.last_checkpoint_lsn= log_sys.next_checkpoint_lsn=
log_sys.write_lsn= log_sys.current_flush_lsn= lsn;
log_sys.next_checkpoint_no= 0;
recv_sys.remove_extra_log_files= true;
return DB_SUCCESS;
}
if (found) {
return(DB_SUCCESS);
}
if (buf[20 + 32 * 9] == 2)
ib::error() << "Cannot decrypt log for upgrading."
" The encrypted log was created before MariaDB 10.2.2.";
else
ib::error() << NO_UPGRADE_RECOVERY_MSG << ".";
ib::error() << "Upgrade after a crash is not supported."
" This redo log was created before MariaDB 10.2.2,"
" and we did not find a valid checkpoint."
" Please follow the instructions at"
" https://mariadb.com/kb/en/library/upgrading/";
return(DB_ERROR);
return DB_ERROR;
}
/** Same as cals_lsn_offset() except that it supports multiple files */
......@@ -1420,61 +1453,6 @@ lsn_t log_t::file::calc_lsn_offset_old(lsn_t lsn) const
return l + LOG_FILE_HDR_SIZE * (1 + l / (file_size - LOG_FILE_HDR_SIZE));
}
/** Determine if a pre-MySQL 5.7.9/MariaDB 10.2.2 redo log is clean.
@param[in] lsn checkpoint LSN
@param[in] crypt whether the log might be encrypted
@return error code
@retval DB_SUCCESS if the redo log is clean
@retval DB_ERROR if the redo log is corrupted or dirty */
static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
{
log_mutex_enter();
const lsn_t source_offset = log_sys.log.calc_lsn_offset_old(lsn);
log_mutex_exit();
byte* buf = log_sys.buf;
static const char* NO_UPGRADE_RECOVERY_MSG =
"Upgrade after a crash is not supported."
" This redo log was created before MariaDB 10.2.2";
recv_sys.read(source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1),
{buf, OS_FILE_LOG_BLOCK_SIZE});
if (log_block_calc_checksum_format_0(buf)
!= log_block_get_checksum(buf)
&& !log_crypt_101_read_block(buf, lsn)) {
ib::error() << NO_UPGRADE_RECOVERY_MSG
<< ", and it appears corrupted.";
return(DB_CORRUPTION);
}
if (log_block_get_data_len(buf)
== (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) {
} else if (crypt) {
ib::error() << "Cannot decrypt log for upgrading."
" The encrypted log was created"
" before MariaDB 10.2.2.";
return DB_ERROR;
} else {
ib::error() << NO_UPGRADE_RECOVERY_MSG << ".";
return(DB_ERROR);
}
/* Mark the redo log for upgrading. */
srv_log_file_size = 0;
recv_sys.parse_start_lsn = recv_sys.recovered_lsn
= recv_sys.scanned_lsn
= recv_sys.mlog_checkpoint_lsn = lsn;
log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn
= log_sys.write_lsn = log_sys.current_flush_lsn = lsn;
log_sys.set_lsn(lsn);
log_sys.set_flushed_lsn(lsn);
log_sys.next_checkpoint_no = 0;
recv_sys.remove_extra_log_files = true;
return(DB_SUCCESS);
}
/** Determine if a redo log from MariaDB 10.2.2+, 10.3, or 10.4 is clean.
@return error code
@retval DB_SUCCESS if the redo log is clean
......@@ -1572,7 +1550,7 @@ recv_find_max_checkpoint(ulint* max_field)
switch (log_sys.log.format) {
case log_t::FORMAT_3_23:
return(recv_find_max_checkpoint_0(max_field));
return recv_log_recover_pre_10_2();
case log_t::FORMAT_10_2:
case log_t::FORMAT_10_2 | log_t::FORMAT_ENCRYPTED:
case log_t::FORMAT_10_3:
......@@ -3325,8 +3303,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
switch (log_sys.log.format) {
case 0:
log_mutex_exit();
return recv_log_format_0_recover(checkpoint_lsn,
buf[20 + 32 * 9] == 2);
return DB_SUCCESS;
default:
if (end_lsn == 0) {
break;
......
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