diff options
author | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-11-28 21:38:30 +0200 |
---|---|---|
committer | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-11-28 21:38:30 +0200 |
commit | 4e0964cb040d833351ddd66c00b146b2e93e9fa7 (patch) | |
tree | e16074ce3069413dcf25dc2c9487938ac5c62806 | |
parent | 63cd7bdcd5f95ed08b521099157ff4c61fa62bc3 (diff) | |
download | mariadb-git-4e0964cb040d833351ddd66c00b146b2e93e9fa7.tar.gz |
Fixed repair_by_sort to work with BLOCK_RECORD
Fixed bugs in undo logging
Fixed bug where head block was split before min_row_length (caused Maria to believe row was crashed on read)
Reserved place for reference-transid on key pages (for packing of transids)
ALTER TABLE and INSERT ... SELECT now uses fast creation of index
Known bugs:
ma_test_recovery fails because of a bug in redo handling when log is cut directly after a redo (Guilhem knows how to fix)
ma_test_recovery.excepted is not totally correct, because of the above bug
mysqld sometimes fails to restart; Fails with error "end_of_redo_phase: Assertion `long_trid != 0' failed"; Guilhem to investigate
include/maria.h:
Prototype changes
Added current_filepos to st_maria_sort_info
mysql-test/r/maria.result:
Updated results that changes as alter table and insert ... select now uses fast creation of index
mysys/mf_iocache.c:
Reset variable to gurard against double invocation
storage/maria/ma_bitmap.c:
Added _ma_bitmap_reset_cache() (needed for repair)
storage/maria/ma_blockrec.c:
Simplify code
More initial allocations
Fixed bug where head block was split before min_row_length (caused Maria to believe row was crashed on read)
storage/maria/ma_blockrec.h:
Moved TRANSID_SIZE to maria_def.h
Added prototype for new functions
storage/maria/ma_check.c:
Simplicy code
Fixed repair_by_sort to work with BLOCK_RECORD
- When using BLOCK_RECORD or UNPACK create new Maria handle
- Use common initializer function
- Align code with maria_repair()
Made some changes to maria_repair_parallel() to use common initializer function
Removed ASK_MONTY section by fixing noted problem
storage/maria/ma_close.c:
Moved check for readonly to _ma_state_info_write()
storage/maria/ma_key_recover.c:
Use different log entries if key root changes or not.
This fixed some bugs when tree grows
storage/maria/ma_key_recover.h:
Added keynr to st_msg_to_write_hook_for_undo_key
storage/maria/ma_loghandler.c:
Added INIT_LOGREC_UNDO_KEY_INSERT_WITH_ROOT
storage/maria/ma_loghandler.h:
Added INIT_LOGREC_UNDO_KEY_INSERT_WITH_ROOT
storage/maria/ma_open.c:
Added TRANSID to all key pages (for future compressing of trans id's)
For compressed records, alloc a bit bigger buffer to avoid valgrind warnings
If table is opened readonly, don't update state
storage/maria/ma_packrec.c:
Allocate bigger array for bit unpacking to avoid valgrind errors
storage/maria/ma_recovery.c:
Added UNDO_KEY_INSERT_WITH_ROOT & UNDO_KEY_DELETE_WITH_ROOT
storage/maria/ma_sort.c:
More logging
storage/maria/ma_test_all.sh:
More tests
storage/maria/ma_test_recovery.expected:
Update results
Note that this is not complete becasue of a bug in recovery
storage/maria/ma_test_recovery:
Removed recreation of index (not needed when we have redo for index pages)
storage/maria/maria_chk.c:
When using flag --read-only, don't update status for files
When using --unpack, don't use REPAIR_BY_SORT if other repair option is given
Enable repair_by_sort for BLOCK records
Removed not needed newline at start of --describe
storage/maria/maria_def.h:
Support for TRANSID_SIZE to key pages
storage/maria/maria_read_log.c:
renamed --only-display to --display-only
-rw-r--r-- | include/maria.h | 16 | ||||
-rw-r--r-- | mysql-test/r/maria.result | 6 | ||||
-rw-r--r-- | mysys/mf_iocache.c | 1 | ||||
-rw-r--r-- | storage/maria/ma_bitmap.c | 56 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 34 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.h | 11 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 649 | ||||
-rw-r--r-- | storage/maria/ma_close.c | 3 | ||||
-rw-r--r-- | storage/maria/ma_key_recover.c | 47 | ||||
-rw-r--r-- | storage/maria/ma_key_recover.h | 1 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.c | 9 | ||||
-rw-r--r-- | storage/maria/ma_loghandler.h | 1 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 13 | ||||
-rw-r--r-- | storage/maria/ma_packrec.c | 12 | ||||
-rw-r--r-- | storage/maria/ma_recovery.c | 31 | ||||
-rw-r--r-- | storage/maria/ma_sort.c | 4 | ||||
-rwxr-xr-x | storage/maria/ma_test_all.sh | 33 | ||||
-rwxr-xr-x | storage/maria/ma_test_recovery | 10 | ||||
-rw-r--r-- | storage/maria/ma_test_recovery.expected | 198 | ||||
-rw-r--r-- | storage/maria/maria_chk.c | 33 | ||||
-rw-r--r-- | storage/maria/maria_def.h | 11 | ||||
-rw-r--r-- | storage/maria/maria_read_log.c | 14 |
22 files changed, 723 insertions, 470 deletions
diff --git a/include/maria.h b/include/maria.h index 6e87c93c7d1..9f6672d482c 100644 --- a/include/maria.h +++ b/include/maria.h @@ -370,7 +370,7 @@ typedef struct st_maria_sort_param ulonglong unique[HA_MAX_KEY_SEG+1]; ulonglong notnull[HA_MAX_KEY_SEG+1]; - MARIA_RECORD_POS pos,max_pos,filepos,start_recpos; + MARIA_RECORD_POS pos,max_pos,filepos,start_recpos, current_filepos; uint key, key_length,real_key_length,sortbuff_size; uint maxbuffers, keys, find_length, sort_keys_length; my_bool fix_datafile, master; @@ -392,18 +392,16 @@ typedef struct st_maria_sort_param /* functions in maria_check */ void maria_chk_init(HA_CHECK *param); int maria_chk_status(HA_CHECK *param, MARIA_HA *info); -int maria_chk_del(HA_CHECK *param, register MARIA_HA *info, uint test_flag); +int maria_chk_del(HA_CHECK *param, MARIA_HA *info, uint test_flag); int maria_chk_size(HA_CHECK *param, MARIA_HA *info); int maria_chk_key(HA_CHECK *param, MARIA_HA *info); int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, int extend); -int maria_repair(HA_CHECK *param, register MARIA_HA *info, - char * name, int rep_quick); -int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, - char * name); -int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, - const char *name, int rep_quick); +int maria_repair(HA_CHECK *param, MARIA_HA *info, char * name, uint rep_quick); +int maria_sort_index(HA_CHECK *param, MARIA_HA *info, char * name); +int maria_repair_by_sort(HA_CHECK *param, MARIA_HA *info, + const char *name, uint rep_quick); int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, - const char *name, int rep_quick); + const char *name, uint rep_quick); int maria_change_to_newfile(const char *filename, const char *old_ext, const char *new_ext, myf myflags); void maria_lock_memory(HA_CHECK *param); diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 7fc6ae39224..97f2850dabd 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -625,7 +625,7 @@ t1 1 a 1 a A NULL NULL NULL YES BTREE disabled alter table t1 enable keys; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 a 1 a A NULL NULL NULL YES BTREE +t1 1 a 1 a A 1000 NULL NULL YES BTREE alter table t1 engine=heap; alter table t1 disable keys; Warnings: @@ -1957,12 +1957,12 @@ create table t2 like t1; insert into t2 select * from t1; analyze table t2; Table Op Msg_type Msg_text -test.t2 analyze status OK +test.t2 analyze status Table is already up to date delete from t2; insert into t2 select * from t1; analyze table t2; Table Op Msg_type Msg_text -test.t2 analyze status OK +test.t2 analyze status Table is already up to date drop table t1,t2; create table t1 (a bigint auto_increment, primary key(a), b char(255), c varchar(20000)); update t1 set b=repeat('a',100) where a between 1 and 100; diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 0f49dd22bb9..8d74894305a 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1834,6 +1834,7 @@ int end_io_cache(IO_CACHE *info) pthread_mutex_destroy(&info->append_buffer_lock); #endif } + info->share= 0; DBUG_RETURN(error); } /* end_io_cache */ diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index a896a9670f9..afe63eea33a 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -124,9 +124,6 @@ #include "maria_def.h" #include "ma_blockrec.h" -/* Number of pages to store blob parts */ -#define BLOB_SEGMENT_MIN_SIZE 128 - #define FULL_HEAD_PAGE 4 #define FULL_TAIL_PAGE 7 @@ -187,7 +184,6 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) return 1; bitmap->file.file= file; - bitmap->changed= 0; bitmap->block_size= share->block_size; /* Size needs to be alligned on 6 */ aligned_bit_blocks= (share->block_size - PAGE_SUFFIX_SIZE) / 6; @@ -212,18 +208,8 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) pthread_mutex_init(&share->bitmap.bitmap_lock, MY_MUTEX_INIT_SLOW); - /* - We can't read a page yet, as in some case we don't have an active - page cache yet. - Pretend we have a dummy, full and not changed bitmap page in memory. - */ + _ma_bitmap_reset_cache(share); - bitmap->page= ~(ulonglong) 0; - bitmap->used_size= bitmap->total_size; - bfill(bitmap->map, share->block_size, 255); -#ifndef DBUG_OFF - memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); -#endif if (share->state.first_bitmap_with_space == ~(ulonglong) 0) { /* Start scanning for free space from start of file */ @@ -313,6 +299,41 @@ void _ma_bitmap_delete_all(MARIA_SHARE *share) } +/** + @brief Reset bitmap caches + + @fn _ma_bitmap_reset_cache() + @param share Maria share + + @notes + This is called after we have swapped file descriptors and we want + bitmap to forget all cached information +*/ + +void _ma_bitmap_reset_cache(MARIA_SHARE *share) +{ + MARIA_FILE_BITMAP *bitmap= &share->bitmap; + + if (bitmap->map) /* If using bitmap */ + { + /* Forget changes in current bitmap page */ + bitmap->changed= 0; + + /* + We can't read a page yet, as in some case we don't have an active + page cache yet. + Pretend we have a dummy, full and not changed bitmap page in memory. + */ + bitmap->page= ~(ulonglong) 0; + bitmap->used_size= bitmap->total_size; + bfill(bitmap->map, share->block_size, 255); +#ifndef DBUG_OFF + memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); +#endif + } +} + + /* Return bitmap pattern for the smallest head block that can hold 'size' @@ -1630,7 +1651,7 @@ my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *row, { MARIA_SHARE *share= info->s; my_bool res= 1; - uint full_page_size, position; + uint position; uint head_length, row_length, rest_length, extents_length; ulonglong bitmap_page; DBUG_ENTER("_ma_bitmap_find_new_place"); @@ -1670,9 +1691,8 @@ my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *row, /* The first segment size is stored in 'row_length' */ row_length= find_where_to_split_row(share, row, extents_length, free_size); - full_page_size= FULL_PAGE_SIZE(share->block_size); position= 0; - if (head_length - row_length <= full_page_size) + if (head_length - row_length < MAX_TAIL_SIZE(share->block_size)) position= ELEMENTS_RESERVED_FOR_MAIN_PART -2; /* Only head and tail */ use_head(info, page, row_length, position); rest_length= head_length - row_length; diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 069d9e95655..f4abbc2c1c5 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -456,6 +456,7 @@ my_bool _ma_once_end_block_record(MARIA_SHARE *share) my_bool _ma_init_block_record(MARIA_HA *info) { MARIA_ROW *row= &info->cur_row, *new_row= &info->new_row; + uint default_extents; DBUG_ENTER("_ma_init_block_record"); if (!my_multi_malloc(MY_WME, @@ -490,17 +491,27 @@ my_bool _ma_init_block_record(MARIA_HA *info) /* Skip over bytes used to store length of field length for logging */ row->field_lengths+= 2; new_row->field_lengths+= 2; + + /* Reserve some initial space to avoid mallocs during execution */ + default_extents= (ELEMENTS_RESERVED_FOR_MAIN_PART + 1 + + (AVERAGE_BLOB_SIZE / + FULL_PAGE_SIZE(info->s->block_size) / + BLOB_SEGMENT_MIN_SIZE)); + if (my_init_dynamic_array(&info->bitmap_blocks, - sizeof(MARIA_BITMAP_BLOCK), - ELEMENTS_RESERVED_FOR_MAIN_PART, 16)) + sizeof(MARIA_BITMAP_BLOCK), default_extents, + 64)) goto err; + if (!(info->cur_row.extents= my_malloc(default_extents * ROW_EXTENT_SIZE, + MYF(MY_WME)))) + goto err; + row->base_length= new_row->base_length= info->s->base_length; /* We need to reserve 'EXTRA_LENGTH_FIELDS' number of parts in null_field_lengths to allow splitting of rows in 'find_where_to_split_row' */ - row->null_field_lengths+= EXTRA_LENGTH_FIELDS; new_row->null_field_lengths+= EXTRA_LENGTH_FIELDS; @@ -3697,7 +3708,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, column < end_column; column++) { uint column_length= column->length; - if (data >= end_of_data && + if (data + column_length > end_of_data && !(data= read_next_extent(info, &extent, &end_of_data))) goto err; memcpy(record + column->offset, data, column_length); @@ -3731,7 +3742,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, case FIELD_NORMAL: /* Fixed length field */ case FIELD_SKIP_PRESPACE: case FIELD_SKIP_ZERO: /* Fixed length field */ - if (data >= end_of_data && + if (data + column->length > end_of_data && !(data= read_next_extent(info, &extent, &end_of_data))) goto err; memcpy(field_pos, data, column->length); @@ -4991,6 +5002,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, MARIA_PINNED_PAGE page_link; enum pagecache_page_lock unlock_method; enum pagecache_page_pin unpin_method; + my_off_t end_of_page; DBUG_ENTER("_ma_apply_redo_insert_row_head_or_tail"); page= page_korr(header); @@ -5000,8 +5012,12 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, (ulong) ma_recordpos(page, rownr), (ulong) page, rownr, (uint) data_length)); - if (((page + 1) * info->s->block_size) > info->state->data_file_length) + end_of_page= (page + 1) * info->s->block_size; + if (end_of_page > info->state->data_file_length) { + DBUG_PRINT("info", ("Enlarging data file from %lu to %lu", + (ulong) info->state->data_file_length, + (ulong) end_of_page)); /* New page at end of file. Note that the test above is also positive if data_file_length is not a multiple of block_size (system crashed while @@ -5153,11 +5169,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, case we extended the file. We could not do it earlier: bitmap code tests data_file_length to know if it has to create a new page or not. */ - { - my_off_t end_of_page= (page + 1) * info->s->block_size; - set_if_bigger(info->state->data_file_length, end_of_page); - } - + set_if_bigger(info->state->data_file_length, end_of_page); DBUG_RETURN(result); err: diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index a792f8c5db5..01d01fc6c1f 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -29,8 +29,8 @@ PAGE_SUFFIX_SIZE) #define BLOCK_RECORD_POINTER_SIZE 6 -#define FULL_PAGE_SIZE(block_size) ((block_size) - LSN_SIZE - PAGE_TYPE_SIZE - \ - PAGE_SUFFIX_SIZE) +#define FULL_PAGE_SIZE(block_size) ((block_size) - LSN_SIZE - \ + PAGE_TYPE_SIZE - PAGE_SUFFIX_SIZE) #define ROW_EXTENT_PAGE_SIZE 5 #define ROW_EXTENT_COUNT_SIZE 2 @@ -40,12 +40,16 @@ #define TAIL_BIT 0x8000 /* Bit in page_count to signify tail */ /* Number of extents reserved MARIA_BITMAP_BLOCKS to store head part */ #define ELEMENTS_RESERVED_FOR_MAIN_PART 4 +/* This is just used to prealloc a dynamic array */ +#define AVERAGE_BLOB_SIZE 1024L*1024L +/* Number of pages to store continuous blob parts */ +#define BLOB_SEGMENT_MIN_SIZE 128 + /* Fields before 'row->null_field_lengths' used by find_where_to_split_row */ #define EXTRA_LENGTH_FIELDS 3 /* Size for the different parts in the row header (and head page) */ #define FLAG_SIZE 1 -#define TRANSID_SIZE 6 #define VERPTR_SIZE 7 #define DIR_ENTRY_SIZE 4 #define FIELD_OFFSET_SIZE 2 /* size of pointers to field starts */ @@ -167,6 +171,7 @@ my_bool _ma_compare_block_record(register MARIA_HA *info, my_bool _ma_bitmap_init(MARIA_SHARE *share, File file); my_bool _ma_bitmap_end(MARIA_SHARE *share); my_bool _ma_flush_bitmap(MARIA_SHARE *share); +void _ma_bitmap_reset_cache(MARIA_SHARE *share); my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, MARIA_BITMAP_BLOCKS *result_blocks); my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 37c01954d9b..f30ebebd6e7 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -87,12 +87,15 @@ static ha_checksum maria_byte_checksum(const uchar *buf, uint length); static void set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share); static void restore_data_file_type(MARIA_SHARE *share); static void change_data_file_descriptor(MARIA_HA *info, File new_file); +static void unuse_data_file_descriptor(MARIA_HA *info); static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info, MARIA_HA *info, uchar *record); static void copy_data_file_state(MARIA_STATE_INFO *to, MARIA_STATE_INFO *from); static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info); static void report_keypage_fault(HA_CHECK *param, my_off_t position); +my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file); + void maria_chk_init(HA_CHECK *param) { @@ -2031,6 +2034,38 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) } /* maria_chk_data_link */ +/** + @brief Initialize variables for repair +*/ + +static void initialize_variables_for_repair(HA_CHECK *param, + MARIA_SORT_INFO *sort_info, + MARIA_SORT_PARAM *sort_param, + MARIA_HA *info, + uint rep_quick) +{ + bzero((char *) sort_info, sizeof(*sort_info)); + bzero((char *) sort_param, sizeof(*sort_param)); + + param->testflag|= T_REP; /* for easy checking */ + if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) + param->testflag|= T_CALC_CHECKSUM; + param->glob_crc= 0; + + sort_param->sort_info= sort_info; + sort_param->fix_datafile= (my_bool) (! rep_quick); + sort_param->calc_checksum= test(param->testflag & T_CALC_CHECKSUM); + sort_info->info= sort_info->new_info= info; + sort_info->param= param; + set_data_file_type(sort_info, info->s); + sort_info->org_data_file_type= info->s->data_file_type; + + bzero(&info->rec_cache, sizeof(info->rec_cache)); + info->rec_cache.file= info->dfile.file; + info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); +} + + /* Recover old table by reading each record and writing all keys @@ -2054,7 +2089,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) */ int maria_repair(HA_CHECK *param, register MARIA_HA *info, - char *name, int rep_quick) + char *name, uint rep_quick) { int error, got_error= 1; uint i; @@ -2071,26 +2106,18 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, MY_SYNC_DIR : 0); DBUG_ENTER("maria_repair"); - bzero((char *)&sort_info, sizeof(sort_info)); - bzero((char *)&sort_param, sizeof(sort_param)); + initialize_variables_for_repair(param, &sort_info, &sort_param, info, + rep_quick); start_records=info->state->records; - new_header_length=(param->testflag & T_UNPACK) ? 0L : - share->pack.header_length; + new_header_length= ((param->testflag & T_UNPACK) ? 0L : + share->pack.header_length); new_file= -1; - sort_param.sort_info=&sort_info; - block_record= org_data_file_type == BLOCK_RECORD; - sort_info.info= sort_info.new_info= info; - bzero(&info->rec_cache,sizeof(info->rec_cache)); if (!(param->testflag & T_SILENT)) { printf("- recovering (with keycache) MARIA-table '%s'\n",name); printf("Data records: %s\n", llstr(info->state->records,llbuff)); } - param->testflag|=T_REP; /* for easy checking */ - - if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - param->testflag|=T_CALC_CHECKSUM; /* The physical size of the data file is sometimes used during repair (see @@ -2121,43 +2148,18 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, new_header_length, "datafile-header")) goto err; info->s->state.dellink= HA_OFFSET_ERROR; - info->rec_cache.file= new_file; + info->rec_cache.file= new_file; /* For sort_delete_record */ if (share->data_file_type == BLOCK_RECORD || (param->testflag & T_UNPACK)) { - MARIA_HA *new_info; - /* - It's ok for Recovery to have two MARIA_SHARE on the same index file - because the one below is not transactional - */ - if (!(sort_info.new_info= maria_open(info->s->open_file_name, O_RDWR, - HA_OPEN_COPY | HA_OPEN_FOR_REPAIR))) - goto err; - new_info= sort_info.new_info; - change_data_file_descriptor(new_info, new_file); - maria_lock_database(new_info, F_EXTRA_LCK); - if ((param->testflag & T_UNPACK) && - share->data_file_type == COMPRESSED_RECORD) - { - (*new_info->s->once_end)(new_info->s); - (*new_info->s->end)(new_info); - restore_data_file_type(new_info->s); - _ma_setup_functions(new_info->s); - if ((*new_info->s->once_init)(new_info->s, new_file) || - (*new_info->s->init)(new_info)) - goto err; - } - _ma_reset_status(sort_info.new_info); - if (_ma_initialize_data_file(sort_info.new_info->s, new_file)) + if (create_new_data_handle(&sort_param, 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; + sort_info.new_info->rec_cache.file= new_file; } } + block_record= sort_info.new_info->s->data_file_type == BLOCK_RECORD; + if (org_data_file_type != BLOCK_RECORD) { /* We need a read buffer to read rows in big blocks */ @@ -2170,14 +2172,16 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, { /* When writing to not block records, we need a write buffer */ if (!rep_quick) - if (init_io_cache(&info->rec_cache, new_file, + { + if (init_io_cache(&sort_info.new_info->rec_cache, new_file, (uint) param->write_buffer_length, WRITE_CACHE, new_header_length, 1, - MYF(MY_WME | MY_WAIT_IF_FULL))) + MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw)) goto err; - info->opt_flag|=WRITE_CACHE_USED; + sort_info.new_info->opt_flag|=WRITE_CACHE_USED; + } } - else + else if (block_record) { scan_inited= 1; if (maria_scan_init(sort_info.info)) @@ -2193,26 +2197,17 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, goto err; } - sort_info.param = param; sort_param.read_cache=param->read_cache; sort_param.pos=sort_param.max_pos=share->pack.header_length; sort_param.filepos=new_header_length; - param->read_cache.end_of_file=sort_info.filelength= + param->read_cache.end_of_file= sort_info.filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0)); - sort_info.dupp=0; - sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master=1; sort_info.max_records= ~(ha_rows) 0; - set_data_file_type(&sort_info, share); del=info->state->del; info->state->records=info->state->del=share->state.split=0; info->state->empty=0; - param->glob_crc=0; - if (param->testflag & T_CALC_CHECKSUM) - sort_param.calc_checksum= 1; - - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); /* Clear all keys. Note that all key blocks allocated until now remain @@ -2235,8 +2230,6 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, maria_lock_memory(param); /* Everything is alloced */ - sort_info.org_data_file_type= info->s->data_file_type; - /* Re-create all keys, which are set in key_map. */ while (!(error=sort_get_next_record(&sort_param))) { @@ -2248,7 +2241,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err; DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength); - _ma_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s", + _ma_check_print_info(param, + "Duplicate key %2d for record at %10s against new record at %10s", info->errkey+1, llstr(sort_param.start_recpos,llbuff), llstr(info->dup_key_pos,llbuff2)); @@ -2279,11 +2273,17 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, } /* purecov: end */ } - if (!block_record && _ma_sort_write_record(&sort_param)) - goto err; + if (!block_record) + { + if (_ma_sort_write_record(&sort_param)) + goto err; + /* Filepos is pointer to where next row will be stored */ + sort_param.current_filepos= sort_param.filepos; + } } if (error > 0 || maria_write_data_suffix(&sort_info, (my_bool)!rep_quick) || - flush_io_cache(&info->rec_cache) || param->read_cache.error < 0) + flush_io_cache(&sort_info.new_info->rec_cache) || + param->read_cache.error < 0) goto err; if (param->testflag & T_WRITE_LOOP) @@ -2317,8 +2317,14 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, } } + VOID(end_io_cache(&sort_info.new_info->rec_cache)); + info->opt_flag&= ~WRITE_CACHE_USED; + if (_ma_flush_table_files_after_repair(param, info)) + goto err; + if (!rep_quick) { + sort_info.new_info->state->data_file_length= sort_param.filepos; if (sort_info.new_info != sort_info.info) { MARIA_STATE_INFO save_state= sort_info.new_info->s->state; @@ -2329,9 +2335,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, } copy_data_file_state(&info->s->state, &save_state); new_file= -1; + sort_info.new_info= info; } - else - info->state->data_file_length= sort_param.filepos; share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ /* Replace the actual file with the temporary file */ @@ -2376,38 +2381,25 @@ err: maria_scan_end(sort_info.info); VOID(end_io_cache(¶m->read_cache)); + VOID(end_io_cache(&sort_info.new_info->rec_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); + sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); /* this below could fail, shouldn't we detect error? */ - VOID(end_io_cache(&info->rec_cache)); - got_error|= _ma_flush_table_files_after_repair(param, info); if (got_error) { if (! param->error_printed) _ma_check_print_error(param,"%d for record at pos %s",my_errno, llstr(sort_param.start_recpos,llbuff)); + (void) _ma_flush_table_files_after_repair(param, info); if (sort_info.new_info && sort_info.new_info != sort_info.info) { - /** - @todo ASK_MONTY - grepping for "dfile.file=" - shows several places (ma_check.c, ma_panic.c, ma_extra.c) where we - modify dfile.file without modifying share->bitmap.file.file; those - sound like bugs because the two variables are normally copies of each - other in BLOCK_RECORD (and in other record formats it does not hurt - to change the unused share->bitmap.file.file). - It does matter, because if we close dfile.file, set dfile.file to -1, - but leave bitmap.file.file to its positive value, maria_close() will - close a file which it is not allowed to (maybe even a file in another - engine or mysqld!). - */ - sort_info.new_info->dfile.file= -1; + unuse_data_file_descriptor(sort_info.new_info); maria_close(sort_info.new_info); } if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); VOID(my_delete(param->temp_filename, MYF(MY_WME))); - info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */ } maria_mark_crashed_on_repair(info); } @@ -2439,7 +2431,7 @@ static int writekeys(MARIA_SORT_PARAM *sort_param) uchar *key; MARIA_HA *info= sort_param->sort_info->info; uchar *buff= sort_param->record; - my_off_t filepos= sort_param->filepos; + my_off_t filepos= sort_param->current_filepos; DBUG_ENTER("writekeys"); key= info->lastkey+info->s->base.max_key_length; @@ -2866,7 +2858,7 @@ err: */ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, - const char * name, int rep_quick) + const char * name, uint rep_quick) { int got_error; uint i; @@ -2883,57 +2875,32 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, ulonglong key_map=share->state.key_map; myf sync_dir= ((share->now_transactional && !share->temporary) ? MY_SYNC_DIR : 0); + my_bool scan_inited= 0; DBUG_ENTER("maria_repair_by_sort"); - bzero((char*)&sort_info,sizeof(sort_info)); - bzero((char *)&sort_param, sizeof(sort_param)); - - start_records=info->state->records; + start_records= info->state->records; + initialize_variables_for_repair(param, &sort_info, &sort_param, info, + rep_quick); got_error=1; new_file= -1; org_header_length= share->pack.header_length; new_header_length= (param->testflag & T_UNPACK) ? 0 : org_header_length; + sort_param.filepos= new_header_length; if (!(param->testflag & T_SILENT)) { printf("- recovering (with sort) MARIA-table '%s'\n",name); printf("Data records: %s\n", llstr(start_records,llbuff)); } - param->testflag|=T_REP; /* for easy checking */ - - if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - param->testflag|=T_CALC_CHECKSUM; + /* Flushing of keys is done later */ 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= - alloc_key_blocks(param, - (uint) param->sort_key_blocks, - share->base.max_key_block_length)) || - init_io_cache(¶m->read_cache, info->dfile.file, - (uint) param->read_buffer_length, - READ_CACHE, org_header_length, 1, MYF(MY_WME)) || - (! rep_quick && - init_io_cache(&info->rec_cache, info->dfile.file, - (uint) param->write_buffer_length, - WRITE_CACHE,new_header_length,1, - MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) + FLUSH_FORCE_WRITE, + (param->testflag & T_CREATE_MISSING_KEYS) ? + FLUSH_FORCE_WRITE : FLUSH_IGNORE_CHANGED) || + _ma_state_info_write(share, 1|2|4)) goto err; - sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; - info->opt_flag|=WRITE_CACHE_USED; - info->rec_cache.file= info->dfile.file; /* for sort_delete_record */ - sort_info.org_data_file_type= info->s->data_file_type; - if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength, - MYF(0))) || - _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, - info->s->base.default_rec_buff_size)) - { - _ma_check_print_error(param, "Not enough memory for extra record"); - goto err; - } if (!rep_quick) { /* Get real path for data file */ @@ -2951,21 +2918,58 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, maria_filecopy(param, new_file, info->dfile.file, 0L, new_header_length, "datafile-header")) goto err; - if (param->testflag & T_UNPACK) - restore_data_file_type(share); + share->state.dellink= HA_OFFSET_ERROR; - info->rec_cache.file=new_file; + info->rec_cache.file= new_file; /* For sort_delete_record */ + if (share->data_file_type == BLOCK_RECORD || + (param->testflag & T_UNPACK)) + { + if (create_new_data_handle(&sort_param, new_file)) + goto err; + sort_info.new_info->rec_cache.file= new_file; + } + } + + if (!(sort_info.key_block= + alloc_key_blocks(param, + (uint) param->sort_key_blocks, + share->base.max_key_block_length))) + goto err; + sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; + + if (info->s->data_file_type != BLOCK_RECORD) + { + /* We need a read buffer to read rows in big blocks */ + if (init_io_cache(¶m->read_cache, info->dfile.file, + (uint) param->read_buffer_length, + READ_CACHE, org_header_length, 1, MYF(MY_WME))) + goto err; + } + if (sort_info.new_info->s->data_file_type != BLOCK_RECORD) + { + /* When writing to not block records, we need a write buffer */ + if (!rep_quick) + { + if (init_io_cache(&sort_info.new_info->rec_cache, new_file, + (uint) param->write_buffer_length, + WRITE_CACHE, new_header_length, 1, + MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw)) + goto err; + sort_info.new_info->opt_flag|= WRITE_CACHE_USED; + } + } + + if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength, + MYF(0))) || + _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, + info->s->base.default_rec_buff_size)) + { + _ma_check_print_error(param, "Not enough memory for extra record"); + goto err; } - info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); if (!(param->testflag & T_CREATE_MISSING_KEYS)) { - /* - Flush key cache for this file if we are calling this outside - maria_chk - */ - flush_pagecache_blocks(share->pagecache, &share->kfile, - FLUSH_IGNORE_CHANGED); /* Clear the pointers to the given rows */ for (i=0 ; i < share->base.keys ; i++) share->state.key_root[i]= HA_OFFSET_ERROR; @@ -2973,22 +2977,10 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, info->state->key_file_length=share->base.keystart; } else - { - if (flush_pagecache_blocks(share->pagecache, &share->kfile, - FLUSH_FORCE_WRITE)) - goto err; key_map= ~key_map; /* Create the missing keys */ - } - - sort_info.info= sort_info.new_info= info; - sort_info.param= param; - set_data_file_type(&sort_info, share); - sort_param.filepos=new_header_length; - sort_info.dupp=0; - sort_info.buff=0; - param->read_cache.end_of_file=sort_info.filelength= - my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); + param->read_cache.end_of_file= sort_info.filelength= + my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0)); sort_param.wordlist=NULL; init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); @@ -3005,14 +2997,9 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, sort_param.key_cmp=sort_key_cmp; sort_param.lock_in_memory=maria_lock_memory; sort_param.tmpdir=param->tmpdir; - sort_param.sort_info=&sort_info; - sort_param.fix_datafile= (my_bool) (! rep_quick); sort_param.master =1; del=info->state->del; - param->glob_crc=0; - if (param->testflag & T_CALC_CHECKSUM) - sort_param.calc_checksum= 1; rec_per_key_part= param->new_rec_per_key_part; for (sort_param.key=0 ; sort_param.key < share->base.keys ; @@ -3091,6 +3078,12 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, sort_param.key_write= sort_key_write; } + if (sort_info.new_info->s->data_file_type == BLOCK_RECORD) + { + scan_inited= 1; + if (maria_scan_init(sort_info.info)) + goto err; + } if (_ma_create_index_by_sort(&sort_param, (my_bool) (!(param->testflag & T_VERBOSE)), (size_t) param->sort_buffer_length)) @@ -3098,26 +3091,36 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, param->retry_repair=1; goto err; } + if (scan_inited) + { + scan_inited= 0; + maria_scan_end(sort_info.info); + } + /* No need to calculate checksum again. */ sort_param.calc_checksum= 0; free_root(&sort_param.wordroot, MYF(0)); /* Set for next loop */ - sort_info.max_records= (ha_rows) info->state->records; + sort_info.max_records= (ha_rows) sort_info.new_info->state->records; if (param->testflag & T_STATISTICS) maria_update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, - param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? - sort_param.notnull : NULL, + (param->stats_method == + MI_STATS_METHOD_IGNORE_NULLS ? + sort_param.notnull : NULL), (ulonglong) info->state->records); maria_set_key_active(share->state.key_map, sort_param.key); if (sort_param.fix_datafile) { param->read_cache.end_of_file=sort_param.filepos; - if (maria_write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) + if (maria_write_data_suffix(&sort_info,1) || + end_io_cache(&sort_info.new_info->rec_cache)) goto err; + sort_info.new_info->opt_flag&= ~WRITE_CACHE_USED; + if (param->testflag & T_SAFE_REPAIR) { /* Don't repair if we loosed more than one row */ @@ -3127,15 +3130,48 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, goto err; } } - share->state.state.data_file_length = info->state->data_file_length= - sort_param.filepos; - /* Only whole records */ - share->state.version=(ulong) time((time_t*) 0); - my_close(info->dfile.file, MYF(0)); - info->dfile.file= new_file; - share->data_file_type= sort_info.new_data_file_type; - org_header_length= (ulong) new_header_length; + + if (_ma_flush_table_files_after_repair(param, info)) + goto err; + + sort_info.new_info->state->data_file_length= sort_param.filepos; + if (sort_info.new_info != sort_info.info) + { + MARIA_STATE_INFO save_state= sort_info.new_info->s->state; + if (maria_close(sort_info.new_info)) + { + _ma_check_print_error(param, "Got error %d on close", my_errno); + goto err; + } + copy_data_file_state(&info->s->state, &save_state); + new_file= -1; + sort_info.new_info= info; + } + + share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ + + /* Replace the actual file with the temporary file */ + if (new_file >= 0) + { + my_close(new_file, MYF(MY_WME)); + new_file= -1; + } + change_data_file_descriptor(info, -1); + if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT, + DATA_TMP_EXT, + (param->testflag & T_BACKUP_DATA ? + MYF(MY_REDEL_MAKE_BACKUP): MYF(0)) | + sync_dir) || + _ma_open_datafile(info, share, -1)) + { + goto err; + } + if (param->testflag & T_UNPACK) + restore_data_file_type(share); + + org_header_length= share->pack.header_length; sort_info.org_data_file_type= info->s->data_file_type; + sort_info.filelength= info->state->data_file_length; sort_param.fix_datafile=0; } else @@ -3177,6 +3213,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, "Can't change size of datafile, error: %d", my_errno); } + if (param->testflag & T_CALC_CHECKSUM) info->state->checksum=param->glob_crc; @@ -3200,41 +3237,40 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, memcpy( &share->state.state, info->state, sizeof(*info->state)); err: - VOID(end_io_cache(&info->rec_cache)); + if (scan_inited) + maria_scan_end(sort_info.info); + + VOID(end_io_cache(&sort_info.new_info->rec_cache)); VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); - got_error|= _ma_flush_table_files_after_repair(param, info); - if (!got_error) - { - /* Replace the actual file with the temporary file */ - if (new_file >= 0) - { - my_close(new_file,MYF(0)); - info->dfile.file= new_file= -1; - if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT, - DATA_TMP_EXT, - MYF((param->testflag & T_BACKUP_DATA ? - MY_REDEL_MAKE_BACKUP : 0) | - sync_dir)) || - _ma_open_datafile(info,share,-1)) - got_error=1; - } - } + sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); if (got_error) { if (! param->error_printed) _ma_check_print_error(param,"%d when fixing table",my_errno); + (void) _ma_flush_table_files_after_repair(param, info); + if (sort_info.new_info && sort_info.new_info != sort_info.info) + { + unuse_data_file_descriptor(sort_info.new_info); + maria_close(sort_info.new_info); + } if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); VOID(my_delete(param->temp_filename, MYF(MY_WME))); - if (info->dfile.file == new_file) - info->dfile.file= -1; } maria_mark_crashed_on_repair(info); } - else if (key_map == share->state.key_map) - share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; + else + { + if (key_map == share->state.key_map) + share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; + /* + Now that we have flushed and forced everything, we can bump + create_rename_lsn: + */ + write_log_record_for_repair(param, info); + } share->state.changed|= STATE_NOT_SORTED_PAGES; share->state.changed&= ~STATE_NOT_OPTIMIZED_ROWS; @@ -3243,8 +3279,6 @@ err: my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); - if (!got_error && (param->testflag & T_UNPACK)) - restore_data_file_type(share); DBUG_RETURN(got_error); } @@ -3291,7 +3325,7 @@ err: */ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, - const char * name, int rep_quick) + const char * name, uint rep_quick) { #ifndef THREAD return maria_repair_by_sort(param, info, name, rep_quick); @@ -3302,7 +3336,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, ha_rows start_records; my_off_t new_header_length,del; File new_file; - MARIA_SORT_PARAM *sort_param=0; + MARIA_SORT_PARAM *sort_param=0, tmp_sort_param; MARIA_SHARE *share=info->s; double *rec_per_key_part; HA_KEYSEG *keyseg; @@ -3316,6 +3350,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, MY_SYNC_DIR : 0; DBUG_ENTER("maria_repair_parallel"); + initialize_variables_for_repair(param, &sort_info, &tmp_sort_param, info, + rep_quick); + start_records=info->state->records; got_error=1; new_file= -1; @@ -3326,7 +3363,6 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, printf("- parallel recovering (with sort) MARIA-table '%s'\n",name); printf("Data records: %s\n", llstr(start_records,llbuff)); } - param->testflag|=T_REP; /* for easy checking */ if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) param->testflag|=T_CALC_CHECKSUM; @@ -3364,13 +3400,11 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, } */ DBUG_PRINT("info", ("is quick repair: %d", rep_quick)); - bzero((char*)&sort_info,sizeof(sort_info)); + /* Initialize pthread structures before goto err. */ pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&sort_info.cond, 0); - sort_info.org_data_file_type= info->s->data_file_type; - if (!(sort_info.key_block= alloc_key_blocks(param, (uint) param->sort_key_blocks, share->base.max_key_block_length)) || @@ -3438,14 +3472,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, key_map= ~key_map; /* Create the missing keys */ } - sort_info.info= sort_info.new_info= info; - sort_info.param= param; - - set_data_file_type(&sort_info, share); - sort_info.dupp=0; - sort_info.buff=0; - param->read_cache.end_of_file=sort_info.filelength= - my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); + param->read_cache.end_of_file= sort_info.filelength= + my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0)); if (sort_info.org_data_file_type == DYNAMIC_RECORD) rec_length=max(share->base.min_pack_length+1,share->base.min_block_length); @@ -3470,7 +3498,6 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, (ha_rows) (sort_info.filelength/rec_length+1)); del=info->state->del; - param->glob_crc=0; if (!(sort_param=(MARIA_SORT_PARAM *) my_malloc((uint) share->base.keys * @@ -3722,9 +3749,10 @@ err: the share by remove_io_thread() or it was not yet started (if the error happend before creating the thread). */ - VOID(end_io_cache(&info->rec_cache)); + VOID(end_io_cache(&sort_info.new_info->rec_cache)); VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); + sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); /* Destroy the new data cache in case of non-quick repair. All slave threads did either detach from the share by remove_io_thread() @@ -3799,15 +3827,18 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, uchar *key) sort_param->key+1); DBUG_RETURN(1); } + if (_ma_sort_write_record(sort_param)) + DBUG_RETURN(1); + sort_param->real_key_length= (info->s->rec_reflength+ _ma_make_key(info, sort_param->key, key, - sort_param->record, sort_param->filepos)); + sort_param->record, sort_param->current_filepos)); #ifdef HAVE_purify bzero(key+sort_param->real_key_length, (sort_param->key_length-sort_param->real_key_length)); #endif - DBUG_RETURN(_ma_sort_write_record(sort_param)); + DBUG_RETURN(0); } /* sort_key_read */ @@ -3826,13 +3857,14 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key) free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); if ((error=sort_get_next_record(sort_param))) DBUG_RETURN(error); + if ((error= _ma_sort_write_record(sort_param))) + DBUG_RETURN(error); if (!(wptr= _ma_ft_parserecord(info,sort_param->key,sort_param->record, &sort_param->wordroot))) DBUG_RETURN(1); if (wptr->pos) break; - error=_ma_sort_write_record(sort_param); } sort_param->wordptr=sort_param->wordlist=wptr; } @@ -3845,7 +3877,7 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key) sort_param->real_key_length=(info->s->rec_reflength+ _ma_ft_make_key(info, sort_param->key, key, wptr++, - sort_param->filepos)); + sort_param->current_filepos)); #ifdef HAVE_purify if (sort_param->key_length > sort_param->real_key_length) bzero(key+sort_param->real_key_length, @@ -3855,7 +3887,6 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key) { free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE)); sort_param->wordlist=0; - error=_ma_sort_write_record(sort_param); } else sort_param->wordptr=(void*)wptr; @@ -3891,8 +3922,9 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key) RETURN -1 end of file 0 ok - sort_param->filepos points to record position. + sort_param->current_filepos points to record position. sort_param->record contains record + sort_param->max_pos contains position to last byte read > 0 error */ @@ -3957,12 +3989,13 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) info->cur_row.checksum= checksum; param->glob_crc+= checksum; } - sort_param->start_recpos= sort_param->filepos= info->cur_row.lastpos; + sort_param->start_recpos= sort_param->current_filepos= + info->cur_row.lastpos; DBUG_RETURN(0); } if (flag == HA_ERR_END_OF_FILE) { - sort_param->max_pos= sort_info->filelength; + sort_param->max_pos= info->state->data_file_length; DBUG_RETURN(-1); } /* Retry only if wrong record, not if disk error */ @@ -3986,7 +4019,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) sort_param->start_recpos=sort_param->pos; if (!sort_param->fix_datafile) { - sort_param->filepos=sort_param->pos; + sort_param->current_filepos= sort_param->pos; if (sort_param->master) share->state.split++; } @@ -4136,7 +4169,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) if (!searching) _ma_check_print_info(param, "Found block with impossible length %u at %s; Skipped", - block_info.block_len+ (uint) (block_info.filepos-pos), + block_info.block_len+ + (uint) (block_info.filepos-pos), llstr(pos,llbuff)); if (found_record) goto try_next; @@ -4176,7 +4210,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) sort_param->find_length=left_length=block_info.rec_len; sort_param->start_recpos=pos; if (!sort_param->fix_datafile) - sort_param->filepos=sort_param->start_recpos; + sort_param->current_filepos= sort_param->start_recpos; if (sort_param->fix_datafile && (param->testflag & T_EXTEND)) sort_param->pos=block_info.filepos+1; else @@ -4348,6 +4382,10 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) llstr(sort_param->pos,llbuff)); continue; } +#ifdef HAVE_purify + bzero(sort_param->rec_buff + block_info.rec_len, + info->s->base.extra_rec_buff_size); +#endif if (_ma_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record, sort_param->rec_buff, block_info.rec_len)) { @@ -4358,12 +4396,12 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) } if (!sort_param->fix_datafile) { - sort_param->filepos=sort_param->pos; + sort_param->current_filepos= sort_param->pos; if (sort_param->master) share->state.split++; } - sort_param->max_pos=(sort_param->pos=block_info.filepos+ - block_info.rec_len); + sort_param->max_pos= (sort_param->pos=block_info.filepos+ + block_info.rec_len); info->packed_length=block_info.rec_len; if (sort_param->calc_checksum) @@ -4380,19 +4418,22 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param) } -/* - Write record to new file. +/** + @brief Write record to new file. - SYNOPSIS - _ma_sort_write_record() - sort_param Sort parameters. + @fn _ma_sort_write_record() + @param sort_param Sort parameters. - NOTE - This is only called by a master thread if parallel repair is used. + @note + This is only called by a master thread if parallel repair is used. - RETURN - 0 OK - 1 Error + @return + @retval 0 OK + sort_param->current_filepos points to inserted record for + block_records and to the place for the next record for + other row types. + sort_param->filepos points to end of file + @retval 1 Error */ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) @@ -4410,13 +4451,15 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param) if (sort_param->fix_datafile) { + sort_param->current_filepos= sort_param->filepos; switch (sort_info->new_data_file_type) { case BLOCK_RECORD: - if ((sort_param->filepos= (*share->write_record_init)(info, - sort_param-> - record)) == + if ((sort_param->current_filepos= + (*share->write_record_init)(info, sort_param->record)) == HA_OFFSET_ERROR) DBUG_RETURN(1); + /* Pointer to end of file */ + sort_param->filepos= info->state->data_file_length; break; case STATIC_RECORD: if (my_b_write(&info->rec_cache,sort_param->record, @@ -4820,7 +4863,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, } /* sort_insert_key */ - /* Delete record when we found a duplicated key */ +/* Delete record when we found a duplicated key */ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) { @@ -4829,57 +4872,61 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) uchar *key; MARIA_SORT_INFO *sort_info=sort_param->sort_info; HA_CHECK *param=sort_info->param; - MARIA_HA *info=sort_info->info; + MARIA_HA *row_info= sort_info->new_info, *key_info= sort_info->info; DBUG_ENTER("sort_delete_record"); if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK) { _ma_check_print_error(param, - "Quick-recover aborted; Run recovery without switch -q or with switch -qq"); + "Quick-recover aborted; Run recovery without switch -q or with " + "switch -qq"); DBUG_RETURN(1); } - if (info->s->options & HA_OPTION_COMPRESS_RECORD) + if (key_info->s->options & HA_OPTION_COMPRESS_RECORD) { _ma_check_print_error(param, - "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'maria_chk --safe-recover' to fix it\n",stderr);; + "Recover aborted; Can't run standard recovery on compressed tables " + "with errors in data-file. Use 'maria_chk --safe-recover' " + "to fix it",stderr);; DBUG_RETURN(1); } - old_file= info->dfile.file; - info->dfile.file= info->rec_cache.file; + old_file= row_info->dfile.file; + /* This only affects static and dynamic row formats */ + row_info->dfile.file= row_info->rec_cache.file; if (sort_info->current_key) { - key= info->lastkey+info->s->base.max_key_length; - if ((error=(*info->s->read_record)(info,sort_param->record, - info->cur_row.lastpos)) && + key= key_info->lastkey + key_info->s->base.max_key_length; + if ((error=(*row_info->s->read_record)(row_info, sort_param->record, + key_info->cur_row.lastpos)) && error != HA_ERR_RECORD_DELETED) { _ma_check_print_error(param,"Can't read record to be removed"); - info->dfile.file= old_file; + row_info->dfile.file= old_file; DBUG_RETURN(1); } for (i=0 ; i < sort_info->current_key ; i++) { - uint key_length= _ma_make_key(info, i, key, sort_param->record, - info->cur_row.lastpos); - if (_ma_ck_delete(info, i, key, key_length)) + uint key_length= _ma_make_key(key_info, i, key, sort_param->record, + key_info->cur_row.lastpos); + if (_ma_ck_delete(key_info, i, key, key_length)) { _ma_check_print_error(param, "Can't delete key %d from record to be removed", i+1); - info->dfile.file= old_file; + row_info->dfile.file= old_file; DBUG_RETURN(1); } } if (sort_param->calc_checksum) - param->glob_crc-=(*info->s->calc_check_checksum)(info, - sort_param->record); + param->glob_crc-=(*key_info->s->calc_check_checksum)(key_info, + sort_param->record); } - error= (flush_io_cache(&info->rec_cache) || - (*info->s->delete_record)(info, sort_param->record)); - info->dfile.file= old_file; /* restore actual value */ - info->state->records--; + error= (flush_io_cache(&row_info->rec_cache) || + (*row_info->s->delete_record)(row_info, sort_param->record)); + row_info->dfile.file= old_file; /* restore actual value */ + row_info->state->records--; DBUG_RETURN(error); } /* sort_delete_record */ @@ -5145,7 +5192,7 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename) (*org_info)->state->empty=info.state->empty; (*org_info)->state->data_file_length=info.state->data_file_length; if (maria_update_state_info(param,*org_info,UPDATE_TIME | UPDATE_STAT | - UPDATE_OPEN_COUNT)) + UPDATE_OPEN_COUNT)) goto end; error=0; end: @@ -5184,6 +5231,7 @@ int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile) int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update) { MARIA_SHARE *share=info->s; + DBUG_ENTER("maria_update_state_info"); if (update & UPDATE_OPEN_COUNT) { @@ -5233,25 +5281,25 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update) share->w_locks=w_locks; share->tot_locks=r_locks+w_locks; if (!error) - return 0; + DBUG_RETURN(0); } err: _ma_check_print_error(param,"%d when updating keyfile",my_errno); - return 1; + DBUG_RETURN(1); } - /* - Update auto increment value for a table - When setting the 'repair_only' flag we only want to change the - old auto_increment value if its wrong (smaller than some given key). - The reason is that we shouldn't change the auto_increment value - for a table without good reason when only doing a repair; If the - user have inserted and deleted rows, the auto_increment value - may be bigger than the biggest current row and this is ok. - - If repair_only is not set, we will update the flag to the value in - param->auto_increment is bigger than the biggest key. - */ +/* + Update auto increment value for a table + When setting the 'repair_only' flag we only want to change the + old auto_increment value if its wrong (smaller than some given key). + The reason is that we shouldn't change the auto_increment value + for a table without good reason when only doing a repair; If the + user have inserted and deleted rows, the auto_increment value + may be bigger than the biggest current row and this is ok. + + If repair_only is not set, we will update the flag to the value in + param->auto_increment is bigger than the biggest key. +*/ void _ma_update_auto_increment_key(HA_CHECK *param, MARIA_HA *info, my_bool repair_only) @@ -5462,7 +5510,7 @@ void maria_disable_non_unique_index(MARIA_HA *info, ha_rows rows) */ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, - ulonglong key_map, my_bool force) + ulonglong key_map, my_bool force) { MARIA_SHARE *share=info->s; MARIA_KEYDEF *key=share->keyinfo; @@ -5474,9 +5522,6 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, */ if (! maria_is_any_key_active(key_map)) return FALSE; /* Can't use sort */ - /* QQ: Remove this when maria_repair_by_sort() works with block format */ - if (info->s->data_file_type == BLOCK_RECORD) - return FALSE; for (i=0 ; i < share->base.keys ; i++,key++) { if (!force && maria_too_big_key_for_sort(key,rows)) @@ -5486,6 +5531,53 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, } +/** + @brief Create a new handle for manipulation the new record file + + @note + It's ok for Recovery to have two MARIA_SHARE on the same index file + because the one we create here is not transactional +*/ + +my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file) +{ + + MARIA_SORT_INFO *sort_info= param->sort_info; + MARIA_HA *info= sort_info->info; + MARIA_HA *new_info; + DBUG_ENTER("create_new_data_handle"); + + if (!(sort_info->new_info= maria_open(info->s->open_file_name, O_RDWR, + HA_OPEN_COPY | HA_OPEN_FOR_REPAIR))) + DBUG_RETURN(1); + + new_info= sort_info->new_info; + change_data_file_descriptor(new_info, new_file); + maria_lock_database(new_info, F_EXTRA_LCK); + if ((sort_info->param->testflag & T_UNPACK) && + info->s->data_file_type == COMPRESSED_RECORD) + { + (*new_info->s->once_end)(new_info->s); + (*new_info->s->end)(new_info); + restore_data_file_type(new_info->s); + _ma_setup_functions(new_info->s); + if ((*new_info->s->once_init)(new_info->s, new_file) || + (*new_info->s->init)(new_info)) + DBUG_RETURN(1); + } + _ma_reset_status(new_info); + if (_ma_initialize_data_file(new_info->s, new_file)) + DBUG_RETURN(1); + + param->filepos= new_info->state->data_file_length; + + /* 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; + DBUG_RETURN(0); +} + + static void set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share) { @@ -5525,6 +5617,22 @@ static void change_data_file_descriptor(MARIA_HA *info, File new_file) { my_close(info->dfile.file, MYF(MY_WME)); info->dfile.file= info->s->bitmap.file.file= new_file; + _ma_bitmap_reset_cache(info->s); +} + + +/** + @brief Mark the data file to not be used + + @note + This is used in repair when we want to ensure the handler will not + write anything to the data file anymore +*/ + +static void unuse_data_file_descriptor(MARIA_HA *info) +{ + info->dfile.file= info->s->bitmap.file.file= -1; + _ma_bitmap_reset_cache(info->s); } @@ -5701,8 +5809,12 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) { MARIA_SHARE *share= info->s; /* in case this is maria_chk or recovery... */ - if (translog_inited && !maria_in_recovery) + if (translog_inited && !maria_in_recovery && + info->s->base.born_transactional) { + my_bool now_transactional= info->s->now_transactional; + info->s->now_transactional= 1; + /* For now this record is only informative. It could serve when applying logs to a backup, but that needs more thought. Assume table became @@ -5745,6 +5857,7 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) */ if (_ma_update_create_rename_lsn(share, lsn, TRUE)) return 1; + info->s->now_transactional= now_transactional; } return 0; } diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index 720a3b53dba..70a6ef9bf35 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -86,8 +86,7 @@ int maria_close(register MARIA_HA *info) may be using the file at this point IF using --external-locking, which does not apply to Maria. */ - if (share->mode != O_RDONLY && - ((share->changed && share->base.born_transactional) || + if (((share->changed && share->base.born_transactional) || maria_is_crashed(info))) { /* diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index af6830564b0..ed9c785439b 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -73,7 +73,8 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, LSN *res_lsn, void *extra_msg) { uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE + CLR_TYPE_STORE_SIZE + - HA_CHECKSUM_STORE_SIZE]; + HA_CHECKSUM_STORE_SIZE+ KEY_NR_STORE_SIZE + PAGE_STORE_SIZE]; + uchar *log_pos; LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 1]; struct st_msg_to_write_hook_for_clr_end msg; my_bool res; @@ -81,10 +82,8 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, /* undo_lsn must be first for compression to work */ lsn_store(log_data, undo_lsn); - clr_type_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, - undo_type); - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= - sizeof(log_data) - HA_CHECKSUM_STORE_SIZE; + clr_type_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, undo_type); + log_pos= log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + CLR_TYPE_STORE_SIZE; /* Extra_msg is handled in write_hook_for_clr_end() */ msg.undone_record_type= undo_type; @@ -95,11 +94,24 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, 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); + ha_checksum_store(log_pos, checksum); + log_pos+= HA_CHECKSUM_STORE_SIZE; } + else if (undo_type == LOGREC_UNDO_KEY_INSERT_WITH_ROOT || + undo_type == LOGREC_UNDO_KEY_DELETE_WITH_ROOT) + { + /* Key root changed. Store new key root */ + struct st_msg_to_write_hook_for_undo_key *undo_msg= extra_msg; + ulonglong page; + key_nr_store(log_pos, undo_msg->keynr); + page= (undo_msg->value == HA_OFFSET_ERROR ? IMPOSSIBLE_PAGE_NO : + undo_msg->value / info->s->block_size); + page_store(log_pos + KEY_NR_STORE_SIZE, page); + log_pos+= KEY_NR_STORE_SIZE + PAGE_STORE_SIZE; + } + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); res= translog_write_record(res_lsn, LOGREC_CLR_END, info->trn, info, log_array[TRANSLOG_INTERNAL_PARTS @@ -141,8 +153,8 @@ my_bool write_hook_for_clr_end(enum translog_record_type type case LOGREC_UNDO_ROW_UPDATE: share->state.state.checksum+= msg->checksum_delta; break; - case LOGREC_UNDO_KEY_INSERT: - case LOGREC_UNDO_KEY_DELETE: + case LOGREC_UNDO_KEY_INSERT_WITH_ROOT: + case LOGREC_UNDO_KEY_DELETE_WITH_ROOT: { /* Update key root */ struct st_msg_to_write_hook_for_undo_key *extra_msg= @@ -150,6 +162,9 @@ my_bool write_hook_for_clr_end(enum translog_record_type type *extra_msg->root= extra_msg->value; break; } + case LOGREC_UNDO_KEY_INSERT: + case LOGREC_UNDO_KEY_DELETE: + break; default: DBUG_ASSERT(0); } @@ -812,9 +827,11 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn, msg.root= &share->state.key_root[keynr]; msg.value= new_root; + msg.keynr= keynr; - if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_KEY_INSERT, 1, 0, &lsn, - (void*) &msg)) + if (_ma_write_clr(info, undo_lsn, *msg.root == msg.value ? + LOGREC_UNDO_KEY_INSERT : LOGREC_UNDO_KEY_INSERT_WITH_ROOT, + 0, 0, &lsn, (void*) &msg)) res= 1; _ma_unpin_all_pages_and_finalize_row(info, lsn); @@ -855,7 +872,11 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_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, + msg.keynr= keynr; + if (_ma_write_clr(info, undo_lsn, + *msg.root == msg.value ? + LOGREC_UNDO_KEY_DELETE : LOGREC_UNDO_KEY_DELETE_WITH_ROOT, + 0, 0, &lsn, (void*) &msg)) res= 1; diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h index 210d58f3eb8..f2fd81f2120 100644 --- a/storage/maria/ma_key_recover.h +++ b/storage/maria/ma_key_recover.h @@ -35,6 +35,7 @@ struct st_msg_to_write_hook_for_undo_key { my_off_t *root; my_off_t value; + uint keynr; }; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index e5e0d4e71bc..2b1d6e4a48d 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -490,6 +490,13 @@ static LOG_DESC INIT_LOGREC_UNDO_KEY_INSERT= NULL, write_hook_for_undo_key, NULL, 1, "undo_key_insert", LOGREC_LAST_IN_GROUP, NULL, NULL}; +/* This will never be in the log, only in the clr */ +static LOG_DESC INIT_LOGREC_UNDO_KEY_INSERT_WITH_ROOT= +{LOGRECTYPE_VARIABLE_LENGTH, 0, + LSN_STORE_SIZE + FILEID_STORE_SIZE + KEY_NR_STORE_SIZE + PAGE_STORE_SIZE, + NULL, write_hook_for_undo_key, NULL, 1, + "undo_key_insert_with_root", LOGREC_LAST_IN_GROUP, NULL, NULL}; + static LOG_DESC INIT_LOGREC_UNDO_KEY_DELETE= {LOGRECTYPE_VARIABLE_LENGTH, 0, LSN_STORE_SIZE + FILEID_STORE_SIZE + KEY_NR_STORE_SIZE, @@ -605,6 +612,8 @@ static void loghandler_init() INIT_LOGREC_UNDO_ROW_UPDATE; log_record_type_descriptor[LOGREC_UNDO_KEY_INSERT]= INIT_LOGREC_UNDO_KEY_INSERT; + log_record_type_descriptor[LOGREC_UNDO_KEY_INSERT_WITH_ROOT]= + INIT_LOGREC_UNDO_KEY_INSERT_WITH_ROOT; log_record_type_descriptor[LOGREC_UNDO_KEY_DELETE]= INIT_LOGREC_UNDO_KEY_DELETE; log_record_type_descriptor[LOGREC_UNDO_KEY_DELETE_WITH_ROOT]= diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 098ddffce66..4aa98cb2f0a 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -123,6 +123,7 @@ enum translog_record_type LOGREC_UNDO_ROW_DELETE, LOGREC_UNDO_ROW_UPDATE, LOGREC_UNDO_KEY_INSERT, + LOGREC_UNDO_KEY_INSERT_WITH_ROOT, LOGREC_UNDO_KEY_DELETE, LOGREC_UNDO_KEY_DELETE_WITH_ROOT, LOGREC_PREPARE, diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 18063dd3845..9fe2b5ec704 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -613,7 +613,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->base.null_bytes + share->base.pack_bytes + test(share->options & HA_OPTION_CHECKSUM)); - share->keypage_header= ((share->base.born_transactional ? LSN_STORE_SIZE : + share->keypage_header= ((share->base.born_transactional ? + LSN_STORE_SIZE + TRANSID_SIZE : 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + KEYPAGE_USED_SIZE); @@ -672,6 +673,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) MARIA_REC_BUFF_OFFSET); share->base.default_rec_buff_size+= share->base.extra_rec_buff_size; } + if (share->data_file_type == COMPRESSED_RECORD) + { + /* Need some extra bytes for decode_bytes */ + share->base.extra_rec_buff_size= 7; + } disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE, end_pos); for (i= j= 0 ; i < share->base.fields ; i++) @@ -1042,6 +1048,9 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo) uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite) { uint res; + if (share->options & HA_OPTION_READ_ONLY_DATA) + return 0; + if (pWrite & 4) pthread_mutex_lock(&share->intern_lock); else if (maria_multi_threaded) @@ -1091,7 +1100,7 @@ uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite) uchar *ptr=buff; uint i, keys= (uint) state->header.keys; size_t res; - DBUG_ENTER("_ma_state_info_write"); + DBUG_ENTER("_ma_state_info_write_sub"); memcpy_fixed(ptr,&state->header,sizeof(state->header)); ptr+=sizeof(state->header); diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index 08959aca079..5d04b9d705a 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -44,7 +44,9 @@ { bits-=(bit+1); break; } \ pos+= *pos -/* Size in uint16 of a Huffman tree for uchar compression of 256 uchar values. */ +/* + Size in uint16 of a Huffman tree for uchar compression of 256 uchar values +*/ #define OFFSET_TABLE_SIZE 512 static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file, @@ -245,7 +247,8 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file, length=(uint) (elements*2+trees*(1 << maria_quick_table_bits)); if (!(share->decode_tables=(uint16*) my_malloc((length+OFFSET_TABLE_SIZE)*sizeof(uint16)+ - (uint) (share->pack.header_length - sizeof(header)), + (uint) (share->pack.header_length - sizeof(header)) + + share->base.extra_rec_buff_size, MYF(MY_WME | MY_ZEROFILL)))) goto err1; tmp_buff=share->decode_tables+length; @@ -255,6 +258,11 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file, (uint) (share->pack.header_length-sizeof(header)), MYF(MY_NABP))) goto err2; +#ifdef HAVE_purify + /* Zero bytes accessed by fill_buffer */ + bzero(disk_cache + (share->pack.header_length-sizeof(header)), + share->base.extra_rec_buff_size); +#endif huff_tree_bits=max_bit(trees ? trees-1 : 0); init_bit_buffer(&bit_buff, disk_cache, diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index df1d1c509d8..c6481412232 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -1147,7 +1147,7 @@ static int new_table(uint16 sid, const char *name, tprint(tracef, ", has wrong state.key_file_length (fixing it)"); share->state.state.key_file_length= kfile_len; } - if ((dfile_len % share->block_size) > 0) + if ((dfile_len % share->block_size) || (kfile_len % share->block_size)) { tprint(tracef, ", has too short last page\n"); /* Recovery will fix this, no error */ @@ -1669,9 +1669,10 @@ prototype_redo_exec_hook(CLR_END) enum translog_record_type undone_record_type; const LOG_DESC *log_desc; my_bool row_entry= 0; + DBUG_ENTER("exec_REDO_LOGREC_CLR_END"); if (info == NULL) - return 0; + DBUG_RETURN(0); share= info->s; previous_undo_lsn= lsn_korr(rec->header); undone_record_type= @@ -1699,6 +1700,28 @@ prototype_redo_exec_hook(CLR_END) case LOGREC_UNDO_KEY_INSERT: case LOGREC_UNDO_KEY_DELETE: break; + case LOGREC_UNDO_KEY_INSERT_WITH_ROOT: + case LOGREC_UNDO_KEY_DELETE_WITH_ROOT: + { + uint key_nr; + my_off_t page; + uchar buff[KEY_NR_STORE_SIZE + PAGE_STORE_SIZE]; + if (translog_read_record(rec->lsn, LSN_STORE_SIZE + FILEID_STORE_SIZE + + CLR_TYPE_STORE_SIZE, + KEY_NR_STORE_SIZE + PAGE_STORE_SIZE, + buff, NULL) != + KEY_NR_STORE_SIZE + PAGE_STORE_SIZE) + { + tprint(tracef, "Failed to read record\n"); + DBUG_RETURN(1); + } + key_nr= key_nr_korr(buff); + page= page_korr(buff + KEY_NR_STORE_SIZE); + share->state.key_root[key_nr]= (page == IMPOSSIBLE_PAGE_NO ? + HA_OFFSET_ERROR : + page * share->block_size); + break; + } default: DBUG_ASSERT(0); } @@ -1710,7 +1733,7 @@ prototype_redo_exec_hook(CLR_END) buff, NULL) != HA_CHECKSUM_STORE_SIZE) { tprint(tracef, "Failed to read record\n"); - return 1; + DBUG_RETURN(1); } share->state.state.checksum+= ha_checksum_korr(buff); } @@ -1719,7 +1742,7 @@ prototype_redo_exec_hook(CLR_END) if (row_entry) tprint(tracef, " rows' count %lu\n", (ulong)share->state.state.records); _ma_unpin_all_pages(info, rec->lsn); - return 0; + DBUG_RETURN(0); } diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index e61019aeb83..69a95db2e09 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -110,7 +110,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, uchar **sort_keys; IO_CACHE tempfile, tempfile_for_exceptions; DBUG_ENTER("_ma_create_index_by_sort"); - DBUG_PRINT("enter",("sort_length: %d", info->key_length)); + DBUG_PRINT("enter",("sort_buff_size: %lu sort_length: %d max_records: %lu", + (ulong) sortbuff_size, info->key_length, + (ulong) info->sort_info->max_records)); if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) { diff --git a/storage/maria/ma_test_all.sh b/storage/maria/ma_test_all.sh index ef12d1340aa..bfadd3d516c 100755 --- a/storage/maria/ma_test_all.sh +++ b/storage/maria/ma_test_all.sh @@ -169,6 +169,11 @@ run_pack_tests() $maria_path/maria_chk$suffix -rus test1 $maria_path/maria_chk$suffix -es test1 + $maria_path/ma_test1$suffix $silent --checksum $row_type + $maria_path/maria_pack$suffix --force -s test1 + $maria_path/maria_chk$suffix -rus --safe-recover test1 + $maria_path/maria_chk$suffix -es test1 + $maria_path/ma_test1$suffix $silent --checksum -S $row_type $maria_path/maria_chk$suffix -se test1 $maria_path/maria_chk$suffix -ros test1 @@ -184,10 +189,10 @@ run_pack_tests() $maria_path/ma_test2$suffix $silent -c -d1 $row_type $maria_path/maria_chk$suffix -s --parallel-recover test2 $maria_path/maria_chk$suffix -se test2 - $maria_path/maria_chk$suffix -s --parallel-recover --unpack test2 + $maria_path/maria_chk$suffix -s --unpack --parallel-recover test2 $maria_path/maria_chk$suffix -se test2 $maria_path/maria_pack$suffix --force -s test1 - $maria_path/maria_chk$suffix -s --parallel-recover --unpack test2 + $maria_path/maria_chk$suffix -s --unpack --parallel-recover test2 $maria_path/maria_chk$suffix -se test2 } @@ -234,6 +239,30 @@ $maria_path/maria_chk$suffix -ssm test2 /bin/sh $maria_path/ma_test_recovery # +# Extra tests that has caused failures in the past +# + +# Problem with re-executing CLR's +rm -f maria_log.* maria_log_control +ma_test2 -s -L -K -W -P -M -T -c -b -t2 -u1 +cp maria_log_control tmp +maria_read_log -a -s +maria_chk -s -e test2 +cp tmp/maria_log_control . +rm test2.MA? +maria_read_log -a -s +maria_chk -s -e test2 + +# Problem with re-executing CLR's +rm -f maria_log.* maria_log_control +ma_test2 -s -L -K -W -P -M -T -c -b -t2 -u1 +maria_read_log -a -s +maria_chk -s -e test2 +rm test2.MA? +maria_read_log -a -s +maria_chk -e -s test2 + +# # Some timing tests # #time $maria_path/ma_test2$suffix $silent diff --git a/storage/maria/ma_test_recovery b/storage/maria/ma_test_recovery index b2329694e62..87b343e9301 100755 --- a/storage/maria/ma_test_recovery +++ b/storage/maria/ma_test_recovery @@ -24,14 +24,7 @@ check_table_is_same() $maria_path/maria_chk -dvv $table | grep -v "Creation time:" > $tmp/maria_chk_message.txt 2>&1 - # save the index file (because we want to test idempotency afterwards) - cp $table.MAI tmp/ - # In the repair below it's good to use -q because it will die on any - # incorrectness of the data file if UNDO was badly applied. - # QQ: Remove the following line when we also can recover the index file - $maria_path/maria_chk -s -rq $table - - $maria_path/maria_chk -s -e $table + $maria_path/maria_chk -s -e --read-only $table checksum2=`$maria_path/maria_chk -dss $table` if test "$checksum" != "$checksum2" then @@ -47,7 +40,6 @@ check_table_is_same() cat $tmp/maria_chk_diff.txt echo "========DIFF END=======" fi - mv tmp/$table.MAI . } apply_log() diff --git a/storage/maria/ma_test_recovery.expected b/storage/maria/ma_test_recovery.expected index 249cefea15d..4c853476a28 100644 --- a/storage/maria/ma_test_recovery.expected +++ b/storage/maria/ma_test_recovery.expected @@ -47,40 +47,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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) @@ -117,40 +117,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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) @@ -187,40 +187,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 204800 +> Datafile length: 114688 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 204800 +> Datafile length: 114688 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 204800 +> Datafile length: 114688 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) @@ -257,40 +257,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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) @@ -327,40 +327,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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) @@ -397,11 +397,11 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 122880 Keyfile length: 212992 @@ -410,27 +410,27 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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) @@ -467,40 +467,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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) @@ -537,37 +537,37 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 Keyfile length: 204800 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 204800 +> Datafile length: 114688 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 90112 Keyfile length: 204800 @@ -607,11 +607,11 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 81920 Keyfile length: 204800 @@ -620,11 +620,11 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 81920 Keyfile length: 204800 @@ -633,11 +633,11 @@ testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 81920 Keyfile length: 204800 @@ -677,40 +677,40 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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) @@ -747,11 +747,11 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 122880 Keyfile length: 212992 @@ -760,11 +760,11 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 122880 Keyfile length: 212992 @@ -773,11 +773,11 @@ testing applying of CLRs to recreate table applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 122880 Keyfile length: 212992 @@ -817,11 +817,11 @@ Dying on request without maria_commit()/maria_close() applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- > Datafile length: 122880 Keyfile length: 212992 @@ -830,25 +830,25 @@ testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 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======= -7c7 +6c6 < Status: checked,analyzed,optimized keys,sorted index pages --- > Status: changed -12c12 +11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 122880 Keyfile length: 212992 +> Datafile length: 155648 Keyfile length: 212992 ========DIFF END======= diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 4b78c5421a7..0203dd2fb26 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -135,7 +135,7 @@ int main(int argc, char **argv) { /* Only if descript */ char buff[22],buff2[22]; if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO) - puts("\n---------\n"); + puts("\n---------"); printf("\nTotal of all %d MARIA-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff), llstr(check_param.total_deleted,buff2)); } @@ -624,9 +624,13 @@ get_one_option(int optid, break; case 'u': if (argument == disabled_my_option) - check_param.testflag&= ~(T_UNPACK | T_REP_BY_SORT); + check_param.testflag&= ~T_UNPACK; else - check_param.testflag|= T_UNPACK | T_REP_BY_SORT; + { + check_param.testflag|= T_UNPACK; + if (!(check_param.testflag & T_REP_ANY)) + check_param.testflag|= T_REP_BY_SORT; + } break; case 'v': /* Verbose */ if (argument == disabled_my_option) @@ -802,13 +806,13 @@ static int maria_chk(HA_CHECK *param, char *filename) datafile=0; param->isam_file_name=filename; /* For error messages */ if (!(info=maria_open(filename, - (param->testflag & (T_DESCRIPT | T_READONLY)) ? - O_RDONLY : O_RDWR, - HA_OPEN_FOR_REPAIR | - ((param->testflag & T_WAIT_FOREVER) ? - HA_OPEN_WAIT_IF_LOCKED : - (param->testflag & T_DESCRIPT) ? - HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED)))) + (param->testflag & (T_DESCRIPT | T_READONLY)) ? + O_RDONLY : O_RDWR, + HA_OPEN_FOR_REPAIR | + ((param->testflag & T_WAIT_FOREVER) ? + HA_OPEN_WAIT_IF_LOCKED : + (param->testflag & T_DESCRIPT) ? + HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED)))) { /* Avoid twice printing of isam file name */ param->error_printed=1; @@ -852,7 +856,6 @@ static int maria_chk(HA_CHECK *param, char *filename) DBUG_RETURN(1); } share=info->s; - share->options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */ share->tot_locks-= share->r_locks; share->r_locks=0; maria_block_size= share->base.block_size; @@ -871,10 +874,10 @@ static int maria_chk(HA_CHECK *param, char *filename) goto end2; } /* We can't do parallell repair with BLOCK_RECORD yet */ - if (param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) + if (param->testflag & T_REP_PARALLEL) { - param->testflag&= ~(T_REP_BY_SORT | T_REP_PARALLEL); - param->testflag|= T_REP; + param->testflag&= ~T_REP_PARALLEL; + param->testflag|= T_REP_BY_SORT; } } @@ -1255,7 +1258,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) DBUG_VOID_RETURN; } - printf("\nMARIA file: %s\n",name); + printf("MARIA file: %s\n",name); printf("Record format: %s\n", record_formats[share->data_file_type]); printf("Crashsafe: %s\n", share->base.born_transactional ? "yes" : "no"); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 95ddf358679..4e771a2c85a 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -118,7 +118,7 @@ typedef struct st_maria_state_info #define MARIA_STATE_KEYBLOCK_SIZE 8 #define MARIA_STATE_KEYSEG_SIZE 12 #define MARIA_STATE_EXTRA_SIZE (MARIA_MAX_KEY*MARIA_STATE_KEY_SIZE + MARIA_MAX_KEY*HA_MAX_KEY_SEG*MARIA_STATE_KEYSEG_SIZE) -#define MARIA_KEYDEF_SIZE (2+ 5*2) +#define MARIA_KEYDEF_SIZE (2+ 5*2) #define MARIA_UNIQUEDEF_SIZE (2+1+1) #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) #define MARIA_COLUMNDEF_SIZE (6+2+2+2+2+2+1+1) @@ -507,6 +507,7 @@ struct st_maria_handler #define USE_WHOLE_KEY 65535 /* Use whole key in _search() */ #define F_EXTRA_LCK -1 +#define TRANSID_SIZE 6 /* bits in opt_flag */ #define MEMMAP_USED 32 @@ -540,7 +541,8 @@ struct st_maria_handler #define KEYPAGE_FLAG_SIZE 1 #define KEYPAGE_CHECKSUM_SIZE 4 #define MAX_KEYPAGE_HEADER_SIZE (LSN_STORE_SIZE + KEYPAGE_USED_SIZE + \ - KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + \ + TRANSID_SIZE) #define _ma_get_page_used(info,x) \ (((uint) mi_uint2korr(x + (info)->s->keypage_header - KEYPAGE_USED_SIZE)) & \ @@ -560,6 +562,11 @@ struct st_maria_handler } #define _ma_store_keynr(info, x, nr) x[(info)->s->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]= nr #define _ma_get_keynr(info, x) ((uchar) x[(info)->s->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]) +#define _ma_store_transid(buff, transid) \ + int6store((buff) + LSN_STORE_SIZE, (transid)) +#define _ma_korr_transid(buff) \ + uint6korr((buff) + LSN_STORE_SIZE) + #define maria_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \ DBUG_PRINT("error", ("Marked table crashed")); \ }while(0) diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 237fad2bf94..22250a630ba 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -29,7 +29,7 @@ const char *default_dbug_option= "d:t:i:O,\\maria_read_log.trace"; const char *default_dbug_option= "d:t:i:o,/tmp/maria_read_log.trace"; #endif #endif /* DBUG_OFF */ -static my_bool opt_only_display, opt_apply, opt_apply_undo, opt_silent, +static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent, opt_check; static ulong opt_page_buffer_size; @@ -84,8 +84,8 @@ int main(int argc, char **argv) goto err; } - if (opt_only_display) - printf("You are using --only-display, NOTHING will be written to disk\n"); + if (opt_display_only) + printf("You are using --display-only, NOTHING will be written to disk\n"); /* LSN could be also --start-from-lsn=# */ lsn= translog_first_lsn_in_log(); @@ -138,7 +138,7 @@ static struct my_option my_long_options[] = (uchar **) &opt_apply, (uchar **) &opt_apply, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', - "if --only-display, check if record is fully readable (for debugging)", + "if --display-only, check if record is fully readable (for debugging)", (uchar **) &opt_check, (uchar **) &opt_check, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF @@ -147,8 +147,8 @@ static struct my_option my_long_options[] = #endif {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"only-display", 'o', "display brief info read from records' header", - (uchar **) &opt_only_display, (uchar **) &opt_only_display, 0, GET_BOOL, + {"display-only", 'o', "display brief info read from records' header", + (uchar **) &opt_display_only, (uchar **) &opt_display_only, 0, GET_BOOL, NO_ARG,0, 0, 0, 0, 0, 0}, { "page_buffer_size", 'P', "", (uchar**) &opt_page_buffer_size, (uchar**) &opt_page_buffer_size, 0, @@ -225,7 +225,7 @@ static void get_options(int *argc,char ***argv) if (!opt_apply) opt_apply_undo= FALSE; - if ((opt_only_display + opt_apply) != 1) + if ((opt_display_only + opt_apply) != 1) { usage(); exit(1); |