Commit 6b3743f0 authored by unknown's avatar unknown

Fixes for redo/undo logging of key pages

New extendable format for maria_log_control file
Fixed some compiler warnings


include/maria.h:
  Added maria_disable_logging() and maria_enable_logging()
mysql-test/include/maria_verify_recovery.inc:
  Updated tests now when key redo/undo works
mysql-test/r/maria-recovery.result:
  Updated tests now when key redo/undo works
storage/maria/ma_blockrec.c:
  Use unified CLR code
  Added rec_lsn for full pages
  Moved clr write hook to ma_key_recover.c
  Changed REDO code to keep pages pinned until undo
  Mark page_link's as changed
storage/maria/ma_blockrec.h:
  Moved write_hook_for_clr_end() to ma_key_recover.c
storage/maria/ma_check.c:
  Changed key check code to use PAGECACHE_READ_UNKNOWN_PAGE
  Fixed wrong warning when checking files after maria_pack
  When unpacking files, we have to use new keypos_to_recpos method
  When doing repair, we can disregard index key file pages in page cache
storage/maria/ma_commit.c:
  Added simple enable/disable logging functions
  (Needed for recovery)
storage/maria/ma_control_file.c:
  Make maria control file extendable without having to make it incompatible for older versions
storage/maria/ma_control_file.h:
  New error messages
  Added CONTROL_FILE_VERSION
storage/maria/ma_delete.c:
  Added redo/undo for key pages
  change_length -> changed_length to make things similar
  More comments & more DBUG
storage/maria/ma_key_recover.c:
  Unified CLR method
  Moved here write_hook_for_clr_end() and common keypage log functions
  Changed REDO to keep pages pinned until undo
  Changed UNDO code to change key_root under log mutex
storage/maria/ma_key_recover.h:
  New structures and functions
storage/maria/ma_loghandler.c:
  Include needed files
storage/maria/ma_open.c:
  Change maria_open() to use pread() instead of read()
storage/maria/ma_page.c:
  Fixed bug in key_del handling
  Clear pages if IDENTICAL_PAGES_AFTER_RECOVERY is defined
storage/maria/ma_pagecache.c:
  Indentation and spelling fixes
  More DBUG
  Added helper function: pagecache_block_link_to_buffer()
storage/maria/ma_pagecache.h:
  Added pagecache_block_link_to_buffer()
storage/maria/ma_recovery.c:
  Fixed state.changed
  Fixed that REDO keeps pages pinned until UNDO
  Some bug fixes from previous commit
  Fixes for UNDO/REDO of key pages
storage/maria/ma_search.c:
  Fixed packing and storing of keys to provide more information to caller so
  that we can do efficent REDO logging of the changes.
storage/maria/ma_test1.c:
  Fixed bug with not initialized variable
storage/maria/ma_test2.c:
  Removed not used code
storage/maria/ma_test_all.res:
  Updated results
storage/maria/ma_test_all.sh:
  Changed one test to test more
  Removed timing tests as not relevant here
storage/maria/ma_test_recovery.expected:
  Updated test result after redo/undo if key pages works
storage/maria/ma_test_recovery:
  Updated test after redo/undo if key pages works
storage/maria/ma_write.c:
  Moved some general log functions to ma_key_recover.c
  Fixed some bugs in undo
  Moved ma_log_split() to _ma_split_page()
  Small changes in some function arguments to be able to do redo logging
storage/maria/maria_chk.c:
  disable logging while doing repair table
storage/maria/maria_def.h:
  New function prototypes
  Move some structs and functions to ma_key_recover.c
storage/maria/unittest/ma_control_file-t.c:
  Updated with patch from Sanja
  NOTE: This is not complete and need to be updated to new control file format
storage/maria/unittest/ma_test_loghandler-t.c:
  Fixed compiler warning
parent 422375fc
...@@ -306,6 +306,8 @@ extern int maria_delete_all_rows(MARIA_HA *info); ...@@ -306,6 +306,8 @@ extern int maria_delete_all_rows(MARIA_HA *info);
extern uint maria_get_pointer_length(ulonglong file_length, uint def); extern uint maria_get_pointer_length(ulonglong file_length, uint def);
extern int maria_commit(MARIA_HA *info); extern int maria_commit(MARIA_HA *info);
extern int maria_begin(MARIA_HA *info); extern int maria_begin(MARIA_HA *info);
extern void maria_disable_logging(MARIA_HA *info);
extern void maria_enable_logging(MARIA_HA *info);
/* this is used to pass to mysql_mariachk_table */ /* this is used to pass to mysql_mariachk_table */
......
...@@ -77,16 +77,15 @@ let $mms_purpose=comparison; ...@@ -77,16 +77,15 @@ let $mms_purpose=comparison;
let $mms_compare_physically=$mms_compare_physically_save; let $mms_compare_physically=$mms_compare_physically_save;
while ($mms_table_to_use) while ($mms_table_to_use)
{ {
# Todo: remove this REPAIR when we have index recovery working. eval check table t$mms_table_to_use extended;
# It is a quick repair, so that it will fail if data file is corrupted.
--echo * rebuilding index (until we have recovery of index)
eval repair table t$mms_table_to_use quick;
--echo * testing that checksum after recovery is as expected --echo * testing that checksum after recovery is as expected
let $new_checksum=`CHECKSUM TABLE t$mms_table_to_use`; let $new_checksum=`CHECKSUM TABLE t$mms_table_to_use`;
let $old_checksum=`CHECKSUM TABLE mysqltest_for_$mms_purpose.t$mms_table_to_use`; let $old_checksum=`CHECKSUM TABLE mysqltest_for_$mms_purpose.t$mms_table_to_use`;
# the $ text variables above are of the form "db.tablename\tchecksum", # the $ text variables above are of the form "db.tablename\tchecksum",
# as db differs, we use substring(). # as db differs, we use substring().
eval select if(substring("$new_checksum",instr("$new_checksum",".t1")) = substring("$old_checksum",instr("$old_checksum",".t1")),"ok","failure"); --disable_query_log
eval select if(substring("$new_checksum",instr("$new_checksum",".t1")) = substring("$old_checksum",instr("$old_checksum",".t1")),"ok","failure") as "Checksum-check";
--enable_query_log
# this script may compare physically or do nothing # this script may compare physically or do nothing
-- source include/maria_make_snapshot.inc -- source include/maria_make_snapshot.inc
dec $mms_table_to_use; dec $mms_table_to_use;
......
...@@ -15,13 +15,11 @@ set global maria_checkpoint_interval=1; ...@@ -15,13 +15,11 @@ set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* copied t1 back for feeding_recovery * copied t1 back for feeding_recovery
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 488070860",instr("mysqltest.t1 488070860",".t1")) = substring("mysqltest_for_comparison.t1 488070860",instr("mysqltest_for_comparison.t1 488070860",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 488070860",instr("mysqltest.t1 488070860",".t1")) = substring("mysqltest_for_comparison.t1 488070860",instr("mysqltest_for_comparison.t1 488070860",".t1")),"ok","failure")
ok ok
* compared t1 to old version * compared t1 to old version
use mysqltest; use mysqltest;
...@@ -39,13 +37,11 @@ SET SESSION debug="+d,maria_crash"; ...@@ -39,13 +37,11 @@ SET SESSION debug="+d,maria_crash";
set global maria_checkpoint_interval=1; set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 976141720",instr("mysqltest.t1 976141720",".t1")) = substring("mysqltest_for_comparison.t1 976141720",instr("mysqltest_for_comparison.t1 976141720",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 976141720",instr("mysqltest.t1 976141720",".t1")) = substring("mysqltest_for_comparison.t1 976141720",instr("mysqltest_for_comparison.t1 976141720",".t1")),"ok","failure")
ok ok
use mysqltest; use mysqltest;
select * from t1; select * from t1;
...@@ -62,13 +58,11 @@ SET SESSION debug="+d,maria_flush_whole_page_cache,maria_crash"; ...@@ -62,13 +58,11 @@ SET SESSION debug="+d,maria_flush_whole_page_cache,maria_crash";
set global maria_checkpoint_interval=1; set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 1464212580",instr("mysqltest.t1 1464212580",".t1")) = substring("mysqltest_for_comparison.t1 1464212580",instr("mysqltest_for_comparison.t1 1464212580",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 1464212580",instr("mysqltest.t1 1464212580",".t1")) = substring("mysqltest_for_comparison.t1 1464212580",instr("mysqltest_for_comparison.t1 1464212580",".t1")),"ok","failure")
ok ok
use mysqltest; use mysqltest;
select * from t1; select * from t1;
...@@ -86,13 +80,11 @@ SET SESSION debug="+d,maria_flush_states,maria_flush_whole_log,maria_crash"; ...@@ -86,13 +80,11 @@ SET SESSION debug="+d,maria_flush_states,maria_flush_whole_log,maria_crash";
set global maria_checkpoint_interval=1; set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 1952283440",instr("mysqltest.t1 1952283440",".t1")) = substring("mysqltest_for_comparison.t1 1952283440",instr("mysqltest_for_comparison.t1 1952283440",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 1952283440",instr("mysqltest.t1 1952283440",".t1")) = substring("mysqltest_for_comparison.t1 1952283440",instr("mysqltest_for_comparison.t1 1952283440",".t1")),"ok","failure")
ok ok
use mysqltest; use mysqltest;
select * from t1; select * from t1;
...@@ -111,13 +103,11 @@ SET SESSION debug="+d,maria_flush_whole_log,maria_crash"; ...@@ -111,13 +103,11 @@ SET SESSION debug="+d,maria_flush_whole_log,maria_crash";
set global maria_checkpoint_interval=1; set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 2440354300",instr("mysqltest.t1 2440354300",".t1")) = substring("mysqltest_for_comparison.t1 2440354300",instr("mysqltest_for_comparison.t1 2440354300",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 2440354300",instr("mysqltest.t1 2440354300",".t1")) = substring("mysqltest_for_comparison.t1 2440354300",instr("mysqltest_for_comparison.t1 2440354300",".t1")),"ok","failure")
ok ok
use mysqltest; use mysqltest;
select * from t1; select * from t1;
...@@ -149,13 +139,11 @@ set global maria_checkpoint_interval=1; ...@@ -149,13 +139,11 @@ set global maria_checkpoint_interval=1;
ERROR HY000: Lost connection to MySQL server during query ERROR HY000: Lost connection to MySQL server during query
* copied t1 back for feeding_recovery * copied t1 back for feeding_recovery
* recovery happens * recovery happens
* rebuilding index (until we have recovery of index) check table t1 extended;
repair table t1 quick;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
mysqltest.t1 repair status OK mysqltest.t1 check status OK
* testing that checksum after recovery is as expected * testing that checksum after recovery is as expected
select if(substring("mysqltest.t1 3472399915",instr("mysqltest.t1 3472399915",".t1")) = substring("mysqltest_for_comparison.t1 3472399915",instr("mysqltest_for_comparison.t1 3472399915",".t1")),"ok","failure"); Checksum-check
if(substring("mysqltest.t1 3472399915",instr("mysqltest.t1 3472399915",".t1")) = substring("mysqltest_for_comparison.t1 3472399915",instr("mysqltest_for_comparison.t1 3472399915",".t1")),"ok","failure")
ok ok
use mysqltest; use mysqltest;
SELECT LENGTH(b) FROM t1 WHERE i=3; SELECT LENGTH(b) FROM t1 WHERE i=3;
......
This diff is collapsed.
...@@ -235,9 +235,6 @@ my_bool write_hook_for_undo_row_delete(enum translog_record_type type, ...@@ -235,9 +235,6 @@ my_bool write_hook_for_undo_row_delete(enum translog_record_type type,
my_bool write_hook_for_undo_row_update(enum translog_record_type type, my_bool write_hook_for_undo_row_update(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, TRN *trn, MARIA_HA *tbl_info,
LSN *lsn, void *hook_arg); LSN *lsn, void *hook_arg);
my_bool write_hook_for_clr_end(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
void *hook_arg);
my_bool write_hook_for_file_id(enum translog_record_type type, my_bool write_hook_for_file_id(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, LSN *lsn, TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
void *hook_arg); void *hook_arg);
...@@ -305,7 +305,7 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info, ...@@ -305,7 +305,7 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info,
&info->s->kfile, next_link/block_size, &info->s->kfile, next_link/block_size,
DFLT_INIT_HITS, DFLT_INIT_HITS,
(uchar*) info->buff, (uchar*) info->buff,
PAGECACHE_PLAIN_PAGE, PAGECACHE_READ_UNKNOWN_PAGE,
PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) PAGECACHE_LOCK_LEFT_UNLOCKED, 0)))
{ {
/* purecov: begin tested */ /* purecov: begin tested */
...@@ -595,7 +595,7 @@ do_stat: ...@@ -595,7 +595,7 @@ do_stat:
puts(""); puts("");
} }
if (param->key_file_blocks != info->state->key_file_length && if (param->key_file_blocks != info->state->key_file_length &&
param->keys_in_use != ~(ulonglong) 0) share->state.key_map == ~(ulonglong) 0)
_ma_check_print_warning(param, "Some data are unreferenced in keyfile"); _ma_check_print_warning(param, "Some data are unreferenced in keyfile");
if (found_keys != full_text_keys) if (found_keys != full_text_keys)
param->record_checksum=old_record_checksum-init_checksum; /* Remove delete links */ param->record_checksum=old_record_checksum-init_checksum; /* Remove delete links */
...@@ -2123,8 +2123,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, ...@@ -2123,8 +2123,7 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
info->s->state.dellink= HA_OFFSET_ERROR; info->s->state.dellink= HA_OFFSET_ERROR;
info->rec_cache.file= new_file; info->rec_cache.file= new_file;
if (share->data_file_type == BLOCK_RECORD || if (share->data_file_type == BLOCK_RECORD ||
((param->testflag & T_UNPACK) && (param->testflag & T_UNPACK))
share->state.header.org_data_file_type == BLOCK_RECORD))
{ {
MARIA_HA *new_info; MARIA_HA *new_info;
/* /*
...@@ -2152,6 +2151,10 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, ...@@ -2152,6 +2151,10 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
if (_ma_initialize_data_file(sort_info.new_info->s, new_file)) if (_ma_initialize_data_file(sort_info.new_info->s, new_file))
goto err; goto err;
block_record= 1; block_record= 1;
/* Use new virtual functions for key generation */
info->s->keypos_to_recpos= new_info->s->keypos_to_recpos;
info->s->recpos_to_keypos= new_info->s->recpos_to_keypos;
} }
} }
...@@ -2901,8 +2904,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, ...@@ -2901,8 +2904,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|=T_CALC_CHECKSUM; param->testflag|=T_CALC_CHECKSUM;
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA, FLUSH_FORCE_WRITE, if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_KEEP)) FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED))
goto err; goto err;
if (!(sort_info.key_block= if (!(sort_info.key_block=
...@@ -3328,8 +3331,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, ...@@ -3328,8 +3331,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|=T_CALC_CHECKSUM; param->testflag|=T_CALC_CHECKSUM;
if (_ma_flush_table_files(info, MARIA_FLUSH_DATA, FLUSH_FORCE_WRITE, if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_KEEP)) FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED))
goto err; goto err;
/* /*
...@@ -5502,12 +5505,19 @@ set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share) ...@@ -5502,12 +5505,19 @@ set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share)
static void restore_data_file_type(MARIA_SHARE *share) static void restore_data_file_type(MARIA_SHARE *share)
{ {
MARIA_SHARE tmp_share;
share->options&= ~HA_OPTION_COMPRESS_RECORD; share->options&= ~HA_OPTION_COMPRESS_RECORD;
mi_int2store(share->state.header.options,share->options); mi_int2store(share->state.header.options,share->options);
share->state.header.data_file_type= share->state.header.data_file_type=
share->state.header.org_data_file_type; share->state.header.org_data_file_type;
share->data_file_type= share->state.header.data_file_type; share->data_file_type= share->state.header.data_file_type;
share->pack.header_length= 0; share->pack.header_length= 0;
/* Use new virtual functions for key generation */
tmp_share= *share;
_ma_setup_functions(&tmp_share);
share->keypos_to_recpos= tmp_share.keypos_to_recpos;
share->recpos_to_keypos= tmp_share.recpos_to_keypos;
} }
......
...@@ -122,3 +122,26 @@ int maria_begin(MARIA_HA *info) ...@@ -122,3 +122,26 @@ int maria_begin(MARIA_HA *info)
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
@brief Disable logging for this table
@note
Mainly used during repair table, where we don't want to log all
changes to index or rows
*/
void maria_disable_logging(MARIA_HA *info)
{
info->s->now_transactional= 0;
info->trn= &dummy_transaction_object;
info->s->page_type= PAGECACHE_PLAIN_PAGE;
}
void maria_enable_logging(MARIA_HA *info)
{
if ((info->s->now_transactional= info->s->base.born_transactional))
info->s->page_type= PAGECACHE_LSN_PAGE;
}
This diff is collapsed.
...@@ -22,6 +22,12 @@ ...@@ -22,6 +22,12 @@
#define _ma_control_file_h #define _ma_control_file_h
#define CONTROL_FILE_BASE_NAME "maria_log_control" #define CONTROL_FILE_BASE_NAME "maria_log_control"
/*
Major version for control file. Should only be changed when doing
big changes that made the new control file incompatible with all
older versions of Maria.
*/
#define CONTROL_FILE_VERSION 1
/* Here is the interface of this module */ /* Here is the interface of this module */
...@@ -43,8 +49,12 @@ typedef enum enum_control_file_error { ...@@ -43,8 +49,12 @@ typedef enum enum_control_file_error {
CONTROL_FILE_TOO_SMALL, CONTROL_FILE_TOO_SMALL,
CONTROL_FILE_TOO_BIG, CONTROL_FILE_TOO_BIG,
CONTROL_FILE_BAD_MAGIC_STRING, CONTROL_FILE_BAD_MAGIC_STRING,
CONTROL_FILE_BAD_VERSION,
CONTROL_FILE_BAD_CHECKSUM, CONTROL_FILE_BAD_CHECKSUM,
CONTROL_FILE_BAD_HEAD_CHECKSUM,
CONTROL_FILE_MISSING, CONTROL_FILE_MISSING,
CONTROL_FILE_INCONSISTENT_INFORMATION,
CONTROL_FILE_WRONG_BLOCKSIZE,
CONTROL_FILE_UNKNOWN_ERROR /* any other error */ CONTROL_FILE_UNKNOWN_ERROR /* any other error */
} CONTROL_FILE_ERROR; } CONTROL_FILE_ERROR;
......
This diff is collapsed.
This diff is collapsed.
...@@ -21,14 +21,48 @@ ...@@ -21,14 +21,48 @@
called). called).
*/ */
/* Struct for clr_end */
struct st_msg_to_write_hook_for_clr_end
{
LSN previous_undo_lsn;
enum translog_record_type undone_record_type;
ha_checksum checksum_delta;
void *extra_msg;
};
struct st_msg_to_write_hook_for_undo_key
{
my_off_t *root;
my_off_t value;
};
/* Function definitions for some redo functions */ /* Function definitions for some redo functions */
my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn,
enum translog_record_type undo_type, enum translog_record_type undo_type,
my_bool store_checksum, ha_checksum checksum, my_bool store_checksum, ha_checksum checksum,
LSN *res_lsn); LSN *res_lsn, void *extra_msg);
my_bool write_hook_for_clr_end(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
void *hook_arg);
extern my_bool write_hook_for_undo_key(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info,
LSN *lsn, void *hook_arg);
void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn); void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn);
my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
uchar *buff, uint changed_length,
int move_length);
my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
uchar *buff, uint org_length,
uint new_length);
my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
uint buff_length, uchar *key_pos,
uint changed_length, int move_length,
my_bool handle_overflow);
uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn,
const uchar *header, uint length); const uchar *header, uint length);
uint _ma_apply_redo_index_free_page(MARIA_HA *info, LSN lsn, uint _ma_apply_redo_index_free_page(MARIA_HA *info, LSN lsn,
......
...@@ -14,8 +14,9 @@ ...@@ -14,8 +14,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "maria_def.h" #include "maria_def.h"
#include "ma_blockrec.h" /* for some constants and in-write hooks */
#include "trnman.h" #include "trnman.h"
#include "ma_blockrec.h" /* for some constants and in-write hooks */
#include "ma_key_recover.h" /* For some in-write hooks */
/** /**
@file @file
......
...@@ -117,7 +117,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, ...@@ -117,7 +117,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
&info.blobs,sizeof(MARIA_BLOB)*share->base.blobs, &info.blobs,sizeof(MARIA_BLOB)*share->base.blobs,
&info.buff,(share->base.max_key_block_length*2+ &info.buff,(share->base.max_key_block_length*2+
share->base.max_key_length), share->base.max_key_length),
&info.lastkey,share->base.max_key_length*3+1, &info.lastkey,share->base.max_key_length*2+1,
&info.first_mbr_key, share->base.max_key_length, &info.first_mbr_key, share->base.max_key_length,
&info.maria_rtree_recursion_state, &info.maria_rtree_recursion_state,
share->have_rtree ? 1024 : 0, share->have_rtree ? 1024 : 0,
...@@ -304,8 +304,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -304,8 +304,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
} }
share->mode=open_mode; share->mode=open_mode;
errpos= 1; errpos= 1;
if (my_read(kfile,share->state.header.file_version, head_length, if (my_pread(kfile,share->state.header.file_version, head_length, 0,
MYF(MY_NABP))) MYF(MY_NABP)))
{ {
my_errno= HA_ERR_NOT_A_TABLE; my_errno= HA_ERR_NOT_A_TABLE;
goto err; goto err;
...@@ -355,11 +355,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -355,11 +355,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
goto err; goto err;
} }
end_pos=disk_cache+info_length; end_pos=disk_cache+info_length;
errpos= 2;
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
errpos= 3; errpos= 3;
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) if (my_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP)))
{ {
my_errno=HA_ERR_CRASHED; my_errno=HA_ERR_CRASHED;
goto err; goto err;
...@@ -418,8 +415,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -418,8 +415,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
goto err; goto err;
} }
/* /*
If page cache is not initialized, then assume we will create it If page cache is not initialized, then assume we will create the
after the table is opened! page_cache after the table is opened!
This is only used by maria_check to allow it to check/repair tables
with different block sizes.
*/ */
if (share->base.block_size != maria_block_size && if (share->base.block_size != maria_block_size &&
share_buff.pagecache->inited != 0) share_buff.pagecache->inited != 0)
...@@ -1226,7 +1225,6 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) ...@@ -1226,7 +1225,6 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state)
@param file file to read from @param file file to read from
@param state state which will be filled @param state state which will be filled
@param pRead if true, use my_pread(), otherwise my_read()
*/ */
uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state) uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state)
......
...@@ -122,6 +122,7 @@ int _ma_write_keypage(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ...@@ -122,6 +122,7 @@ int _ma_write_keypage(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
#ifdef IDENTICAL_PAGES_AFTER_RECOVERY #ifdef IDENTICAL_PAGES_AFTER_RECOVERY
{ {
uint length= _ma_get_page_used(info, buff); uint length= _ma_get_page_used(info, buff);
DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE);
bzero(buff + length, block_size - length); bzero(buff + length, block_size - length);
} }
#endif #endif
...@@ -186,13 +187,14 @@ int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read) ...@@ -186,13 +187,14 @@ int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read)
(void) _ma_lock_key_del(info, 0); (void) _ma_lock_key_del(info, 0);
old_link= share->state.key_del; old_link= share->current_key_del;
share->state.key_del= pos; share->current_key_del= pos;
page_no= pos / block_size; page_no= pos / block_size;
bzero(buff, share->keypage_header); bzero(buff, share->keypage_header);
_ma_store_keynr(info, buff, (uchar) MARIA_DELETE_KEY_NR); _ma_store_keynr(info, buff, (uchar) MARIA_DELETE_KEY_NR);
mi_sizestore(buff + share->keypage_header, old_link); mi_sizestore(buff + share->keypage_header, old_link);
share->state.changed|= STATE_NOT_SORTED_PAGES; share->state.changed|= STATE_NOT_SORTED_PAGES;
if (info->s->now_transactional) if (info->s->now_transactional)
{ {
LSN lsn; LSN lsn;
...@@ -239,6 +241,14 @@ int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read) ...@@ -239,6 +241,14 @@ int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read)
0, share->keypage_header+8, 0, 0)) 0, share->keypage_header+8, 0, 0))
result= 1; result= 1;
#ifdef IDENTICAL_PAGES_AFTER_RECOVERY
{
uchar *page_buff= pagecache_block_link_to_buffer(page_link.link);
bzero(page_buff + share->keypage_header + 8,
block_size - share->keypage_header - 8 - KEYPAGE_CHECKSUM_SIZE);
}
#endif
if (page_not_read) if (page_not_read)
{ {
/* It was not locked before, we have to unlock it when we unpin pages */ /* It was not locked before, we have to unlock it when we unpin pages */
...@@ -295,7 +305,7 @@ my_off_t _ma_new(register MARIA_HA *info, int level, ...@@ -295,7 +305,7 @@ my_off_t _ma_new(register MARIA_HA *info, int level,
TODO: replace PAGECACHE_PLAIN_PAGE with PAGECACHE_LSN_PAGE when TODO: replace PAGECACHE_PLAIN_PAGE with PAGECACHE_LSN_PAGE when
LSN on the pages will be implemented LSN on the pages will be implemented
*/ */
pos= info->s->state.key_del; /* Protected */ pos= share->current_key_del; /* Protected */
DBUG_ASSERT(share->pagecache->block_size == block_size); DBUG_ASSERT(share->pagecache->block_size == block_size);
if (!(buff= pagecache_read(share->pagecache, if (!(buff= pagecache_read(share->pagecache,
&share->kfile, pos / block_size, level, &share->kfile, pos / block_size, level,
...@@ -312,7 +322,7 @@ my_off_t _ma_new(register MARIA_HA *info, int level, ...@@ -312,7 +322,7 @@ my_off_t _ma_new(register MARIA_HA *info, int level,
(*page_link)->unlock= PAGECACHE_LOCK_WRITE_UNLOCK; (*page_link)->unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
(*page_link)->write_lock= PAGECACHE_LOCK_WRITE; (*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
(*page_link)->changed= 0; (*page_link)->changed= 0;
push_dynamic(&info->pinned_pages, (void*) &page_link); push_dynamic(&info->pinned_pages, (void*) *page_link);
*page_link= dynamic_element(&info->pinned_pages, *page_link= dynamic_element(&info->pinned_pages,
info->pinned_pages.elements-1, info->pinned_pages.elements-1,
MARIA_PINNED_PAGE *); MARIA_PINNED_PAGE *);
......
...@@ -405,8 +405,7 @@ static my_bool info_check_lock(PAGECACHE_BLOCK_LINK *block, ...@@ -405,8 +405,7 @@ static my_bool info_check_lock(PAGECACHE_BLOCK_LINK *block,
(PAGECACHE_LOCK_INFO *) info_find((PAGECACHE_PIN_INFO *) block->lock_list, (PAGECACHE_LOCK_INFO *) info_find((PAGECACHE_PIN_INFO *) block->lock_list,
thread); thread);
DBUG_ENTER("info_check_lock"); DBUG_ENTER("info_check_lock");
switch(lock) switch(lock) {
{
case PAGECACHE_LOCK_LEFT_UNLOCKED: case PAGECACHE_LOCK_LEFT_UNLOCKED:
if (pin != PAGECACHE_PIN_LEFT_UNPINNED || if (pin != PAGECACHE_PIN_LEFT_UNPINNED ||
info) info)
...@@ -1199,7 +1198,7 @@ static inline void link_to_changed_list(PAGECACHE *pagecache, ...@@ -1199,7 +1198,7 @@ static inline void link_to_changed_list(PAGECACHE *pagecache,
none none
NOTES. NOTES.
The LRU chain is represented by a curcular list of block structures. The LRU chain is represented by a circular list of block structures.
The list is double-linked of the type (**prev,*next) type. The list is double-linked of the type (**prev,*next) type.
The LRU chain is divided into two parts - hot and warm. The LRU chain is divided into two parts - hot and warm.
There are two pointers to access the last blocks of these two There are two pointers to access the last blocks of these two
...@@ -1268,7 +1267,7 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, ...@@ -1268,7 +1267,7 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
} }
#else /* THREAD */ #else /* THREAD */
KEYCACHE_DBUG_ASSERT(! (!hot && pagecache->waiting_for_block.last_thread)); KEYCACHE_DBUG_ASSERT(! (!hot && pagecache->waiting_for_block.last_thread));
/* Condition not transformed using DeMorgan, to keep the text identical */ /* Condition not transformed using DeMorgan, to keep the text identical */
#endif /* THREAD */ #endif /* THREAD */
ptr_ins= hot ? &pagecache->used_ins : &pagecache->used_last; ptr_ins= hot ? &pagecache->used_ins : &pagecache->used_last;
ins= *ptr_ins; ins= *ptr_ins;
...@@ -2730,10 +2729,10 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -2730,10 +2729,10 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
LSN lsn, my_bool was_changed) LSN lsn, my_bool was_changed)
{ {
DBUG_ENTER("pagecache_unlock_by_link"); DBUG_ENTER("pagecache_unlock_by_link");
DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu %s %s", DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s",
(ulong) block, (ulong) block,
(uint) block->hash_link->file.file, (uint) block->hash_link->file.file,
(ulong) block->hash_link->pageno, (ulong) block->hash_link->pageno, was_changed,
page_cache_page_lock_str[lock], page_cache_page_lock_str[lock],
page_cache_page_pin_str[pin])); page_cache_page_pin_str[pin]));
/* /*
...@@ -2799,7 +2798,6 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -2799,7 +2798,6 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
(ulong) block)); (ulong) block));
} }
pagecache_set_block_rec_lsn(block, first_REDO_LSN_for_page);
if (make_lock_and_pin(pagecache, block, lock, pin, 0)) if (make_lock_and_pin(pagecache, block, lock, pin, 0))
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
...@@ -4246,6 +4244,11 @@ static void test_key_cache(PAGECACHE *pagecache __attribute__((unused)), ...@@ -4246,6 +4244,11 @@ static void test_key_cache(PAGECACHE *pagecache __attribute__((unused)),
} }
#endif #endif
uchar *pagecache_block_link_to_buffer(PAGECACHE_BLOCK_LINK *block)
{
return block->buffer;
}
#if defined(PAGECACHE_TIMEOUT) #if defined(PAGECACHE_TIMEOUT)
#define KEYCACHE_DUMP_FILE "pagecache_dump.txt" #define KEYCACHE_DUMP_FILE "pagecache_dump.txt"
......
...@@ -269,6 +269,7 @@ extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, ...@@ -269,6 +269,7 @@ extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache,
LEX_STRING *str, LEX_STRING *str,
LSN *min_lsn); LSN *min_lsn);
extern int reset_pagecache_counters(const char *name, PAGECACHE *pagecache); extern int reset_pagecache_counters(const char *name, PAGECACHE *pagecache);
extern uchar *pagecache_block_link_to_buffer(PAGECACHE_BLOCK_LINK *block);
/* Functions to handle multiple key caches */ /* Functions to handle multiple key caches */
......
...@@ -1529,7 +1529,8 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE) ...@@ -1529,7 +1529,8 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE)
} }
share->state.state.checksum+= ha_checksum_korr(buff); share->state.state.checksum+= ha_checksum_korr(buff);
} }
share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED; share->state.changed|= (STATE_CHANGED | STATE_NOT_ANALYZED |
STATE_NOT_OPTIMIZED_ROWS);
} }
tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records);
_ma_unpin_all_pages(info, rec->lsn); _ma_unpin_all_pages(info, rec->lsn);
...@@ -1569,6 +1570,9 @@ prototype_redo_exec_hook(UNDO_ROW_UPDATE) ...@@ -1569,6 +1570,9 @@ prototype_redo_exec_hook(UNDO_ROW_UPDATE)
prototype_redo_exec_hook(UNDO_KEY_INSERT) prototype_redo_exec_hook(UNDO_KEY_INSERT)
{ {
MARIA_HA *info;
if (!(info= get_MARIA_HA_from_UNDO_record(rec)))
return 0;
set_undo_lsn_for_active_trans(rec->short_trid, rec->lsn); set_undo_lsn_for_active_trans(rec->short_trid, rec->lsn);
_ma_unpin_all_pages(info, rec->lsn); _ma_unpin_all_pages(info, rec->lsn);
return 0; return 0;
...@@ -1577,6 +1581,9 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT) ...@@ -1577,6 +1581,9 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT)
prototype_redo_exec_hook(UNDO_KEY_DELETE) prototype_redo_exec_hook(UNDO_KEY_DELETE)
{ {
MARIA_HA *info;
if (!(info= get_MARIA_HA_from_UNDO_record(rec)))
return 0;
set_undo_lsn_for_active_trans(rec->short_trid, rec->lsn); set_undo_lsn_for_active_trans(rec->short_trid, rec->lsn);
_ma_unpin_all_pages(info, rec->lsn); _ma_unpin_all_pages(info, rec->lsn);
return 0; return 0;
...@@ -1595,9 +1602,9 @@ prototype_redo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT) ...@@ -1595,9 +1602,9 @@ prototype_redo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT)
{ {
uint key_nr; uint key_nr;
my_off_t page; my_off_t page;
page= page_korr(rec->header + LSN_STORE_SIZE + FILEID_STORE_SIZE); key_nr= key_nr_korr(rec->header + LSN_STORE_SIZE + FILEID_STORE_SIZE);
key_nr= key_nr_korr(rec->header + LSN_STORE_SIZE + FILEID_STORE_SIZE + page= page_korr(rec->header + LSN_STORE_SIZE + FILEID_STORE_SIZE +
PAGE_STORE_SIZE); KEY_NR_STORE_SIZE);
share->state.key_root[key_nr]= (page == IMPOSSIBLE_PAGE_NO ? share->state.key_root[key_nr]= (page == IMPOSSIBLE_PAGE_NO ?
HA_OFFSET_ERROR : HA_OFFSET_ERROR :
page * share->block_size); page * share->block_size);
...@@ -1653,6 +1660,7 @@ prototype_redo_exec_hook(CLR_END) ...@@ -1653,6 +1660,7 @@ prototype_redo_exec_hook(CLR_END)
LSN previous_undo_lsn; LSN previous_undo_lsn;
enum translog_record_type undone_record_type; enum translog_record_type undone_record_type;
const LOG_DESC *log_desc; const LOG_DESC *log_desc;
my_bool row_entry= 0;
if (info == NULL) if (info == NULL)
return 0; return 0;
...@@ -1668,33 +1676,40 @@ prototype_redo_exec_hook(CLR_END) ...@@ -1668,33 +1676,40 @@ prototype_redo_exec_hook(CLR_END)
if (cmp_translog_addr(rec->lsn, share->state.is_of_horizon) >= 0) if (cmp_translog_addr(rec->lsn, share->state.is_of_horizon) >= 0)
{ {
tprint(tracef, " state older than record, updating rows' count\n"); tprint(tracef, " state older than record, updating rows' count\n");
if (share->calc_checksum)
{
uchar buff[HA_CHECKSUM_STORE_SIZE];
if (translog_read_record(rec->lsn, LSN_STORE_SIZE + FILEID_STORE_SIZE +
CLR_TYPE_STORE_SIZE, HA_CHECKSUM_STORE_SIZE,
buff, NULL) != HA_CHECKSUM_STORE_SIZE)
{
tprint(tracef, "Failed to read record\n");
return 1;
}
share->state.state.checksum+= ha_checksum_korr(buff);
}
switch (undone_record_type) { switch (undone_record_type) {
case LOGREC_UNDO_ROW_DELETE: case LOGREC_UNDO_ROW_DELETE:
row_entry= 1;
share->state.state.records++; share->state.state.records++;
break; break;
case LOGREC_UNDO_ROW_INSERT: case LOGREC_UNDO_ROW_INSERT:
share->state.state.records--; share->state.state.records--;
row_entry= 1;
break; break;
case LOGREC_UNDO_ROW_UPDATE: case LOGREC_UNDO_ROW_UPDATE:
row_entry= 1;
break;
case LOGREC_UNDO_KEY_INSERT:
case LOGREC_UNDO_KEY_DELETE:
break; break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
if (row_entry && share->calc_checksum)
{
uchar buff[HA_CHECKSUM_STORE_SIZE];
if (translog_read_record(rec->lsn, LSN_STORE_SIZE + FILEID_STORE_SIZE +
CLR_TYPE_STORE_SIZE, HA_CHECKSUM_STORE_SIZE,
buff, NULL) != HA_CHECKSUM_STORE_SIZE)
{
tprint(tracef, "Failed to read record\n");
return 1;
}
share->state.state.checksum+= ha_checksum_korr(buff);
}
share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED; share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
} }
tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); if (row_entry)
tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records);
_ma_unpin_all_pages(info, rec->lsn); _ma_unpin_all_pages(info, rec->lsn);
return 0; return 0;
} }
...@@ -2356,19 +2371,22 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const ...@@ -2356,19 +2371,22 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const
pgcache_page_no_t page; pgcache_page_no_t page;
MARIA_HA *info; MARIA_HA *info;
char llbuf[22]; char llbuf[22];
my_bool index_page_redo_entry= 0;
print_redo_phase_progress(rec->lsn); print_redo_phase_progress(rec->lsn);
sid= fileid_korr(rec->header); sid= fileid_korr(rec->header);
page= page_korr(rec->header + FILEID_STORE_SIZE); page= page_korr(rec->header + FILEID_STORE_SIZE);
switch(rec->type) { switch (rec->type) {
/* not all REDO records have a page: */ /* not all REDO records have a page: */
case LOGREC_REDO_INDEX_NEW_PAGE:
case LOGREC_REDO_INDEX:
case LOGREC_REDO_INDEX_FREE_PAGE:
index_page_redo_entry= 1;
/* Fall trough*/
case LOGREC_REDO_INSERT_ROW_HEAD: case LOGREC_REDO_INSERT_ROW_HEAD:
case LOGREC_REDO_INSERT_ROW_TAIL: case LOGREC_REDO_INSERT_ROW_TAIL:
case LOGREC_REDO_PURGE_ROW_HEAD: case LOGREC_REDO_PURGE_ROW_HEAD:
case LOGREC_REDO_PURGE_ROW_TAIL: case LOGREC_REDO_PURGE_ROW_TAIL:
case LOGREC_REDO_INDEX_NEW_PAGE:
case LOGREC_REDO_INDEX:
case LOGREC_REDO_INDEX_FREE_PAGE:
llstr(page, llbuf); llstr(page, llbuf);
tprint(tracef, " For page %s of table of short id %u", llbuf, sid); tprint(tracef, " For page %s of table of short id %u", llbuf, sid);
break; break;
...@@ -2407,12 +2425,9 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const ...@@ -2407,12 +2425,9 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const
DBUG_ASSERT(info->s->last_version != 0); DBUG_ASSERT(info->s->last_version != 0);
if (cmp_translog_addr(rec->lsn, checkpoint_start) < 0) if (cmp_translog_addr(rec->lsn, checkpoint_start) < 0)
{ {
/**
@todo RECOVERY BUG always assuming this is REDO for data file, but it
could soon be index file
*/
uint64 file_and_page_id= uint64 file_and_page_id=
(((uint64)all_tables[sid].org_dfile) << 32) | page; (((uint64) (index_page_redo_entry ? all_tables[sid].org_kfile :
all_tables[sid].org_dfile)) << 32) | page;
struct st_dirty_page *dirty_page= (struct st_dirty_page *) struct st_dirty_page *dirty_page= (struct st_dirty_page *)
hash_search(&all_dirty_pages, hash_search(&all_dirty_pages,
(uchar *)&file_and_page_id, sizeof(file_and_page_id)); (uchar *)&file_and_page_id, sizeof(file_and_page_id));
......
...@@ -1182,7 +1182,10 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, ...@@ -1182,7 +1182,10 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* /*
@brief Get last key from key-page @brief Get last key from key-page before 'endpos'
@note
endpos may be either end of buffer or start of a key
@return @return
@retval pointer to where key starts @retval pointer to where key starts
...@@ -1506,7 +1509,7 @@ _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, ...@@ -1506,7 +1509,7 @@ _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
const uchar *key, MARIA_KEY_PARAM *s_temp) const uchar *key, MARIA_KEY_PARAM *s_temp)
{ {
s_temp->key= key; s_temp->key= key;
return (int) (s_temp->totlength=keyinfo->keylength+nod_flag); return (int) (s_temp->move_length= keyinfo->keylength + nod_flag);
} }
/* Variable length key */ /* Variable length key */
...@@ -1519,26 +1522,28 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, ...@@ -1519,26 +1522,28 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
const uchar *key, MARIA_KEY_PARAM *s_temp) const uchar *key, MARIA_KEY_PARAM *s_temp)
{ {
s_temp->key= key; s_temp->key= key;
return (int) (s_temp->totlength= _ma_keylength(keyinfo,key)+nod_flag); return (int) (s_temp->move_length= _ma_keylength(keyinfo,key)+nod_flag);
} }
/* /**
length of key with a variable length first segment which is prefix @brief Calc length needed to store prefixed compressed keys
compressed (maria_chk reports 'packed + stripped')
Keys are compressed the following way: @info
Variable length first segment which is prefix compressed
(maria_chk reports 'packed + stripped')
If the max length of first key segment <= 127 bytes the prefix is Keys are compressed the following way:
1 uchar else it's 2 byte
prefix byte(s) The high bit is set if this is a prefix for the prev key If the max length of first key segment <= 127 bytes the prefix is
length Packed length if the previous was a prefix byte 1 uchar else it's 2 byte
[length] data bytes ('length' bytes)
next-key-seg Next key segments
If the first segment can have NULL: prefix byte(s) The high bit is set if this is a prefix for the prev key
The length is 0 for NULLS and 1+length for not null columns. length Packed length if the previous was a prefix byte
[length] data bytes ('length' bytes)
next-key-seg Next key segments
If the first segment can have NULL:
The length is 0 for NULLS and 1+length for not null columns.
*/ */
int int
...@@ -1589,7 +1594,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1589,7 +1594,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->key_length= 0; s_temp->key_length= 0;
s_temp->totlength= key_length-1+diff_flag; s_temp->totlength= key_length-1+diff_flag;
s_temp->next_key_pos= 0; /* No next key */ s_temp->next_key_pos= 0; /* No next key */
return (s_temp->totlength); return (s_temp->move_length= s_temp->totlength);
} }
s_temp->store_not_null=1; s_temp->store_not_null=1;
key_length--; /* We don't store NULL */ key_length--; /* We don't store NULL */
...@@ -1744,7 +1749,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1744,7 +1749,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->n_ref_length=s_temp->n_length= org_key_length; s_temp->n_ref_length=s_temp->n_length= org_key_length;
length+= org_key_length; length+= org_key_length;
} }
return (int) length; return (s_temp->move_length= (int) length);
} }
ref_length=n_length; ref_length=n_length;
...@@ -1757,7 +1762,8 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1757,7 +1762,8 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->part_of_prev_key= 0; s_temp->part_of_prev_key= 0;
s_temp->prev_length= ref_length; s_temp->prev_length= ref_length;
s_temp->n_ref_length= s_temp->n_length= n_length+ref_length; s_temp->n_ref_length= s_temp->n_length= n_length+ref_length;
return (int) length+ref_length-next_length_pack; return s_temp->move_length= ((int) length+ref_length-
next_length_pack);
} }
if (ref_length+pack_marker > new_ref_length) if (ref_length+pack_marker > new_ref_length)
{ {
...@@ -1768,7 +1774,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1768,7 +1774,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length; s_temp->n_ref_length=s_temp->n_length=n_length + s_temp->prev_length;
s_temp->prev_key+= new_pack_length; s_temp->prev_key+= new_pack_length;
length-= (next_length_pack - get_pack_length(s_temp->n_length)); length-= (next_length_pack - get_pack_length(s_temp->n_length));
return (int) length + s_temp->prev_length; return s_temp->move_length= ((int) length + s_temp->prev_length);
} }
} }
else else
...@@ -1803,7 +1809,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1803,7 +1809,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
if (!(tmp_length=(uint) (key-start))) if (!(tmp_length=(uint) (key-start)))
{ /* Key can't be re-packed */ { /* Key can't be re-packed */
s_temp->next_key_pos=0; s_temp->next_key_pos=0;
return length; return (s_temp->move_length= length);
} }
ref_length+=tmp_length; ref_length+=tmp_length;
n_length-=tmp_length; n_length-=tmp_length;
...@@ -1821,7 +1827,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1821,7 +1827,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
} }
} }
} }
return length; return (s_temp->move_length= length);
} }
...@@ -1884,8 +1890,9 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1884,8 +1890,9 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->n_ref_length= ref_length; s_temp->n_ref_length= ref_length;
s_temp->prev_length= next_length-ref_length; s_temp->prev_length= next_length-ref_length;
s_temp->prev_key+= ref_length; s_temp->prev_key+= ref_length;
return (int) (length+ s_temp->prev_length - next_length_pack + return s_temp->move_length= ((int) (length+ s_temp->prev_length -
get_pack_length(ref_length)); next_length_pack +
get_pack_length(ref_length)));
} }
/* Check how many characters are identical to next key */ /* Check how many characters are identical to next key */
key= s_temp->key+next_length; key= s_temp->key+next_length;
...@@ -1893,14 +1900,15 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, ...@@ -1893,14 +1900,15 @@ int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
if ((ref_length= (uint) (key - s_temp->key)-1) == next_length) if ((ref_length= (uint) (key - s_temp->key)-1) == next_length)
{ {
s_temp->next_key_pos=0; s_temp->next_key_pos=0;
return length; /* can't pack next key */ return (s_temp->move_length= length); /* Can't pack next key */
} }
s_temp->prev_length=0; s_temp->prev_length=0;
s_temp->n_ref_length=ref_length; s_temp->n_ref_length=ref_length;
return (int) (length-(ref_length - next_length) - next_length_pack + return s_temp->move_length= (int) (length-(ref_length - next_length) -
get_pack_length(ref_length)); next_length_pack +
get_pack_length(ref_length));
} }
return (int) length; return (s_temp->move_length= (int) length);
} }
...@@ -1914,8 +1922,8 @@ void _ma_store_static_key(MARIA_KEYDEF *keyinfo __attribute__((unused)), ...@@ -1914,8 +1922,8 @@ void _ma_store_static_key(MARIA_KEYDEF *keyinfo __attribute__((unused)),
register uchar *key_pos, register uchar *key_pos,
register MARIA_KEY_PARAM *s_temp) register MARIA_KEY_PARAM *s_temp)
{ {
memcpy(key_pos, s_temp->key,(size_t) s_temp->totlength); memcpy(key_pos, s_temp->key,(size_t) s_temp->move_length);
s_temp->changed_length= s_temp->totlength; s_temp->changed_length= s_temp->move_length;
} }
......
...@@ -97,7 +97,7 @@ int main(int argc,char *argv[]) ...@@ -97,7 +97,7 @@ int main(int argc,char *argv[])
static int run_test(const char *filename) static int run_test(const char *filename)
{ {
MARIA_HA *file; MARIA_HA *file;
int i,j,error,deleted,rec_length,uniques=0; int i,j= 0,error,deleted,rec_length,uniques=0;
uint offset_to_key; uint offset_to_key;
ha_rows found,row_count; ha_rows found,row_count;
uchar record[MAX_REC_LENGTH],key[MAX_REC_LENGTH],read_record[MAX_REC_LENGTH]; uchar record[MAX_REC_LENGTH],key[MAX_REC_LENGTH],read_record[MAX_REC_LENGTH];
...@@ -275,7 +275,7 @@ static int run_test(const char *filename) ...@@ -275,7 +275,7 @@ static int run_test(const char *filename)
{ {
if (!silent) if (!silent)
printf("- Checking unique constraint\n"); printf("- Checking unique constraint\n");
create_record(record,j); create_record(record,j); /* Check last created row */
if (!maria_write(file,record) || my_errno != HA_ERR_FOUND_DUPP_UNIQUE) if (!maria_write(file,record) || my_errno != HA_ERR_FOUND_DUPP_UNIQUE)
{ {
printf("unique check failed\n"); printf("unique check failed\n");
......
...@@ -880,15 +880,6 @@ int main(int argc, char *argv[]) ...@@ -880,15 +880,6 @@ int main(int argc, char *argv[])
goto err; goto err;
} }
opt_delete++; opt_delete++;
#if TO_BE_REMOVED
/
/*
179 is ok, 180 causes a difference between runtime and log-applying.
This is now fixed (we zero the last directory entry during
log-applying, just to eliminate this irrelevant difference).
*/
if (opt_delete==180) goto end;
#endif
} }
else else
found_parts++; found_parts++;
......
Running tests with dynamic row format Running tests with dynamic row format
Running tests with static row format Running tests with static row format
Running tests with block row format Running tests with block row format
Running tests with block row format and transactions
ma_test2 -s -L -K -R1 -m2000 ; Should give error 135 ma_test2 -s -L -K -R1 -m2000 ; Should give error 135
Error: 135 in write at record: 1099 Error: 135 in write at record: 1099
got error: 135 when using MARIA-database got error: 135 when using MARIA-database
...@@ -8,55 +9,6 @@ got error: 135 when using MARIA-database ...@@ -8,55 +9,6 @@ got error: 135 when using MARIA-database
maria_chk: MARIA file test2 maria_chk: MARIA file test2
maria_chk: warning: Datafile is almost full, 65516 of 65534 used maria_chk: warning: Datafile is almost full, 65516 of 65534 used
MARIA-table 'test2' is usable but should be fixed MARIA-table 'test2' is usable but should be fixed
MARIA RECOVERY TESTS
real 0m0.808s ALL RECOVERY TESTS OK
user 0m0.584s !!!!!!!! BUT REMEMBER to FIX this BLOB issue !!!!!!!
sys 0m0.212s
real 0m0.780s
user 0m0.584s
sys 0m0.176s
real 0m0.809s
user 0m0.616s
sys 0m0.180s
real 0m1.356s
user 0m1.140s
sys 0m0.188s
real 0m0.783s
user 0m0.600s
sys 0m0.176s
real 0m1.390s
user 0m1.184s
sys 0m0.152s
real 0m1.875s
user 0m1.632s
sys 0m0.244s
real 0m1.313s
user 0m1.148s
sys 0m0.160s
real 0m1.846s
user 0m1.644s
sys 0m0.188s
real 0m1.875s
user 0m1.632s
sys 0m0.212s
real 0m1.819s
user 0m1.672s
sys 0m0.124s
real 0m2.117s
user 0m1.816s
sys 0m0.292s
real 0m1.871s
user 0m1.636s
sys 0m0.196s
...@@ -115,7 +115,7 @@ run_tests() ...@@ -115,7 +115,7 @@ run_tests()
$maria_path/maria_chk$suffix -sm test2 $maria_path/maria_chk$suffix -sm test2
$maria_path/ma_test2$suffix $silent -m10000 -e4096 -K $row_type $maria_path/ma_test2$suffix $silent -m10000 -e4096 -K $row_type
$maria_path/maria_chk$suffix -sm test2 $maria_path/maria_chk$suffix -sm test2
$maria_path/ma_test2$suffix $silent -m10000 -e8192 -K $row_type $maria_path/ma_test2$suffix $silent -m10000 -e8192 -K $row_type -P
$maria_path/maria_chk$suffix -sm test2 $maria_path/maria_chk$suffix -sm test2
$maria_path/ma_test2$suffix $silent -m10000 -e16384 -E16384 -K -L $row_type $maria_path/ma_test2$suffix $silent -m10000 -e16384 -E16384 -K -L $row_type
$maria_path/maria_chk$suffix -sm test2 $maria_path/maria_chk$suffix -sm test2
...@@ -232,16 +232,16 @@ $maria_path/maria_chk$suffix -ssm test2 ...@@ -232,16 +232,16 @@ $maria_path/maria_chk$suffix -ssm test2
# #
# Some timing tests # Some timing tests
# #
time $maria_path/ma_test2$suffix $silent #time $maria_path/ma_test2$suffix $silent
time $maria_path/ma_test2$suffix $silent -S #time $maria_path/ma_test2$suffix $silent -S
time $maria_path/ma_test2$suffix $silent -M #time $maria_path/ma_test2$suffix $silent -M
time $maria_path/ma_test2$suffix $silent -B #time $maria_path/ma_test2$suffix $silent -B
time $maria_path/ma_test2$suffix $silent -L #time $maria_path/ma_test2$suffix $silent -L
time $maria_path/ma_test2$suffix $silent -K #time $maria_path/ma_test2$suffix $silent -K
time $maria_path/ma_test2$suffix $silent -K -B #time $maria_path/ma_test2$suffix $silent -K -B
time $maria_path/ma_test2$suffix $silent -L -B #time $maria_path/ma_test2$suffix $silent -L -B
time $maria_path/ma_test2$suffix $silent -L -K -B #time $maria_path/ma_test2$suffix $silent -L -K -B
time $maria_path/ma_test2$suffix $silent -L -K -W -B #time $maria_path/ma_test2$suffix $silent -L -K -W -B
time $maria_path/ma_test2$suffix $silent -L -K -W -B -S #time $maria_path/ma_test2$suffix $silent -L -K -W -B -S
time $maria_path/ma_test2$suffix $silent -L -K -W -B -M #time $maria_path/ma_test2$suffix $silent -L -K -W -B -M
time $maria_path/ma_test2$suffix $silent -D -K -W -B -S #time $maria_path/ma_test2$suffix $silent -D -K -W -B -S
...@@ -87,9 +87,6 @@ apply_log() ...@@ -87,9 +87,6 @@ apply_log()
( (
# this message is to remember about the problem with -b (see @todo below)
echo "!!!!!!!! REMEMBER to FIX this BLOB issue !!!!!!!"
echo "Testing the REDO PHASE ALONE" echo "Testing the REDO PHASE ALONE"
# runs a program inserting/deleting rows, then moves the resulting table # runs a program inserting/deleting rows, then moves the resulting table
# elsewhere; applies the log and checks that the data file is # elsewhere; applies the log and checks that the data file is
...@@ -111,10 +108,12 @@ do ...@@ -111,10 +108,12 @@ do
mv $table.MAI $tmp/$table-good.MAI mv $table.MAI $tmp/$table-good.MAI
apply_log "shouldnotchangelog" apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table-good.MAD cmp $table.MAD $tmp/$table-good.MAD
cmp $table.MAI $tmp/$table-good.MAI
check_table_is_same check_table_is_same
echo "testing idempotency" echo "testing idempotency"
apply_log "shouldnotchangelog" apply_log "shouldnotchangelog"
cmp $table.MAD $tmp/$table-good.MAD cmp $table.MAD $tmp/$table-good.MAD
cmp $table.MAI $tmp/$table-good.MAI
check_table_is_same check_table_is_same
shift shift
done done
...@@ -157,6 +156,12 @@ do ...@@ -157,6 +156,12 @@ do
echo "TEST WITH $prog $abort_run_args$test_undo (additional aborted work)" echo "TEST WITH $prog $abort_run_args$test_undo (additional aborted work)"
$maria_path/$prog $abort_run_args$test_undo $maria_path/$prog $abort_run_args$test_undo
cp $table.MAD $tmp/$table.MAD.before_undo cp $table.MAD $tmp/$table.MAD.before_undo
# We have to copy and restore logs, as running maria_read_log will
# change the maria_control_file
rm -f $tmp/maria_log.* $tmp/maria_log_control
cp $maria_path/maria_log* $tmp
if [ $test_undo -lt 3 ] if [ $test_undo -lt 3 ]
then then
apply_log "shouldchangelog" # should undo aborted work apply_log "shouldchangelog" # should undo aborted work
...@@ -179,19 +184,9 @@ do ...@@ -179,19 +184,9 @@ do
check_table_is_same check_table_is_same
echo "testing applying of CLRs to recreate table" echo "testing applying of CLRs to recreate table"
rm $table.MA? rm $table.MA?
apply_log "shouldnotchangelog" cp $tmp/maria_log* $maria_path
# the cmp below fails with ma_test1+blobs! @todo RECOVERY BUG why? apply_log "dontknow"
# It is probably serious; REDOs shouldn't place rows in different cmp $table.MAD $tmp/$table.MAD.after_undo
# positions from what the run-time code did. Indeed it may lead to
# more or less free space...
# Execution of UNDO re-inserted rows at different positions than
# originally. This generated REDOs which do not insert at the same
# positions as the execution of UNDOs, but at the same positions
# as before the row was originally deleted.
if [ "$blobs" == "" ]
then
cmp $table.MAD $tmp/$table.MAD.after_undo
fi
check_table_is_same check_table_is_same
shift 3 shift 3
done done
...@@ -213,5 +208,3 @@ if [ "$diff_failed" == "1" ] ...@@ -213,5 +208,3 @@ if [ "$diff_failed" == "1" ]
exit 1 exit 1
fi fi
echo "ALL RECOVERY TESTS OK" echo "ALL RECOVERY TESTS OK"
# this message is to remember about the problem with -b (see @todo above)
echo "!!!!!!!! BUT REMEMBER to FIX this BLOB issue !!!!!!!"
This diff is collapsed.
This diff is collapsed.
...@@ -1007,6 +1007,9 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1007,6 +1007,9 @@ static int maria_chk(HA_CHECK *param, char *filename)
if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX)) if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX))
{ {
/* Mark table as not transactional to avoid logging */
maria_disable_logging(info);
if (param->testflag & T_REP_ANY) if (param->testflag & T_REP_ANY)
{ {
ulonglong tmp=share->state.key_map; ulonglong tmp=share->state.key_map;
...@@ -1181,6 +1184,7 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1181,6 +1184,7 @@ static int maria_chk(HA_CHECK *param, char *filename)
((param->testflag & T_SORT_RECORDS) ? ((param->testflag & T_SORT_RECORDS) ?
UPDATE_SORT : 0))); UPDATE_SORT : 0)));
info->update&= ~HA_STATE_CHANGED; info->update&= ~HA_STATE_CHANGED;
maria_enable_logging(info);
maria_lock_database(info, F_UNLCK); maria_lock_database(info, F_UNLCK);
end2: end2:
......
This diff is collapsed.
This diff is collapsed.
...@@ -337,7 +337,7 @@ int main(int argc __attribute__((unused)), char *argv[]) ...@@ -337,7 +337,7 @@ int main(int argc __attribute__((unused)), char *argv[])
if (translog_flush(translog_get_horizon())) if (translog_flush(translog_get_horizon()))
{ {
fprintf(stderr, "Can't flush up to horizon\n", (ulong) i); fprintf(stderr, "Can't flush up to horizon\n");
translog_destroy(); translog_destroy();
ok(0, "flush"); ok(0, "flush");
exit(1); exit(1);
......
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