/* Innodb page type. */ struct innodb_page_type { int n_undo_state_active; int n_undo_state_cached; int n_undo_state_to_purge; int n_undo_state_prepared; int n_undo_state_other; int n_undo; int n_fil_page_index; int n_fil_page_undo_log; int n_fil_page_inode; int n_fil_page_ibuf_free_list; int n_fil_page_ibuf_bitmap; int n_fil_page_type_sys; int n_fil_page_type_trx_sys; int n_fil_page_type_fsp_hdr; int n_fil_page_type_allocated; int n_fil_page_type_xdes; int n_fil_page_type_blob; int n_fil_page_type_zblob; int n_fil_page_type_other; int n_fil_page_type_zblob2; int n_fil_page_type_page_compressed; int n_fil_page_type_page_compressed_encrypted;
} page_type;
/*!< first element for empty pages,
last element for pages with more than logical_page_size */ unsignedlonglong pages_in_size_range[SIZE_RANGES_FOR_PAGE+2];
/* CreateFile() also provide advisory lock with the usage of
access and share mode of the file.*/
hFile = CreateFile(
(LPCTSTR) name, access, 0L, NULL,
OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { /* print the error message. */
fprintf(stderr, "Filename::%s %s\n", name,
error_message(GetLastError()));
return (NULL);
}
/* get the file descriptor. */
fd= _open_osfhandle((intptr_t)hFile, flags); #else/* _WIN32 */
int create_flag; /* define the advisory lock and open file mode. */ if (do_write) {
create_flag = O_RDWR;
lk.l_type = F_WRLCK;
} else {
create_flag = O_RDONLY;
lk.l_type = F_RDLCK;
}
/** Check whether the page contains all zeroes. @param[in]bufpage @param[in]sizephysicalsizeofthepage
@return true if the page is all zeroes; else false */ staticbool is_page_all_zeroes(
byte* buf,
ulint size)
{ /* On pages that are not all zero, the page number
must match. */ const ulint* p = reinterpret_cast<const ulint*>(buf); const ulint* const end = reinterpret_cast<const ulint*>(buf + size); do { if (*p++) { returnfalse;
}
} while (p != end);
returntrue;
}
/** Check if page is corrupted or not. @param[in]bufpageframe @param[in]is_encryptedtrueifpage0containedcryp_data withcrypt_schemeencrypted @param[in]flagstablespaceflags
@retval true if page is corrupted otherwise false. */ staticbool is_page_corrupted(byte *buf, bool is_encrypted, uint32_t flags)
{
/* enable if page is corrupted. */ bool is_corrupted; /* use to store LSN values. */
uint32_t logseq;
uint32_t logseqfield; const uint16_t page_type = mach_read_from_2(buf+FIL_PAGE_TYPE);
uint32_t key_version = buf_page_get_key_version(buf, flags);
uint32_t space_id = mach_read_from_4(
buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
ulint zip_size = fil_space_t::zip_size(flags);
ulint is_compressed = fil_space_t::is_compressed(flags); constbool use_full_crc32 = fil_space_t::full_crc32(flags);
if (mach_read_from_4(buf + FIL_PAGE_OFFSET) != cur_page_num
|| (space_id != cur_space
&& (!use_full_crc32 || (!is_encrypted && !is_compressed)))) { /* On pages that are not all zero, the page number
must match. */ if (is_page_all_zeroes(buf,
fil_space_t::physical_size(flags))) { returnfalse;
}
if (is_log_enabled) {
fprintf(log_file, "page id mismatch space::" UINT32PF " page::" UINT32PF " \n",
space_id, cur_page_num);
}
returntrue;
}
/* We can't trust only a page type, thus we take account
also fsp_flags or crypt_data on page 0 */ if ((page_type == FIL_PAGE_PAGE_COMPRESSED && is_compressed) ||
(page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED &&
is_compressed && is_encrypted)) { /* Page compressed tables do not contain post compression
checksum. */ return (false);
}
if (is_corrupted) {
is_corrupted = buf_page_is_corrupted(true, buf, flags);
}
return(is_corrupted);
}
/** Check if page is doublewrite buffer or not.
@retval true if page is doublewrite buffer otherwise false. */ staticbool is_page_doublewritebuffer()
{ if (cur_space != 0) returnfalse; const uint32_t extent{static_cast<uint32_t>(
cur_page_num & ~(extent_size - 1))}; return cur_page_num > FSP_DICT_HDR_PAGE_NO &&
extent && (extent == dblwr_1 || extent == dblwr_2);
}
/*******************************************************//*
Check if page is empty ornot.
@param [in] page page to checked for empty.
@param [in] len size of page.
@retval trueif page is empty.
@retval falseif page is not empty.
*/ static bool
is_page_empty( const byte* page,
size_t len)
{ while (len--) { if (*page++) { return (false);
}
}
return (true);
}
/********************************************************************//**
Rewrite the checksum for the page.
@param [in/out] page page buffer
@param [in] flags tablespace flags
@retval true : do rewrite
@retval false : skip the rewrite as checksum stored match with
calculated or page is doublewrite buffer.
*/ staticbool update_checksum(byte* page, uint32_t flags)
{
ib_uint32_t checksum = 0;
byte stored1[4]; /* get FIL_PAGE_SPACE_OR_CHKSUM field checksum */
byte stored2[4]; /* get FIL_PAGE_END_LSN_OLD_CHKSUM field checksum */
ut_ad(page); /* If page is doublewrite buffer, skip the rewrite of checksum. */ if (skip_page) { return (false);
}
func_exit: /* The following code is to check the stored checksum with the calculatedchecksum.Ifitmatches,thenreturnFALSEtoskip
the rewrite of checksum, otherwise return TRUE. */ if (iscompressed) { if (!memcmp(stored1, page + FIL_PAGE_SPACE_OR_CHKSUM, 4)) { return (false);
} return (true);
}
if (file != stdin) { if (do_update) { /* Set the previous file pointer position
saved in pos to current file position. */ if (0 != fsetpos(file, pos)) {
perror("fsetpos"); return(false);
}
} else { /* Store the current file position in pos */ if (0 != fgetpos(file, pos)) {
perror("fgetpos"); return(false);
} return(true);
}
}
if (physical_page_size
!= fwrite(buf, 1, physical_page_size,
file == stdin ? stdout : file)) {
fprintf(stderr, "Failed to write page::" UINT32PF " to %s: %s\n",
cur_page_num, filename, strerror(errno));
return(false);
} if (file != stdin) {
fflush(file); /* Store the current file position in pos */ if (0 != fgetpos(file, pos)) {
perror("fgetpos"); return(false);
}
}
break;
} case FIL_PAGE_UNDO_LOG:
page_type.n_fil_page_undo_log++;
undo_page_type = mach_read_from_2(page +
TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE); if (file) {
fprintf(file, "#::" UINT32PF "\t\t|\t\tUndo log page\t\t\t|",
cur_page_num);
}
page_type.n_undo++;
undo_page_type = mach_read_from_2(page + TRX_UNDO_SEG_HDR +
TRX_UNDO_STATE); switch (undo_page_type) { case TRX_UNDO_ACTIVE:
page_type.n_undo_state_active++; if (file) {
fprintf(file, ", %s", "Undo log of " "an active transaction");
} break;
case TRX_UNDO_CACHED:
page_type.n_undo_state_cached++; if (file) {
fprintf(file, ", %s", "Page is " "cached for quick reuse");
} break;
case TRX_UNDO_TO_PURGE:
page_type.n_undo_state_to_purge++; if (file) {
fprintf(file, ", %s", "Will be " "freed in purge when all undo" "data in it is removed");
} break;
case TRX_UNDO_PREPARED:
page_type.n_undo_state_prepared++; if (file) {
fprintf(file, ", %s", "Undo log of " "an prepared transaction");
} break;
/** Verify page checksum. @param[in]bufpagetoverify @param[in]zip_sizeROW_FORMAT=COMPRESSEDpagesize,or0 @param[in]is_encryptedtrueiftablespaceisencrypted @param[in,out]mismatch_countNumberofpagesfailedinchecksumverify @param[in]flagstablespaceflags
@retval 0 if page checksum matches or 1 if it does not match */ staticint verify_checksum(
byte* buf, bool is_encrypted, unsignedlonglong* mismatch_count,
uint32_t flags)
{ int exit_status = 0; if (is_page_corrupted(buf, is_encrypted, flags)) {
fprintf(stderr, "Fail: page::" UINT32PF " invalid\n",
cur_page_num);
(*mismatch_count)++;
if (*mismatch_count > allow_mismatches) {
fprintf(stderr, "Exceeded the " "maximum allowed " "checksum mismatch " "count::%llu current::%llu\n",
*mismatch_count,
allow_mismatches);
exit_status = 1;
}
}
return (exit_status);
}
/** Rewrite page checksum if needed. @param[in]filenameFilename @param[in]fil_inFilepointer @param[in]bufpage @param[in]posFileposition @param[in]is_encryptedtrueiftablespaceisencrypted @param[in]flagstablespaceflags
@retval 0 if checksum rewrite was successful, 1 if error was detected */ static int
rewrite_checksum( constchar* filename,
FILE* fil_in,
byte* buf,
fpos_t* pos, bool is_encrypted,
uint32_t flags)
{ bool is_compressed = fil_space_t::is_compressed(flags);
/* Rewrite checksum. Note that for encrypted and
page compressed tables this is not currently supported. */ return do_write && !is_encrypted && !is_compressed
&& !write_file(filename, fil_in, buf, flags, pos);
}
/** Read and validate page 0, then initialize tablespace flags andpagesize. @paramfil_inFilepointer @parambufBuffertoreadpageinto
@return whether the page was read successfully */ staticbool read_and_validate_page0(FILE *fil_in, byte *buf)
{ /* Read the minimum page size first */
size_t initial_page_size= UNIV_ZIP_SIZE_MIN; if (tablespace_flags != USE_FSP_FLAGS)
{
init_page_size_from_flags(tablespace_flags);
initial_page_size= physical_page_size;
}
/* Read just enough to get the tablespace flags */
size_t bytes= fread(buf, 1, initial_page_size, fil_in);
if (bytes != initial_page_size)
{
fprintf(stderr, "Error: Was not able to read the " "minimum page size of %zu bytes. Bytes read " "was %zu\n", initial_page_size, bytes); returnfalse;
}
/* Get tablespace flags from the FSP header */
uint32_t flags= mach_read_from_4(buf + FSP_HEADER_OFFSET +
FSP_SPACE_FLAGS);
if (tablespace_flags != USE_FSP_FLAGS)
{ if (cur_page_num == 0 && flags != tablespace_flags)
fprintf(stderr, "Error: Mismatch between provided tablespace " "flags (0x%x) and file flags (0x%x)\n",
tablespace_flags, flags);
} else
{ if (cur_page_num)
{
fprintf(stderr, "Error: First page of the tablespace file " "should be 0, but encountered page number %" PRIu32 ". " "If you are checking multi file system " "tablespace files, please specify the correct " "tablespace flags using --tablespace-flags option.\n",
cur_page_num); returnfalse;
} /* Initialize page size parameters based on flags */
init_page_size_from_flags(flags); /* Read the rest of the page if it's larger than the minimum size */ if (physical_page_size > UNIV_ZIP_SIZE_MIN)
{ /* Read rest of the page 0 to determine crypt_data */
ulint bytes= read_file(buf, true, physical_page_size, fil_in); if (bytes != physical_page_size)
{
fprintf(stderr, "Error: Was not able to read the rest of the " "page of " ULINTPF " bytes. Bytes read was " ULINTPF "\n",
physical_page_size - UNIV_ZIP_SIZE_MIN, bytes); returnfalse;
}
}
tablespace_flags= flags;
}
/* The file name is not optional. */ for (int i = 0; i < argc; ++i) {
/* Reset parameters for each file. */
filename = argv[i];
memset(&page_type, 0, sizeof(innodb_page_type));
partial_page_read = false;
skip_page = false;
if (is_log_enabled) {
fprintf(log_file, "Filename = %s\n", filename);
}
if (*filename == '-') { /* read from stdin. */
fil_in = stdin;
read_from_stdin = true;
}
/* stat the file to get size and page count. */ if (!read_from_stdin && #ifdef _WIN32
_stat64(filename, &st)) { #else
stat(filename, &st)) { #endif/* _WIN32 */
fprintf(stderr, "Error: %s cannot be found\n",
filename);
exit_status = 1; goto my_exit;
}
if (!read_from_stdin) {
size = st.st_size;
fil_in = open_file(filename); /*If fil_in is NULL, terminate as some error encountered */ if(fil_in == NULL) {
exit_status = 1; goto my_exit;
} /* Save the current file pointer in pos variable.*/ if (0 != fgetpos(fil_in, &pos)) {
perror("fgetpos");
exit_status = 1; goto my_exit;
}
}
/* Read and validate page 0 */ if (!read_and_validate_page0(fil_in, buf)) {
exit_status = 1; goto my_exit;
}
/* Check if tablespace is encrypted */ bool is_encrypted = check_encryption(filename, buf);
/* Verify page 0 contents. Note that we can't allow checksummismatchonpage0,becausethatwouldmeanwe
could not trust it content. */ if (!no_check) { unsignedlonglong tmp_allow_mismatches = allow_mismatches;
allow_mismatches = 0;
off_t cur_offset = 0; /* Find the first non all-zero page and fetch the
space id from there. */ while (is_page_all_zeroes(buf, physical_page_size)) {
bytes = ulong(read_file(
buf, false, physical_page_size,
fil_in));
if (feof(fil_in)) {
fprintf(stderr, "All are " "zero-filled pages."); goto my_exit;
}
if (cur_offset > 0) { /* Re-read the non-zero page to check the checksum.Somovethefilepointerto
previous position and reset the page number too. */
cur_page_num = mach_read_from_4(buf + FIL_PAGE_OFFSET); if (!start_page) { goto first_non_zero;
}
}
/* seek to the necessary position */ if (start_page) { if (!read_from_stdin) { /* If read is not from stdin, we can use fseeko()topositionthefilepointerto
the desired page. */
partial_page_read = false;
offset = off_t(ulonglong(start_page)
* physical_page_size); if (IF_WIN(_fseeki64,fseeko)(fil_in, offset,
SEEK_SET)) {
perror("Error: Unable to seek to " "necessary offset");
exit_status = 1; goto my_exit;
} /* Save the current file pointer in
pos variable. */ if (0 != fgetpos(fil_in, &pos)) {
perror("fgetpos");
exit_status = 1; goto my_exit;
}
} else {
ulong count = 0;
while (!feof(fil_in)) { if (start_page == count) { break;
} /* We read a part of page to find the minimumpagesize.Wecannotreset thefilepointertothebeginningof thepageifwearereadingfromstdin (fseeko()onstdindoesn'twork).So readonlytheremainingpartofpage,
if partial_page_read is enable. */
bytes = read_file(buf,
partial_page_read,
physical_page_size,
fil_in);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.