diff options
Diffstat (limited to 'storage/maria/ma_blockrec.c')
-rw-r--r-- | storage/maria/ma_blockrec.c | 286 |
1 files changed, 200 insertions, 86 deletions
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 0d1a530dbfc..1687b043eee 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -52,10 +52,11 @@ Page header: - LSN 7 bytes Log position for last page change - PAGE_TYPE 1 uchar 1 for head / 2 for tail / 3 for blob - NO 1 uchar Number of row/tail entries on page - empty space 2 bytes Empty space on page + LSN 7 bytes Log position for last page change + PAGE_TYPE 1 uchar 1 for head / 2 for tail / 3 for blob + DIR_COUNT 1 uchar Number of row/tail entries on page + FREE_DIR_LINK 1 uchar Pointer to first free director entry or 255 if no + empty space 2 bytes Empty space on page The most significant bit in PAGE_TYPE is set to 1 if the data on the page can be compacted to get more space. (PAGE_CAN_BE_COMPACTED) @@ -65,22 +66,27 @@ Row directory of NO entries, that consist of the following for each row (in reverse order; i.e., first record is stored last): - Position 2 bytes Position of row on page - Length 2 bytes Length of entry + Position 2 bytes Position of row on page + Length 2 bytes Length of entry For Position and Length, the 1 most significant bit of the position and the 1 most significant bit of the length could be used for some states of the row (in other words, we should try to keep these reserved) - eof flag 1 uchar Reserved for full page read testing. (Ie, did the - previous write get the whole block on disk. + Position is 0 if the entry is not used. In this case length[0] points + to a previous free entry (255 if no previous entry) and length[1] + to the next free entry (or 255 if last free entry). This works because + the directory entry 255 can never be marked free (if the first directory + entry is freed, the directory is shrinked). + + checksum 4 bytes Reserved for full page read testing and live backup. ---------------- Structure of blob pages: - LSN 7 bytes Log position for last page change - PAGE_TYPE 1 uchar 3 + LSN 7 bytes Log position for last page change + PAGE_TYPE 1 uchar 3 data @@ -104,7 +110,7 @@ Number of ROW_EXTENT's 1-3 uchar Length encoded, optional This is the number of extents the row is split into - First row_extent 7 uchar Pointer to first row extent (optional) + First row_extent 7 uchar Pointer to first row extent (optional) Total length of length array 1-3 uchar Only used if we have char/varchar/blob fields. @@ -206,7 +212,7 @@ to handle DROP COLUMN, we must store in the index header the fields that has been dropped. When unpacking a row we will ignore dropped fields. When storing a row, we will mark a dropped field either with a - null in the null bit map or in the empty_bits and not store any data + null in the null bit map or in the empty_bits and not store any data for it. TODO: Add code for handling dropped fields. @@ -229,6 +235,7 @@ 00 00 00 00 00 00 00 LSN 01 Only one row in page + FF No free dir entry xx xx Empty space on page 10 Flag: row split, VER_PTR exists @@ -252,11 +259,10 @@ ..... until end of page - 09 00 F4 1F 00 (Start position 9, length 8180, end byte) + 09 00 F4 1F Start position 9, length 8180 + xx xx xx xx Checksum */ -#define SANITY_CHECKS - #include "maria_def.h" #include "ma_blockrec.h" #include <lf.h> @@ -625,17 +631,42 @@ static my_bool extend_area_on_page(uchar *buff, uchar *dir, uint *ret_length) { uint rec_offset, length; + uint max_entry= (uint) buff[DIR_COUNT_OFFSET]; DBUG_ENTER("extend_area_on_page"); rec_offset= uint2korr(dir); - length= uint2korr(dir + 2); - DBUG_PRINT("enter", ("rec_offset: %u length: %u request_length: %u", - rec_offset, length, request_length)); + if (rec_offset) + { + /* Extending old row; Mark current space as 'free' */ + length= uint2korr(dir + 2); + DBUG_PRINT("info", ("rec_offset: %u length: %u request_length: %u " + "empty_space: %u", + rec_offset, length, request_length, *empty_space)); - *empty_space+= length; + *empty_space+= length; + } + else + { + /* Reusing free directory entry; Free it from the directory list */ + if (dir[2] == END_OF_DIR_FREE_LIST) + buff[DIR_FREE_OFFSET]= dir[3]; + else + { + uchar *prev_dir= dir_entry_pos(buff, block_size, (uint) dir[2]); + DBUG_ASSERT(uint2korr(prev_dir) == 0 && prev_dir[3] == (uchar) rownr); + prev_dir[3]= dir[3]; + } + if (dir[3] != END_OF_DIR_FREE_LIST) + { + uchar *next_dir= dir_entry_pos(buff, block_size, (uint) dir[3]); + DBUG_ASSERT(uint2korr(next_dir) == 0 && next_dir[2] == (uchar) rownr); + next_dir[2]= dir[2]; + } + rec_offset= start_of_next_entry(dir); + length= 0; + } if (length < request_length) { - uint max_entry= (uint) ((uchar*) buff)[DIR_COUNT_OFFSET]; uint old_rec_offset; /* New data did not fit in old position. @@ -672,7 +703,13 @@ static my_bool extend_area_on_page(uchar *buff, uchar *dir, rec_offset= uint2korr(dir); length= uint2korr(dir+2); if (length < request_length) + { + DBUG_PRINT("error", ("Not enough space: " + "length: %u request_length: %u", + length, request_length)); + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ DBUG_RETURN(1); /* Error in block */ + } *empty_space= length; /* All space is here */ } } @@ -850,60 +887,76 @@ static uint empty_space_on_page(uchar *buff, uint block_size) buff[EMPTY_SPACE_OFFSET] is NOT updated but left up to the caller + See start of file for description of how free directory entires are linked + RETURN 0 Error (directory full or last block goes over directory) # Pointer to directory entry on page */ static uchar *find_free_position(uchar *buff, uint block_size, uint *res_rownr, - uint *res_length, uint *empty_space) + uint *res_length, uint *empty_space) { - uint max_entry= (uint) ((uchar*) buff)[DIR_COUNT_OFFSET]; - uint entry, length, first_pos; - uchar *dir, *end; + uint max_entry, free_entry; + uint length, first_pos; + uchar *dir, *first_dir; DBUG_ENTER("find_free_position"); - DBUG_PRINT("info", ("max_entry: %u", max_entry)); - - dir= (buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE); - end= buff + block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE; + max_entry= (uint) buff[DIR_COUNT_OFFSET]; + free_entry= (uint) buff[DIR_FREE_OFFSET]; *empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); - /* Search after first empty position */ - first_pos= PAGE_HEADER_SIZE; - for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry++) + DBUG_PRINT("info", ("max_entry: %u free_entry: %u", max_entry, free_entry)); + + first_dir= dir_entry_pos(buff, block_size, max_entry - 1); + + /* Search after first free position */ + if (free_entry != END_OF_DIR_FREE_LIST) { - uint tmp= uint2korr(end); - if (!tmp) /* Found not used entry */ + if (free_entry >= max_entry) + DBUG_RETURN(0); + dir= dir_entry_pos(buff, block_size, free_entry); + DBUG_ASSERT(uint2korr(dir) == 0 && dir[2] == END_OF_DIR_FREE_LIST); + /* Relink free list */ + if ((buff[DIR_FREE_OFFSET]= dir[3]) != END_OF_DIR_FREE_LIST) { - length= start_of_next_entry(end) - first_pos; - int2store(end, first_pos); /* Update dir entry */ - int2store(end + 2, length); - *res_rownr= entry; - *res_length= length; - DBUG_RETURN(end); + uchar *next_entry= dir_entry_pos(buff, block_size, (uint) dir[3]); + DBUG_ASSERT((uint) next_entry[2] == free_entry && + uint2korr(next_entry) == 0); + next_entry[2]= END_OF_DIR_FREE_LIST; /* Backlink */ } - first_pos= tmp + uint2korr(end + 2); + + first_pos= end_of_previous_entry(dir, buff + block_size - + PAGE_SUFFIX_SIZE); + length= start_of_next_entry(dir) - first_pos; + int2store(dir, first_pos); /* Update dir entry */ + int2store(dir + 2, length); + *res_rownr= free_entry; + *res_length= length; + DBUG_RETURN(dir); } - /* No empty places in dir; create a new one */ - dir= end; + /* No free places in dir; create a new one */ + /* Check if there is place for the directory entry */ if (max_entry == MAX_ROWS_PER_PAGE) DBUG_RETURN(0); - /* Check if there is place for the directory entry */ + dir= first_dir - DIR_ENTRY_SIZE; + /* Last used place on page */ + first_pos= uint2korr(first_dir) + uint2korr(first_dir + 2); + /* Check if there is place for the directory entry on the page */ if ((uint) (dir - buff) < first_pos) { /* Create place for directory */ compact_page(buff, block_size, max_entry-1, 0); - first_pos= (uint2korr(end + DIR_ENTRY_SIZE) + - uint2korr(end + DIR_ENTRY_SIZE+ 2)); + first_pos= (uint2korr(first_dir) + uint2korr(first_dir + 2)); *empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); + DBUG_ASSERT(*empty_space > DIR_ENTRY_SIZE); } - buff[DIR_COUNT_OFFSET]= (uchar) (uchar) max_entry+1; + buff[DIR_COUNT_OFFSET]= (uchar) max_entry+1; length= (uint) (dir - buff - first_pos); DBUG_ASSERT(length <= *empty_space - DIR_ENTRY_SIZE); int2store(dir, first_pos); - int2store(dir+2, length); /* Current max length */ + int2store(dir+2, length); /* Max length of region */ *res_rownr= max_entry; *res_length= length; @@ -1108,8 +1161,8 @@ static void compact_page(uchar *buff, uint block_size, uint rownr, PAGE_SUFFIX_SIZE) / DIR_ENTRY_SIZE); /* Move all entries before and including rownr up to start of page */ - dir= buff + block_size - DIR_ENTRY_SIZE * (rownr+1) - PAGE_SUFFIX_SIZE; - end= buff + block_size - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE; + dir= dir_entry_pos(buff, block_size, rownr); + end= dir_entry_pos(buff, block_size, 0); page_pos= next_free_pos= start_of_found_block= PAGE_HEADER_SIZE; diff= 0; for (; dir <= end ; end-= DIR_ENTRY_SIZE) @@ -1198,7 +1251,7 @@ static void compact_page(uchar *buff, uint block_size, uint rownr, if (extend_block) { /* Extend last block cover whole page */ - uint length= (uint) (dir - buff) - start_of_found_block; + uint length= ((uint) (dir - buff) - start_of_found_block); int2store(dir+2, length); } else @@ -1228,22 +1281,31 @@ static void compact_page(uchar *buff, uint block_size, uint rownr, EMPTY_SPACE is not updated */ -static void make_empty_page(uchar *buff, uint block_size, uint page_type) +static void make_empty_page(MARIA_HA *info, uchar *buff, uint page_type) { + uint block_size= info->s->block_size; + DBUG_ENTER("make_empty_page"); bzero(buff, PAGE_HEADER_SIZE); + +#ifndef DONT_ZERO_PAGE_BLOCKS /* We zero the rest of the block to avoid getting old memory information to disk and to allow the file to be compressed better if archived. - The rest of the code does not assume the block is zeroed above - PAGE_OVERHEAD_SIZE + The code does not assume the block is zeroed. */ - bzero(buff+ PAGE_HEADER_SIZE, block_size - PAGE_HEADER_SIZE); + bzero(buff+ PAGE_HEADER_SIZE, block_size - PAGE_HEADER_SIZE - + DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); +#endif buff[PAGE_TYPE_OFFSET]= (uchar) page_type; buff[DIR_COUNT_OFFSET]= 1; - /* Store position to the first row */ + buff[DIR_FREE_OFFSET]= END_OF_DIR_FREE_LIST; int2store(buff + block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE, PAGE_HEADER_SIZE); + if (!(info->s->options & HA_OPTION_PAGE_CHECKSUM)) + bfill(buff + block_size - KEYPAGE_CHECKSUM_SIZE, + KEYPAGE_CHECKSUM_SIZE, (uchar) 255); + DBUG_VOID_RETURN; } @@ -1295,7 +1357,7 @@ static my_bool get_head_or_tail_page(MARIA_HA *info, if (block->org_bitmap_value == 0) /* Empty block */ { /* New page */ - make_empty_page(buff, block_size, page_type); + make_empty_page(info, buff, page_type); res->buff= buff; res->empty_space= res->length= (block_size - PAGE_OVERHEAD_SIZE); res->data= (buff + PAGE_HEADER_SIZE); @@ -1328,8 +1390,7 @@ static my_bool get_head_or_tail_page(MARIA_HA *info, { compact_page(res->buff, block_size, res->rownr, 1); /* All empty space are now after current position */ - dir= (res->buff + block_size - DIR_ENTRY_SIZE * res->rownr - - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + dir= dir_entry_pos(res->buff, block_size, res->rownr); res->length= res->empty_space= uint2korr(dir+2); } if (res->length < length) @@ -1433,7 +1494,7 @@ static my_bool write_tail(MARIA_HA *info, during _ma_bitmap_find_place() allocate more entries on the tail page than it can hold */ - block->empty_space= ((uint) ((uchar*) row_pos.buff)[DIR_COUNT_OFFSET] <= + block->empty_space= ((uint) (row_pos.buff)[DIR_COUNT_OFFSET] <= MAX_ROWS_PER_PAGE - 1 - share->base.blobs ? empty_space : 0); block->used= BLOCKUSED_USED | BLOCKUSED_TAIL; @@ -1535,6 +1596,9 @@ static my_bool write_full_pages(MARIA_HA *info, copy_length= min(data_size, length); memcpy(buff + LSN_SIZE + PAGE_TYPE_SIZE, data, copy_length); length-= copy_length; + if (!(info->s->options & HA_OPTION_PAGE_CHECKSUM)) + bfill(buff + block_size - KEYPAGE_CHECKSUM_SIZE, + KEYPAGE_CHECKSUM_SIZE, (uchar) 255); DBUG_ASSERT(share->pagecache->block_size == block_size); if (pagecache_write(share->pagecache, @@ -2363,7 +2427,7 @@ static my_bool write_block_record(MARIA_HA *info, (uint) (log_array_pos - log_array), log_array, log_data, NULL); if (log_array != tmp_log_array) - my_free((uchar*) log_array, MYF(0)); + my_free(log_array, MYF(0)); if (error) goto disk_err; } @@ -2566,6 +2630,7 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, if (_ma_bitmap_find_place(info, row, blocks)) DBUG_RETURN(1); /* Error reading bitmap */ + /* page will be pinned & locked by get_head_or_tail_page */ if (get_head_or_tail_page(info, blocks->block, info->buff, row->space_on_head_page, HEAD_PAGE, @@ -2791,8 +2856,7 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, org_empty_size= uint2korr(buff + EMPTY_SPACE_OFFSET); rownr= ma_recordpos_to_dir_entry(record_pos); - dir= (buff + block_size - DIR_ENTRY_SIZE * rownr - - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + dir= dir_entry_pos(buff, block_size, rownr); if ((org_empty_size + cur_row->head_length) >= new_row->total_length) { @@ -2903,9 +2967,9 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, uint *empty_space_res) { - uint number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET]; + uint number_of_records= (uint) buff[DIR_COUNT_OFFSET]; uint length, empty_space; - uchar *dir, *org_dir; + uchar *dir; DBUG_ENTER("delete_dir_entry"); #ifdef SANITY_CHECKS @@ -2921,33 +2985,74 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, #endif empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); - org_dir= dir= (buff + block_size - DIR_ENTRY_SIZE * record_number - - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + dir= dir_entry_pos(buff, block_size, record_number); length= uint2korr(dir + 2); if (record_number == number_of_records - 1) { - /* Delete this entry and all following empty directory entries */ + /* Delete this entry and all following free directory entries */ uchar *end= buff + block_size - PAGE_SUFFIX_SIZE; - do + number_of_records--; + dir+= DIR_ENTRY_SIZE; + empty_space+= DIR_ENTRY_SIZE; + + /* Unlink and free the next empty ones */ + while (dir < end && dir[0] == 0 && dir[1] == 0) { number_of_records--; + if (dir[2] == END_OF_DIR_FREE_LIST) + buff[DIR_FREE_OFFSET]= dir[3]; + else + { + uchar *prev_entry= dir_entry_pos(buff, block_size, (uint) dir[2]); + DBUG_ASSERT(uint2korr(prev_entry) == 0 && prev_entry[3] == + number_of_records); + prev_entry[3]= dir[3]; + } + if (dir[3] != END_OF_DIR_FREE_LIST) + { + uchar *next_entry= dir_entry_pos(buff, block_size, (uint) dir[3]); + DBUG_ASSERT(uint2korr(next_entry) == 0 && next_entry[2] == + number_of_records); + next_entry[2]= dir[2]; + } dir+= DIR_ENTRY_SIZE; empty_space+= DIR_ENTRY_SIZE; - } while (dir < end && dir[0] == 0 && dir[1] == 0); + } if (number_of_records == 0) { + /* All entries on page deleted */ + DBUG_PRINT("info", ("Page marked as unallocated")); buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE; +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY + { + uchar *dir= dir_entry_pos(buff, block_size, record_number); + bzero(dir, (record_number+1) * DIR_ENTRY_SIZE); + } +#endif *empty_space_res= block_size; DBUG_RETURN(1); } buff[DIR_COUNT_OFFSET]= (uchar) number_of_records; } + else + { + /* Update directory */ + dir[0]= dir[1]= 0; + dir[2]= END_OF_DIR_FREE_LIST; + if ((dir[3]= buff[DIR_FREE_OFFSET]) != END_OF_DIR_FREE_LIST) + { + /* Relink next entry to point to newly freed entry */ + uchar *next_entry= dir_entry_pos(buff, block_size, (uint) dir[3]); + DBUG_ASSERT(uint2korr(next_entry) == 0 && + next_entry[2] == END_OF_DIR_FREE_LIST); + next_entry[2]= record_number; + } + buff[DIR_FREE_OFFSET]= record_number; + } empty_space+= length; - /* Update directory */ - org_dir[0]= org_dir[1]= 0; org_dir[2]= org_dir[3]= 0; /* Delete entry */ int2store(buff + EMPTY_SPACE_OFFSET, empty_space); buff[PAGE_TYPE_OFFSET]|= (uchar) PAGE_CAN_BE_COMPACTED; @@ -3214,7 +3319,7 @@ err: static uchar *get_record_position(uchar *buff, uint block_size, uint record_number, uchar **end_of_data) { - uint number_of_records= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET]; + uint number_of_records= (uint) buff[DIR_COUNT_OFFSET]; uchar *dir; uchar *data; uint offset, length; @@ -3231,8 +3336,7 @@ static uchar *get_record_position(uchar *buff, uint block_size, } #endif - dir= (buff + block_size - DIR_ENTRY_SIZE * record_number - - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE); + dir= dir_entry_pos(buff, block_size, record_number); offset= uint2korr(dir); length= uint2korr(dir + 2); #ifdef SANITY_CHECKS @@ -3354,7 +3458,7 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, goto crashed; extent->page++; /* point to next page */ extent->page_count--; - *end_of_data= buff + share->block_size; + *end_of_data= buff + share->block_size - PAGE_SUFFIX_SIZE; info->cur_row.full_page_count++; /* For maria_chk */ DBUG_RETURN(extent->data_start= buff + LSN_SIZE + PAGE_TYPE_SIZE); } @@ -4176,8 +4280,8 @@ static void _ma_print_directory(uchar *buff, uint block_size) uint end_of_prev_row= PAGE_HEADER_SIZE; uchar *dir, *end; - dir= buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE; - end= buff + block_size - DIR_ENTRY_SIZE - PAGE_SUFFIX_SIZE; + dir= dir_entry_pos(buff, block_size, max_entry-1); + end= dir_entry_pos(buff, block_size, 0); DBUG_LOCK_FILE; fprintf(DBUG_FILE,"Directory dump (pos:length):\n"); @@ -4936,7 +5040,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, DBUG_ASSERT(rownr == 0); if (rownr != 0) goto err; - make_empty_page(buff, block_size, page_type); + make_empty_page(info, buff, page_type); empty_space= (block_size - PAGE_OVERHEAD_SIZE); rec_offset= PAGE_HEADER_SIZE; dir= buff+ block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE; @@ -4945,7 +5049,6 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, } else { - uint max_entry; if (!(buff= pagecache_read(share->pagecache, &info->dfile, page, 0, 0, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, @@ -4966,25 +5069,27 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, unlock_method= PAGECACHE_LOCK_WRITE_UNLOCK; unpin_method= PAGECACHE_UNPIN; - max_entry= (uint) ((uchar*) buff)[DIR_COUNT_OFFSET]; if (((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != page_type)) { /* This is a page that has been freed before and now should be changed to new type. */ - if ((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != BLOB_PAGE && - (buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != UNALLOCATED_PAGE) + DBUG_ASSERT(rownr == 0); + if (((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != BLOB_PAGE && + (buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != UNALLOCATED_PAGE) || + rownr != 0) goto err; - make_empty_page(buff, block_size, page_type); + make_empty_page(info, buff, page_type); empty_space= (block_size - PAGE_OVERHEAD_SIZE); rec_offset= PAGE_HEADER_SIZE; dir= buff+ block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE; } else { - dir= (buff + block_size - DIR_ENTRY_SIZE * (rownr + 1) - - PAGE_SUFFIX_SIZE); + uint max_entry= (uint) buff[DIR_COUNT_OFFSET]; + + dir= dir_entry_pos(buff, block_size, rownr); empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); if (max_entry <= rownr) @@ -5000,7 +5105,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, /* Create place for directory & data */ compact_page(buff, block_size, max_entry - 1, 0); rec_offset= (uint2korr(dir + DIR_ENTRY_SIZE) + - uint2korr(dir + DIR_ENTRY_SIZE +2)); + uint2korr(dir + DIR_ENTRY_SIZE + 2)); empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); DBUG_ASSERT(!((uint) (dir - buff) < rec_offset + data_length)); if ((uint) (dir - buff) < rec_offset + data_length) @@ -5218,6 +5323,15 @@ uint _ma_apply_redo_purge_blocks(MARIA_HA *info, continue; } buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE; +#ifdef IDENTICAL_PAGES_AFTER_RECOVERY + { + uint number_of_records= (uint) buff[DIR_COUNT_OFFSET]; + uchar *dir= dir_entry_pos(buff, info->s->block_size, + number_of_records-1); + buff[DIR_FREE_OFFSET]= END_OF_DIR_FREE_LIST; + bzero(dir, number_of_records * DIR_ENTRY_SIZE); + } +#endif lsn_store(buff, lsn); if (pagecache_write(share->pagecache, &info->dfile, page+i, 0, |