mariadb/storage/maria/ma_pagecrc.c
unknown 5ad477f6cb Added --with-maria-tmp-tables (default one) to allow on to configure if Maria should be used for internal temporary tables
Abort mysqld if Maria engine didn't start and we are using Maria for temporary tables
Fixed bug that caused update of big blobs to crash
Use pagecache_page_no_t as type for pages (to get rid of compiler warnings)
Added cast to get rid of compiler warning
Fixed wrong types of variables and arguments that caused lost information
Fixed wrong DBUG_ASSERT() that caused REDO of big blobs to fail
Removed some historical ifdefs that caused problem with windows compilations


BUILD/SETUP.sh:
  Added --with-maria-tmp-tables
include/maria.h:
  Use pagecache_page_no_t as type for pages
  Use my_bool as parameter for 'rep_quick' option
include/my_base.h:
  Added comment
mysql-test/r/maria-big.result:
  Added test that uses big blobs
mysql-test/t/maria-big.test:
  Added test that uses big blobs
sql/mysqld.cc:
  Abort mysqld if Maria engine didn't start and we are using Maria for temporary tables
sql/sql_class.h:
  Don't use Maria for temporary tables if --with-maria-tmp-tables is not defined
sql/sql_select.cc:
  Don't use Maria for temporary tables if --with-maria-tmp-tables is not defined
storage/maria/ha_maria.cc:
  Fixed compiler warnings reported by MCC
  - Fixed usage of wrong types that caused data loss
  - Changed parameter for rep_quick to my_bool
  - Added safe casts
  
  Fixed indentation
storage/maria/ma_bitmap.c:
  Use pagecache_page_no_t as type for pages
  Fixed compiler warnings
  Fixed bug that caused update of big blobs to crash
storage/maria/ma_blockrec.c:
  Use pagecache_page_no_t as type for pages
  Use my_bool as parameter for 'rep_quick' option
  Fixed compiler warnings
  Fixed wrong DBUG_ASSERT()
storage/maria/ma_blockrec.h:
  Use pagecache_page_no_t as type for pages
storage/maria/ma_check.c:
  Fixed some wrong parameters where we didn't get all bits for test_flag
  Changed rep_quick to be of type my_bool
  Use pagecache_page_no_t as type for pages
  Added cast's to get rid of compiler warnings
  Changed type of record_pos to get rid of compiler warning
storage/maria/ma_create.c:
  Added safe cast's to get rid of compiler warnings
storage/maria/ma_dynrec.c:
  Fixed usage of wrong type
storage/maria/ma_key.c:
  Fixed compiler warning
storage/maria/ma_key_recover.c:
  Use pagecache_page_no_t as type for pages
storage/maria/ma_loghandler_lsn.h:
  Added cast's to get rid of compiler warnings
storage/maria/ma_page.c:
  Changed variable name from 'page' to 'pos' as it was an offset and not a page address
  Moved page_size inside block to get rid of compiler warning
storage/maria/ma_pagecache.c:
  Fixed compiler warnings
  Replaced compile time assert with TODO
storage/maria/ma_pagecache.h:
  Use pagecache_page_no_t as type for pages
storage/maria/ma_pagecrc.c:
  Allow bitmap pages that is all zero
storage/maria/ma_preload.c:
  Added cast to get rid of compiler warning
storage/maria/ma_recovery.c:
  Changed types to get rid of compiler warnings
  Use bool for quick_repair to get rid of compiler warning
  Fixed some variables that was wrongly declared (not enough precission)
  Added cast to get rid of compiler warning
storage/maria/ma_test2.c:
  Remove historical undefs
storage/maria/maria_chk.c:
  Changed rep_quick to bool
  Fixed wrong parameter to maria_chk_data_link()
storage/maria/maria_def.h:
  Use pagecache_page_no_t as type for pages
storage/maria/maria_pack.c:
  Renamed isam -> maria
storage/maria/plug.in:
  Added option --with-maria-tmp-tables
storage/maria/trnman.c:
  Added cast to get rid of compiler warning
storage/myisam/mi_test2.c:
  Remove historical undefs
2008-01-10 21:21:36 +02:00

359 lines
11 KiB
C

/* TODO: copyright & Co */
#include "maria_def.h"
/**
@brief calculate crc of the page avoiding special values
@param start The value to start CRC (we use page number here)
@param data data pointer
@param length length of the data
@return crc of the page without special values
*/
static uint32 maria_page_crc(uint32 start, uchar *data, uint length)
{
uint32 crc= crc32(start, data, length);
/* we need this assert to get following comparison working */
compile_time_assert(MARIA_NO_CRC_BITMAP_PAGE ==
MARIA_NO_CRC_NORMAL_PAGE - 1 &&
MARIA_NO_CRC_NORMAL_PAGE == 0xffffffff);
if (crc >= MARIA_NO_CRC_BITMAP_PAGE)
crc= MARIA_NO_CRC_BITMAP_PAGE - 1;
return(crc);
}
/**
@brief Maria pages read callback (checks the page CRC)
@param page The page data to check
@param page_no The page number (<offset>/<page length>)
@param data_ptr pointer to MARIA_SHARE
@param no_crc_val Value which means CRC absence
(MARIA_NO_CRC_NORMAL_PAGE or MARIA_NO_CRC_BITMAP_PAGE)
@param data_length length of data to calculate CRC
@retval 0 OK
@retval 1 Error
*/
static my_bool maria_page_crc_check(uchar *page,
pgcache_page_no_t page_no,
MARIA_SHARE *share,
uint32 no_crc_val,
int data_length)
{
uint32 crc= uint4korr(page + share->block_size - CRC_SIZE), new_crc;
my_bool res;
DBUG_ENTER("maria_page_crc_check");
DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE);
/* we need this assert to get following comparison working */
compile_time_assert(MARIA_NO_CRC_BITMAP_PAGE ==
MARIA_NO_CRC_NORMAL_PAGE - 1 &&
MARIA_NO_CRC_NORMAL_PAGE == 0xffffffff);
/*
If crc is no_crc_val then
the page has no crc, so there is nothing to check.
*/
if (crc >= MARIA_NO_CRC_BITMAP_PAGE)
{
DBUG_PRINT("info", ("No crc: %lu crc: %lu page: %lu ",
(ulong) no_crc_val, (ulong) crc, (ulong) page_no));
if (crc != no_crc_val)
{
my_errno= HA_ERR_WRONG_CRC;
DBUG_PRINT("error", ("Wrong no CRC value"));
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
new_crc= maria_page_crc(page_no & UINT_MAX32, page, data_length);
DBUG_ASSERT(new_crc != no_crc_val);
res= test(new_crc != crc);
if (res)
{
/*
Bitmap pages may be totally zero filled in some cases.
This happens when we get a crash after the pagecache has written
out a page that is on a newly created bitmap page and we get
a crash before the bitmap page is written out.
We handle this case with the following logic:
When reading, approve of bitmap pages where all bytes are zero
(This is after all a bitmap pages where no data is reserved and
the CRC will be corrected at next write)
*/
if (no_crc_val == MARIA_NO_CRC_BITMAP_PAGE &&
crc == 0 && _ma_check_if_zero(page, data_length))
{
DBUG_PRINT("warning", ("Found bitmap page that was not initialized"));
DBUG_RETURN(0);
}
DBUG_PRINT("error", ("Page: %lu crc: %lu calculated crc: %lu",
(ulong) page_no, (ulong) crc, (ulong) new_crc));
my_errno= HA_ERR_WRONG_CRC;
}
DBUG_RETURN(res);
}
/**
@brief Maria pages write callback (sets the page CRC for data and index
files)
@param page The page data to set
@param page_no The page number (<offset>/<page length>)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
*/
my_bool maria_page_crc_set_normal(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr)
{
MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
int data_length= share->block_size - CRC_SIZE;
uint32 crc= maria_page_crc(page_no & UINT_MAX32, page, data_length);
DBUG_ENTER("maria_page_crc_set_normal");
DBUG_PRINT("info", ("Page %lu crc: %lu", (ulong) page_no, (ulong)crc));
/* crc is on the stack so it is aligned, pagecache buffer is aligned, too */
int4store_aligned(page + data_length, crc);
DBUG_RETURN(0);
}
/**
@brief Maria pages write callback (sets the page CRC for keys)
@param page The page data to set
@param page_no The page number (<offset>/<page length>)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
*/
my_bool maria_page_crc_set_index(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr)
{
MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
int data_length= _ma_get_page_used(share, page);
uint32 crc= maria_page_crc(page_no & UINT_MAX32, page, data_length);
DBUG_ENTER("maria_page_crc_set");
DBUG_PRINT("info", ("Page %lu crc: %lu",
(ulong) page_no, (ulong) crc));
DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE);
/* crc is on the stack so it is aligned, pagecache buffer is aligned, too */
int4store_aligned(page + share->block_size - CRC_SIZE, crc);
DBUG_RETURN(0);
}
/* interface functions */
/**
@brief Maria pages read callback (checks the page CRC) for index/data pages
@param page The page data to check
@param page_no The page number (<offset>/<page length>)
@param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
@retval 1 Error
*/
my_bool maria_page_crc_check_data(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr)
{
MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
return (maria_page_crc_check(page, page_no & UINT_MAX32, share,
MARIA_NO_CRC_NORMAL_PAGE,
share->block_size - CRC_SIZE));
}
/**
@brief Maria pages read callback (checks the page CRC) for bitmap pages
@param page The page data to check
@param page_no The page number (<offset>/<page length>)
@param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
@retval 1 Error
*/
my_bool maria_page_crc_check_bitmap(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr)
{
MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
return (maria_page_crc_check(page, page_no & UINT_MAX32, share,
MARIA_NO_CRC_BITMAP_PAGE,
share->block_size - CRC_SIZE));
}
/**
@brief Maria pages read callback (checks the page CRC) for index pages
@param page The page data to check
@param page_no The page number (<offset>/<page length>)
@param data_ptr Read callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
@retval 1 Error
*/
my_bool maria_page_crc_check_index(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr)
{
MARIA_SHARE *share= (MARIA_SHARE *)data_ptr;
uint length= _ma_get_page_used(share, page);
if (length > share->block_size - CRC_SIZE)
{
DBUG_PRINT("error", ("Wrong page length: %u", length));
return (my_errno= HA_ERR_WRONG_CRC);
}
return maria_page_crc_check(page, page_no & UINT_MAX32, share,
MARIA_NO_CRC_NORMAL_PAGE,
length);
}
/**
@brief Maria pages dumme read callback for temporary tables
@retval 0 OK
@retval 1 Error
*/
my_bool maria_page_crc_check_none(uchar *page __attribute__((unused)),
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr __attribute__((unused)))
{
return 0;
}
/**
@brief Maria pages write callback (sets the page filler for index/data)
@param page The page data to set
@param page_no The page number (<offset>/<page length>)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
*/
my_bool maria_page_filler_set_normal(uchar *page,
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr)
{
DBUG_ENTER("maria_page_filler_set_normal");
DBUG_ASSERT(page_no != 0); /* Catches some simple bugs */
int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE,
MARIA_NO_CRC_NORMAL_PAGE);
DBUG_RETURN(0);
}
/**
@brief Maria pages write callback (sets the page filler for bitmap)
@param page The page data to set
@param page_no The page number (<offset>/<page length>)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
*/
my_bool maria_page_filler_set_bitmap(uchar *page,
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr)
{
DBUG_ENTER("maria_page_filler_set_bitmap");
int4store_aligned(page + ((MARIA_SHARE *)data_ptr)->block_size - CRC_SIZE,
MARIA_NO_CRC_BITMAP_PAGE);
DBUG_RETURN(0);
}
/**
@brief Maria pages dummy write callback for temporary tables
@retval 0 OK
*/
my_bool maria_page_filler_set_none(uchar *page __attribute__((unused)),
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr __attribute__((unused)))
{
return 0;
}
/**
@brief Write failure callback (mark table as corrupted)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
*/
void maria_page_write_failure(uchar* data_ptr)
{
maria_mark_crashed_share((MARIA_SHARE *)data_ptr);
}
/**
@brief Maria flush log log if needed
@param page The page data to set
@param page_no The page number (<offset>/<page length>)
@param data_ptr Write callback data pointer (pointer to MARIA_SHARE)
@retval 0 OK
@retval 1 error
*/
my_bool maria_flush_log_for_page(uchar *page,
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr)
{
LSN lsn;
const MARIA_SHARE *share= (MARIA_SHARE*) data_ptr;
DBUG_ENTER("maria_flush_log_for_page");
/* share is 0 here only in unittest */
DBUG_ASSERT(!share || (share->page_type == PAGECACHE_LSN_PAGE &&
share->now_transactional));
lsn= lsn_korr(page);
if (translog_flush(lsn))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
my_bool maria_flush_log_for_page_none(uchar *page __attribute__((unused)),
pgcache_page_no_t page_no
__attribute__((unused)),
uchar *data_ptr __attribute__((unused)))
{
return 0;
}