diff options
30 files changed, 1535 insertions, 1904 deletions
diff --git a/include/maria.h b/include/maria.h index c70d36557ab..6e87c93c7d1 100644 --- a/include/maria.h +++ b/include/maria.h @@ -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 int maria_commit(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 */ diff --git a/mysql-test/include/maria_verify_recovery.inc b/mysql-test/include/maria_verify_recovery.inc index be93c3dead0..25f6fd87db2 100644 --- a/mysql-test/include/maria_verify_recovery.inc +++ b/mysql-test/include/maria_verify_recovery.inc @@ -77,16 +77,15 @@ let $mms_purpose=comparison; let $mms_compare_physically=$mms_compare_physically_save; while ($mms_table_to_use) { - # Todo: remove this REPAIR when we have index recovery working. - # 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; + eval check table t$mms_table_to_use extended; --echo * testing that checksum after recovery is as expected let $new_checksum=`CHECKSUM TABLE 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", # 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 -- source include/maria_make_snapshot.inc dec $mms_table_to_use; diff --git a/mysql-test/r/maria-recovery.result b/mysql-test/r/maria-recovery.result index 42bc4e9f39c..70f0a7be596 100644 --- a/mysql-test/r/maria-recovery.result +++ b/mysql-test/r/maria-recovery.result @@ -15,13 +15,11 @@ set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * copied t1 back for feeding_recovery * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok * compared t1 to old version use mysqltest; @@ -39,13 +37,11 @@ SET SESSION debug="+d,maria_crash"; set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok use mysqltest; select * from t1; @@ -62,13 +58,11 @@ SET SESSION debug="+d,maria_flush_whole_page_cache,maria_crash"; set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok use mysqltest; select * from t1; @@ -86,13 +80,11 @@ SET SESSION debug="+d,maria_flush_states,maria_flush_whole_log,maria_crash"; set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok use mysqltest; select * from t1; @@ -111,13 +103,11 @@ SET SESSION debug="+d,maria_flush_whole_log,maria_crash"; set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok use mysqltest; select * from t1; @@ -149,13 +139,11 @@ set global maria_checkpoint_interval=1; ERROR HY000: Lost connection to MySQL server during query * copied t1 back for feeding_recovery * recovery happens -* rebuilding index (until we have recovery of index) -repair table t1 quick; +check table t1 extended; Table Op Msg_type Msg_text -mysqltest.t1 repair status OK +mysqltest.t1 check status OK * 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"); -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 ok use mysqltest; SELECT LENGTH(b) FROM t1 WHERE i=3; diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index be8ad67b579..fc134df3b99 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -1549,14 +1549,13 @@ static my_bool write_full_pages(MARIA_HA *info, KEYPAGE_CHECKSUM_SIZE, (uchar) 255); DBUG_ASSERT(share->pagecache->block_size == block_size); - /** @todo RECOVERY BUG the page does not get a rec_lsn with this! */ if (pagecache_write(share->pagecache, &info->dfile, page, 0, buff, share->page_type, PAGECACHE_LOCK_LEFT_UNLOCKED, PAGECACHE_PIN_LEFT_UNPINNED, PAGECACHE_WRITE_DELAY, - 0, LSN_IMPOSSIBLE)) + 0, info->trn->rec_lsn)) DBUG_RETURN(1); page++; block->used= BLOCKUSED_USED; @@ -2491,34 +2490,17 @@ static my_bool write_block_record(MARIA_HA *info, if (undo_lsn != LSN_ERROR) { - uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE + HA_CHECKSUM_STORE_SIZE]; - struct st_msg_to_write_hook_for_clr_end msg; - /* undo_lsn must be first for compression to work */ - lsn_store(log_data, undo_lsn); /* Store if this CLR is about UNDO_DELETE or UNDO_UPDATE; in the first case, Recovery, when it sees the CLR_END in the REDO phase, may decrement the records' count. */ - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= - sizeof(log_data) - HA_CHECKSUM_STORE_SIZE; - msg.undone_record_type= - old_record ? LOGREC_UNDO_ROW_UPDATE : LOGREC_UNDO_ROW_DELETE; - clr_type_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, - msg.undone_record_type); - msg.previous_undo_lsn= undo_lsn; - store_checksum_in_rec(share, msg.checksum_delta, - row->checksum - old_record_checksum, - log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE, - log_array[TRANSLOG_INTERNAL_PARTS + 0].length); - if (translog_write_record(&lsn, LOGREC_CLR_END, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + 0].length, - TRANSLOG_INTERNAL_PARTS + 1, log_array, - log_data + LSN_STORE_SIZE, &msg)) + if (_ma_write_clr(info, undo_lsn, + old_record ? LOGREC_UNDO_ROW_UPDATE : + LOGREC_UNDO_ROW_DELETE, + share->calc_checksum != 0, + row->checksum - old_record_checksum, + &lsn, (void*) 0)) goto disk_err; } else @@ -2804,29 +2786,11 @@ my_bool _ma_write_abort_block_record(MARIA_HA *info) if (share->now_transactional) { - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 1]; - uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE + HA_CHECKSUM_STORE_SIZE]; - struct st_msg_to_write_hook_for_clr_end msg; - - lsn_store(log_data, info->cur_row.orig_undo_lsn); - msg.previous_undo_lsn= info->cur_row.orig_undo_lsn; - msg.undone_record_type= LOGREC_UNDO_ROW_INSERT; - clr_type_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, - LOGREC_UNDO_ROW_INSERT); - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= - sizeof(log_data) - HA_CHECKSUM_STORE_SIZE; - store_checksum_in_rec(share, msg.checksum_delta, - - info->cur_row.checksum, - log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + - CLR_TYPE_STORE_SIZE, - log_array[TRANSLOG_INTERNAL_PARTS + 0].length); - if (translog_write_record(&lsn, LOGREC_CLR_END, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + 0].length, - TRANSLOG_INTERNAL_PARTS + 1, log_array, - log_data + LSN_STORE_SIZE, &msg)) + if (_ma_write_clr(info, info->cur_row.orig_undo_lsn, + LOGREC_UNDO_ROW_INSERT, + share->calc_checksum != 0, + -info->cur_row.checksum, + &lsn, (void*) 0)) res= 1; } _ma_unpin_all_pages_and_finalize_row(info, lsn); @@ -4971,49 +4935,6 @@ my_bool write_hook_for_undo_row_update(enum translog_record_type type /** - @brief Sets transaction's undo_lsn, first_undo_lsn if needed - - @return Operation status, always 0 (success) -*/ - -my_bool write_hook_for_clr_end(enum translog_record_type type - __attribute__ ((unused)), - TRN *trn, MARIA_HA *tbl_info - __attribute__ ((unused)), - LSN *lsn __attribute__ ((unused)), - void *hook_arg) -{ - MARIA_SHARE *share= tbl_info->s; - struct st_msg_to_write_hook_for_clr_end *msg= - (struct st_msg_to_write_hook_for_clr_end *)hook_arg; - DBUG_ASSERT(trn->trid != 0); - trn->undo_lsn= msg->previous_undo_lsn; - - switch (msg->undone_record_type) { - case LOGREC_UNDO_ROW_DELETE: - share->state.state.records++; - share->state.state.checksum+= msg->checksum_delta; - break; - case LOGREC_UNDO_ROW_INSERT: - share->state.state.records--; - share->state.state.checksum+= msg->checksum_delta; - break; - case LOGREC_UNDO_ROW_UPDATE: - share->state.state.checksum+= msg->checksum_delta; - break; - case LOGREC_UNDO_KEY_INSERT: - case LOGREC_UNDO_KEY_DELETE: - break; - default: - DBUG_ASSERT(0); - } - if (trn->undo_lsn == LSN_IMPOSSIBLE) /* has fully rolled back */ - trn->first_undo_lsn= LSN_WITH_FLAGS_TO_FLAGS(trn->first_undo_lsn); - return 0; -} - - -/** @brief Updates table's lsn_of_file_id. @return Operation status, always 0 (success) @@ -5066,6 +4987,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint block_size= share->block_size; uint rec_offset; uchar *buff, *dir; + uint result; MARIA_PINNED_PAGE page_link; enum pagecache_page_lock unlock_method; enum pagecache_page_pin unpin_method; @@ -5202,25 +5124,29 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, int2store(buff + EMPTY_SPACE_OFFSET, empty_space); /* - Write modified page. We don't update its LSN, and keep it pinned. When we - have processed all REDOs for this page in the current REDO's group, we - will stamp page with UNDO's LSN (if we stamped it now, a next REDO, in + If page was not read before, write it but keep it pinned. + We don't update its LSN When we have processed all REDOs for this page + in the current REDO's group, we will stamp page with UNDO's LSN + (if we stamped it now, a next REDO, in this group, for this page, would be skipped) and unpin then. */ - if (pagecache_write(share->pagecache, + result= 0; + if (unlock_method == PAGECACHE_LOCK_WRITE && + pagecache_write(share->pagecache, &info->dfile, page, 0, buff, PAGECACHE_PLAIN_PAGE, unlock_method, unpin_method, PAGECACHE_WRITE_DELAY, &page_link.link, LSN_IMPOSSIBLE)) - DBUG_RETURN(my_errno); + result= my_errno; page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; push_dynamic(&info->pinned_pages, (void*) &page_link); /* Fix bitmap */ if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, empty_space)) - DBUG_RETURN(my_errno); + result= my_errno; /* Data page and bitmap page are in place, we can update data_file_length in @@ -5232,7 +5158,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, set_if_bigger(info->state->data_file_length, end_of_page); } - DBUG_RETURN(0); + DBUG_RETURN(result); err: if (unlock_method == PAGECACHE_LOCK_LEFT_WRITELOCKED) @@ -5322,23 +5248,14 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, if (delete_dir_entry(buff, block_size, rownr, &empty_space) < 0) goto err; + page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; + push_dynamic(&info->pinned_pages, (void*) &page_link); + result= 0; - if (pagecache_write(share->pagecache, - &info->dfile, page, 0, - buff, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_WRITELOCKED, - PAGECACHE_PIN_LEFT_PINNED, - PAGECACHE_WRITE_DELAY, 0, - LSN_IMPOSSIBLE)) + /* This will work even if the page was marked as UNALLOCATED_PAGE */ + if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, empty_space)) result= my_errno; - else - { - page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; - push_dynamic(&info->pinned_pages, (void*) &page_link); - /* This will work even if the page was marked as UNALLOCATED_PAGE */ - if (_ma_bitmap_set(info, page, page_type == HEAD_PAGE, empty_space)) - result= my_errno; - } DBUG_RETURN(result); @@ -5387,10 +5304,8 @@ uint _ma_apply_redo_free_blocks(MARIA_HA *info, header+= PAGE_STORE_SIZE; /* Page range may have this bit set to indicate a tail page */ page_range= pagerange_korr(header) & ~TAIL_BIT; - /** @todo RECOVERY BUG enable this assertion when newer tree pulled */ -#if 0 DBUG_ASSERT(page_range > 0); -#endif + header+= PAGERANGE_STORE_SIZE; DBUG_PRINT("info", ("page: %lu pages: %u", (long) page, page_range)); @@ -5466,13 +5381,10 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, bzero(dir, number_of_records * DIR_ENTRY_SIZE); } #endif - lsn_store(buff, lsn); - if (pagecache_write(share->pagecache, - &info->dfile, page, 0, - buff, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, - PAGECACHE_WRITE_DELAY, 0)) - DBUG_RETURN(1); + + page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; + push_dynamic(&info->pinned_pages, (void*) &page_link); } /** @todo leave bitmap lock to the bitmap code... */ pthread_mutex_lock(&share->bitmap.bitmap_lock); @@ -5591,6 +5503,11 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, unlock_method= PAGECACHE_LOCK_WRITE_UNLOCK; unpin_method= PAGECACHE_UNPIN; } + + /* + Blob pages are never updated twice in same redo-undo chain, so + it's safe to update lsn for them here + */ lsn_store(buff, lsn); buff[PAGE_TYPE_OFFSET]= BLOB_PAGE; @@ -5610,7 +5527,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, &info->dfile, page, 0, buff, PAGECACHE_PLAIN_PAGE, unlock_method, unpin_method, - PAGECACHE_WRITE_DELAY, 0)) + PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE)) DBUG_RETURN(my_errno); } /** @todo leave bitmap lock to the bitmap code... */ @@ -5674,7 +5591,7 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, if (share->calc_checksum) checksum= -ha_checksum_korr(header); if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_ROW_INSERT, - share->calc_checksum != 0, checksum, &lsn)) + share->calc_checksum != 0, checksum, &lsn, (void*) 0)) goto err; res= 0; diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 7f3bf11d96c..a792f8c5db5 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -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, TRN *trn, MARIA_HA *tbl_info, 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, TRN *trn, MARIA_HA *tbl_info, LSN *lsn, void *hook_arg); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 0f970e77a0f..37c01954d9b 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -305,7 +305,7 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info, &info->s->kfile, next_link/block_size, DFLT_INIT_HITS, (uchar*) info->buff, - PAGECACHE_PLAIN_PAGE, + PAGECACHE_READ_UNKNOWN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, 0))) { /* purecov: begin tested */ @@ -595,7 +595,7 @@ do_stat: puts(""); } 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"); if (found_keys != full_text_keys) 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, info->s->state.dellink= HA_OFFSET_ERROR; info->rec_cache.file= new_file; if (share->data_file_type == BLOCK_RECORD || - ((param->testflag & T_UNPACK) && - share->state.header.org_data_file_type == BLOCK_RECORD)) + (param->testflag & T_UNPACK)) { MARIA_HA *new_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)) goto err; 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, if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) param->testflag|=T_CALC_CHECKSUM; - if (_ma_flush_table_files(info, MARIA_FLUSH_DATA, FLUSH_FORCE_WRITE, - FLUSH_KEEP)) + if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, + FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED)) goto err; if (!(sort_info.key_block= @@ -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)) param->testflag|=T_CALC_CHECKSUM; - if (_ma_flush_table_files(info, MARIA_FLUSH_DATA, FLUSH_FORCE_WRITE, - FLUSH_KEEP)) + if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, + FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED)) goto err; /* @@ -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) { + MARIA_SHARE tmp_share; share->options&= ~HA_OPTION_COMPRESS_RECORD; mi_int2store(share->state.header.options,share->options); share->state.header.data_file_type= share->state.header.org_data_file_type; share->data_file_type= share->state.header.data_file_type; 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; } diff --git a/storage/maria/ma_commit.c b/storage/maria/ma_commit.c index 8a0a4c136bb..d9aa39c634d 100644 --- a/storage/maria/ma_commit.c +++ b/storage/maria/ma_commit.c @@ -122,3 +122,26 @@ int maria_begin(MARIA_HA *info) } 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; +} diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 122fa9f38ee..3d3a23cdb8b 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2007 MySQL AB & Guilhem Bichot & Michael Widenius This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,31 +16,79 @@ /* WL#3234 Maria control file First version written by Guilhem Bichot on 2006-04-27. - Does not compile yet. */ #include "maria_def.h" -/* Here is the implementation of this module */ +/* + A control file contains the following objects: + +Start of create time variables (at start of file): + - Magic string (including version number of Maria control file) + - Uuid + - Size of create time part + - Size of dynamic part + - Maria block size +..... Here we can add new variables without changing format + - Checksum of create time part (last of block) + +Start of changeable part: + - Checksum of changeable part + - LSN of last checkpoint + - Number of last log file +..... Here we can add new variables without changing format + +The idea is that one can add new variables to the control file and still +use it with old program versions. If one needs to do an incompatible change +one should increment the control file version number. +*/ + +/* Total size should be < sector size for atomic write operation */ +#define CF_MAX_SIZE 512 +#define CF_MIN_SIZE (CF_BLOCKSIZE_OFFSET + CF_BLOCKSIZE_SIZE + \ + CF_CHECKSUM_SIZE * 2 + CF_LSN_SIZE + CF_FILENO_SIZE) + +/* Create time variables */ +#define CF_MAGIC_STRING "\xfe\xfe\xc" +#define CF_MAGIC_STRING_OFFSET 0 +#define CF_MAGIC_STRING_SIZE (sizeof(CF_MAGIC_STRING)-1) +#define CF_VERSION_OFFSET (CF_MAGIC_STRING_OFFSET + CF_MAGIC_STRING_SIZE) +#define CF_VERSION_SIZE 1 +#define CF_UUID_OFFSET (CF_VERSION_OFFSET + CF_VERSION_SIZE) +#define CF_UUID_SIZE MY_UUID_SIZE +#define CF_CREATE_TIME_SIZE_OFFSET (CF_UUID_OFFSET + CF_UUID_SIZE) +#define CF_SIZE_SIZE 2 +#define CF_CHANGEABLE_SIZE_OFFSET (CF_CREATE_TIME_SIZE_OFFSET + CF_SIZE_SIZE) +#define CF_BLOCKSIZE_OFFSET (CF_CHANGEABLE_SIZE_OFFSET + CF_SIZE_SIZE) +#define CF_BLOCKSIZE_SIZE 2 + +#define CF_CREATE_TIME_TOTAL_SIZE (CF_BLOCKSIZE_OFFSET + CF_BLOCKSIZE_SIZE + \ + CF_CHECKSUM_SIZE) + +/* + Start of the part that changes during execution + This is stored at offset uint2korr(file[CF_CHANGEABLE_SIZE]) +*/ +#define CF_CHECKSUM_OFFSET 0 +#define CF_CHECKSUM_SIZE 4 +#define CF_LSN_OFFSET (CF_CHECKSUM_OFFSET + CF_CHECKSUM_SIZE) +#define CF_LSN_SIZE LSN_STORE_SIZE +#define CF_FILENO_OFFSET (CF_LSN_OFFSET + CF_LSN_SIZE) +#define CF_FILENO_SIZE 4 + +#define CF_CHANGEABLE_TOTAL_SIZE (CF_FILENO_OFFSET + CF_FILENO_SIZE) /* - a control file contains 3 objects: magic string, LSN of last checkpoint, - number of last log. + The following values should not be changed, except when changing version + number of the maria control file. These are the minimum sizes of the + parts the code can handle. */ -/* total size should be < sector size for atomic write operation */ -#define CONTROL_FILE_MAGIC_STRING "\xfe\xfe\xc\1MACF" -#define CONTROL_FILE_MAGIC_STRING_OFFSET 0 -#define CONTROL_FILE_MAGIC_STRING_SIZE (sizeof(CONTROL_FILE_MAGIC_STRING)-1) -#define CONTROL_FILE_UUID_OFFSET (CONTROL_FILE_MAGIC_STRING_OFFSET + CONTROL_FILE_MAGIC_STRING_SIZE) -#define CONTROL_FILE_UUID_SIZE MY_UUID_SIZE -#define CONTROL_FILE_CHECKSUM_OFFSET (CONTROL_FILE_UUID_OFFSET + CONTROL_FILE_UUID_SIZE) -#define CONTROL_FILE_CHECKSUM_SIZE 4 -#define CONTROL_FILE_LSN_OFFSET (CONTROL_FILE_CHECKSUM_OFFSET + CONTROL_FILE_CHECKSUM_SIZE) -#define CONTROL_FILE_LSN_SIZE LSN_STORE_SIZE -#define CONTROL_FILE_FILENO_OFFSET (CONTROL_FILE_LSN_OFFSET + CONTROL_FILE_LSN_SIZE) -#define CONTROL_FILE_FILENO_SIZE 4 -#define CONTROL_FILE_SIZE (CONTROL_FILE_FILENO_OFFSET + CONTROL_FILE_FILENO_SIZE) +#define CF_MIN_CREATE_TIME_TOTAL_SIZE \ +(CF_BLOCKSIZE_OFFSET + CF_BLOCKSIZE_SIZE + CF_CHECKSUM_SIZE) +#define CF_MIN_CHANGEABLE_TOTAL_SIZE \ +(CF_FILENO_OFFSET + CF_FILENO_SIZE) + /* This module owns these two vars. */ /** @@ -66,6 +114,77 @@ my_bool maria_in_recovery= FALSE; */ static int control_file_fd= -1; +static uint cf_create_time_size; +static uint cf_changeable_size; + +/** + @brief Create Maria control file +*/ + +static CONTROL_FILE_ERROR create_control_file(const char *name, + int open_flags) +{ + uint32 sum; + uchar buffer[CF_CREATE_TIME_TOTAL_SIZE]; + DBUG_ENTER("maria_create_control_file"); + + /* in a recovery, we expect to find a control file */ + if (maria_in_recovery) + DBUG_RETURN(CONTROL_FILE_MISSING); + if ((control_file_fd= my_create(name, 0, + open_flags, + MYF(MY_SYNC_DIR | MY_WME))) < 0) + DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR); + + /* Reset variables, as we are creating the file */ + cf_create_time_size= CF_CREATE_TIME_TOTAL_SIZE; + cf_changeable_size= CF_CHANGEABLE_TOTAL_SIZE; + + /* Create unique uuid for the control file */ + my_uuid_init((ulong) &buffer, (ulong) &maria_uuid); + my_uuid(maria_uuid); + + /* Prepare and write the file header */ + memcpy(buffer, CF_MAGIC_STRING, CF_MAGIC_STRING_SIZE); + buffer[CF_VERSION_OFFSET]= CONTROL_FILE_VERSION; + memcpy(buffer + CF_UUID_OFFSET, maria_uuid, CF_UUID_SIZE); + int2store(buffer + CF_CREATE_TIME_SIZE_OFFSET, cf_create_time_size); + int2store(buffer + CF_CHANGEABLE_SIZE_OFFSET, cf_changeable_size); + + /* Write create time variables */ + int2store(buffer + CF_BLOCKSIZE_OFFSET, maria_block_size); + + /* Store checksum for create time parts */ + sum= (uint32) my_checksum(0, buffer, cf_create_time_size - + CF_CHECKSUM_SIZE); + int4store(buffer + cf_create_time_size - CF_CHECKSUM_SIZE, sum); + + if (my_pwrite(control_file_fd, buffer, cf_create_time_size, + 0, MYF(MY_FNABP | MY_WME))) + DBUG_RETURN(1); + + /* + To be safer we should make sure that there are no logs or data/index + files around (indeed it could be that the control file alone was deleted + or not restored, and we should not go on with life at this point). + + TODO: For now we trust (this is alpha version), but for beta if would + be great to verify. + + We could have a tool which can rebuild the control file, by reading the + directory of logs, finding the newest log, reading it to find last + checkpoint... Slow but can save your db. For this to be possible, we + must always write to the control file right after writing the checkpoint + log record, and do nothing in between (i.e. the checkpoint must be + usable as soon as it has been written to the log). + */ + + /* init the file with these "undefined" values */ + DBUG_RETURN(ma_control_file_write_and_force(LSN_IMPOSSIBLE, + FILENO_IMPOSSIBLE, + CONTROL_FILE_UPDATE_ALL)); +} + /* @brief Initialize control file subsystem @@ -75,12 +194,8 @@ static int control_file_fd= -1; Called at engine's start. @note - The format of the control file is: - 4 bytes: magic string - 4 bytes: checksum of the following bytes - 4 bytes: number of log where last checkpoint is - 4 bytes: offset in log where last checkpoint is - 4 bytes: number of last log + The format of the control file is defined in the comments and defines + at the start of this file. @note If in recovery, file is not created @@ -88,13 +203,14 @@ static int control_file_fd= -1; @retval 0 OK @retval 1 Error (in which case the file is left closed) */ + CONTROL_FILE_ERROR ma_control_file_create_or_open() { - char buffer[CONTROL_FILE_SIZE]; - char name[FN_REFLEN]; + uchar buffer[CF_MAX_SIZE]; + char name[FN_REFLEN], errmsg_buff[256]; const char *errmsg; MY_STAT stat_buff; - my_bool create_file; + uint new_cf_create_time_size, new_cf_changeable_size, new_block_size; int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR; int error= CONTROL_FILE_UNKNOWN_ERROR; DBUG_ENTER("ma_control_file_create_or_open"); @@ -104,8 +220,8 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() "*store" and "*korr" calls in this file, and can even create backward compatibility problems. Beware! */ - DBUG_ASSERT(CONTROL_FILE_LSN_SIZE == (3+4)); - DBUG_ASSERT(CONTROL_FILE_FILENO_SIZE == 4); + DBUG_ASSERT(CF_LSN_SIZE == (3+4)); + DBUG_ASSERT(CF_FILENO_SIZE == 4); if (control_file_fd >= 0) /* already open */ DBUG_RETURN(0); @@ -114,43 +230,8 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() maria_data_root, "", MYF(MY_WME)) == NullS) DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR); - create_file= test(my_access(name,F_OK)); - - if (create_file) - { - /* in a recovery, we expect to find a control file */ - if (maria_in_recovery) - DBUG_RETURN(CONTROL_FILE_MISSING); - if ((control_file_fd= my_create(name, 0, - open_flags, - MYF(MY_SYNC_DIR | MY_WME))) < 0) - DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR); - - /* Create unique uuid for the control file */ - my_uuid_init((ulong) &buffer, (ulong) &maria_uuid); - my_uuid(maria_uuid); - - /* - To be safer we should make sure that there are no logs or data/index - files around (indeed it could be that the control file alone was deleted - or not restored, and we should not go on with life at this point). - - TODO: For now we trust (this is alpha version), but for beta if would - be great to verify. - - We could have a tool which can rebuild the control file, by reading the - directory of logs, finding the newest log, reading it to find last - checkpoint... Slow but can save your db. For this to be possible, we - must always write to the control file right after writing the checkpoint - log record, and do nothing in between (i.e. the checkpoint must be - usable as soon as it has been written to the log). - */ - - /* init the file with these "undefined" values */ - DBUG_RETURN(ma_control_file_write_and_force(LSN_IMPOSSIBLE, - FILENO_IMPOSSIBLE, - CONTROL_FILE_UPDATE_ALL)); - } + if (my_access(name,F_OK)) + DBUG_RETURN(create_control_file(name, open_flags)); /* Otherwise, file exists */ @@ -166,7 +247,7 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() goto err; } - if ((uint)stat_buff.st_size < CONTROL_FILE_SIZE) + if ((uint) stat_buff.st_size < CF_MIN_SIZE) { /* Given that normally we write only a sector and it's atomic, the only @@ -179,49 +260,89 @@ CONTROL_FILE_ERROR ma_control_file_create_or_open() disk/filesystem has a problem. So let's be rigid. */ - /* - TODO: store a message "too small file" somewhere, so that it goes to - MySQL's error log at startup. - */ error= CONTROL_FILE_TOO_SMALL; - errmsg= "File size to small"; + errmsg= "Size of control file is smaller than expected"; goto err; } - if ((uint)stat_buff.st_size > CONTROL_FILE_SIZE) + /* Check if control file is unexpectedly big */ + if ((uint)stat_buff.st_size > CF_MAX_SIZE) { - /* TODO: store "too big file" message */ error= CONTROL_FILE_TOO_BIG; errmsg= "File size bigger than expected"; goto err; } - if (my_read(control_file_fd, buffer, CONTROL_FILE_SIZE, MYF(MY_FNABP))) + if (my_read(control_file_fd, buffer, stat_buff.st_size, MYF(MY_FNABP))) { errmsg= "Can't read file"; goto err; } - if (memcmp(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET, - CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE)) + + if (memcmp(buffer + CF_MAGIC_STRING_OFFSET, + CF_MAGIC_STRING, CF_MAGIC_STRING_SIZE)) { - /* TODO: store message "bad magic string" somewhere */ error= CONTROL_FILE_BAD_MAGIC_STRING; - errmsg= "Missing valid id at start of file"; + errmsg= "Missing valid id at start of file. File is not a valid maria control file"; + goto err; + } + + if (buffer[CF_VERSION_OFFSET] > CONTROL_FILE_VERSION) + { + error= CONTROL_FILE_BAD_VERSION; + sprintf(errmsg_buff, "File is from a future maria system: %d. Current version is: %d", + (int) buffer[CF_VERSION_OFFSET], CONTROL_FILE_VERSION); + errmsg= errmsg_buff; + goto err; + } + + new_cf_create_time_size= uint2korr(buffer + CF_CREATE_TIME_SIZE_OFFSET); + new_cf_changeable_size= uint2korr(buffer + CF_CHANGEABLE_SIZE_OFFSET); + + if (new_cf_create_time_size < CF_MIN_CREATE_TIME_TOTAL_SIZE || + new_cf_changeable_size < CF_MIN_CHANGEABLE_TOTAL_SIZE || + new_cf_create_time_size + new_cf_changeable_size != + stat_buff.st_size) + { + error= CONTROL_FILE_INCONSISTENT_INFORMATION; + errmsg= "Sizes stored in control file are inconsistent"; + goto err; + } + + new_block_size= uint2korr(buffer + CF_BLOCKSIZE_OFFSET); + if (new_block_size != maria_block_size) + { + error= CONTROL_FILE_WRONG_BLOCKSIZE; + sprintf(errmsg_buff, + "Block size in control file (%u) is different than given maria_block_size: %u", + new_block_size, (uint) maria_block_size); + errmsg= errmsg_buff; goto err; } - memcpy(maria_uuid, buffer + CONTROL_FILE_UUID_OFFSET, - CONTROL_FILE_UUID_SIZE); - if (my_checksum(0, buffer + CONTROL_FILE_LSN_OFFSET, - CONTROL_FILE_SIZE - CONTROL_FILE_LSN_OFFSET) != - uint4korr(buffer + CONTROL_FILE_CHECKSUM_OFFSET)) + if (my_checksum(0, buffer, new_cf_create_time_size - CF_CHECKSUM_SIZE) != + uint4korr(buffer + new_cf_create_time_size - CF_CHECKSUM_SIZE)) + { + error= CONTROL_FILE_BAD_HEAD_CHECKSUM; + errmsg= "Fixed part checksum mismatch"; + goto err; + } + + if (my_checksum(0, buffer + new_cf_create_time_size + CF_CHECKSUM_SIZE, + new_cf_changeable_size - CF_CHECKSUM_SIZE) != + uint4korr(buffer + new_cf_create_time_size)) { error= CONTROL_FILE_BAD_CHECKSUM; - errmsg= "Checksum missmatch"; + errmsg= "Changeable part (end of control file) checksum missmatch"; goto err; } - last_checkpoint_lsn= lsn_korr(buffer + CONTROL_FILE_LSN_OFFSET); - last_logno= uint4korr(buffer + CONTROL_FILE_FILENO_OFFSET); + + memcpy(maria_uuid, buffer + CF_UUID_OFFSET, CF_UUID_SIZE); + cf_create_time_size= new_cf_create_time_size; + cf_changeable_size= new_cf_changeable_size; + last_checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size + + CF_LSN_OFFSET); + last_logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET); DBUG_RETURN(0); @@ -247,12 +368,12 @@ err: checkpoint_lsn LSN of last checkpoint logno last log file number objs_to_write which of the arguments should be used as new values - (for example, CONTROL_FILE_UPDATE_ONLY_LSN will not + (for example, CF_UPDATE_ONLY_LSN will not write the logno argument to the control file and will not update the last_logno global variable); can be: - CONTROL_FILE_UPDATE_ALL - CONTROL_FILE_UPDATE_ONLY_LSN - CONTROL_FILE_UPDATE_ONLY_LOGNO. + CF_UPDATE_ALL + CF_UPDATE_ONLY_LSN + CF_UPDATE_ONLY_LOGNO. NOTE We always want to do one single my_pwrite() here to be as atomic as @@ -266,8 +387,9 @@ err: int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno, uint objs_to_write) { - char buffer[CONTROL_FILE_SIZE]; + char buffer[CF_MAX_SIZE]; my_bool update_checkpoint_lsn= FALSE, update_logno= FALSE; + uint32 sum; DBUG_ENTER("ma_control_file_write_and_force"); DBUG_ASSERT(control_file_fd >= 0); /* must be open */ @@ -276,11 +398,6 @@ int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno, translog_lock_assert_owner(); #endif - memcpy(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET, - CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE); - memcpy(buffer + CONTROL_FILE_UUID_OFFSET, maria_uuid, - CONTROL_FILE_UUID_SIZE); - if (objs_to_write == CONTROL_FILE_UPDATE_ONLY_LSN) update_checkpoint_lsn= TRUE; else if (objs_to_write == CONTROL_FILE_UPDATE_ONLY_LOGNO) @@ -291,24 +408,31 @@ int ma_control_file_write_and_force(const LSN checkpoint_lsn, uint32 logno, DBUG_ASSERT(0); if (update_checkpoint_lsn) - lsn_store(buffer + CONTROL_FILE_LSN_OFFSET, checkpoint_lsn); + lsn_store(buffer + CF_LSN_OFFSET, checkpoint_lsn); else /* store old value == change nothing */ - lsn_store(buffer + CONTROL_FILE_LSN_OFFSET, last_checkpoint_lsn); + lsn_store(buffer + CF_LSN_OFFSET, last_checkpoint_lsn); if (update_logno) - int4store(buffer + CONTROL_FILE_FILENO_OFFSET, logno); + int4store(buffer + CF_FILENO_OFFSET, logno); else - int4store(buffer + CONTROL_FILE_FILENO_OFFSET, last_logno); + int4store(buffer + CF_FILENO_OFFSET, last_logno); - { - uint32 sum= (uint32) - my_checksum(0, buffer + CONTROL_FILE_LSN_OFFSET, - CONTROL_FILE_SIZE - CONTROL_FILE_LSN_OFFSET); - int4store(buffer + CONTROL_FILE_CHECKSUM_OFFSET, sum); - } - - if (my_pwrite(control_file_fd, buffer, sizeof(buffer), - 0, MYF(MY_FNABP | MY_WME)) || + /* + Clear unknown part of changeable part. + Other option would be to remember the original values in the file + and copy them here, but this should be safer. + */ + bzero(buffer + CF_CHANGEABLE_TOTAL_SIZE, + cf_changeable_size - CF_CHANGEABLE_TOTAL_SIZE); + + /* Checksum is stored first */ + compile_time_assert(CF_CHECKSUM_OFFSET == 0); + sum= my_checksum(0, buffer + CF_CHECKSUM_SIZE, + cf_changeable_size - CF_CHECKSUM_SIZE); + int4store(buffer, sum); + + if (my_pwrite(control_file_fd, buffer, cf_changeable_size, + cf_create_time_size, MYF(MY_FNABP | MY_WME)) || my_sync(control_file_fd, MYF(MY_WME))) DBUG_RETURN(1); diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h index 88a1780543a..e051ac01b28 100644 --- a/storage/maria/ma_control_file.h +++ b/storage/maria/ma_control_file.h @@ -22,6 +22,12 @@ #define _ma_control_file_h #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 */ @@ -43,8 +49,12 @@ typedef enum enum_control_file_error { CONTROL_FILE_TOO_SMALL, CONTROL_FILE_TOO_BIG, CONTROL_FILE_BAD_MAGIC_STRING, + CONTROL_FILE_BAD_VERSION, CONTROL_FILE_BAD_CHECKSUM, + CONTROL_FILE_BAD_HEAD_CHECKSUM, CONTROL_FILE_MISSING, + CONTROL_FILE_INCONSISTENT_INFORMATION, + CONTROL_FILE_WRONG_BLOCKSIZE, CONTROL_FILE_UNKNOWN_ERROR /* any other error */ } CONTROL_FILE_ERROR; diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index fb13118ab75..12e2f2e426d 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Remove a row from a MARIA table */ - #include "ma_fulltext.h" #include "ma_rt_index.h" #include "trnman.h" @@ -25,19 +23,21 @@ static int d_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uint comp_flag, my_off_t page, uchar *anc_buff, MARIA_PINNED_PAGE *anc_page_link); static int del(MARIA_HA *info,MARIA_KEYDEF *keyinfo, uchar *key, - uchar *anc_buff, my_off_t leaf_page, uchar *leaf_buff, - MARIA_PINNED_PAGE *leaf_page_link, uchar *keypos, - my_off_t next_block, uchar *ret_key); -static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *anc_buff, - my_off_t leaf_page,uchar *leaf_buff, + my_off_t anc_page, uchar *anc_buff, my_off_t leaf_page, + uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link, + uchar *keypos, my_off_t next_block, uchar *ret_key); +static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo, + my_off_t anc_page, uchar *anc_buff, + my_off_t leaf_page, uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link, uchar *keypos); static uint remove_key(MARIA_KEYDEF *keyinfo,uint nod_flag,uchar *keypos, uchar *lastkey,uchar *page_end, my_off_t *next_block, MARIA_KEY_PARAM *s_temp); static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *key_pos, uint move_length, - uint change_length); + uchar *key_pos, uint changed_length, + uint move_length); +/* @breif Remove a row from a MARIA table */ int maria_delete(MARIA_HA *info,const uchar *record) { @@ -48,8 +48,7 @@ int maria_delete(MARIA_HA *info,const uchar *record) MARIA_SHARE *share=info->s; DBUG_ENTER("maria_delete"); - /* Test if record is in datafile */ - + /* Test if record is in datafile */ DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_usage", maria_print_error(share, HA_ERR_CRASHED); DBUG_RETURN(my_errno= HA_ERR_CRASHED);); @@ -157,8 +156,15 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, int res; LSN lsn= LSN_IMPOSSIBLE; my_off_t new_root= info->s->state.key_root[keynr]; + uchar key_buff[HA_MAX_KEY_BUFF]; DBUG_ENTER("_ma_ck_delete"); + if (info->s->now_transactional) + { + /* Save original value as the key may change */ + memcpy(key_buff, key, key_length + info->s->rec_reflength); + } + res= _ma_ck_real_delete(info, info->s->keyinfo+keynr, key, key_length, &new_root); @@ -184,9 +190,10 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, log_type= LOGREC_UNDO_KEY_DELETE_WITH_ROOT; } + key_length+= info->s->rec_reflength; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key; + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key_buff; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length; msg.root= &info->s->state.key_root[keynr]; @@ -278,16 +285,16 @@ err: } /* _ma_ck_real_delete */ -/* - @brief Remove key below key root +/** + @brief Remove key below key root - @param key Key to delete. Will contain new key if block was enlarged + @param key Key to delete. Will contain new key if block was enlarged - @return - @retval 0 ok (anc_page is not changed) - @retval 1 If data on page is too small; In this case anc_buff is not saved - @retval 2 If data on page is too big - @retval -1 On errors + @return + @retval 0 ok (anc_page is not changed) + @retval 1 If data on page is too small; In this case anc_buff is not saved + @retval 2 If data on page is too big + @retval -1 On errors */ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, @@ -421,14 +428,15 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { /* Found key */ uint tmp; - length= _ma_get_page_used(info, anc_buff); - if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length, + uint anc_buff_length= _ma_get_page_used(info, anc_buff); + if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey, + anc_buff + anc_buff_length, &next_block, &s_temp))) goto err; anc_page_link->changed= 1; - length-= tmp; - _ma_store_page_used(info, anc_buff, length, nod_flag); + anc_buff_length-= tmp; + _ma_store_page_used(info, anc_buff, anc_buff_length, nod_flag); /* Log initial changes on pages @@ -437,14 +445,14 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, */ if (info->s->now_transactional && _ma_log_delete(info, anc_page, anc_buff, s_temp.key_pos, - s_temp.move_length, s_temp.changed_length)) + s_temp.changed_length, s_temp.move_length)) DBUG_RETURN(-1); if (!nod_flag) { /* On leaf page */ - if (test(length <= (info->quick_mode ? - MARIA_MIN_KEYBLOCK_LENGTH : - (uint) keyinfo->underflow_block_length))) + if (test(anc_buff_length <= (info->quick_mode ? + MARIA_MIN_KEYBLOCK_LENGTH : + (uint) keyinfo->underflow_block_length))) { /* Page will be written by caller if we return 1 */ DBUG_RETURN(1); @@ -456,15 +464,16 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_RETURN(0); } save_flag=1; /* Mark that anc_buff is changed */ - ret_value= del(info, keyinfo, key, anc_buff, leaf_page, leaf_buff, - leaf_page_link, keypos, next_block, lastkey); + ret_value= del(info, keyinfo, key, anc_page, anc_buff, + leaf_page, leaf_buff, leaf_page_link, + keypos, next_block, lastkey); } if (ret_value >0) { save_flag=1; if (ret_value == 1) - ret_value= underflow(info, keyinfo, anc_buff, leaf_page, leaf_buff, - leaf_page_link, keypos); + ret_value= underflow(info, keyinfo, anc_page, anc_buff, + leaf_page, leaf_buff, leaf_page_link, keypos); else { /* This happens only with packed keys */ DBUG_PRINT("test",("Enlarging of key when deleting")); @@ -478,8 +487,12 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (ret_value == 0 && _ma_get_page_used(info, anc_buff) > (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { + /* parent buffer got too big ; We have to split the page */ save_flag=1; - ret_value= _ma_split_page(info,keyinfo,key,anc_buff,lastkey,0) | 2; + ret_value= _ma_split_page(info, keyinfo, key, anc_page, anc_buff, + (uint) (keyinfo->block_length - + KEYPAGE_CHECKSUM_SIZE), + (uchar*) 0, 0, 0, lastkey, 0) | 2; } if (save_flag && ret_value != 1) { @@ -503,17 +516,39 @@ err: } /* d_search */ -/* Remove a key that has a page-reference */ +/** + @brief Remove a key that has a page-reference + + @param info Maria handler + @param key Buffer for key to be inserted at upper level + @param anc_page Page address for page where deleted key was + @param anc_buff Page buffer (nod) where deleted key was + @param leaf_page Page address for nod before the deleted key + @param leaf_buff Buffer for leaf_page + @param leaf_buff_link Pinned page link for leaf_buff + @param keypos Pos to where deleted key was on anc_buff + @param next_block Page adress for nod after deleted key + @param ret_key Key before keypos in anc_buff + + @notes + leaf_buff is written to disk + anc_buff is not updated on disk. Caller should do this + + @return + @retval < 0 Error + @retval 0 OK + @retval 1 key contains key to upper level (from balance page) + @retval 2 key contains key to upper level (from split space) +*/ -static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uchar *anc_buff, my_off_t leaf_page, - uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link, - uchar *keypos, /* Pos to where deleted key was */ - my_off_t next_block, - uchar *ret_key) /* key before keypos in anc_buff */ +static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uchar *key, my_off_t anc_page, uchar *anc_buff, + my_off_t leaf_page, uchar *leaf_buff, + MARIA_PINNED_PAGE *leaf_page_link, + uchar *keypos, my_off_t next_block, uchar *ret_key) { int ret_value,length; - uint a_length, nod_flag, used_length, tmp; + uint a_length, nod_flag, leaf_length, tmp; my_off_t next_page; uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; MARIA_SHARE *share=info->s; @@ -523,10 +558,10 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page, (ulong) keypos)); - _ma_get_used_and_nod(info, leaf_buff, used_length, nod_flag); - DBUG_DUMP("leaf_buff", leaf_buff, used_length); + _ma_get_used_and_nod(info, leaf_buff, leaf_length, nod_flag); + DBUG_DUMP("leaf_buff", leaf_buff, leaf_length); - endpos= leaf_buff + used_length; + endpos= leaf_buff + leaf_length; if (!(key_start= _ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, &tmp))) DBUG_RETURN(-1); @@ -543,21 +578,26 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { DBUG_DUMP("next_page", next_buff, _ma_get_page_used(info, next_buff)); - if ((ret_value= del(info,keyinfo,key,anc_buff, next_page, next_buff, - next_page_link, keypos, next_block, ret_key)) >0) + if ((ret_value= del(info, keyinfo, key, anc_page, anc_buff, next_page, + next_buff, next_page_link, keypos, next_block, + ret_key)) >0) { /* Get new length after key was deleted */ endpos=leaf_buff+_ma_get_page_used(info, leaf_buff); if (ret_value == 1) { - ret_value= underflow(info, keyinfo, leaf_buff, next_page, + ret_value= underflow(info, keyinfo, leaf_page, leaf_buff, next_page, next_buff, next_page_link, endpos); if (ret_value == 0 && _ma_get_page_used(info, leaf_buff) > (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { - ret_value= (_ma_split_page(info,keyinfo,key,leaf_buff,ret_key,0) | - 2); + ret_value= (_ma_split_page(info, keyinfo, key, + leaf_page, leaf_buff, + (uint) (keyinfo->block_length - + KEYPAGE_CHECKSUM_SIZE), + (uchar*) 0, 0, 0, + ret_key, 0) | 2); } } else @@ -582,8 +622,14 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } /* Remove last key from leaf page */ - leaf_page_link->changed= 1; _ma_store_page_used(info, leaf_buff, key_start-leaf_buff, nod_flag); + + if (info->s->now_transactional && + _ma_log_suffix(info, leaf_page, leaf_buff, leaf_length, + (uint) (key_start - leaf_buff))) + goto err; + + leaf_page_link->changed= 1; if (_ma_write_keypage(info, keyinfo, leaf_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, leaf_buff)) @@ -607,6 +653,8 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else bmove(keypos,keypos-length, (int) (endpos-keypos)+length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); + key_start= keypos; + /* Save pointer to next leaf */ if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key)) goto err; @@ -614,6 +662,11 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, _ma_store_page_used(info, anc_buff, a_length + length, share->base.key_reflength); + if (info->s->now_transactional && + _ma_log_add(info, anc_page, anc_buff, a_length + length, + key_start, s_temp.changed_length, s_temp.move_length, 1)) + goto err; + DBUG_RETURN(_ma_get_page_used(info, leaf_buff) <= (info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : (uint) keyinfo->underflow_block_length)); @@ -622,25 +675,44 @@ err: } /* del */ - /* Balances adjacent pages if underflow occours */ +/** + @brief Balances adjacent pages if underflow occours + + @fn underflow() + @param anc_buff Anchestor page data + @param leaf_page Page number of leaf page + @param leaf_buff Leaf page (page that underflowed) + @param leaf_page_link Pointer to pin information about leaf page + @param keypos Position after current key in anc_buff + + @note + This function writes redo entries for all changes + Caller must save anc_buff + + @return + @retval 0 ok + @retval 1 ok, but anc_buff did underflow + @retval -1 error + */ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *anc_buff, - my_off_t leaf_page,/* Ancestor page and underflow page */ - uchar *leaf_buff, + my_off_t anc_page, uchar *anc_buff, + my_off_t leaf_page, uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link, - uchar *keypos) /* Position to pos after key */ + uchar *keypos) { int t_length; - uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag, - key_reflength,key_length; + uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag; + uint next_buff_length, new_buff_length, key_reflength, key_length; + uint unchanged_leaf_length, new_leaf_length; my_off_t next_page; uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF]; - uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key; - uchar *after_key; - MARIA_KEY_PARAM s_temp; + uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*prev_key; + uchar *after_key, *anc_end_pos; + MARIA_KEY_PARAM key_deleted, key_inserted; MARIA_SHARE *share=info->s; MARIA_PINNED_PAGE *next_page_link; + my_bool first_key; DBUG_ENTER("underflow"); DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page, (ulong) keypos)); @@ -657,10 +729,12 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, key_reflength=share->base.key_reflength; if (info->s->keyinfo+info->lastinx == keyinfo) info->page_changed=1; + first_key= keypos == anc_buff + info->s->keypage_header + key_reflength; if ((keypos < anc_buff + anc_length && (info->state->records & 1)) || - keypos == anc_buff + info->s->keypage_header + key_reflength) - { /* Use page right of anc-page */ + first_key) + { + /* Use page right of anc-page */ DBUG_PRINT("test",("use right page")); if (keyinfo->flag & HA_BINARY_PACK_KEY) @@ -681,8 +755,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!_ma_fetch_keypage(info,keyinfo, next_page, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, buff, 0, &next_page_link)) goto err; - buff_length= _ma_get_page_used(info, buff); - DBUG_DUMP("next",buff,buff_length); + next_buff_length= _ma_get_page_used(info, buff); + DBUG_DUMP("next", buff, next_buff_length); /* find keys to make a big key-page */ bmove(next_keypos-key_reflength, buff + info->s->keypage_header, @@ -696,67 +770,97 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,buff+p_length, prev_key, prev_key, - anc_key, &s_temp); - length=buff_length-p_length; + anc_key, &key_inserted); + length= next_buff_length - p_length; endpos=buff+length+leaf_length+t_length; /* buff will always be larger than before !*/ - bmove_upp(endpos, buff+buff_length,length); + bmove_upp(endpos, buff + next_buff_length, length); memcpy(buff, leaf_buff,(size_t) leaf_length); - (*keyinfo->store_key)(keyinfo,buff+leaf_length,&s_temp); - buff_length=(uint) (endpos-buff); + (*keyinfo->store_key)(keyinfo, buff+leaf_length, &key_inserted); + buff_length= (uint) (endpos-buff); _ma_store_page_used(info, buff, buff_length, nod_flag); /* remove key from anc_buff */ - if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key, - anc_buff+anc_length,(my_off_t *) 0, &s_temp))) + anc_buff+anc_length,(my_off_t *) 0, + &key_deleted))) goto err; anc_length-=s_length; _ma_store_page_used(info, anc_buff, anc_length, key_reflength); if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) - { /* Keys in one page */ - memcpy(leaf_buff,buff,(size_t) buff_length); + { + /* All keys fitted into one page */ next_page_link->changed= 1; if (_ma_dispose(info, next_page, 0)) goto err; + + memcpy(leaf_buff, buff, (size_t) buff_length); + + if (info->s->now_transactional) + { + /* Log changes to parent page */ + if (_ma_log_delete(info, anc_page, anc_buff, key_deleted.key_pos, + key_deleted.changed_length, + key_deleted.move_length)) + goto err; + /* + Log changes to leaf page. Data for leaf page is in buff + which contains original leaf_buff, parting key and next_buff + */ + if (_ma_log_suffix(info, leaf_page, leaf_buff, + leaf_length, buff_length)) + goto err; + } } else - { /* Page is full */ - endpos=anc_buff+anc_length; - DBUG_PRINT("test",("anc_buff: 0x%lx endpos: 0x%lx", - (long) anc_buff, (long) endpos)); - if (keypos != anc_buff + info->s->keypage_header + key_reflength && + { + /* + Balancing didn't free a page, so we have to split 'buff' into two + pages: + - Find key in middle of buffer + - Store everything before key in 'leaf_buff' + - Pack key into anc_buff at position of deleted key + Note that anc_buff may overflow! (is handled by caller) + - Store remaining keys in next_page (buff) + */ + MARIA_KEY_PARAM anc_key_inserted; + + anc_end_pos= anc_buff + anc_length; + DBUG_PRINT("test",("anc_buff: 0x%lx anc_end_pos: 0x%lx", + (long) anc_buff, (long) anc_end_pos)); + if (!first_key && !_ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length)) goto err; if (!(half_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key, &key_length, &after_key))) goto err; - length=(uint) (half_pos-buff); - memcpy(leaf_buff,buff,(size_t) length); - _ma_store_page_used(info, leaf_buff, length, nod_flag); + new_leaf_length= (uint) (half_pos-buff); + memcpy(leaf_buff, buff, (size_t) new_leaf_length); + _ma_store_page_used(info, leaf_buff, new_leaf_length, nod_flag); /* Correct new keypointer to leaf_page */ half_pos=after_key; _ma_kpointer(info,leaf_key+key_length,next_page); + /* Save key in anc_buff */ - prev_key=(keypos == anc_buff + info->s->keypage_header + key_reflength ? - (uchar*) 0 : anc_key), + prev_key= (first_key ? (uchar*) 0 : anc_key); t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, - (keypos == endpos ? (uchar*) 0 : + (keypos == anc_end_pos ? (uchar*) 0 : keypos), prev_key, prev_key, - leaf_key, &s_temp); + leaf_key, &anc_key_inserted); if (t_length >= 0) - bmove_upp(endpos+t_length, endpos, (uint) (endpos-keypos)); + bmove_upp(anc_end_pos+t_length, anc_end_pos, + (uint) (anc_end_pos - keypos)); else - bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length); - (*keyinfo->store_key)(keyinfo,keypos,&s_temp); + bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length); + (*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted); anc_length+= t_length; _ma_store_page_used(info, anc_buff, anc_length, key_reflength); - /* Store key first in new page */ + /* Store key first in new page */ if (nod_flag) bmove(buff+info->s->keypage_header, half_pos-nod_flag, (size_t) nod_flag); @@ -764,19 +868,73 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (uchar*) 0, (uchar*) 0, (uchar*) 0, - leaf_key, &s_temp); + leaf_key, &key_inserted); /* t_length will always be > 0 for a new page !*/ - length=(uint) ((buff+_ma_get_page_used(info, buff))-half_pos); + length= (uint) ((buff + buff_length) - half_pos); bmove(buff+p_length+t_length, half_pos, (size_t) length); - (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp); - _ma_store_page_used(info, buff, length + t_length + p_length, nod_flag); + (*keyinfo->store_key)(keyinfo,buff+p_length, &key_inserted); + new_buff_length= length + t_length + p_length; + _ma_store_page_used(info, buff, new_buff_length, nod_flag); + + if (info->s->now_transactional) + { + /* + Log changes to parent page + This has one key deleted from it and one key inserted to it at + keypos + + ma_log_add ensures that we don't log changes that is outside of + key block size, as the REDO code can't handle that + */ + if (_ma_log_add(info, anc_page, anc_buff, anc_length, + keypos, + anc_key_inserted.move_length + + min(anc_key_inserted.changed_length - + anc_key_inserted.move_length, + key_deleted.changed_length), + anc_key_inserted.move_length - + key_deleted.move_length, 1)) + goto err; + /* + Log changes to leaf page. + This contains original data with new data added at end + */ + DBUG_ASSERT(leaf_length <= new_leaf_length); + if (_ma_log_suffix(info, leaf_page, leaf_buff, leaf_length, + new_leaf_length)) + goto err; + /* + Log changes to next page + + This contains original data with some prefix data deleted and + some compressed data at start possible extended + + Data in buff was originally: + org_leaf_buff [leaf_length] + separator_key [buff_key_inserted.move_length] + next_key_changes [buff_key_inserted.changed_length -move_length] + next_page_data [next_buff_length - p_length - + (buff_key_inserted.changed_length -move_length)] + + After changes it's now: + unpacked_key [key_inserted.changed_length] + next_suffix [next_buff_length - key_inserted.changed_length] + + */ + DBUG_ASSERT(new_buff_length <= next_buff_length); + if (_ma_log_prefix(info, next_page, buff, + key_inserted.changed_length, + (int) (new_buff_length - next_buff_length))) + goto err; + } next_page_link->changed= 1; if (_ma_write_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, buff)) goto err; } + leaf_page_link->changed= 1; if (_ma_write_keypage(info, keyinfo, leaf_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, @@ -796,7 +954,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DFLT_INIT_HITS, buff, 0, &next_page_link)) goto err; buff_length= _ma_get_page_used(info, buff); - endpos=buff+buff_length; + endpos= buff + buff_length; DBUG_DUMP("prev",buff,buff_length); /* find keys to make a big key-page */ @@ -815,59 +973,96 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, (leaf_length == p_length ? (uchar*) 0 : leaf_buff+p_length), prev_key, prev_key, - anc_key, &s_temp); + anc_key, &key_inserted); if (t_length >= 0) bmove(endpos+t_length, leaf_buff+p_length, (size_t) (leaf_length-p_length)); else /* We gained space */ bmove(endpos,leaf_buff+((int) p_length-t_length), (size_t) (leaf_length-p_length+t_length)); + (*keyinfo->store_key)(keyinfo,endpos, &key_inserted); - (*keyinfo->store_key)(keyinfo,endpos,&s_temp); - buff_length=buff_length+leaf_length-p_length+t_length; - _ma_store_page_used(info, buff, buff_length, nod_flag); + /* Remember for logging how many bytes of leaf_buff that are not changed */ + DBUG_ASSERT((int) key_inserted.changed_length >= key_inserted.move_length); + unchanged_leaf_length= leaf_length - (key_inserted.changed_length - + key_inserted.move_length); + + new_buff_length= buff_length + leaf_length - p_length + t_length; + _ma_store_page_used(info, buff, new_buff_length, nod_flag); /* remove key from anc_buff */ if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key, - anc_buff+anc_length,(my_off_t *) 0, &s_temp))) + anc_buff+anc_length,(my_off_t *) 0, + &key_deleted))) goto err; anc_length-=s_length; _ma_store_page_used(info, anc_buff, anc_length, key_reflength); - if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) - { /* Keys in one page */ + if (new_buff_length <= (uint) (keyinfo->block_length - + KEYPAGE_CHECKSUM_SIZE)) + { + /* All keys fitted into one page */ leaf_page_link->changed= 1; if (_ma_dispose(info, leaf_page, 0)) goto err; + + if (info->s->now_transactional) + { + /* Log changes to parent page */ + if (_ma_log_delete(info, anc_page, anc_buff, key_deleted.key_pos, + key_deleted.changed_length, key_deleted.move_length)) + + goto err; + /* + Log changes to next page. Data for leaf page is in buff + that contains original leaf_buff, parting key and next_buff + */ + if (_ma_log_suffix(info, next_page, buff, + buff_length, new_buff_length)) + goto err; + } } else - { /* Page is full */ - if (keypos == anc_buff+ info->s->keypage_header + key_reflength) - anc_pos=0; /* First key */ + { + /* + Balancing didn't free a page, so we have to split 'buff' into two + pages + - Find key in middle of buffer (buff) + - Pack key at half_buff into anc_buff at position of deleted key + Note that anc_buff may overflow! (is handled by caller) + - Move everything after middlekey to 'leaf_buff' + - Shorten buff at 'endpos' + */ + MARIA_KEY_PARAM anc_key_inserted; + + if (first_key) + anc_pos= 0; /* First key */ else if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_pos=anc_key,keypos, &length)) goto err; - endpos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key, - &key_length, &half_pos); - if (!endpos) + if (!(endpos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key, + &key_length, &half_pos))) goto err; + + /* Correct new keypointer to leaf_page */ _ma_kpointer(info,leaf_key+key_length,leaf_page); + /* Save key in anc_buff */ DBUG_DUMP("anc_buff",anc_buff,anc_length); DBUG_DUMP("key_to_anc",leaf_key,key_length); - - temp_pos=anc_buff+anc_length; + anc_end_pos= anc_buff + anc_length; t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, - keypos == temp_pos ? (uchar*) 0 + keypos == anc_end_pos ? (uchar*) 0 : keypos, anc_pos, anc_pos, - leaf_key,&s_temp); - if (t_length > 0) - bmove_upp(temp_pos+t_length, temp_pos, (uint) (temp_pos-keypos)); + leaf_key, &anc_key_inserted); + if (t_length >= 0) + bmove_upp(anc_end_pos+t_length, anc_end_pos, + (uint) (anc_end_pos-keypos)); else - bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length); - (*keyinfo->store_key)(keyinfo,keypos,&s_temp); + bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length); + (*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted); anc_length+= t_length; _ma_store_page_used(info, anc_buff, anc_length, key_reflength); @@ -879,20 +1074,63 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; DBUG_DUMP("key_to_leaf",leaf_key,length); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0, - (uchar*) 0, (uchar*) 0, leaf_key, &s_temp); - length=(uint) ((buff+buff_length)-half_pos); + (uchar*) 0, (uchar*) 0, leaf_key, + &key_inserted); + /* t_length will always be > 0 for a new page !*/ + length= (uint) ((buff + new_buff_length) - half_pos); DBUG_PRINT("info",("t_length: %d length: %d",t_length,(int) length)); - bmove(leaf_buff+p_length+t_length,half_pos, - (size_t) length); - (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp); - _ma_store_page_used(info, leaf_buff, length + t_length + p_length, - nod_flag); + bmove(leaf_buff+p_length+t_length, half_pos, (size_t) length); + (*keyinfo->store_key)(keyinfo,leaf_buff+p_length, &key_inserted); + new_leaf_length= length + t_length + p_length; + _ma_store_page_used(info, leaf_buff, new_leaf_length, nod_flag); + new_buff_length= (uint) (endpos - buff); + _ma_store_page_used(info, buff, new_buff_length, nod_flag); + + if (info->s->now_transactional) + { + /* + Log changes to parent page + This has one key deleted from it and one key inserted to it at + keypos + + ma_log_add() ensures that we don't log changes that is outside of + key block size, as the REDO code can't handle that + */ + if (_ma_log_add(info, anc_page, anc_buff, anc_length, + keypos, + anc_key_inserted.move_length + + min(anc_key_inserted.changed_length - + anc_key_inserted.move_length, + key_deleted.changed_length), + anc_key_inserted.move_length - + key_deleted.move_length, 1)) + goto err; + + /* + Log changes to leaf page. + This contains original data with new data added first + */ + DBUG_ASSERT(leaf_length <= new_leaf_length); + if (_ma_log_prefix(info, leaf_page, leaf_buff, + new_leaf_length - unchanged_leaf_length, + (int) (new_leaf_length - leaf_length))) + goto err; + /* + Log changes to next page + This contains original data with some suffix data deleted + + */ + DBUG_ASSERT(new_buff_length <= buff_length); + if (_ma_log_suffix(info, next_page, buff, + buff_length, new_buff_length)) + goto err; + } + leaf_page_link->changed= 1; if (_ma_write_keypage(info, keyinfo, leaf_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, leaf_buff)) goto err; - _ma_store_page_used(info, buff, (uint) (endpos - buff),nod_flag); } next_page_link->changed= 1; if (_ma_write_keypage(info, keyinfo, next_page, @@ -906,7 +1144,7 @@ err: } /* underflow */ -/* +/** @brief Remove a key from page @fn remove_key() @@ -1067,13 +1305,22 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag, Logging of redos ****************************************************************************/ -/* - @brief log entry where some parts are deleted and some things are changed +/** + @brief log entry where some parts are deleted and some things are changed + + @fn _ma_log_delete() + @param info Maria handler + @param page Pageaddress for changed page + @param buff Page buffer + @param key_pos Start of change area + @param changed_length How many bytes where changed at key_pos + @param move_length How many bytes where deleted at key_pos + */ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *key_pos, uint move_length, - uint change_length) + uchar *key_pos, uint changed_length, + uint move_length) { LSN lsn; uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 9], *log_pos; @@ -1081,6 +1328,8 @@ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, uint translog_parts; uint offset= (uint) (key_pos - buff); DBUG_ENTER("_ma_log_delete"); + DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d", + (ulong) page, changed_length, move_length)); DBUG_ASSERT(info->s->now_transactional && move_length); /* Store address of new root page */ @@ -1093,14 +1342,14 @@ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, int2store(log_pos+4, -(int) move_length); log_pos+= 6; translog_parts= 1; - if (change_length) + if (changed_length) { log_pos[0]= KEY_OP_CHANGE; - int2store(log_pos+1, change_length); + int2store(log_pos+1, changed_length); log_pos+= 3; translog_parts= 2; log_array[TRANSLOG_INTERNAL_PARTS + 1].str= buff + offset; - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= change_length; + log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; } log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; @@ -1109,7 +1358,7 @@ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, if (translog_write_record(&lsn, LOGREC_REDO_INDEX, info->trn, info, log_array[TRANSLOG_INTERNAL_PARTS + 0].length + - change_length, + changed_length, TRANSLOG_INTERNAL_PARTS + translog_parts, log_array, log_data, NULL)) DBUG_RETURN(1); diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index b2655e53260..a62eb0cf0e0 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -24,7 +24,7 @@ Some helper functions used both by key page loggin and block page loggin ****************************************************************************/ -/* +/** @brief Unpin all pinned pages @fn _ma_unpin_all_pages() @@ -50,7 +50,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) DBUG_PRINT("info", ("undo_lsn: %lu", (ulong) undo_lsn)); if (!info->s->now_transactional) - undo_lsn= LSN_IMPOSSIBLE; /* don't try to set a LSN on pages */ + DBUG_ASSERT(undo_lsn == LSN_IMPOSSIBLE || maria_in_recovery); while (pinned_page-- != page_link) { @@ -70,7 +70,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, enum translog_record_type undo_type, my_bool store_checksum, ha_checksum checksum, - LSN *res_lsn) + LSN *res_lsn, void *extra_msg) { uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE + @@ -86,11 +86,16 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, undo_type); log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data) - HA_CHECKSUM_STORE_SIZE; + + /* Extra_msg is handled in write_hook_for_clr_end() */ msg.undone_record_type= undo_type; msg.previous_undo_lsn= undo_lsn; + msg.extra_msg= extra_msg; + msg.checksum_delta= 0; if (store_checksum) { + msg.checksum_delta= checksum; ha_checksum_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + CLR_TYPE_STORE_SIZE, checksum); log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); @@ -106,6 +111,293 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, } +/** + @brief Sets transaction's undo_lsn, first_undo_lsn if needed + + @return Operation status, always 0 (success) +*/ + +my_bool write_hook_for_clr_end(enum translog_record_type type + __attribute__ ((unused)), + TRN *trn, MARIA_HA *tbl_info + __attribute__ ((unused)), + LSN *lsn __attribute__ ((unused)), + void *hook_arg) +{ + MARIA_SHARE *share= tbl_info->s; + struct st_msg_to_write_hook_for_clr_end *msg= + (struct st_msg_to_write_hook_for_clr_end *)hook_arg; + DBUG_ASSERT(trn->trid != 0); + trn->undo_lsn= msg->previous_undo_lsn; + + switch (msg->undone_record_type) { + case LOGREC_UNDO_ROW_DELETE: + share->state.state.records++; + share->state.state.checksum+= msg->checksum_delta; + break; + case LOGREC_UNDO_ROW_INSERT: + share->state.state.records--; + share->state.state.checksum+= msg->checksum_delta; + break; + case LOGREC_UNDO_ROW_UPDATE: + share->state.state.checksum+= msg->checksum_delta; + break; + case LOGREC_UNDO_KEY_INSERT: + case LOGREC_UNDO_KEY_DELETE: + { + /* Update key root */ + struct st_msg_to_write_hook_for_undo_key *extra_msg= + (struct st_msg_to_write_hook_for_undo_key *) msg->extra_msg; + *extra_msg->root= extra_msg->value; + break; + } + default: + DBUG_ASSERT(0); + } + if (trn->undo_lsn == LSN_IMPOSSIBLE) /* has fully rolled back */ + trn->first_undo_lsn= LSN_WITH_FLAGS_TO_FLAGS(trn->first_undo_lsn); + return 0; +} + + +/** + @brief write hook for undo key insert +*/ + +my_bool write_hook_for_undo_key(enum translog_record_type type, + TRN *trn, MARIA_HA *tbl_info, + LSN *lsn, void *hook_arg) +{ + struct st_msg_to_write_hook_for_undo_key *msg= + (struct st_msg_to_write_hook_for_undo_key *) hook_arg; + + *msg->root= msg->value; + _ma_fast_unlock_key_del(tbl_info); + return write_hook_for_undo(type, trn, tbl_info, lsn, 0); +} + + +/***************************************************************************** + Functions for logging of key page changes +*****************************************************************************/ + +/** + @brief + Write log entry for page that has got data added or deleted at start of page +*/ + +my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, + uchar *buff, uint changed_length, + int move_length) +{ + uint translog_parts; + LSN lsn; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7], *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + DBUG_ENTER("_ma_log_prefix"); + DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d", + (ulong) page, changed_length, move_length)); + + page/= info->s->block_size; + log_pos= log_data + FILEID_STORE_SIZE; + page_store(log_pos, page); + log_pos+= PAGE_STORE_SIZE; + + if (move_length < 0) + { + /* Delete prefix */ + log_pos[0]= KEY_OP_DEL_PREFIX; + int2store(log_pos+1, -move_length); + log_pos+= 3; + translog_parts= 1; + if (changed_length) + { + /* + We don't need a KEY_OP_OFFSET as KEY_OP_DEL_PREFIX has an implicit + offset + */ + log_pos[0]= KEY_OP_CHANGE; + int2store(log_pos+1, changed_length); + log_pos+= 3; + } + } + else + { + /* Add prefix */ + DBUG_ASSERT(changed_length >0 && (int) changed_length >= move_length); + log_pos[0]= KEY_OP_ADD_PREFIX; + int2store(log_pos+1, move_length); + int2store(log_pos+3, changed_length); + log_pos+= 5; + } + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - + log_data); + if (changed_length) + { + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= ((char*) buff + + info->s->keypage_header); + log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; + translog_parts= 2; + } + + DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, + info->trn, info, + log_array[TRANSLOG_INTERNAL_PARTS + + 0].length + changed_length, + TRANSLOG_INTERNAL_PARTS + translog_parts, + log_array, log_data, NULL)); +} + + +/** + @brief + Write log entry for page that has got data added or deleted at end of page +*/ + +my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, + uchar *buff, uint org_length, uint new_length) +{ + LSN lsn; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10], *log_pos; + int diff; + uint translog_parts, extra_length; + DBUG_ENTER("_ma_log_suffix"); + DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u", + (ulong) page, org_length, new_length)); + + page/= info->s->block_size; + + log_pos= log_data + FILEID_STORE_SIZE; + page_store(log_pos, page); + log_pos+= PAGE_STORE_SIZE; + + if ((diff= (int) (new_length - org_length)) < 0) + { + log_pos[0]= KEY_OP_DEL_SUFFIX; + int2store(log_pos+1, -diff); + log_pos+= 3; + translog_parts= 1; + extra_length= 0; + } + else + { + log_pos[0]= KEY_OP_ADD_SUFFIX; + int2store(log_pos+1, diff); + log_pos+= 3; + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) buff + org_length; + log_array[TRANSLOG_INTERNAL_PARTS + 1].length= (uint) diff; + translog_parts= 2; + extra_length= (uint) diff; + } + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - + log_data); + + DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, + info->trn, info, + log_array[TRANSLOG_INTERNAL_PARTS + + 0].length + extra_length, + TRANSLOG_INTERNAL_PARTS + translog_parts, + log_array, log_data, NULL)); +} + + +/** + @brief Log that a key was added to the page + + @note + If handle_overflow is set, then we have to protect against + logging changes that is outside of the page. + This may happen during underflow() handling where the buffer + in memory temporary contains more data than block_size +*/ + +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 __attribute__ ((unused))) +{ + LSN lsn; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3+ 3 + 3 + 3], *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + uint offset= (uint) (key_pos - buff); + uint page_length= info->s->block_size - KEYPAGE_CHECKSUM_SIZE; + DBUG_ENTER("_ma_log_add"); + DBUG_PRINT("enter", ("page: %lu page_length: %u changed_length: %u " + "move_length: %d", + (ulong) page, buff_length, changed_length, + move_length)); + DBUG_ASSERT(info->s->now_transactional); + + /* + Write REDO entry that contains the logical operations we need + to do the page + */ + log_pos= log_data + FILEID_STORE_SIZE; + page/= info->s->block_size; + page_store(log_pos, page); + log_pos+= PAGE_STORE_SIZE; + + if (buff_length + move_length > page_length) + { + /* + Overflow. Cut either key or data from page end so that key fits + The code that splits the too big page will ignore logging any + data over page_length + */ + DBUG_ASSERT(handle_overflow); + if (offset + changed_length > page_length) + { + changed_length= page_length - offset; + move_length= 0; + } + else + { + uint diff= buff_length + move_length - page_length; + log_pos[0]= KEY_OP_DEL_SUFFIX; + int2store(log_pos+1, diff); + log_pos+= 3; + buff_length= page_length - move_length; + } + } + + if (offset == buff_length) + log_pos[0]= KEY_OP_ADD_SUFFIX; + else + { + log_pos[0]= KEY_OP_OFFSET; + int2store(log_pos+1, offset); + log_pos+= 3; + if (move_length) + { + log_pos[0]= KEY_OP_SHIFT; + int2store(log_pos+1, move_length); + log_pos+= 3; + } + log_pos[0]= KEY_OP_CHANGE; + } + int2store(log_pos+1, changed_length); + log_pos+= 3; + + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - + log_data); + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key_pos; + log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; + + if (translog_write_record(&lsn, LOGREC_REDO_INDEX, + info->trn, info, + log_array[TRANSLOG_INTERNAL_PARTS + + 0].length + changed_length, + TRANSLOG_INTERNAL_PARTS + 2, log_array, + log_data, NULL)) + DBUG_RETURN(-1); + DBUG_RETURN(0); +} + + /**************************************************************************** Redo of key pages ****************************************************************************/ @@ -136,6 +428,8 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, uint result; MARIA_SHARE *share= info->s; DBUG_ENTER("_ma_apply_redo_index_new_page"); + DBUG_PRINT("enter", ("root_page: %lu free_page: %lu", + (ulong) root_page, (ulong) free_page)); /* Set header to point at key data */ @@ -156,7 +450,8 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, file_size= (my_off_t) (root_page + 1) * share->block_size; /* If root page */ - if (page_type_flag) + if (page_type_flag && + cmp_translog_addr(lsn, share->state.is_of_horizon) >= 0) share->state.key_root[key_nr]= file_size - share->block_size; if (file_size > info->state->key_file_length) @@ -164,8 +459,8 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, info->state->key_file_length= file_size; buff= info->keyread_buff; info->keyread_buff_used= 1; - unlock_method= PAGECACHE_LOCK_LEFT_UNLOCKED; - unpin_method= PAGECACHE_PIN_LEFT_UNPINNED; + unlock_method= PAGECACHE_LOCK_WRITE; + unpin_method= PAGECACHE_PIN; } else { @@ -183,24 +478,32 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, result= 0; goto err; } - unlock_method= PAGECACHE_LOCK_WRITE_UNLOCK; - unpin_method= PAGECACHE_UNPIN; + unlock_method= PAGECACHE_LOCK_LEFT_WRITELOCKED; + unpin_method= PAGECACHE_PIN_LEFT_PINNED; } /* Write modified page */ - lsn_store(buff, lsn); memcpy(buff + LSN_STORE_SIZE, header, length); bzero(buff + LSN_STORE_SIZE + length, share->block_size - LSN_STORE_SIZE - KEYPAGE_CHECKSUM_SIZE - length); bfill(buff + share->block_size - KEYPAGE_CHECKSUM_SIZE, KEYPAGE_CHECKSUM_SIZE, (uchar) 255); - if (pagecache_write(share->pagecache, + + result= 0; + if (unlock_method == PAGECACHE_LOCK_WRITE && + pagecache_write(share->pagecache, &share->kfile, root_page, 0, buff, PAGECACHE_PLAIN_PAGE, unlock_method, unpin_method, - PAGECACHE_WRITE_DELAY, 0)) - DBUG_RETURN(my_errno); - DBUG_RETURN(0); + PAGECACHE_WRITE_DELAY, &page_link.link, + LSN_IMPOSSIBLE)) + result= 1; + + /* Mark page to be unlocked and written at _ma_unpin_all_pages() */ + page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; + push_dynamic(&info->pinned_pages, (void*) &page_link); + DBUG_RETURN(result); err: pagecache_unlock_by_link(share->pagecache, page_link.link, @@ -234,14 +537,16 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info, uchar *buff; int result; DBUG_ENTER("_ma_apply_redo_index_free_page"); + DBUG_PRINT("enter", ("page: %lu free_page: %lu", + (ulong) page, (ulong) free_page)); share->state.changed|= (STATE_CHANGED | STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES); - old_link= share->state.key_del; - share->state.key_del= ((free_page != IMPOSSIBLE_PAGE_NO) ? - (my_off_t) free_page * share->block_size : - HA_OFFSET_ERROR); + share->state.key_del= (my_off_t) page * share->block_size; + old_link= ((free_page != IMPOSSIBLE_PAGE_NO) ? + (my_off_t) free_page * share->block_size : + HA_OFFSET_ERROR); if (!(buff= pagecache_read(share->pagecache, &info->s->kfile, page, 0, 0, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, @@ -256,20 +561,24 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info, result= 0; goto err; } - /* Write modified page */ - lsn_store(buff, lsn); + /* Free page */ bzero(buff + LSN_STORE_SIZE, share->keypage_header - LSN_STORE_SIZE); _ma_store_keynr(info, buff, (uchar) MARIA_DELETE_KEY_NR); mi_sizestore(buff + share->keypage_header, old_link); share->state.changed|= STATE_NOT_SORTED_PAGES; - if (pagecache_write(share->pagecache, - &info->s->kfile, page, 0, - buff, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_WRITE_UNLOCK, - PAGECACHE_UNPIN, - PAGECACHE_WRITE_DELAY, 0)) - DBUG_RETURN(my_errno); +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY + { + bzero(buff + share->keypage_header + 8, + share->block_size - share->keypage_header - 8 - + KEYPAGE_CHECKSUM_SIZE); + } +#endif + + /* Mark page to be unlocked and written at _ma_unpin_all_pages() */ + page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; + push_dynamic(&info->pinned_pages, (void*) &page_link); DBUG_RETURN(0); err: @@ -303,7 +612,7 @@ err: KEY_OP_DEL_PREFIX 2 length Bytes to be deleted at page start KEY_OP_ADD_SUFFIX 2 length, data Add data to end of page KEY_OP_DEL_SUFFIX 2 length Reduce page length with this - + Sets position to start of page @return Operation status @retval 0 OK @retval 1 Error @@ -322,6 +631,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, int result; uint org_page_length; DBUG_ENTER("_ma_apply_redo_index"); + DBUG_PRINT("enter", ("page: %lu", (ulong) page)); /* Set header to point at key data */ header+= PAGE_STORE_SIZE; @@ -344,6 +654,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, _ma_get_used_and_nod(info, buff, page_length, nod_flag); keypage_header= share->keypage_header; org_page_length= page_length; + DBUG_PRINT("info", ("page_length: %u", page_length)); /* Apply modifications to page */ do @@ -358,7 +669,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, { int length= sint2korr(header); header+= 2; - DBUG_ASSERT(page_offset != 0 && page_offset < page_length && + DBUG_ASSERT(page_offset != 0 && page_offset <= page_length && page_length + length < share->block_size); if (length < 0) @@ -382,14 +693,14 @@ uint _ma_apply_redo_index(MARIA_HA *info, case KEY_OP_ADD_PREFIX: { uint insert_length= uint2korr(header); - uint change_length= uint2korr(header+2); - DBUG_ASSERT(insert_length <= change_length && - page_length + change_length <= share->block_size); + uint changed_length= uint2korr(header+2); + DBUG_ASSERT(insert_length <= changed_length && + page_length + changed_length <= share->block_size); bmove_upp(buff + page_length + insert_length, buff + page_length, page_length - keypage_header); - memcpy(buff + keypage_header, header + 4 , change_length); - header+= 4 + change_length; + memcpy(buff + keypage_header, header + 4 , changed_length); + header+= 4 + changed_length; page_length+= insert_length; break; } @@ -402,6 +713,8 @@ uint _ma_apply_redo_index(MARIA_HA *info, bmove(buff + keypage_header, buff + keypage_header + length, page_length - keypage_header - length); page_length-= length; + + page_offset= keypage_header; /* Prepare for change */ break; } case KEY_OP_ADD_SUFFIX: @@ -432,7 +745,6 @@ uint _ma_apply_redo_index(MARIA_HA *info, DBUG_ASSERT(header == header_end); /* Write modified page */ - lsn_store(buff, lsn); _ma_store_page_used(info, buff, page_length, nod_flag); /* @@ -442,12 +754,19 @@ uint _ma_apply_redo_index(MARIA_HA *info, if (page_length < org_page_length) bzero(buff + page_length, org_page_length-page_length); + result= 0; if (pagecache_write(share->pagecache, &info->s->kfile, page, 0, buff, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, - PAGECACHE_WRITE_DELAY, 0)) - DBUG_RETURN(my_errno); + PAGECACHE_LOCK_LEFT_WRITELOCKED, + PAGECACHE_PIN_LEFT_PINNED, + PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE)) + result= 1; + + /* Mark page to be unlocked and written at _ma_unpin_all_pages() */ + page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; + page_link.changed= 1; + push_dynamic(&info->pinned_pages, (void*) &page_link); DBUG_RETURN(0); err: @@ -463,7 +782,6 @@ err: Undo of key block changes ****************************************************************************/ - /** @brief Undo of insert of key (ie, delete the inserted key) */ @@ -476,6 +794,8 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn, uint keynr; uchar key[HA_MAX_KEY_BUFF]; MARIA_SHARE *share= info->s; + my_off_t new_root; + struct st_msg_to_write_hook_for_undo_key msg; DBUG_ENTER("_ma_apply_undo_key_insert"); share->state.changed|= (STATE_CHANGED | STATE_NOT_OPTIMIZED_KEYS | @@ -484,15 +804,20 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn, length-= KEY_NR_STORE_SIZE; /* We have to copy key as _ma_ck_real_delete() may change it */ - memcpy(key, header+ KEY_NR_STORE_SIZE, length); + memcpy(key, header + KEY_NR_STORE_SIZE, length); + DBUG_DUMP("key", key, length); + + new_root= share->state.key_root[keynr]; + res= _ma_ck_real_delete(info, share->keyinfo+keynr, key, + length - info->s->rec_reflength, &new_root); - res= _ma_ck_real_delete(info, share->keyinfo+keynr, key, length, - &share->state.key_root[keynr]); + msg.root= &share->state.key_root[keynr]; + msg.value= new_root; - if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_KEY_INSERT, 1, 0, &lsn)) + if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_KEY_INSERT, 1, 0, &lsn, + (void*) &msg)) res= 1; - _ma_fast_unlock_key_del(info); _ma_unpin_all_pages_and_finalize_row(info, lsn); DBUG_RETURN(res); } @@ -510,6 +835,8 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn, uint keynr; uchar key[HA_MAX_KEY_BUFF]; MARIA_SHARE *share= info->s; + my_off_t new_root; + struct st_msg_to_write_hook_for_undo_key msg; DBUG_ENTER("_ma_apply_undo_key_delete"); share->state.changed|= (STATE_CHANGED | STATE_NOT_OPTIMIZED_KEYS | @@ -517,17 +844,22 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn, keynr= key_nr_korr(header); length-= KEY_NR_STORE_SIZE; - /* We have to copy key as _ma_ck_real_delete() may change it */ - memcpy(key, header+ KEY_NR_STORE_SIZE, length); + /* We have to copy key as _ma_ck_real_write_btree() may change it */ + memcpy(key, header + KEY_NR_STORE_SIZE, length); + DBUG_DUMP("key", key, length); - res= _ma_ck_real_write_btree(info, share->keyinfo+keynr, key, length, - &share->state.key_root[keynr], + new_root= share->state.key_root[keynr]; + res= _ma_ck_real_write_btree(info, share->keyinfo+keynr, key, + length - info->s->rec_reflength, + &new_root, share->keyinfo[keynr].write_comp_flag); - if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_KEY_DELETE, 1, 0, &lsn)) + msg.root= &share->state.key_root[keynr]; + msg.value= new_root; + if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_KEY_DELETE, 1, 0, &lsn, + (void*) &msg)) res= 1; - _ma_fast_unlock_key_del(info); _ma_unpin_all_pages_and_finalize_row(info, lsn); DBUG_RETURN(res); } @@ -537,7 +869,7 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn, Handle some local variables ****************************************************************************/ -/* +/** @brief lock key_del for other threads usage @fn _ma_lock_key_del() @@ -573,13 +905,14 @@ my_bool _ma_lock_key_del(MARIA_HA *info, my_bool insert_at_end) #endif info->used_key_del= 1; share->used_key_del= 1; + share->current_key_del= share->state.key_del; pthread_mutex_unlock(&share->intern_lock); } return 0; } -/* +/** @brief copy changes to key_del and unlock it */ diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h index 9d3548ac472..210d58f3eb8 100644 --- a/storage/maria/ma_key_recover.h +++ b/storage/maria/ma_key_recover.h @@ -21,14 +21,48 @@ 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 */ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, enum translog_record_type undo_type, 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); +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, const uchar *header, uint length); uint _ma_apply_redo_index_free_page(MARIA_HA *info, LSN lsn, diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index c17da41af5a..c6c8dbd2818 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -14,8 +14,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "maria_def.h" -#include "ma_blockrec.h" /* for some constants and in-write hooks */ #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 diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index fc5c850fbf7..18063dd3845 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -117,7 +117,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, &info.blobs,sizeof(MARIA_BLOB)*share->base.blobs, &info.buff,(share->base.max_key_block_length*2+ 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.maria_rtree_recursion_state, share->have_rtree ? 1024 : 0, @@ -304,8 +304,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } share->mode=open_mode; errpos= 1; - if (my_read(kfile,share->state.header.file_version, head_length, - MYF(MY_NABP))) + if (my_pread(kfile,share->state.header.file_version, head_length, 0, + MYF(MY_NABP))) { my_errno= HA_ERR_NOT_A_TABLE; goto err; @@ -355,11 +355,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) goto err; } end_pos=disk_cache+info_length; - errpos= 2; - - VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0))); 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; goto err; @@ -418,8 +415,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) goto err; } /* - If page cache is not initialized, then assume we will create it - after the table is opened! + If page cache is not initialized, then assume we will create the + 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 && share_buff.pagecache->inited != 0) @@ -1226,7 +1225,6 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) @param file file to read from @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) diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index 40b271552ac..906c6161faf 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -122,6 +122,7 @@ int _ma_write_keypage(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, #ifdef IDENTICAL_PAGES_AFTER_RECOVERY { uint length= _ma_get_page_used(info, buff); + DBUG_ASSERT(length <= block_size - KEYPAGE_CHECKSUM_SIZE); bzero(buff + length, block_size - length); } #endif @@ -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); - old_link= share->state.key_del; - share->state.key_del= pos; + old_link= share->current_key_del; + share->current_key_del= pos; page_no= pos / block_size; bzero(buff, share->keypage_header); _ma_store_keynr(info, buff, (uchar) MARIA_DELETE_KEY_NR); mi_sizestore(buff + share->keypage_header, old_link); share->state.changed|= STATE_NOT_SORTED_PAGES; + if (info->s->now_transactional) { LSN lsn; @@ -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)) 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) { /* 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, TODO: replace PAGECACHE_PLAIN_PAGE with PAGECACHE_LSN_PAGE when 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); if (!(buff= pagecache_read(share->pagecache, &share->kfile, pos / block_size, 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)->write_lock= PAGECACHE_LOCK_WRITE; (*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, info->pinned_pages.elements-1, MARIA_PINNED_PAGE *); diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 7768cb1c03c..e0c9a8f9208 100755 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -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, thread); DBUG_ENTER("info_check_lock"); - switch(lock) - { + switch(lock) { case PAGECACHE_LOCK_LEFT_UNLOCKED: if (pin != PAGECACHE_PIN_LEFT_UNPINNED || info) @@ -1199,7 +1198,7 @@ static inline void link_to_changed_list(PAGECACHE *pagecache, none 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 LRU chain is divided into two parts - hot and warm. 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, } #else /* 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 */ ptr_ins= hot ? &pagecache->used_ins : &pagecache->used_last; ins= *ptr_ins; @@ -2730,10 +2729,10 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, LSN lsn, my_bool was_changed) { 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, (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_pin_str[pin])); /* @@ -2799,7 +2798,6 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, (ulong) block)); } - pagecache_set_block_rec_lsn(block, first_REDO_LSN_for_page); if (make_lock_and_pin(pagecache, block, lock, pin, 0)) DBUG_ASSERT(0); /* should not happend */ @@ -4246,6 +4244,11 @@ static void test_key_cache(PAGECACHE *pagecache __attribute__((unused)), } #endif +uchar *pagecache_block_link_to_buffer(PAGECACHE_BLOCK_LINK *block) +{ + return block->buffer; +} + #if defined(PAGECACHE_TIMEOUT) #define KEYCACHE_DUMP_FILE "pagecache_dump.txt" diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index df6f4d07eef..f6d2da66ede 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -269,6 +269,7 @@ extern my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, LEX_STRING *str, LSN *min_lsn); 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 */ diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 4d91367203b..352ece03b05 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -1529,7 +1529,8 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE) } 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); _ma_unpin_all_pages(info, rec->lsn); @@ -1569,6 +1570,9 @@ prototype_redo_exec_hook(UNDO_ROW_UPDATE) 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); _ma_unpin_all_pages(info, rec->lsn); return 0; @@ -1577,6 +1581,9 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT) 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); _ma_unpin_all_pages(info, rec->lsn); return 0; @@ -1595,9 +1602,9 @@ prototype_redo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT) { uint key_nr; 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 + - PAGE_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 + + KEY_NR_STORE_SIZE); share->state.key_root[key_nr]= (page == IMPOSSIBLE_PAGE_NO ? HA_OFFSET_ERROR : page * share->block_size); @@ -1653,6 +1660,7 @@ prototype_redo_exec_hook(CLR_END) LSN previous_undo_lsn; enum translog_record_type undone_record_type; const LOG_DESC *log_desc; + my_bool row_entry= 0; if (info == NULL) return 0; @@ -1668,33 +1676,40 @@ prototype_redo_exec_hook(CLR_END) if (cmp_translog_addr(rec->lsn, share->state.is_of_horizon) >= 0) { 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) { case LOGREC_UNDO_ROW_DELETE: + row_entry= 1; share->state.state.records++; break; case LOGREC_UNDO_ROW_INSERT: share->state.state.records--; + row_entry= 1; break; case LOGREC_UNDO_ROW_UPDATE: + row_entry= 1; + break; + case LOGREC_UNDO_KEY_INSERT: + case LOGREC_UNDO_KEY_DELETE: break; default: 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; } - 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); return 0; } @@ -2356,19 +2371,22 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const pgcache_page_no_t page; MARIA_HA *info; char llbuf[22]; + my_bool index_page_redo_entry= 0; print_redo_phase_progress(rec->lsn); sid= fileid_korr(rec->header); page= page_korr(rec->header + FILEID_STORE_SIZE); - switch(rec->type) { + switch (rec->type) { /* 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_TAIL: case LOGREC_REDO_PURGE_ROW_HEAD: 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); tprint(tracef, " For page %s of table of short id %u", llbuf, sid); break; @@ -2407,12 +2425,9 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const DBUG_ASSERT(info->s->last_version != 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)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 *) hash_search(&all_dirty_pages, (uchar *)&file_and_page_id, sizeof(file_and_page_id)); diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 8eaff88155e..78e787eae4d 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -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 @retval pointer to where key starts @@ -1506,7 +1509,7 @@ _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, const uchar *key, MARIA_KEY_PARAM *s_temp) { 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 */ @@ -1519,26 +1522,28 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag, const uchar *key, MARIA_KEY_PARAM *s_temp) { 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 - compressed (maria_chk reports 'packed + stripped') +/** + @brief Calc length needed to store prefixed compressed keys - 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 - 1 uchar else it's 2 byte + Keys are compressed the following way: - prefix byte(s) The high bit is set if this is a prefix for the prev key - length Packed length if the previous was a prefix byte - [length] data bytes ('length' bytes) - next-key-seg Next key segments + If the max length of first key segment <= 127 bytes the prefix is + 1 uchar else it's 2 byte - If the first segment can have NULL: - The length is 0 for NULLS and 1+length for not null columns. + prefix byte(s) The high bit is set if this is a prefix for the prev key + 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 @@ -1589,7 +1594,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, s_temp->key_length= 0; s_temp->totlength= key_length-1+diff_flag; 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; key_length--; /* We don't store NULL */ @@ -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; length+= org_key_length; } - return (int) length; + return (s_temp->move_length= (int) length); } ref_length=n_length; @@ -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->prev_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) { @@ -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->prev_key+= new_pack_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 @@ -1803,7 +1809,7 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, if (!(tmp_length=(uint) (key-start))) { /* Key can't be re-packed */ s_temp->next_key_pos=0; - return length; + return (s_temp->move_length= length); } ref_length+=tmp_length; n_length-=tmp_length; @@ -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, s_temp->n_ref_length= ref_length; s_temp->prev_length= next_length-ref_length; s_temp->prev_key+= ref_length; - return (int) (length+ s_temp->prev_length - next_length_pack + - get_pack_length(ref_length)); + return s_temp->move_length= ((int) (length+ s_temp->prev_length - + next_length_pack + + get_pack_length(ref_length))); } /* Check how many characters are identical to next key */ key= s_temp->key+next_length; @@ -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) { 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->n_ref_length=ref_length; - return (int) (length-(ref_length - next_length) - next_length_pack + - get_pack_length(ref_length)); + return s_temp->move_length= (int) (length-(ref_length - next_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)), register uchar *key_pos, register MARIA_KEY_PARAM *s_temp) { - memcpy(key_pos, s_temp->key,(size_t) s_temp->totlength); - s_temp->changed_length= s_temp->totlength; + memcpy(key_pos, s_temp->key,(size_t) s_temp->move_length); + s_temp->changed_length= s_temp->move_length; } diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 1a8a55e7f90..d46072e626a 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -97,7 +97,7 @@ int main(int argc,char *argv[]) static int run_test(const char *filename) { 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; ha_rows found,row_count; 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) { if (!silent) 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) { printf("unique check failed\n"); diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index d9a24eb7dff..762d2d7ebb0 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -880,15 +880,6 @@ int main(int argc, char *argv[]) goto err; } 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 found_parts++; diff --git a/storage/maria/ma_test_all.res b/storage/maria/ma_test_all.res index 57b0feeeae8..586aaf68020 100644 --- a/storage/maria/ma_test_all.res +++ b/storage/maria/ma_test_all.res @@ -1,6 +1,7 @@ Running tests with dynamic row format Running tests with static 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 Error: 135 in write at record: 1099 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: warning: Datafile is almost full, 65516 of 65534 used MARIA-table 'test2' is usable but should be fixed - -real 0m0.808s -user 0m0.584s -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 +MARIA RECOVERY TESTS +ALL RECOVERY TESTS OK +!!!!!!!! BUT REMEMBER to FIX this BLOB issue !!!!!!! diff --git a/storage/maria/ma_test_all.sh b/storage/maria/ma_test_all.sh index 2c1cf659c94..96f8bf0ef08 100755 --- a/storage/maria/ma_test_all.sh +++ b/storage/maria/ma_test_all.sh @@ -115,7 +115,7 @@ run_tests() $maria_path/maria_chk$suffix -sm test2 $maria_path/ma_test2$suffix $silent -m10000 -e4096 -K $row_type $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/ma_test2$suffix $silent -m10000 -e16384 -E16384 -K -L $row_type $maria_path/maria_chk$suffix -sm test2 @@ -232,16 +232,16 @@ $maria_path/maria_chk$suffix -ssm test2 # # Some timing tests # -time $maria_path/ma_test2$suffix $silent -time $maria_path/ma_test2$suffix $silent -S -time $maria_path/ma_test2$suffix $silent -M -time $maria_path/ma_test2$suffix $silent -B -time $maria_path/ma_test2$suffix $silent -L -time $maria_path/ma_test2$suffix $silent -K -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 -K -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 -M -time $maria_path/ma_test2$suffix $silent -D -K -W -B -S +#time $maria_path/ma_test2$suffix $silent +#time $maria_path/ma_test2$suffix $silent -S +#time $maria_path/ma_test2$suffix $silent -M +#time $maria_path/ma_test2$suffix $silent -B +#time $maria_path/ma_test2$suffix $silent -L +#time $maria_path/ma_test2$suffix $silent -K +#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 -K -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 -M +#time $maria_path/ma_test2$suffix $silent -D -K -W -B -S diff --git a/storage/maria/ma_test_recovery b/storage/maria/ma_test_recovery index 1219114ebc5..b2329694e62 100755 --- a/storage/maria/ma_test_recovery +++ b/storage/maria/ma_test_recovery @@ -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" # runs a program inserting/deleting rows, then moves the resulting table # elsewhere; applies the log and checks that the data file is @@ -111,10 +108,12 @@ do mv $table.MAI $tmp/$table-good.MAI apply_log "shouldnotchangelog" cmp $table.MAD $tmp/$table-good.MAD + cmp $table.MAI $tmp/$table-good.MAI check_table_is_same echo "testing idempotency" apply_log "shouldnotchangelog" cmp $table.MAD $tmp/$table-good.MAD + cmp $table.MAI $tmp/$table-good.MAI check_table_is_same shift done @@ -157,6 +156,12 @@ do echo "TEST WITH $prog $abort_run_args$test_undo (additional aborted work)" $maria_path/$prog $abort_run_args$test_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 ] then apply_log "shouldchangelog" # should undo aborted work @@ -179,19 +184,9 @@ do check_table_is_same echo "testing applying of CLRs to recreate table" rm $table.MA? - apply_log "shouldnotchangelog" - # the cmp below fails with ma_test1+blobs! @todo RECOVERY BUG why? - # It is probably serious; REDOs shouldn't place rows in different - # 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 + cp $tmp/maria_log* $maria_path + apply_log "dontknow" + cmp $table.MAD $tmp/$table.MAD.after_undo check_table_is_same shift 3 done @@ -213,5 +208,3 @@ if [ "$diff_failed" == "1" ] exit 1 fi 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 !!!!!!!" diff --git a/storage/maria/ma_test_recovery.expected b/storage/maria/ma_test_recovery.expected index a73d1f82f64..249cefea15d 100644 --- a/storage/maria/ma_test_recovery.expected +++ b/storage/maria/ma_test_recovery.expected @@ -1,110 +1,26 @@ -!!!!!!!! REMEMBER to FIX this BLOB issue !!!!!!! Testing the REDO PHASE ALONE TEST WITH ma_test1 -s -M -T -c applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number 1 8192 8192 ---- -> 1 2 6 unique number 1 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number 1 8192 8192 ---- -> 1 2 6 unique number 1 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 114688 Keyfile length: 204800 ---- -> Datafile length: 114688 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 114688 Keyfile length: 204800 ---- -> Datafile length: 114688 Keyfile length: 8192 -========DIFF END======= TEST WITH ma_test2 -s -M -T -c -b65000 applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 2531328 Keyfile length: 155648 ---- -> Datafile length: 2531328 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 2531328 Keyfile length: 155648 ---- -> Datafile length: 2531328 Keyfile length: 8192 -========DIFF END======= Testing the REDO AND UNDO PHASE TEST WITH ma_test1 -s -M -T -c -N --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N --testflag=2 --test-undo=1 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N --testflag=4 --test-undo=1 (additional aborted work) @@ -115,143 +31,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N --testflag=3 --test-undo=1 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t2 -u1 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 8192 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N --testflag=2 --test-undo=2 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N --testflag=4 --test-undo=2 (additional aborted work) @@ -262,143 +101,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N --testflag=3 --test-undo=2 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t2 -u2 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 8192 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N --testflag=2 --test-undo=3 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N --testflag=4 --test-undo=3 (additional aborted work) @@ -409,143 +171,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N --testflag=3 --test-undo=3 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -t2 -u3 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 204800 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 114688 Keyfile length: 8192 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 --test-undo=1 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b --testflag=4 --test-undo=1 (additional aborted work) @@ -556,143 +241,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 --test-undo=1 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t2 -u1 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 --test-undo=2 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b --testflag=4 --test-undo=2 (additional aborted work) @@ -703,143 +311,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 --test-undo=2 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t2 -u2 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 --test-undo=3 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b --testflag=4 --test-undo=3 (additional aborted work) @@ -850,135 +381,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b --testflag=3 --test-undo=3 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -t2 -u3 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=2 --test-undo=1 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=4 --test-undo=1 (additional aborted work) @@ -989,63 +451,27 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 --test-undo=1 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t2 -u1 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 90112 Keyfile length: 204800 @@ -1054,11 +480,11 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 90112 Keyfile length: 204800 @@ -1067,49 +493,24 @@ testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=2 --test-undo=2 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=4 --test-undo=2 (additional aborted work) @@ -1120,63 +521,27 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 --test-undo=2 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t2 -u2 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 90112 Keyfile length: 204800 @@ -1185,11 +550,11 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 90112 Keyfile length: 204800 @@ -1198,49 +563,24 @@ testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 90112 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -H1 --testflag=2 --test-undo=3 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=4 --test-undo=3 (additional aborted work) @@ -1251,127 +591,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -H2 --testflag=3 --test-undo=3 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 16384 Keyfile length: 16384 ---- -> Datafile length: 16384 Keyfile length: 8192 -18c18 -< 1 2 6 unique number NULL 0 8192 8192 ---- -> 1 2 6 unique number NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -H1 -t2 -u3 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 81920 Keyfile length: 204800 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=2 --test-undo=1 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=4 --test-undo=1 (additional aborted work) @@ -1382,127 +661,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 --test-undo=1 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t2 -u1 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=2 --test-undo=2 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=4 --test-undo=2 (additional aborted work) @@ -1513,127 +731,66 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 --test-undo=2 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t2 -u2 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=1 (commit at end) TEST WITH ma_test1 -s -M -T -c -N -b -H1 --testflag=2 --test-undo=3 (additional aborted work) Terminating after inserts Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 (commit at end) Terminating after updates TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=4 --test-undo=3 (additional aborted work) @@ -1644,90 +801,54 @@ testing idempotency applying log testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=2 (commit at end) Terminating after inserts TEST WITH ma_test1 -s -M -T -c -N -b -H2 --testflag=3 --test-undo=3 (additional aborted work) Terminating after updates Dying on request without maria_commit()/maria_close() applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing idempotency applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -========DIFF END======= testing applying of CLRs to recreate table applying log -Differences in maria_chk -dvv, recovery not yet perfect ! -========DIFF START======= -11c11 -< Datafile length: 49152 Keyfile length: 16384 ---- -> Datafile length: 49152 Keyfile length: 8192 -18c18 -< 1 2 6 unique varchar BLOB NULL 0 8192 8192 ---- -> 1 2 6 unique varchar BLOB NULL 0 8192 -========DIFF END======= TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t1 (commit at end) TEST WITH ma_test2 -s -L -K -W -P -M -T -c -b -H1 -t2 -u3 (additional aborted work) Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 212992 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -6c6 +7c7 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -11c11 +12c12 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 155648 Keyfile length: 8192 +> Datafile length: 122880 Keyfile length: 212992 ========DIFF END======= diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 0f980bbb1cc..5348e4c6ac2 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -47,9 +47,6 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t *root, uint comp_flag); static my_bool _ma_log_new(MARIA_HA *info, my_off_t page, uchar *buff, uint page_length, uint key_nr, my_bool root_page); -static my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *end_buff, uchar *key_pos, - uint changed_length, int move_length); static my_bool _ma_log_change(MARIA_HA *info, my_off_t page, uchar *buff, uchar *key_pos, uint length); static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, @@ -58,7 +55,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, uint key_length, int move_length, enum en_key_op prefix_or_suffix, uchar *data, uint data_length, - uint change_length); + uint changed_length); static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page, uchar *buff, uint org_length, uint new_length, uchar *key_pos, uint key_length, @@ -70,12 +67,6 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page, uchar *buff, uint data_deleted_last, uchar *key_pos, uint key_length, int move_length); -static my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, - uchar *buff, uint changed_length, - int move_length); -static my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, - uchar *buff, uint org_length, - uint new_length); /* @brief Default handler for returing position to new row @@ -388,10 +379,17 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, LSN lsn= LSN_IMPOSSIBLE; int error; my_off_t new_root= *root; + uchar key_buff[HA_MAX_KEY_BUFF]; #ifdef NOT_YET DBUG_ENTER("_ma_ck_write_btree_with_log"); #endif + if (info->s->now_transactional) + { + /* Save original value as the key may change */ + memcpy(key_buff, key, key_length + info->s->rec_reflength); + } + error= _ma_ck_real_write_btree(info, keyinfo, key, key_length, &new_root, comp_flag); if (!error && info->s->now_transactional) @@ -404,9 +402,10 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, lsn_store(log_data, info->trn->undo_lsn); key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keyinfo->key_nr); + key_length+= info->s->rec_reflength; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key; + log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) key_buff; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length; msg.root= root; @@ -460,23 +459,6 @@ int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } /* _ma_ck_real_write_btree */ -/* - @brief write hook for undo key insert -*/ - -my_bool write_hook_for_undo_key(enum translog_record_type type, - TRN *trn, MARIA_HA *tbl_info, - LSN *lsn, void *hook_arg) -{ - struct st_msg_to_write_hook_for_undo_key *msg= - (struct st_msg_to_write_hook_for_undo_key *) hook_arg; - - *msg->root= msg->value; - _ma_fast_unlock_key_del(tbl_info); - return write_hook_for_undo(type, trn, tbl_info, lsn, 0); -} - - /** @brief Make a new root with key as only pointer @@ -675,6 +657,9 @@ err: Insert new key at right of key_pos. Note that caller must save anc_buff + This function writes log records for all changed pages + (Including anc_buff and father page) + RETURN < 0 Error. 0 OK @@ -689,7 +674,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, my_bool insert_last) { uint a_length, nod_flag, org_anc_length; - int t_length, res; + int t_length; uchar *endpos, *prev_key; MARIA_KEY_PARAM s_temp; DBUG_ENTER("_ma_insert"); @@ -804,8 +789,8 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { if (info->s->now_transactional && - _ma_log_add(info, anc_page, anc_buff, endpos, key_pos, - s_temp.changed_length, t_length)) + _ma_log_add(info, anc_page, anc_buff, (uint) (endpos - anc_buff), + key_pos, s_temp.changed_length, t_length, 0)) DBUG_RETURN(-1); } DBUG_RETURN(0); /* There is room on page */ @@ -817,44 +802,51 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, father_buff && !insert_last) { s_temp.key_pos= key_pos; - s_temp.move_length= t_length; father_page_link->changed= 1; DBUG_RETURN(_ma_balance_page(info, keyinfo, key, anc_buff, anc_page, father_page, father_buff, father_key_pos, &s_temp)); } - - res= _ma_split_page(info,keyinfo,key,anc_buff,key_buff, insert_last); - if (res < 0) - DBUG_RETURN(res); /* Error */ - - if (info->s->now_transactional) - { - if (_ma_log_split(info, anc_page, anc_buff, org_anc_length, - _ma_get_page_used(info, anc_buff), - key_pos, - s_temp.changed_length, - t_length, KEY_OP_NONE, (uchar*) 0, 0, 0)) - res= -1; - } - DBUG_RETURN(res); + DBUG_RETURN(_ma_split_page(info, keyinfo, key, anc_page, + anc_buff, org_anc_length, + key_pos, s_temp.changed_length, t_length, + key_buff, insert_last)); } /* _ma_insert */ /** @brief split a full page in two and assign emerging item to key - RETURN - @retval 0 ok + @fn _ma_split_page() + info Maria handler + keyinfo Key handler + key Buffer for middle key + split_page Address on disk for split_buff + split_buff Page buffer for page that should be split + org_split_length Original length of split_buff before key was inserted + inserted_key_pos Address in buffer where key was inserted + changed_length Number of bytes changed at 'inserted_key_pos' + move_length Number of bytes buffer was moved when key was inserted + key_buff Key buffer to use for temporary storage of key + insert_last_key If we are insert key on rightmost key page + + @note + split_buff is not stored on disk (caller has to do this) + + @return + @retval 2 ok (Middle key up from _ma_insert()) @retval -1 error */ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff, - my_bool insert_last_key) + uchar *key, my_off_t split_page, uchar *split_buff, + uint org_split_length, + uchar *inserted_key_pos, uint changed_length, + int move_length, + uchar *key_buff, my_bool insert_last_key) { uint length,a_length,key_ref_length,t_length,nod_flag,key_length; - uint page_length; + uint page_length, split_length; uchar *key_pos,*pos, *after_key, *new_buff; my_off_t new_pos; MARIA_KEY_PARAM s_temp; @@ -863,25 +855,26 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_ENTER("maria_split_page"); LINT_INIT(after_key); - DBUG_DUMP("buff", buff, _ma_get_page_used(info, buff)); + DBUG_DUMP("buff", split_buff, _ma_get_page_used(info, split_buff)); info->page_changed=1; /* Info->buff is used */ info->keyread_buff_used=1; new_buff= info->buff; - nod_flag=_ma_test_if_nod(info, buff); + nod_flag=_ma_test_if_nod(info, split_buff); key_ref_length= info->s->keypage_header + nod_flag; if (insert_last_key) - key_pos= _ma_find_last_pos(info, keyinfo, buff, key_buff, &key_length, + key_pos= _ma_find_last_pos(info, keyinfo, split_buff, + key_buff, &key_length, &after_key); else - key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, key_buff, + key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, split_buff, key_buff, &key_length, &after_key); if (!key_pos) DBUG_RETURN(-1); - length=(uint) (key_pos-buff); - a_length= _ma_get_page_used(info, buff); - _ma_store_page_used(info, buff, length, nod_flag); + split_length= (uint) (key_pos - split_buff); + a_length= _ma_get_page_used(info, split_buff); + _ma_store_page_used(info, split_buff, split_length, nod_flag); key_pos=after_key; if (nod_flag) @@ -898,14 +891,14 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_RETURN(-1); _ma_kpointer(info, _ma_move_key(keyinfo,key,key_buff),new_pos); - /* Store new page */ + /* Store new page */ if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff)) DBUG_RETURN(-1); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0, (uchar*) 0, key_buff, &s_temp); - length=(uint) ((buff+a_length)-key_pos); + length=(uint) ((split_buff + a_length) - key_pos); memcpy((uchar*) new_buff+key_ref_length+t_length,(uchar*) key_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,new_buff+key_ref_length,&s_temp); @@ -916,8 +909,8 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* Copy key number */ new_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]= - buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - - KEYPAGE_FLAG_SIZE]; + split_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - + KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]; res= 2; /* Middle key up */ if (info->s->now_transactional && @@ -928,6 +921,15 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(info, keyinfo, new_pos, page_link->write_lock, DFLT_INIT_HITS, new_buff)) res= -1; + + /* Save changes to split pages */ + if (info->s->now_transactional && + _ma_log_split(info, split_page, split_buff, org_split_length, + split_length, + inserted_key_pos, changed_length, move_length, + KEY_OP_NONE, (uchar*) 0, 0, 0)) + res= -1; + DBUG_DUMP("key",(uchar*) key, _ma_keylength(keyinfo,key)); DBUG_RETURN(res); } /* _ma_split_page */ @@ -1046,10 +1048,11 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo, @notes Father_buff will always be changed + Caller must handle saving of curr_buff @return - @retval 0 Balance was done - @retval 1 Middle key up + @retval 0 Balance was done (father buff is saved) + @retval 1 Middle key up (father buff is not saved) @retval -1 Error */ @@ -1360,7 +1363,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, Log changes to page on left (page shortened page at end) */ if (_ma_log_split(info, curr_page, curr_buff, - left_length, new_left_length, + left_length - s_temp->move_length, new_left_length, s_temp->key_pos, s_temp->changed_length, s_temp->move_length, KEY_OP_NONE, (uchar*) 0, 0, 0)) @@ -1370,7 +1373,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, This contains the last 'extra_buff' from 'buff' */ if (_ma_log_prefix(info, next_page, extra_buff, - 0, (int) (extra_length - right_length))) + 0, (int) (extra_buff_length - right_length))) goto err; /* @@ -1654,68 +1657,6 @@ static my_bool _ma_log_new(MARIA_HA *info, my_off_t page, uchar *buff, /** @brief - Log that a key was added to the page -*/ - -static my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, - uchar *end_buff, uchar *key_pos, - uint changed_length, int move_length) -{ - LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - DBUG_ENTER("_ma_log_add"); - DBUG_PRINT("enter", ("page: %lu", (ulong) page)); - - DBUG_ASSERT(info->s->now_transactional); - - /* - Write REDO entry that contains the logical operations we need - to do the page - */ - log_pos= log_data + FILEID_STORE_SIZE; - page/= info->s->block_size; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if (key_pos == end_buff) - log_pos[0]= KEY_OP_ADD_SUFFIX; - else - { - uint offset= (uint) (key_pos - buff); - log_pos[0]= KEY_OP_OFFSET; - int2store(log_pos+1, offset); - log_pos+= 3; - if (move_length) - { - log_pos[0]= KEY_OP_SHIFT; - int2store(log_pos+1, move_length); - log_pos+= 3; - } - log_pos[0]= KEY_OP_CHANGE; - } - int2store(log_pos+1, changed_length); - log_pos+= 3; - - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - - log_data); - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key_pos; - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; - - if (translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + changed_length, - TRANSLOG_INTERNAL_PARTS + 2, log_array, - log_data, NULL)) - DBUG_RETURN(-1); - DBUG_RETURN(0); -} - - -/** - @brief Log when some part of the key page changes */ @@ -1755,12 +1696,14 @@ static my_bool _ma_log_change(MARIA_HA *info, my_off_t page, uchar *buff, /** - @brief - Write log entry for page that has got a key added to the page under - one and only one of the following senarios: - - Page is shortened from end - - Data is added to end of page - - Data added at front of page + @brief Write log entry for page splitting + + @note + Write log entry for page that has got a key added to the page under + one and only one of the following senarios: + - Page is shortened from end + - Data is added to end of page + - Data added at front of page @param prefix_or_suffix KEY_OP_NONE Ignored KEY_OP_ADD_PREFIX Add data to start of page @@ -1773,7 +1716,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, uchar *key_pos, uint key_length, int move_length, enum en_key_op prefix_or_suffix, uchar *data, uint data_length, - uint change_length) + uint changed_length) { LSN lsn; uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3+3+3+3+3+2]; @@ -1790,7 +1733,7 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, page_store(log_pos, page); log_pos+= PAGE_STORE_SIZE; - if (new_length <= offset) + if (new_length <= offset || !key_pos) { /* Page was split before inserted key. Write redo entry where @@ -1859,9 +1802,9 @@ static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, uchar *buff, log_pos+= 3; if (prefix_or_suffix == KEY_OP_ADD_PREFIX) { - int2store(log_pos+1, change_length); + int2store(log_pos+1, changed_length); log_pos+= 2; - data_length= change_length; + data_length= changed_length; } log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= (char*) data; log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= data_length; @@ -2089,118 +2032,6 @@ static my_bool _ma_log_key_middle(MARIA_HA *info, my_off_t page, uchar *buff, } -/** - @brief - Write log entry for page that has got data added or deleted at start of page -*/ - -static my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, - uchar *buff, uint changed_length, - int move_length) -{ - uint translog_parts; - LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - DBUG_ENTER("_ma_log_prefix"); - DBUG_PRINT("enter", ("page: %lu change_length: %u move_length: %d", - (ulong) page, changed_length, move_length)); - - page/= info->s->block_size; - log_pos= log_data + FILEID_STORE_SIZE; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if (move_length < 0) - { - /* Delete prefix */ - DBUG_ASSERT(changed_length == 0); - log_pos[0]= KEY_OP_DEL_PREFIX; - int2store(log_pos+1, -move_length); - log_pos+= 3; - translog_parts= 1; - } - else - { - /* Add prefix */ - DBUG_ASSERT(changed_length >0 && (int) changed_length >= move_length); - log_pos[0]= KEY_OP_ADD_PREFIX; - int2store(log_pos+1, move_length); - int2store(log_pos+3, changed_length); - log_pos+= 5; - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= ((char*) buff + - info->s->keypage_header); - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; - translog_parts= 2; - } - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - - log_data); - - DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + changed_length, - TRANSLOG_INTERNAL_PARTS + translog_parts, - log_array, log_data, NULL)); -} - - -/** - @brief - Write log entry for page that has got data added or deleted at end of page -*/ - -static my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, - uchar *buff, uint org_length, - uint new_length) -{ - LSN lsn; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10], *log_pos; - int diff; - uint translog_parts, extra_length; - DBUG_ENTER("_ma_log_suffix"); - DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u", - (ulong) page, org_length, new_length)); - - page/= info->s->block_size; - - log_pos= log_data + FILEID_STORE_SIZE; - page_store(log_pos, page); - log_pos+= PAGE_STORE_SIZE; - - if ((diff= (int) (new_length - org_length)) < 0) - { - log_pos[0]= KEY_OP_DEL_SUFFIX; - int2store(log_pos+1, -diff); - log_pos+= 3; - translog_parts= 1; - extra_length= 0; - } - else - { - log_pos[0]= KEY_OP_ADD_SUFFIX; - int2store(log_pos+1, diff); - log_pos+= 3; - log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) buff + org_length; - log_array[TRANSLOG_INTERNAL_PARTS + 1].length= (uint) diff; - translog_parts= 2; - extra_length= (uint) diff; - } - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - - log_data); - - DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, - info->trn, info, - log_array[TRANSLOG_INTERNAL_PARTS + - 0].length + extra_length, - TRANSLOG_INTERNAL_PARTS + translog_parts, - log_array, log_data, NULL)); -} - - #ifdef NOT_NEEDED /** diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index d36b440541b..9f6571bade8 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -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)) { + /* Mark table as not transactional to avoid logging */ + maria_disable_logging(info); + if (param->testflag & T_REP_ANY) { ulonglong tmp=share->state.key_map; @@ -1181,6 +1184,7 @@ static int maria_chk(HA_CHECK *param, char *filename) ((param->testflag & T_SORT_RECORDS) ? UPDATE_SORT : 0))); info->update&= ~HA_STATE_CHANGED; + maria_enable_logging(info); maria_lock_database(info, F_UNLCK); end2: diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 620b71f71a4..95ddf358679 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -29,7 +29,9 @@ #include "ma_control_file.h" /* For testing recovery */ +#ifndef DBUG_OFF #define IDENTICAL_PAGES_AFTER_RECOVERY 1 +#endif /* Do extra sanity checking */ #define SANITY_CHECKS 1 @@ -718,17 +720,18 @@ extern int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, extern int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, uint key_length, MARIA_RECORD_POS *root, uint comp_flag); -extern int _ma_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, - uchar *key, uchar *buff, uchar *key_buff, - my_bool insert_last); +extern int _ma_split_page(register MARIA_HA *info, + register MARIA_KEYDEF *keyinfo, + uchar *key, my_off_t split_page, uchar *split_buff, + uint org_split_length, + uchar *inserted_key_pos, uint changed_length, + int move_length, + uchar *key_buff, my_bool insert_last_key); extern uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uint *return_key_length, uchar ** after_key); -extern my_bool write_hook_for_undo_key(enum translog_record_type type, - TRN *trn, MARIA_HA *tbl_info, - LSN *lsn, void *hook_arg); extern int _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag, uchar *key_pos, uchar *org_key, uchar *key_buff, const uchar *key, @@ -912,21 +915,6 @@ typedef struct st_maria_block_info #define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) #define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) -/* 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; -}; - -struct st_msg_to_write_hook_for_undo_key -{ - my_off_t *root; - my_off_t value; -}; - #define fast_ma_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _ma_writeinfo((INFO),0) #define fast_ma_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _ma_readinfo((INFO),F_RDLCK,1) diff --git a/storage/maria/unittest/ma_control_file-t.c b/storage/maria/unittest/ma_control_file-t.c index db0a1690ab8..50b3407bb15 100644 --- a/storage/maria/unittest/ma_control_file-t.c +++ b/storage/maria/unittest/ma_control_file-t.c @@ -60,6 +60,7 @@ static int test_start_stop(); static int test_2_open_and_2_close(); static int test_bad_magic_string(); static int test_bad_checksum(); +static int test_bad_hchecksum(); static int test_bad_size(); /* Utility */ @@ -85,7 +86,7 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); maria_data_root= "."; - plan(9); + plan(10); diag("Unit tests for control file"); @@ -106,6 +107,7 @@ int main(int argc,char *argv[]) "test of two open and two close (strange call sequence)"); ok(0 == test_bad_magic_string(), "test of bad magic string"); ok(0 == test_bad_checksum(), "test of bad checksum"); + ok(0 == test_bad_hchecksum(), "test of bad hchecksum"); ok(0 == test_bad_size(), "test of too small/big file"); return exit_status(); @@ -264,18 +266,18 @@ static int test_binary_content() future change/breakage. */ - char buffer[23]; + char buffer[43]; RET_ERR_UNLESS((fd= my_open(file_name, O_BINARY | O_RDWR, MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_read(fd, buffer, 23, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_read(fd, buffer, 43, MYF(MY_FNABP | MY_WME)) == 0); RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); - i= uint3korr(buffer+12); + i= uint3korr(buffer + 32 ); RET_ERR_UNLESS(i == LSN_FILE_NO(last_checkpoint_lsn)); - i= uint4korr(buffer+15); + i= uint4korr(buffer + 35); RET_ERR_UNLESS(i == LSN_OFFSET(last_checkpoint_lsn)); - i= uint4korr(buffer+19); + i= uint4korr(buffer + 39); RET_ERR_UNLESS(i == last_logno); RET_ERR_UNLESS(close_file() == 0); return 0; @@ -342,15 +344,42 @@ static int test_bad_checksum() RET_ERR_UNLESS((fd= my_open(file_name, O_BINARY | O_RDWR, MYF(MY_WME))) >= 0); - RET_ERR_UNLESS(my_pread(fd, buffer, 1, 8, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_pread(fd, buffer, 1, 28, MYF(MY_FNABP | MY_WME)) == 0); buffer[0]+= 3; /* mangle checksum */ - RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 8, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 28, MYF(MY_FNABP | MY_WME)) == 0); /* Check that control file module sees the problem */ RET_ERR_UNLESS(ma_control_file_create_or_open(TRUE) == CONTROL_FILE_BAD_CHECKSUM); /* Restore checksum */ buffer[0]-= 3; - RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 4, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 28, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); + + return 0; +} + + +static int test_bad_hchecksum() +{ + char buffer[4]; + int fd; + + RET_ERR_UNLESS(create_or_open_file() == CONTROL_FILE_OK); + RET_ERR_UNLESS(close_file() == 0); + + /* Corrupt checksum */ + RET_ERR_UNLESS((fd= my_open(file_name, + O_BINARY | O_RDWR, + MYF(MY_WME))) >= 0); + RET_ERR_UNLESS(my_pread(fd, buffer, 1, 24, MYF(MY_FNABP | MY_WME)) == 0); + buffer[0]+= 3; /* mangle checksum */ + RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 24, MYF(MY_FNABP | MY_WME)) == 0); + /* Check that control file module sees the problem */ + RET_ERR_UNLESS(ma_control_file_create_or_open(TRUE) == + CONTROL_FILE_BAD_HEAD_CHECKSUM); + /* Restore checksum */ + buffer[0]-= 3; + RET_ERR_UNLESS(my_pwrite(fd, buffer, 1, 24, MYF(MY_FNABP | MY_WME)) == 0); RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); return 0; @@ -359,7 +388,7 @@ static int test_bad_checksum() static int test_bad_size() { - char buffer[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + char buffer[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; int fd; /* A too short file */ @@ -371,7 +400,7 @@ static int test_bad_size() /* Check that control file module sees the problem */ RET_ERR_UNLESS(ma_control_file_create_or_open(TRUE) == CONTROL_FILE_TOO_SMALL); - RET_ERR_UNLESS(my_write(fd, buffer, 30, MYF(MY_FNABP | MY_WME)) == 0); + RET_ERR_UNLESS(my_write(fd, buffer, 50, MYF(MY_FNABP | MY_WME)) == 0); /* Check that control file module sees the problem */ RET_ERR_UNLESS(ma_control_file_create_or_open(TRUE) == CONTROL_FILE_TOO_BIG); RET_ERR_UNLESS(my_close(fd, MYF(MY_WME)) == 0); diff --git a/storage/maria/unittest/ma_test_loghandler-t.c b/storage/maria/unittest/ma_test_loghandler-t.c index 3035a9baaef..48aae3e1b3e 100644 --- a/storage/maria/unittest/ma_test_loghandler-t.c +++ b/storage/maria/unittest/ma_test_loghandler-t.c @@ -337,7 +337,7 @@ int main(int argc __attribute__((unused)), char *argv[]) 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(); ok(0, "flush"); exit(1); |