diff options
Diffstat (limited to 'storage/maria')
31 files changed, 1395 insertions, 987 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 0ec080ce383..42bfe679aa7 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -409,8 +409,9 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, - compare FULLTEXT keys; - compare SPATIAL keys; - compare FIELD_SKIP_ZERO which is converted to FIELD_NORMAL correctly - (should be corretly detected in table2maria). + (should be correctly detected in table2maria). */ + int maria_check_definition(MARIA_KEYDEF *t1_keyinfo, MARIA_COLUMNDEF *t1_recinfo, uint t1_keys, uint t1_recs, @@ -727,9 +728,6 @@ err: int ha_maria::open(const char *name, int mode, uint test_if_locked) { - MARIA_KEYDEF *keyinfo; - MARIA_COLUMNDEF *recinfo= 0; - uint recs; uint i; #ifdef NOT_USED @@ -755,39 +753,6 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER))) return (my_errno ? my_errno : -1); - /** - @todo ASK_MONTY - This is a protection for the case of a frm and MAI containing incompatible - table definitions (as in BUG#25908). This was merged from MyISAM. - But it breaks maria.test and ps_maria.test ("incorrect key file") if the - table is BLOCK_RECORD (does it have to do with column reordering done in - ma_create.c ?). - */ - if (!table->s->tmp_table) /* No need to perform a check for tmp table */ - { - if ((my_errno= table2maria(table, &keyinfo, &recinfo, &recs))) - { - /* purecov: begin inspected */ - DBUG_PRINT("error", ("Failed to convert TABLE object to Maria " - "key and column definition")); - goto err; - /* purecov: end */ - } -#ifdef ASK_MONTY - if (maria_check_definition(keyinfo, recinfo, table->s->keys, recs, - file->s->keyinfo, file->s->columndef, - file->s->base.keys, file->s->base.fields, true)) -#else - if (0) -#endif - { - /* purecov: begin inspected */ - my_errno= HA_ERR_CRASHED; - goto err; - /* purecov: end */ - } - } - if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE)) VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0)); @@ -819,16 +784,6 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) table->key_info[i].block_size= file->s->keyinfo[i].block_length; } my_errno= 0; - goto end; - err: - this->close(); - end: - /* - Both recinfo and keydef are allocated by my_multi_malloc(), thus only - recinfo must be freed. - */ - if (recinfo) - my_free((uchar*) recinfo, MYF(0)); return my_errno; } @@ -1917,9 +1872,12 @@ int ha_maria::info(uint flag) share->keys_for_keyread.intersect(share->keys_in_use); share->db_record_offset= maria_info.record_offset; if (share->key_parts) - memcpy((char*) table->key_info[0].rec_per_key, - (char*) maria_info.rec_per_key, - sizeof(table->key_info[0].rec_per_key) * share->key_parts); + { + ulong *to= table->key_info[0].rec_per_key, *end; + double *from= maria_info.rec_per_key; + for (end= to+ share->key_parts ; to < end ; to++, from++) + *to= (ulong) (*from + 0.5); + } if (share->tmp_table == NO_TMP_TABLE) pthread_mutex_unlock(&share->mutex); @@ -2111,6 +2069,10 @@ void ha_maria::update_create_info(HA_CREATE_INFO *create_info) } create_info->data_file_name= data_file_name; create_info->index_file_name= index_file_name; + /* We need to restore the row type as Maria can change it */ + if (create_info->row_type != ROW_TYPE_DEFAULT && + !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) + create_info->row_type= get_row_type(); } @@ -2160,7 +2122,16 @@ int ha_maria::create(const char *name, register TABLE *table_arg, break; } } + /* Note: BLOCK_RECORD is used if table is transactional */ row_type= maria_row_type(ha_create_info); + if (ha_create_info->transactional == HA_CHOICE_YES && + ha_create_info->row_type != ROW_TYPE_PAGE && + ha_create_info->row_type != ROW_TYPE_NOT_USED && + ha_create_info->row_type != ROW_TYPE_DEFAULT) + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA_CREATE_OPTION, + "Row format set to PAGE because of TRANSACTIONAL=1 option"); + if ((error= table2maria(table_arg, &keydef, &recinfo, &records))) DBUG_RETURN(error); /* purecov: inspected */ bzero((char*) &create_info, sizeof(create_info)); @@ -2174,21 +2145,17 @@ int ha_maria::create(const char *name, register TABLE *table_arg, share->avg_row_length); create_info.data_file_name= ha_create_info->data_file_name; create_info.index_file_name= ha_create_info->index_file_name; -#ifdef ASK_MONTY - /** - @todo ASK_MONTY - Where "transactional" in the frm and in the engine can go out of sync. - Don't we want to do, after the setting, this test: - if (!create_info.transactional && - ha_create_info->transactional == HA_CHOICE_YES) - error; - ? - Why fool the user? + + /* + Table is transactional: + - If the user specify that table is transactional (in this case + row type is forced to BLOCK_RECORD) + - If they specify BLOCK_RECORD without specifying transactional behaviour + Shouldn't this test be pushed down to maria_create()? Because currently, ma_test1 -T crashes: it creates a table with DYNAMIC_RECORD but has born_transactional==1, which confuses some recovery-related code. */ -#endif create_info.transactional= (row_type == BLOCK_RECORD && ha_create_info->transactional != HA_CHOICE_NO); @@ -2202,6 +2169,8 @@ int ha_maria::create(const char *name, register TABLE *table_arg, create_flags|= HA_CREATE_CHECKSUM; if (options & HA_OPTION_DELAY_KEY_WRITE) create_flags|= HA_CREATE_DELAY_KEY_WRITE; + if (ha_create_info->page_checksum != HA_CHOICE_NO) + create_flags|= HA_CREATE_PAGE_CHECKSUM; /* TODO: Check that the following fn_format is really needed */ error= diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 4046857d2a7..1d66583fcc5 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -130,8 +130,11 @@ #define FULL_HEAD_PAGE 4 #define FULL_TAIL_PAGE 7 -/** all bitmap pages end with this 2-byte signature */ -uchar maria_bitmap_marker[2]= {(uchar) 'b',(uchar) 'm'}; +/* If we don't have page checksum enabled, the bitmap page ends with this */ +uchar maria_bitmap_marker[4]= +{(uchar) 255, (uchar) 255, (uchar) 255, (uchar) 254}; +uchar maria_normal_page_marker[4]= +{(uchar) 255, (uchar) 255, (uchar) 255, (uchar) 255}; static my_bool _ma_read_bitmap_page(MARIA_SHARE *share, MARIA_FILE_BITMAP *bitmap, @@ -186,7 +189,7 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) bitmap->changed= 0; bitmap->block_size= share->block_size; /* Size needs to be alligned on 6 */ - aligned_bit_blocks= share->block_size / 6; + aligned_bit_blocks= (share->block_size - PAGE_SUFFIX_SIZE) / 6; bitmap->total_size= aligned_bit_blocks * 6; /* In each 6 bytes, we have 6*8/3 = 16 pages covered @@ -455,10 +458,6 @@ static void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap) fprintf(DBUG_FILE,"\nBitmap page changes at page %lu\n", (ulong) bitmap->page); - DBUG_ASSERT(memcmp(bitmap->map + bitmap->block_size - - sizeof(maria_bitmap_marker), - maria_bitmap_marker, sizeof(maria_bitmap_marker)) == 0); - page= (ulong) bitmap->page+1; for (pos= bitmap->map, org_pos= bitmap->map + bitmap->block_size ; pos < end ; @@ -544,14 +543,30 @@ static my_bool _ma_read_bitmap_page(MARIA_SHARE *share, } bitmap->used_size= bitmap->total_size; DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size); - res= ((pagecache_read(share->pagecache, + res= pagecache_read(share->pagecache, (PAGECACHE_FILE*)&bitmap->file, page, 0, (uchar*) bitmap->map, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL) || - memcmp(bitmap->map + bitmap->block_size - - sizeof(maria_bitmap_marker), - maria_bitmap_marker, sizeof(maria_bitmap_marker))); + PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL; + + /* + We can't check maria_bitmap_marker here as if the bitmap page + previously had a true checksum and the user switched mode to not checksum + this may have any value, except maria_normal_page_marker. + + Using maria_normal_page_marker gives us a protection against bugs + when running without any checksums. + */ + + if (!res && !(share->options & HA_OPTION_PAGE_CHECKSUM) && + !memcmp(bitmap->map + bitmap->block_size - + sizeof(maria_normal_page_marker), + maria_normal_page_marker, + sizeof(maria_normal_page_marker))) + { + res= 1; + my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ + } #ifndef DBUG_OFF if (!res) memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); @@ -1428,6 +1443,7 @@ static my_bool write_rest_of_head(MARIA_HA *info, uint position, row->space_on_head_page contains minimum number of bytes we expect to put on the head page. 1 error + my_errno is set to error */ my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, @@ -2068,9 +2084,16 @@ int _ma_bitmap_create_first(MARIA_SHARE *share) { uint block_size= share->bitmap.block_size; File file= share->bitmap.file.file; + char marker[sizeof(maria_bitmap_marker)]; + + if (share->options & HA_OPTION_PAGE_CHECKSUM) + bzero(marker, sizeof(marker)); + else + bmove(marker, maria_bitmap_marker, sizeof(marker)); + if (my_chsize(file, block_size - sizeof(maria_bitmap_marker), 0, MYF(MY_WME)) || - my_pwrite(file, maria_bitmap_marker, sizeof(maria_bitmap_marker), + my_pwrite(file, marker, sizeof(maria_bitmap_marker), block_size - sizeof(maria_bitmap_marker), MYF(MY_NABP | MY_WME))) return 1; 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, diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index 0bce4015daf..e840562b749 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -13,22 +13,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* Storage of records in block */ #define LSN_SIZE 7 #define DIR_COUNT_SIZE 1 /* Stores number of rows on page */ +#define DIR_FREE_SIZE 1 /* Pointer to first free dir entry */ #define EMPTY_SPACE_SIZE 2 /* Stores empty space on page */ #define PAGE_TYPE_SIZE 1 -#define PAGE_SUFFIX_SIZE 0 /* Bytes for page suffix */ -#define PAGE_HEADER_SIZE (LSN_SIZE + DIR_COUNT_SIZE + EMPTY_SPACE_SIZE +\ - PAGE_TYPE_SIZE) +#define PAGE_SUFFIX_SIZE 4 /* Bytes for checksum */ +#define PAGE_HEADER_SIZE (LSN_SIZE + DIR_COUNT_SIZE + DIR_FREE_SIZE +\ + EMPTY_SPACE_SIZE + PAGE_TYPE_SIZE) #define PAGE_OVERHEAD_SIZE (PAGE_HEADER_SIZE + DIR_ENTRY_SIZE + \ PAGE_SUFFIX_SIZE) #define BLOCK_RECORD_POINTER_SIZE 6 -#define FULL_PAGE_SIZE(block_size) ((block_size) - LSN_SIZE - PAGE_TYPE_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,7 +43,6 @@ #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 @@ -51,12 +53,13 @@ #define BASE_ROW_HEADER_SIZE FLAG_SIZE #define TRANS_ROW_EXTRA_HEADER_SIZE TRANSID_SIZE -#define PAGE_TYPE_MASK 127 +#define PAGE_TYPE_MASK 7 enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_TYPE }; #define PAGE_TYPE_OFFSET LSN_SIZE -#define DIR_COUNT_OFFSET LSN_SIZE+PAGE_TYPE_SIZE -#define EMPTY_SPACE_OFFSET (DIR_COUNT_OFFSET + DIR_COUNT_SIZE) +#define DIR_COUNT_OFFSET (LSN_SIZE+PAGE_TYPE_SIZE) +#define DIR_FREE_OFFSET (DIR_COUNT_OFFSET+DIR_COUNT_SIZE) +#define EMPTY_SPACE_OFFSET (DIR_FREE_OFFSET+DIR_FREE_SIZE) #define PAGE_CAN_BE_COMPACTED 128 /* Bit in PAGE_TYPE */ @@ -84,6 +87,7 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_ /* We use 1 uchar in record header to store number of directory entries */ #define MAX_ROWS_PER_PAGE 255 +#define END_OF_DIR_FREE_LIST ((uchar) 255) /* Bits for MARIA_BITMAP_BLOCKS->used */ /* We stored data on disk in the block */ @@ -123,6 +127,12 @@ static inline uint ma_recordpos_to_dir_entry(MARIA_RECORD_POS record_pos) return (uint) (record_pos & 255); } +static inline uchar *dir_entry_pos(uchar *buff, uint block_size, uint pos) +{ + return (buff + block_size - DIR_ENTRY_SIZE * pos - PAGE_SUFFIX_SIZE - + DIR_ENTRY_SIZE); +} + /* ma_blockrec.c */ void _ma_init_block_record_data(void); my_bool _ma_once_init_block_record(MARIA_SHARE *share, File dfile); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index dec70028596..4716a0bd209 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -314,7 +314,11 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info, DBUG_RETURN(1); /* purecov: end */ } - next_link=mi_sizekorr(buff); + if (_ma_get_keynr(info, buff) != MARIA_DELETE_KEY_NR) + _ma_check_print_error(param, "Page at %s is not delete marked", + llstr(next_link, llbuff)); + + next_link= mi_sizekorr(buff + info->s->keypage_header); records--; param->key_file_blocks+=block_size; } @@ -419,7 +423,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) ha_rows keys; ha_checksum old_record_checksum,init_checksum; my_off_t all_keydata,all_totaldata,key_totlength,length; - ulong *rec_per_key_part; + double *rec_per_key_part; MARIA_SHARE *share=info->s; MARIA_KEYDEF *keyinfo; char buff[22],buff2[22]; @@ -445,7 +449,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) old_record_checksum= (calc_checksum(info->state->records + info->state->del-1) * share->base.pack_reclength); - rec_per_key_part= param->rec_per_key_part; + rec_per_key_part= param->new_rec_per_key_part; for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ; rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++) { @@ -455,7 +459,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, (char*) (share->state.rec_per_key_part + - (uint) (rec_per_key_part - param->rec_per_key_part)), + (uint) (rec_per_key_part - param->new_rec_per_key_part)), keyinfo->keysegs*sizeof(*rec_per_key_part)); continue; } @@ -628,7 +632,7 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info, { /* purecov: begin tested */ _ma_check_print_error(param, "Mis-aligned key block: %s " - "minimum key block length: %u", + "key block length: %u", llstr(page, llbuff), info->s->block_size); goto err; /* purecov: end */ @@ -743,7 +747,7 @@ int maria_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, } - /* Check if index is ok */ +/* Check if index is ok */ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, @@ -756,7 +760,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, char llbuff[22]; uint diff_pos[2]; DBUG_ENTER("chk_index"); - DBUG_DUMP("buff",(uchar*) buff,maria_data_on_page(buff)); + DBUG_DUMP("buff", buff, _ma_get_page_used(info, buff)); /* TODO: implement appropriate check for RTree keys */ if (keyinfo->flag & HA_SPATIAL) @@ -772,16 +776,22 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* Not real duplicates */ else comp_flag=SEARCH_SAME; /* Keys in positionorder */ - nod_flag=_ma_test_if_nod(buff); - used_length= maria_data_on_page(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; - param->keydata+=used_length; param->totaldata+=keyinfo->block_length; /* INFO */ + _ma_get_used_and_nod(info, buff, used_length, nod_flag); + keypos= buff + info->s->keypage_header + nod_flag; + endpos= buff + used_length; + + param->keydata+= used_length; + param->totaldata+= keyinfo->block_length; /* INFO */ param->key_blocks++; if (level > param->max_level) param->max_level=level; + if (_ma_get_keynr(info, buff) != (uint) (keyinfo - info->s->keyinfo)) + _ma_check_print_error(param, "Page at %s is not marked for index %u", + llstr(page, llbuff), + (uint) (keyinfo - info->s->keyinfo)); + if (used_length > keyinfo->block_length) { _ma_check_print_error(param,"Wrong pageinfo at page: %s", @@ -1389,7 +1399,7 @@ end: /* - Check if layout on a page is ok + Check if layout on head or tail page is ok NOTES This is for rows-in-block format. @@ -1400,17 +1410,62 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info, uint row_count, uint head_empty, uint *real_rows_found) { - uint empty, last_row_end, row, first_dir_entry; + uint empty, last_row_end, row, first_dir_entry, free_entry, block_size; + uint free_entries, prev_free_entry; uchar *dir_entry; char llbuff[22]; + my_bool error_in_free_list= 0; DBUG_ENTER("check_page_layout"); + block_size= info->s->block_size; empty= 0; last_row_end= PAGE_HEADER_SIZE; *real_rows_found= 0; + /* Check free directory list */ + free_entry= (uint) page[DIR_FREE_OFFSET]; + free_entries= 0; + prev_free_entry= END_OF_DIR_FREE_LIST; + while (free_entry != END_OF_DIR_FREE_LIST) + { + uchar *dir; + if (free_entry > row_count) + { + _ma_check_print_error(param, + "Page %9s: Directory free entry points outside " + "directory", + llstr(page_pos, llbuff)); + error_in_free_list= 1; + break; + } + dir= dir_entry_pos(page, block_size, free_entry); + if (uint2korr(dir) != 0) + { + _ma_check_print_error(param, + "Page %9s: Directory free entry points to " + "not deleted entry", + llstr(page_pos, llbuff)); + error_in_free_list= 1; + break; + } + if (dir[2] != prev_free_entry) + { + _ma_check_print_error(param, + "Page %9s: Directory free list back pointer " + "points to wrong entry", + llstr(page_pos, llbuff)); + error_in_free_list= 1; + break; + } + prev_free_entry= free_entry; + free_entry= dir[3]; + free_entries++; + } + + /* Check directry */ dir_entry= page+ info->s->block_size - PAGE_SUFFIX_SIZE; - first_dir_entry= info->s->block_size - row_count* DIR_ENTRY_SIZE; + first_dir_entry= (info->s->block_size - row_count* DIR_ENTRY_SIZE - + PAGE_SUFFIX_SIZE); for (row= 0 ; row < row_count ; row++) { uint pos, length; @@ -1418,6 +1473,7 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info, pos= uint2korr(dir_entry); if (!pos) { + free_entries--; if (row == row_count -1) { _ma_check_print_error(param, @@ -1455,9 +1511,18 @@ static int check_page_layout(HA_CHECK *param, MARIA_HA *info, _ma_check_print_error(param, "Page %9s: Wrong empty size. Stored: %5u Actual: %5u", llstr(page_pos, llbuff), head_empty, empty); - DBUG_RETURN(param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)); + param->err_count++; } - DBUG_RETURN(0); + if (free_entries != 0 && !error_in_free_list) + { + _ma_check_print_error(param, + "Page %9s: Directory free link don't include " + "all free entries", + llstr(page_pos, llbuff)); + param->err_count++; + } + DBUG_RETURN(param->err_count && + (param->err_count >= MAXERR || !(param->testflag & T_VERBOSE))); } @@ -1666,7 +1731,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE) { _ma_check_print_error(param, - "Page %9s: Found wrong page type %d\n", + "Page %9s: Found wrong page type %d", llstr(pos, llbuff), page_type); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; @@ -1832,7 +1897,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))) { _ma_check_print_warning(param, - "Record checksum is not the same as checksum stored in the index file\n"); + "Record checksum is not the same as checksum stored in the index file"); error=1; } else if (!extend) @@ -2425,7 +2490,7 @@ int maria_movepoint(register MARIA_HA *info, uchar *record, (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF), info->s->state.key_root[i])) DBUG_RETURN(-1); - nod_flag=_ma_test_if_nod(info->buff); + nod_flag=_ma_test_if_nod(info, info->buff); _ma_dpointer(info,info->int_keypos-nod_flag- info->s->rec_reflength,newpos); if (_ma_write_keypage(info,keyinfo,info->last_keypage, @@ -2621,11 +2686,11 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, llstr(pagepos,llbuff)); goto err; } - if ((nod_flag=_ma_test_if_nod(buff)) || keyinfo->flag & HA_FULLTEXT) + if ((nod_flag=_ma_test_if_nod(info, buff)) || keyinfo->flag & HA_FULLTEXT) { - used_length= maria_data_on_page(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; + used_length= _ma_get_page_used(info, buff); + keypos=buff + info->s->keypage_header + nod_flag; + endpos=buff + used_length; for ( ;; ) { if (nod_flag) @@ -2667,7 +2732,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, } /* Fill block with zero and write it to the new index file */ - length= maria_data_on_page(buff); + length= _ma_get_page_used(info, buff); bzero((uchar*) buff+length,keyinfo->block_length-length); if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length, new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL))) @@ -2776,7 +2841,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, MARIA_SORT_PARAM sort_param; MARIA_SHARE *share=info->s; HA_KEYSEG *keyseg; - ulong *rec_per_key_part; + double *rec_per_key_part; char llbuff[22]; MARIA_SORT_INFO sort_info; ulonglong key_map=share->state.key_map; @@ -2913,7 +2978,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, if (param->testflag & T_CALC_CHECKSUM) sort_param.calc_checksum= 1; - rec_per_key_part= param->rec_per_key_part; + rec_per_key_part= param->new_rec_per_key_part; for (sort_param.key=0 ; sort_param.key < share->base.keys ; rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++) { @@ -2925,7 +2990,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, (char*) (share->state.rec_per_key_part + - (uint) (rec_per_key_part - param->rec_per_key_part)), + (uint) (rec_per_key_part - param->new_rec_per_key_part)), sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part)); continue; } @@ -2991,8 +3056,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, } if (_ma_create_index_by_sort(&sort_param, - (my_bool) (!(param->testflag & T_VERBOSE)), - (uint) param->sort_buffer_length)) + (my_bool) (!(param->testflag & T_VERBOSE)), + (size_t) param->sort_buffer_length)) { param->retry_repair=1; goto err; @@ -3005,9 +3070,11 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, sort_info.max_records= (ha_rows) 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,(ulonglong) info->state->records); + 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, + (ulonglong) info->state->records); maria_set_key_active(share->state.key_map, sort_param.key); if (sort_param.fix_datafile) @@ -3201,7 +3268,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, File new_file; MARIA_SORT_PARAM *sort_param=0; MARIA_SHARE *share=info->s; - ulong *rec_per_key_part; + double *rec_per_key_part; HA_KEYSEG *keyseg; char llbuff[22]; IO_CACHE new_data_cache; /* For non-quick repair. */ @@ -3378,7 +3445,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, goto err; } total_key_length=0; - rec_per_key_part= param->rec_per_key_part; + rec_per_key_part= param->new_rec_per_key_part; info->state->records=info->state->del=share->state.split=0; info->state->empty=0; @@ -3393,7 +3460,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, (char*) (share->state.rec_per_key_part+ - (uint) (rec_per_key_part - param->rec_per_key_part)), + (uint) (rec_per_key_part - param->new_rec_per_key_part)), sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part)); istep=0; continue; @@ -4657,12 +4724,14 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, _ma_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks"); DBUG_RETURN(1); } - a_length=2+nod_flag; - key_block->end_pos=anc_buff+2; + a_length= info->s->keypage_header + nod_flag; + key_block->end_pos= anc_buff + info->s->keypage_header; + _ma_store_keynr(info, anc_buff, (uint) (sort_param->keyinfo - + info->s->keyinfo)); lastkey=0; /* No previous key in block */ } else - a_length= maria_data_on_page(anc_buff); + a_length= _ma_get_page_used(info, anc_buff); /* Save pointer to previous block */ if (nod_flag) @@ -4673,7 +4742,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, &s_temp); (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp); a_length+=t_length; - maria_putint(anc_buff,a_length,nod_flag); + _ma_store_page_used(info, anc_buff, a_length, nod_flag); key_block->end_pos+=t_length; if (a_length <= keyinfo->block_length) { @@ -4682,8 +4751,8 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, DBUG_RETURN(0); } - /* Fill block with end-zero and write filled block */ - maria_putint(anc_buff,key_block->last_length,nod_flag); + /* Fill block with end-zero and write filled block */ + _ma_store_page_used(info, anc_buff, key_block->last_length, nod_flag); bzero(anc_buff+key_block->last_length, keyinfo->block_length- key_block->last_length); key_file_length=info->state->key_file_length; @@ -4699,7 +4768,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, else if (my_pwrite(info->s->kfile.file, anc_buff, (uint) keyinfo->block_length,filepos, param->myf_rw)) DBUG_RETURN(1); - DBUG_DUMP("buff",anc_buff,maria_data_on_page(anc_buff)); + DBUG_DUMP("buff", anc_buff, _ma_get_page_used(info, anc_buff)); /* Write separator-key to block in next level */ if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos)) @@ -4793,7 +4862,7 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param) for (key_block=sort_info->key_block ; key_block->inited ; key_block++) { key_block->inited=0; - length= maria_data_on_page(key_block->buff); + length= _ma_get_page_used(info, key_block->buff); if (nod_flag) _ma_kpointer(info,key_block->end_pos,filepos); key_file_length=info->state->key_file_length; @@ -5080,13 +5149,13 @@ int maria_update_state_info(HA_CHECK *param, MARIA_HA *info,uint update) if (update & UPDATE_STAT) { uint i, key_parts= mi_uint2korr(share->state.header.key_parts); - share->state.rec_per_key_rows=info->state->records; + share->state.records_at_analyze= info->state->records; share->state.changed&= ~STATE_NOT_ANALYZED; if (info->state->records) { for (i=0; i<key_parts; i++) { - if (!(share->state.rec_per_key_part[i]=param->rec_per_key_part[i])) + if (!(share->state.rec_per_key_part[i]=param->new_rec_per_key_part[i])) share->state.changed|= STATE_NOT_ANALYZED; } } @@ -5247,13 +5316,14 @@ void _ma_update_auto_increment_key(HA_CHECK *param, MARIA_HA *info, IGNORE_NULLS n/a tuples that don't have NULLs */ -void maria_update_key_parts(MARIA_KEYDEF *keyinfo, ulong *rec_per_key_part, +void maria_update_key_parts(MARIA_KEYDEF *keyinfo, double *rec_per_key_part, ulonglong *unique, ulonglong *notnull, ulonglong records) { - ulonglong count=0,tmp, unique_tuples; + ulonglong count=0, unique_tuples; ulonglong tuples= records; uint parts; + double tmp; for (parts=0 ; parts < keyinfo->keysegs ; parts++) { count+=unique[parts]; @@ -5272,20 +5342,17 @@ void maria_update_key_parts(MARIA_KEYDEF *keyinfo, ulong *rec_per_key_part, if (unique_tuples == 0) tmp= 1; else if (count == 0) - tmp= tuples; /* 1 unique tuple */ + tmp= ulonglong2double(tuples); /* 1 unique tuple */ else - tmp= (tuples + unique_tuples/2) / unique_tuples; + tmp= ulonglong2double(tuples) / ulonglong2double(unique_tuples); /* for some weird keys (e.g. FULLTEXT) tmp can be <1 here. let's ensure it is not */ set_if_bigger(tmp,1); - if (tmp >= (ulonglong) ~(ulong) 0) - tmp=(ulonglong) ~(ulong) 0; - *rec_per_key_part=(ulong) tmp; - rec_per_key_part++; + *rec_per_key_part++= tmp; } } diff --git a/storage/maria/ma_checksum.c b/storage/maria/ma_checksum.c index 9076b3ebb86..b48eae1c27d 100644 --- a/storage/maria/ma_checksum.c +++ b/storage/maria/ma_checksum.c @@ -17,23 +17,40 @@ #include "maria_def.h" +/** + Calculate a checksum for the record + + _ma_checksum() + @param info Maria handler + @param record Record + + @note + To ensure that the checksum is independent of the row format + we need to always calculate the checksum in the original field order. + + @return checksum +*/ + ha_checksum _ma_checksum(MARIA_HA *info, const uchar *record) { ha_checksum crc=0; - MARIA_COLUMNDEF *column= info->s->columndef; - MARIA_COLUMNDEF *column_end= column+ info->s->base.fields; + uint i,end; + MARIA_COLUMNDEF *base_column= info->s->columndef; + uint16 *column_nr= info->s->column_nr; if (info->s->base.null_bytes) crc= my_checksum(crc, record, info->s->base.null_bytes); - for ( ; column != column_end ; column++) + for (i= 0, end= info->s->base.fields ; i < end ; i++) { - const uchar *pos= record + column->offset; + MARIA_COLUMNDEF *column= base_column + column_nr[i]; + const uchar *pos; ulong length; if (record[column->null_pos] & column->null_bit) continue; /* Null field */ + pos= record + column->offset; switch (column->type) { case FIELD_BLOB: { diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index d2ec3bc0d68..cdb28e11ae3 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -50,7 +50,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, key_length,info_length,key_segs,options,min_key_length_skip, base_pos,long_varchar_count,varchar_length, unique_key_parts,fulltext_keys,offset, not_block_record_extra_length; - uint max_field_lengths, extra_header_size; + uint max_field_lengths, extra_header_size, column_nr; ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN], linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; @@ -62,7 +62,9 @@ int maria_create(const char *name, enum data_file_type datafile_type, MARIA_UNIQUEDEF *uniquedef; HA_KEYSEG *keyseg,tmp_keyseg; MARIA_COLUMNDEF *column, *end_column; - ulong *rec_per_key_part; + double *rec_per_key_part; + ulong *nulls_per_key_part; + uint16 *column_array; my_off_t key_root[HA_MAX_POSSIBLE_KEY], kfile_size_before_extension; MARIA_CREATE_INFO tmp_create_info; my_bool tmp_table= FALSE; /* cache for presence of HA_OPTION_TMP_TABLE */ @@ -111,9 +113,16 @@ int maria_create(const char *name, enum data_file_type datafile_type, ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */ if (!(rec_per_key_part= - (ulong*) my_malloc((keys + uniques)*HA_MAX_KEY_SEG*sizeof(long), - MYF(MY_WME | MY_ZEROFILL)))) + (double*) my_malloc((keys + uniques)*HA_MAX_KEY_SEG*sizeof(double) + + (keys + uniques)*HA_MAX_KEY_SEG*sizeof(ulong) + + sizeof(uint16) * columns, + MYF(MY_WME | MY_ZEROFILL)))) DBUG_RETURN(my_errno); + nulls_per_key_part= (ulong*) (rec_per_key_part + + (keys + uniques) * HA_MAX_KEY_SEG); + column_array= (uint16*) (nulls_per_key_part + + (keys + uniques) * HA_MAX_KEY_SEG); + /* Start by checking fields and field-types used */ @@ -121,12 +130,14 @@ int maria_create(const char *name, enum data_file_type datafile_type, pack_reclength= max_field_lengths= 0; reclength= min_pack_length= ci->null_bytes; forced_packed= 0; + column_nr= 0; for (column= columndef, end_column= column + columns ; column != end_column ; column++) { /* Fill in not used struct parts */ + column->column_nr= column_nr++; column->offset= reclength; column->empty_pos= 0; column->empty_bit= 0; @@ -282,6 +293,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) options|= HA_OPTION_RELIES_ON_SQL_LAYER; + if (flags & HA_CREATE_PAGE_CHECKSUM) + options|= HA_OPTION_PAGE_CHECKSUM; pack_bytes= (packed + 7) / 8; if (pack_reclength != INT_MAX32) @@ -315,7 +328,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, ulonglong data_file_length= ci->data_file_length; if (!data_file_length) data_file_length= ((((ulonglong) 1 << ((BLOCK_RECORD_POINTER_SIZE-1) * - 8)) -1)); + 8)) -1) * maria_block_size); if (rows_per_page > 0) { set_if_smaller(rows_per_page, MAX_ROWS_PER_PAGE); @@ -335,15 +348,19 @@ int maria_create(const char *name, enum data_file_type datafile_type, max_rows= (ulonglong) ci->max_rows; if (datafile_type == BLOCK_RECORD) { - /* The + 1 is for record position withing page */ + /* + The + 1 is for record position withing page + The / 2 is because we need one bit for knowing if there is transid's + after the row pointer + */ pointer= maria_get_pointer_length((ci->data_file_length / - maria_block_size), 3) + 1; + (maria_block_size * 2)), 3) + 1; set_if_smaller(pointer, BLOCK_RECORD_POINTER_SIZE); if (!max_rows) max_rows= (((((ulonglong) 1 << ((pointer-1)*8)) -1) * maria_block_size) / - min_pack_length); - } + min_pack_length / 2); + } else { if (datafile_type != STATIC_RECORD) @@ -366,7 +383,8 @@ int maria_create(const char *name, enum data_file_type datafile_type, max_key_length=0; tot_length=0 ; key_segs=0; fulltext_keys=0; - share.state.rec_per_key_part=rec_per_key_part; + share.state.rec_per_key_part= rec_per_key_part; + share.state.nulls_per_key_part= nulls_per_key_part; share.state.key_root=key_root; share.state.key_del= HA_OFFSET_ERROR; if (uniques) @@ -607,7 +625,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, keys * MARIA_KEYDEF_SIZE+ uniques * MARIA_UNIQUEDEF_SIZE + (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ - columns*MARIA_COLUMNDEF_SIZE); + columns*(MARIA_COLUMNDEF_SIZE + 2)); DBUG_PRINT("info", ("info_length: %u", info_length)); /* There are only 16 bits for the total header length. */ @@ -621,9 +639,9 @@ int maria_create(const char *name, enum data_file_type datafile_type, } bmove(share.state.header.file_version,(uchar*) maria_file_magic,4); - ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? - HA_OPTION_COMPRESS_RECORD | - HA_OPTION_TEMP_COMPRESS_RECORD: 0); + ci->old_options=options | (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? + HA_OPTION_COMPRESS_RECORD | + HA_OPTION_TEMP_COMPRESS_RECORD: 0); mi_int2store(share.state.header.options,ci->old_options); mi_int2store(share.state.header.header_length,info_length); mi_int2store(share.state.header.state_info_length,MARIA_STATE_INFO_SIZE); @@ -901,6 +919,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, (qsort_cmp) compare_columns); for (i=0 ; i < share.base.fields ; i++) { + column_array[col_order[i]->column_nr]= i; if (_ma_columndef_write(file, col_order[i])) { my_free((uchar*) col_order, MYF(0)); @@ -912,9 +931,14 @@ int maria_create(const char *name, enum data_file_type datafile_type, else { for (i=0 ; i < share.base.fields ; i++) + { + column_array[i]= (uint16) i; if (_ma_columndef_write(file, &columndef[i])) goto err; + } } + if (_ma_column_nr_write(file, column_array, columns)) + goto err; if ((kfile_size_before_extension= my_tell(file,MYF(0))) == MY_FILEPOS_ERROR) goto err; diff --git a/storage/maria/ma_dbug.c b/storage/maria/ma_dbug.c index a23e7248029..5996e42a101 100644 --- a/storage/maria/ma_dbug.c +++ b/storage/maria/ma_dbug.c @@ -92,7 +92,7 @@ void _ma_print_key(FILE *stream, register HA_KEYSEG *keyseg, key=end; break; case HA_KEYTYPE_ULONG_INT: - l_1=mi_sint4korr(key); + l_1=mi_uint4korr(key); VOID(fprintf(stream,"%lu",(ulong) l_1)); key=end; break; diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 3f88f9025a3..543be5142d2 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -179,8 +179,8 @@ static int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, goto err; } if ((error=d_search(info,keyinfo, - (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND | SEARCH_UPDATE - : SEARCH_SAME), + (keyinfo->flag & HA_FULLTEXT ? + SEARCH_FIND | SEARCH_UPDATE : SEARCH_SAME), key,key_length,old_root,root_buff)) >0) { if (error == 2) @@ -190,11 +190,14 @@ static int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, } else /* error == 1 */ { - if (maria_data_on_page(root_buff) <= (nod_flag=_ma_test_if_nod(root_buff))+3) + uint used_length; + _ma_get_used_and_nod(info, root_buff, used_length, nod_flag); + if (used_length <= nod_flag + info->s->keypage_header + 1) { error=0; if (nod_flag) - *root= _ma_kpos(nod_flag,root_buff+2+nod_flag); + *root= _ma_kpos(nod_flag, root_buff +info->s->keypage_header + + nod_flag); else *root=HA_OFFSET_ERROR; if (_ma_dispose(info,keyinfo,old_root,DFLT_INIT_HITS)) @@ -212,13 +215,14 @@ err: } /* _ma_ck_real_delete */ - /* - ** Remove key below key root - ** Return values: - ** 1 if there are less buffers; In this case anc_buff is not saved - ** 2 if there are more buffers - ** -1 on errors - */ +/* + @brief Remove key below key root + + @return + @retval 1 If there are less buffers; In this case anc_buff is not saved + @retval 2 If there are more buffers + @retval -1 On errors +*/ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uint comp_flag, uchar *key, uint key_length, @@ -231,7 +235,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, my_off_t leaf_page,next_block; uchar lastkey[HA_MAX_KEY_BUFF]; DBUG_ENTER("d_search"); - DBUG_DUMP("page",anc_buff,maria_data_on_page(anc_buff)); + DBUG_DUMP("page",anc_buff,_ma_get_page_used(info, anc_buff)); search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length, @@ -241,7 +245,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_PRINT("error",("Found wrong key")); DBUG_RETURN(-1); } - nod_flag=_ma_test_if_nod(anc_buff); + nod_flag=_ma_test_if_nod(info, anc_buff); if (!flag && keyinfo->flag & HA_FULLTEXT) { @@ -341,14 +345,14 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else { /* Found key */ uint tmp; - length= maria_data_on_page(anc_buff); + length= _ma_get_page_used(info, anc_buff); if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length, &next_block))) goto err; length-= tmp; - maria_putint(anc_buff,length,nod_flag); + _ma_store_page_used(info, anc_buff, length, nod_flag); if (!nod_flag) { /* On leaf page */ if (_ma_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff)) @@ -378,7 +382,8 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, (uchar*) 0,(uchar*) 0,(my_off_t) 0,(my_bool) 0); } } - if (ret_value == 0 && maria_data_on_page(anc_buff) > keyinfo->block_length) + if (ret_value == 0 && _ma_get_page_used(info, anc_buff) > + (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { save_flag=1; ret_value= _ma_split_page(info,keyinfo,key,anc_buff,lastkey,0) | 2; @@ -387,7 +392,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ret_value|= _ma_write_keypage(info,keyinfo,page,DFLT_INIT_HITS,anc_buff); else { - DBUG_DUMP("page",anc_buff,maria_data_on_page(anc_buff)); + DBUG_DUMP("page", anc_buff, _ma_get_page_used(info, anc_buff)); } my_afree(leaf_buff); DBUG_PRINT("exit",("Return: %d",ret_value)); @@ -410,7 +415,7 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *ret_key) /* key before keypos in anc_buff */ { int ret_value,length; - uint a_length,nod_flag,tmp; + uint a_length, nod_flag, used_length, tmp; my_off_t next_page; uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; MARIA_SHARE *share=info->s; @@ -418,14 +423,16 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_ENTER("del"); DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page, (ulong) keypos)); - DBUG_DUMP("leaf_buff",leaf_buff,maria_data_on_page(leaf_buff)); - endpos= leaf_buff+ maria_data_on_page(leaf_buff); + _ma_get_used_and_nod(info, leaf_buff, used_length, nod_flag); + DBUG_DUMP("leaf_buff", leaf_buff, used_length); + + endpos= leaf_buff + used_length; if (!(key_start= _ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, &tmp))) DBUG_RETURN(-1); - if ((nod_flag=_ma_test_if_nod(leaf_buff))) + if (nod_flag) { next_page= _ma_kpos(nod_flag,endpos); if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ @@ -435,18 +442,22 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ret_value= -1; else { - DBUG_DUMP("next_page",next_buff,maria_data_on_page(next_buff)); + DBUG_DUMP("next_page", next_buff, _ma_get_page_used(info, next_buff)); if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff, keypos,next_block,ret_key)) >0) { - endpos=leaf_buff+maria_data_on_page(leaf_buff); + /* Get new length after key was deleted */ + endpos=leaf_buff+_ma_get_page_used(info, leaf_buff); if (ret_value == 1) { ret_value=underflow(info,keyinfo,leaf_buff,next_page, next_buff,endpos); - if (ret_value == 0 && maria_data_on_page(leaf_buff) > keyinfo->block_length) + if (ret_value == 0 && + _ma_get_page_used(info, leaf_buff) > + (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { - ret_value= _ma_split_page(info,keyinfo,key,leaf_buff,ret_key,0) | 2; + ret_value= (_ma_split_page(info,keyinfo,key,leaf_buff,ret_key,0) | + 2); } } else @@ -467,20 +478,19 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } /* Remove last key from leaf page */ - - maria_putint(leaf_buff,key_start-leaf_buff,nod_flag); + _ma_store_page_used(info, leaf_buff, key_start-leaf_buff, nod_flag); if (_ma_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff)) goto err; /* Place last key in ancestor page on deleted key position */ - a_length= maria_data_on_page(anc_buff); + a_length= _ma_get_page_used(info, anc_buff); endpos=anc_buff+a_length; - if (keypos != anc_buff+2+share->base.key_reflength && + if (keypos != anc_buff+info->s->keypage_header + share->base.key_reflength && !_ma_get_last_key(info,keyinfo,anc_buff,ret_key,keypos,&tmp)) goto err; - prev_key=(keypos == anc_buff+2+share->base.key_reflength ? - 0 : ret_key); + prev_key= (keypos == anc_buff + info->s->keypage_header + + share->base.key_reflength ? 0 : ret_key); length=(*keyinfo->pack_key)(keyinfo,share->base.key_reflength, keypos == endpos ? (uchar*) 0 : keypos, prev_key, prev_key, @@ -494,11 +504,12 @@ static int del(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key)) goto err; _ma_kpointer(info,keypos - share->base.key_reflength,next_block); - maria_putint(anc_buff,a_length+length,share->base.key_reflength); + _ma_store_page_used(info, anc_buff, a_length + length, + share->base.key_reflength); - DBUG_RETURN( maria_data_on_page(leaf_buff) <= - (info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : - (uint) keyinfo->underflow_block_length)); + DBUG_RETURN(_ma_get_page_used(info, leaf_buff) <= + (info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : + (uint) keyinfo->underflow_block_length)); err: DBUG_RETURN(-1); } /* del */ @@ -524,22 +535,22 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_ENTER("underflow"); DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page, (ulong) keypos)); - DBUG_DUMP("anc_buff",anc_buff,maria_data_on_page(anc_buff)); - DBUG_DUMP("leaf_buff",leaf_buff,maria_data_on_page(leaf_buff)); + DBUG_DUMP("anc_buff", anc_buff, _ma_get_page_used(info, anc_buff)); + DBUG_DUMP("leaf_buff", leaf_buff, _ma_get_page_used(info, leaf_buff)); buff=info->buff; info->keyread_buff_used=1; next_keypos=keypos; - nod_flag=_ma_test_if_nod(leaf_buff); - p_length=nod_flag+2; - anc_length= maria_data_on_page(anc_buff); - leaf_length= maria_data_on_page(leaf_buff); + nod_flag= _ma_test_if_nod(info, leaf_buff); + p_length= nod_flag+info->s->keypage_header; + anc_length= _ma_get_page_used(info, anc_buff); + leaf_length= _ma_get_page_used(info, leaf_buff); key_reflength=share->base.key_reflength; if (info->s->keyinfo+info->lastinx == keyinfo) info->page_changed=1; - if ((keypos < anc_buff+anc_length && (info->state->records & 1)) || - keypos == anc_buff+2+key_reflength) + if ((keypos < anc_buff + anc_length && (info->state->records & 1)) || + keypos == anc_buff + info->s->keypage_header + key_reflength) { /* Use page right of anc-page */ DBUG_PRINT("test",("use right page")); @@ -560,14 +571,15 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, next_page= _ma_kpos(key_reflength,next_keypos); if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0)) goto err; - buff_length= maria_data_on_page(buff); + buff_length= _ma_get_page_used(info, buff); DBUG_DUMP("next",buff,buff_length); /* find keys to make a big key-page */ - bmove(next_keypos-key_reflength, buff+2, key_reflength); - if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length) - || !_ma_get_last_key(info,keyinfo,leaf_buff,leaf_key, - leaf_buff+leaf_length,&length)) + bmove(next_keypos-key_reflength, buff + info->s->keypage_header, + key_reflength); + if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length) || + !_ma_get_last_key(info,keyinfo,leaf_buff,leaf_key, + leaf_buff+leaf_length,&length)) goto err; /* merge pages and put parting key from anc_buff between */ @@ -582,7 +594,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, memcpy(buff, leaf_buff,(size_t) leaf_length); (*keyinfo->store_key)(keyinfo,buff+leaf_length,&s_temp); buff_length=(uint) (endpos-buff); - maria_putint(buff,buff_length,nod_flag); + _ma_store_page_used(info, buff, buff_length, nod_flag); /* remove key from anc_buff */ @@ -591,9 +603,9 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; anc_length-=s_length; - maria_putint(anc_buff,anc_length,key_reflength); + _ma_store_page_used(info, anc_buff, anc_length, key_reflength); - if (buff_length <= keyinfo->block_length) + if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { /* Keys in one page */ memcpy(leaf_buff,buff,(size_t) buff_length); if (_ma_dispose(info,keyinfo,next_page,DFLT_INIT_HITS)) @@ -604,21 +616,22 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, endpos=anc_buff+anc_length; DBUG_PRINT("test",("anc_buff: 0x%lx endpos: 0x%lx", (long) anc_buff, (long) endpos)); - if (keypos != anc_buff+2+key_reflength && + if (keypos != anc_buff + info->s->keypage_header + key_reflength && !_ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length)) goto err; - if (!(half_pos= _ma_find_half_pos(nod_flag, keyinfo, buff, leaf_key, - &key_length, &after_key))) + if (!(half_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, + leaf_key, &key_length, &after_key))) goto err; length=(uint) (half_pos-buff); memcpy(leaf_buff,buff,(size_t) length); - maria_putint(leaf_buff,length,nod_flag); + _ma_store_page_used(info, leaf_buff, length, nod_flag); /* Correct new keypointer to leaf_page */ half_pos=after_key; _ma_kpointer(info,leaf_key+key_length,next_page); /* Save key in anc_buff */ - prev_key=(keypos == anc_buff+2+key_reflength ? (uchar*) 0 : anc_key), + prev_key=(keypos == anc_buff + info->s->keypage_header + key_reflength ? + (uchar*) 0 : anc_key), t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, (keypos == endpos ? (uchar*) 0 : keypos), @@ -629,21 +642,23 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); - maria_putint(anc_buff,(anc_length+=t_length),key_reflength); + anc_length+= t_length; + _ma_store_page_used(info, anc_buff, anc_length, key_reflength); /* Store key first in new page */ if (nod_flag) - bmove(buff+2,half_pos-nod_flag,(size_t) nod_flag); + bmove(buff+info->s->keypage_header, half_pos-nod_flag, + (size_t) nod_flag); if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)) goto err; t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (uchar*) 0, (uchar*) 0, (uchar*) 0, leaf_key, &s_temp); /* t_length will always be > 0 for a new page !*/ - length=(uint) ((buff+maria_data_on_page(buff))-half_pos); + length=(uint) ((buff+_ma_get_page_used(info, buff))-half_pos); bmove(buff+p_length+t_length, half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,buff+p_length,&s_temp); - maria_putint(buff,length+t_length+p_length,nod_flag); + _ma_store_page_used(info, buff, length + t_length + p_length, nod_flag); if (_ma_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff)) goto err; @@ -662,12 +677,13 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, next_page= _ma_kpos(key_reflength,keypos); if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff,0)) goto err; - buff_length= maria_data_on_page(buff); + buff_length= _ma_get_page_used(info, buff); endpos=buff+buff_length; DBUG_DUMP("prev",buff,buff_length); /* find keys to make a big key-page */ - bmove(next_keypos - key_reflength, leaf_buff+2, key_reflength); + bmove(next_keypos - key_reflength, leaf_buff + info->s->keypage_header, + key_reflength); next_keypos=keypos; if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos, anc_key)) @@ -691,7 +707,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, (*keyinfo->store_key)(keyinfo,endpos,&s_temp); buff_length=buff_length+leaf_length-p_length+t_length; - maria_putint(buff,buff_length,nod_flag); + _ma_store_page_used(info, buff, buff_length, nod_flag); /* remove key from anc_buff */ if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key, @@ -699,22 +715,22 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; anc_length-=s_length; - maria_putint(anc_buff,anc_length,key_reflength); + _ma_store_page_used(info, anc_buff, anc_length, key_reflength); - if (buff_length <= keyinfo->block_length) + if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { /* Keys in one page */ if (_ma_dispose(info,keyinfo,leaf_page,DFLT_INIT_HITS)) goto err; } else { /* Page is full */ - if (keypos == anc_buff+2+key_reflength) + if (keypos == anc_buff+ info->s->keypage_header + key_reflength) anc_pos=0; /* First key */ else if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_pos=anc_key,keypos, &length)) goto err; - endpos= _ma_find_half_pos(nod_flag,keyinfo,buff,leaf_key, - &key_length, &half_pos); + endpos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key, + &key_length, &half_pos); if (!endpos) goto err; _ma_kpointer(info,leaf_key+key_length,leaf_page); @@ -733,11 +749,13 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos,&s_temp); - maria_putint(anc_buff,(anc_length+=t_length),key_reflength); + anc_length+= t_length; + _ma_store_page_used(info, anc_buff, anc_length, key_reflength); /* Store first key on new page */ if (nod_flag) - bmove(leaf_buff+2,half_pos-nod_flag,(size_t) nod_flag); + bmove(leaf_buff + info->s->keypage_header, half_pos-nod_flag, + (size_t) nod_flag); if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))) goto err; DBUG_DUMP("key_to_leaf",leaf_key,length); @@ -748,14 +766,16 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, bmove(leaf_buff+p_length+t_length,half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,leaf_buff+p_length,&s_temp); - maria_putint(leaf_buff,length+t_length+p_length,nod_flag); + _ma_store_page_used(info, leaf_buff, length + t_length + p_length, + nod_flag); if (_ma_write_keypage(info,keyinfo,leaf_page,DFLT_INIT_HITS,leaf_buff)) goto err; - maria_putint(buff,endpos-buff,nod_flag); + _ma_store_page_used(info, buff, (uint) (endpos - buff),nod_flag); } if (_ma_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff)) goto err; - DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2); + DBUG_RETURN(anc_length <= (uint) + (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)/2); err: DBUG_RETURN(-1); diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c index f36147ccde2..ce173993b6d 100644 --- a/storage/maria/ma_ft_update.c +++ b/storage/maria/ma_ft_update.c @@ -327,9 +327,10 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key) } /* creating pageful of keys */ - maria_putint(info->buff,length+2,0); - memcpy(info->buff+2, key_ptr, length); - info->keyread_buff_used=info->page_changed=1; /* info->buff is used */ + _ma_store_keynr(info, info->buff, keynr); + _ma_store_page_used(info, info->buff, length + info->s->keypage_header, 0); + memcpy(info->buff + info->s->keypage_header, key_ptr, length); + info->keyread_buff_used= info->page_changed=1; /* info->buff is used */ if ((root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR || _ma_write_keypage(info,keyinfo,root,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 9ea3bfca263..f6629f6fd64 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -46,7 +46,7 @@ /* short transaction ID type */ typedef uint16 SHORT_TRANSACTION_ID; -struct st_maria_info; +struct st_maria_handler; /* Changing one of the "SIZE" below will break backward-compatibility! */ /* Length of CRC at end of pages */ @@ -236,7 +236,7 @@ extern my_bool translog_init(const char *directory, uint32 log_file_max_size, extern my_bool translog_write_record(LSN *lsn, enum translog_record_type type, struct st_transaction *trn, - struct st_maria_info *tbl_info, + MARIA_HA *tbl_info, translog_size_t rec_len, uint part_no, LEX_STRING *parts_data, uchar *store_share_id, void *hook_arg); @@ -272,7 +272,7 @@ extern my_bool translog_unlock(); extern void translog_lock_assert_owner(); extern TRANSLOG_ADDRESS translog_get_horizon(); extern TRANSLOG_ADDRESS translog_get_horizon_no_lock(); -extern int translog_assign_id_to_share(struct st_maria_info *tbl_info, +extern int translog_assign_id_to_share(struct st_maria_handler *tbl_info, struct st_transaction *trn); extern void translog_deassign_id_from_share(struct st_maria_share *share); extern void @@ -307,11 +307,13 @@ struct st_translog_parts }; typedef my_bool(*prewrite_rec_hook) (enum translog_record_type type, - TRN *trn, struct st_maria_info *tbl_info, + TRN *trn, + struct st_maria_handler *tbl_info, void *hook_arg); typedef my_bool(*inwrite_rec_hook) (enum translog_record_type type, - TRN *trn, struct st_maria_info *tbl_info, + TRN *trn, + struct st_maria_handler *tbl_info, LSN *lsn, void *hook_arg); typedef uint16(*read_rec_hook) (enum translog_record_type type, diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 39d2c1c7422..50126775b03 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -81,8 +81,8 @@ MARIA_HA *_ma_test_if_reopen(const char *filename) share Share of already open table mode Mode of table (O_RDONLY | O_RDWR) data_file Filedescriptor of data file to use < 0 if one should open - open it. - + open it. + RETURN # Maria handler 0 Error @@ -252,7 +252,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) uchar *disk_cache, *disk_pos, *end_pos; MARIA_HA info,*m_info,*old_info; MARIA_SHARE share_buff,*share; - ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG]; + double rec_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG]; + long nulls_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG]; my_off_t key_root[HA_MAX_POSSIBLE_KEY]; ulonglong max_key_file_length, max_data_file_length; File data_file= -1; @@ -273,7 +274,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) { share= &share_buff; bzero((uchar*) &share_buff,sizeof(share_buff)); - share_buff.state.rec_per_key_part=rec_per_key_part; + share_buff.state.rec_per_key_part= rec_per_key_part; + share_buff.state.nulls_per_key_part= nulls_per_key_part; share_buff.state.key_root=key_root; share_buff.pagecache= multi_pagecache_search((uchar*) name_buff, strlen(name_buff), @@ -315,10 +317,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE | - HA_OPTION_RELIES_ON_SQL_LAYER | HA_OPTION_NULL_FIELDS)) + HA_OPTION_RELIES_ON_SQL_LAYER | HA_OPTION_NULL_FIELDS | + HA_OPTION_PAGE_CHECKSUM)) { DBUG_PRINT("error",("wrong options: 0x%lx", share->options)); - my_errno=HA_ERR_OLD_FILE; + my_errno=HA_ERR_NEW_FILE; goto err; } if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) && @@ -442,7 +445,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if (!my_multi_malloc(MY_WME, &share,sizeof(*share), - &share->state.rec_per_key_part,sizeof(long)*key_parts, + &share->state.rec_per_key_part, + sizeof(double) * key_parts, + &share->state.nulls_per_key_part, + sizeof(long)* key_parts, &share->keyinfo,keys*sizeof(MARIA_KEYDEF), &share->uniqueinfo,uniques*sizeof(MARIA_UNIQUEDEF), &share->keyparts, @@ -450,6 +456,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) sizeof(HA_KEYSEG), &share->columndef, (share->base.fields+1)*sizeof(MARIA_COLUMNDEF), + &share->column_nr, share->base.fields*sizeof(uint16), &share->blobs,sizeof(MARIA_BLOB)*share->base.blobs, &share->unique_file_name,strlen(name_buff)+1, &share->index_file_name,strlen(index_name)+1, @@ -466,7 +473,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) *share=share_buff; memcpy((char*) share->state.rec_per_key_part, - (char*) rec_per_key_part, sizeof(long)*key_parts); + (char*) rec_per_key_part, sizeof(double)*key_parts); + memcpy((char*) share->state.nulls_per_key_part, + (char*) nulls_per_key_part, sizeof(long)*key_parts); memcpy((char*) share->state.key_root, (char*) key_root, sizeof(my_off_t)*keys); strmov(share->unique_file_name, name_buff); @@ -596,6 +605,10 @@ 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 : + 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + + KEYPAGE_USED_SIZE); + if (open_flags & HA_OPEN_COPY) { /* @@ -667,6 +680,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } } share->columndef[i].type=(int) FIELD_LAST; /* End marker */ + disk_pos= _ma_column_nr_read(disk_pos, share->column_nr, + share->base.fields); if ((share->data_file_type == BLOCK_RECORD || share->data_file_type == COMPRESSED_RECORD)) @@ -694,7 +709,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if ((*share->once_init)(share, info.dfile.file)) goto err; share->is_log_table= FALSE; - if (open_flags & HA_OPEN_TMP_TABLE) + if (open_flags & HA_OPEN_TMP_TABLE) share->options|= HA_OPTION_TMP_TABLE; if (open_flags & HA_OPEN_DELAY_KEY_WRITE) share->options|= HA_OPTION_DELAY_KEY_WRITE; @@ -772,7 +787,7 @@ err: VOID(my_close(data_file, MYF(0))); if (old_info) break; /* Don't remove open table */ - (*share->once_end)(share); + (*share->once_end)(share); /* fall through */ case 4: my_free((uchar*) share,MYF(0)); @@ -915,7 +930,7 @@ void _ma_setup_functions(register MARIA_SHARE *share) share->file_read= _ma_nommap_pread; share->file_write= _ma_nommap_pwrite; share->calc_check_checksum= share->calc_checksum; - + if (!(share->options & HA_OPTION_CHECKSUM) && share->data_file_type != COMPRESSED_RECORD) share->calc_checksum= share->calc_write_checksum= 0; @@ -1096,10 +1111,13 @@ uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite) mi_int8store(ptr,(ulonglong) state->create_time); ptr+= 8; mi_int8store(ptr,(ulonglong) state->recover_time); ptr+= 8; mi_int8store(ptr,(ulonglong) state->check_time); ptr+= 8; - mi_sizestore(ptr,state->rec_per_key_rows); ptr+= 8; + mi_sizestore(ptr, state->records_at_analyze); ptr+= 8; + /* reserve place for some information per key */ + bzero(ptr, keys*4); ptr+= keys*4; for (i=0 ; i < key_parts ; i++) { - mi_int4store(ptr,state->rec_per_key_part[i]); ptr+=4; + float8store(ptr, state->rec_per_key_part[i]); ptr+= 8; + mi_int4store(ptr, state->nulls_per_key_part[i]); ptr+= 4; } } @@ -1136,7 +1154,9 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) state->state.key_empty= mi_sizekorr(ptr); ptr+= 8; state->auto_increment=mi_uint8korr(ptr); ptr+= 8; state->state.checksum=(ha_checksum) mi_uint8korr(ptr);ptr+= 8; + /* Not used (legacy from MyISAM) */ state->process= mi_uint4korr(ptr); ptr+= 4; + /* Not used (legacy from MyISAM) */ state->unique = mi_uint4korr(ptr); ptr+= 4; state->status = mi_uint4korr(ptr); ptr+= 4; state->update_count=mi_uint4korr(ptr); ptr+= 4; @@ -1155,10 +1175,12 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) state->create_time = (time_t) mi_sizekorr(ptr); ptr+= 8; state->recover_time =(time_t) mi_sizekorr(ptr); ptr+= 8; state->check_time = (time_t) mi_sizekorr(ptr); ptr+= 8; - state->rec_per_key_rows=mi_sizekorr(ptr); ptr+= 8; + state->records_at_analyze= mi_sizekorr(ptr); ptr+= 8; + ptr+= keys * 4; /* Skip reserved bytes */ for (i=0 ; i < key_parts ; i++) { - state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4; + float8get(state->rec_per_key_part[i], ptr); ptr+= 8; + state->nulls_per_key_part[i]= mi_uint4korr(ptr); ptr+= 4; } return ptr; } @@ -1200,6 +1222,8 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) { uchar buff[MARIA_BASE_INFO_SIZE], *ptr=buff; + bmove(ptr, maria_uuid, MY_UUID_SIZE); + ptr+= MY_UUID_SIZE; mi_sizestore(ptr,base->keystart); ptr+= 8; mi_sizestore(ptr,base->max_data_file_length); ptr+= 8; mi_sizestore(ptr,base->max_key_file_length); ptr+= 8; @@ -1216,7 +1240,7 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) mi_int2store(ptr,base->fixed_not_null_fields_length); ptr+= 2; mi_int2store(ptr,base->max_field_lengths); ptr+= 2; mi_int2store(ptr,base->pack_fields); ptr+= 2; - mi_int2store(ptr,0); ptr+= 2; + mi_int2store(ptr,base->extra_options) ptr+= 2; mi_int2store(ptr,base->null_bytes); ptr+= 2; mi_int2store(ptr,base->original_null_bytes); ptr+= 2; mi_int2store(ptr,base->field_offsets); ptr+= 2; @@ -1242,6 +1266,7 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) { + bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE; base->keystart= mi_sizekorr(ptr); ptr+= 8; base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8; base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8; @@ -1258,7 +1283,7 @@ static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2; base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2; base->pack_fields= mi_uint2korr(ptr); ptr+= 2; - ptr+= 2; + base->extra_options= mi_uint2korr(ptr); ptr+= 2; base->null_bytes= mi_uint2korr(ptr); ptr+= 2; base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2; base->field_offsets= mi_uint2korr(ptr); ptr+= 2; @@ -1285,7 +1310,7 @@ static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) maria_keydef ---------------------------------------------------------------------------*/ -uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef) +my_bool _ma_keydef_write(File file, MARIA_KEYDEF *keydef) { uchar buff[MARIA_KEYDEF_SIZE]; uchar *ptr=buff; @@ -1321,7 +1346,7 @@ uchar *_ma_keydef_read(uchar *ptr, MARIA_KEYDEF *keydef) ** maria_keyseg ***************************************************************************/ -int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg) +my_bool _ma_keyseg_write(File file, const HA_KEYSEG *keyseg) { uchar buff[HA_KEYSEG_SIZE]; uchar *ptr=buff; @@ -1371,7 +1396,7 @@ uchar *_ma_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg) maria_uniquedef ---------------------------------------------------------------------------*/ -uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *def) +my_bool _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *def) { uchar buff[MARIA_UNIQUEDEF_SIZE]; uchar *ptr=buff; @@ -1395,12 +1420,12 @@ uchar *_ma_uniquedef_read(uchar *ptr, MARIA_UNIQUEDEF *def) ** MARIA_COLUMNDEF ***************************************************************************/ -uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef) +my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef) { uchar buff[MARIA_COLUMNDEF_SIZE]; uchar *ptr=buff; - mi_int6store(ptr,columndef->offset); ptr+= 6; + mi_int2store(ptr,(ulong) columndef->offset); ptr+= 2; mi_int2store(ptr,columndef->type); ptr+= 2; mi_int2store(ptr,columndef->length); ptr+= 2; mi_int2store(ptr,columndef->fill_length); ptr+= 2; @@ -1408,12 +1433,13 @@ uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef) mi_int2store(ptr,columndef->empty_pos); ptr+= 2; (*ptr++)= columndef->null_bit; (*ptr++)= columndef->empty_bit; + ptr[0]= ptr[1]= ptr[2]= ptr[3]= 0; ptr+= 4; /* For future */ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0; } uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef) { - columndef->offset= mi_uint6korr(ptr); ptr+= 6; + columndef->offset= mi_uint2korr(ptr); ptr+= 2; columndef->type= mi_sint2korr(ptr); ptr+= 2; columndef->length= mi_uint2korr(ptr); ptr+= 2; columndef->fill_length= mi_uint2korr(ptr); ptr+= 2; @@ -1421,9 +1447,36 @@ uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef) columndef->empty_pos= mi_uint2korr(ptr); ptr+= 2; columndef->null_bit= (uint8) *ptr++; columndef->empty_bit= (uint8) *ptr++; + ptr+= 4; return ptr; } +my_bool _ma_column_nr_write(File file, uint16 *offsets, uint columns) +{ + uchar *buff, *ptr, *end; + size_t size= columns*2; + my_bool res; + + if (!(buff= (uchar*) my_alloca(size))) + return 1; + for (ptr= buff, end= ptr + size; ptr < end ; ptr+= 2, offsets++) + int2store(ptr, *offsets); + res= my_write(file, buff, size, MYF(MY_NABP)) != 0; + my_afree(buff); + return res; +} + + +uchar *_ma_column_nr_read(uchar *ptr, uint16 *offsets, uint columns) +{ + uchar *end; + size_t size= columns*2; + for (end= ptr + size; ptr < end ; ptr+=2, offsets++) + *offsets= uint2korr(ptr); + return ptr; +} + + /************************************************************************** Open data file We can't use dup() here as the data file descriptors need to have different diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index ac9e33f896a..a7973af3f57 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -48,17 +48,21 @@ uchar *_ma_fetch_keypage(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, DBUG_RETURN(0); } info->last_keypage=page; - page_size= maria_data_on_page(tmp); - if (page_size < 4 || page_size > keyinfo->block_length) +#ifdef EXTRA_DEBUG + page_size= _ma_get_page_used(info, tmp); + if (page_size < 4 || page_size > keyinfo->block_length || + _ma_get_keynr(info, tmp) > info->s->base.keys) { - DBUG_PRINT("error",("page %lu had wrong page length: %u", - (ulong) page, page_size)); + DBUG_PRINT("error",("page %lu had wrong page length: %u keynr: %u", + (ulong) page, page_size, + _ma_get_keynr(info, tmp))); DBUG_DUMP("page", (char*) tmp, keyinfo->block_length); info->last_keypage = HA_OFFSET_ERROR; maria_print_error(info->s, HA_ERR_CRASHED); my_errno= HA_ERR_CRASHED; tmp= 0; } +#endif DBUG_RETURN(tmp); } /* _ma_fetch_keypage */ @@ -84,19 +88,27 @@ int _ma_write_keypage(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_RETURN((-1)); } DBUG_PRINT("page",("write page at: %lu",(long) page)); - DBUG_DUMP("buff",(uchar*) buff,maria_data_on_page(buff)); + DBUG_DUMP("buff", buff,_ma_get_page_used(info, buff)); #endif + /* Verify that keynr is correct */ + DBUG_ASSERT(_ma_get_keynr(info, buff) == + (uint) (keyinfo - info->s->keyinfo)); + #ifdef HAVE_purify { /* Clear unitialized part of page to avoid valgrind/purify warnings */ - uint length= maria_data_on_page(buff); - bzero((uchar*) buff+length,keyinfo->block_length-length); + uint length= _ma_get_page_used(info, buff); + bzero(buff+length, keyinfo->block_length-length); length=keyinfo->block_length; } #endif DBUG_ASSERT(info->s->pagecache->block_size == keyinfo->block_length); + if (!(info->s->options & HA_OPTION_PAGE_CHECKSUM)) + bfill(buff + keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE, + KEYPAGE_CHECKSUM_SIZE, (uchar) 255); + /* TODO: replace PAGECACHE_PLAIN_PAGE with PAGECACHE_LSN_PAGE when LSN on the pages will be implemented @@ -116,7 +128,7 @@ int _ma_dispose(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, int level) { my_off_t old_link; - uchar buff[8]; + uchar buff[MAX_KEYPAGE_HEADER_SIZE+8]; uint offset; pgcache_page_no_t page_no; DBUG_ENTER("_ma_dispose"); @@ -126,7 +138,9 @@ int _ma_dispose(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, info->s->state.key_del= pos; page_no= pos / keyinfo->block_length; offset= pos % keyinfo->block_length; - mi_sizestore(buff,old_link); + bzero(buff, info->s->keypage_header); + _ma_store_keynr(info, buff, (uchar) MARIA_DELETE_KEY_NR); + mi_sizestore(buff + info->s->keypage_header, old_link); info->s->state.changed|= STATE_NOT_SORTED_PAGES; DBUG_ASSERT(info->s->pagecache->block_size == keyinfo->block_length && @@ -141,11 +155,11 @@ int _ma_dispose(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, my_off_t pos, PAGECACHE_LOCK_LEFT_UNLOCKED, PAGECACHE_PIN_LEFT_UNPINNED, PAGECACHE_WRITE_DELAY, 0, - offset, sizeof(buff), 0, 0)); + offset, info->s->keypage_header+8, 0, 0)); } /* _ma_dispose */ - /* Make new page on disk */ +/* Make new page on disk */ my_off_t _ma_new(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level) { @@ -166,6 +180,7 @@ my_off_t _ma_new(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level) } else { + /* QQ: Remove this alloc (We don't have to copy the page) */ buff= my_alloca(info->s->block_size); DBUG_ASSERT(info->s->pagecache->block_size == keyinfo->block_length && info->s->pagecache->block_size == info->s->block_size); @@ -180,7 +195,7 @@ my_off_t _ma_new(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level) PAGECACHE_LOCK_LEFT_UNLOCKED, 0)) pos= HA_OFFSET_ERROR; else - info->s->state.key_del= mi_sizekorr(buff); + info->s->state.key_del= mi_sizekorr(buff+info->s->keypage_header); my_afree(buff); } info->s->state.changed|= STATE_NOT_SORTED_PAGES; diff --git a/storage/maria/ma_preload.c b/storage/maria/ma_preload.c index 138bb94f7d0..b3a0b97a58f 100644 --- a/storage/maria/ma_preload.c +++ b/storage/maria/ma_preload.c @@ -40,12 +40,10 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) { - uint i; ulong length, block_length= 0; uchar *buff= NULL; MARIA_SHARE* share= info->s; uint keys= share->state.header.keys; - MARIA_KEYDEF *keyinfo= share->keyinfo; my_off_t key_file_length= share->state.state.key_file_length; my_off_t pos= share->base.keystart; DBUG_ENTER("maria_preload"); @@ -53,20 +51,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) if (!keys || !maria_is_any_key_active(key_map) || key_file_length == pos) DBUG_RETURN(0); - block_length= keyinfo[0].block_length; - - if (ignore_leaves) - { - /* Check whether all indexes use the same block size */ - for (i= 1 ; i < keys ; i++) - { - if (keyinfo[i].block_length != block_length) - DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); - } - } - else - block_length= share->pagecache->block_size; - + block_length= share->pagecache->block_size; length= info->preload_buff_size/block_length * block_length; set_if_bigger(length, block_length); @@ -78,6 +63,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) do { + uchar *end; /* Read the next block of index file into the preload buffer */ if ((my_off_t) length > (key_file_length-pos)) length= (ulong) (key_file_length-pos); @@ -85,41 +71,25 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) MYF(MY_FAE|MY_FNABP))) goto err; - if (ignore_leaves) + for (end= buff + length ; buff < end ; buff+= block_length) { - uchar *end= buff+length; - do + uint keynr= _ma_get_keynr(info, buff); + if ((ignore_leaves && !_ma_test_if_nod(info, buff)) || + keynr == MARIA_DELETE_KEY_NR || + !(key_map & ((ulonglong) 1 << keynr))) { - if (_ma_test_if_nod(buff)) - { - DBUG_ASSERT(share->pagecache->block_size == block_length); - if (pagecache_write(share->pagecache, - &share->kfile, pos / block_length, - DFLT_INIT_HITS, - (uchar*) buff, - PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_UNLOCKED, - PAGECACHE_PIN_LEFT_UNPINNED, - PAGECACHE_WRITE_DONE, 0)) - goto err; - } - pos+= block_length; + DBUG_ASSERT(share->pagecache->block_size == block_length); + if (pagecache_write(share->pagecache, + &share->kfile, pos / block_length, + DFLT_INIT_HITS, + (uchar*) buff, + PAGECACHE_PLAIN_PAGE, + PAGECACHE_LOCK_LEFT_UNLOCKED, + PAGECACHE_PIN_LEFT_UNPINNED, + PAGECACHE_WRITE_DONE, 0)) + goto err; } - while ((buff+= block_length) != end); - buff= end-length; - } - else - { - if (pagecache_write(share->pagecache, - &share->kfile, pos / block_length, - DFLT_INIT_HITS, - (uchar*) buff, - PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_UNLOCKED, - PAGECACHE_PIN_LEFT_UNPINNED, - PAGECACHE_WRITE_DONE, 0)) - goto err; - pos+= length; + pos+= block_length; } } while (pos != key_file_length); diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c index 02616d8ac5c..8ef6dc87c0c 100644 --- a/storage/maria/ma_range.c +++ b/storage/maria/ma_range.c @@ -215,7 +215,7 @@ static double _ma_search_pos(register MARIA_HA *info, goto err; flag=(*keyinfo->bin_search)(info, keyinfo, buff, key, key_len, nextflag, &keypos,info->lastkey, &after_key); - nod_flag=_ma_test_if_nod(buff); + nod_flag=_ma_test_if_nod(info, buff); keynr= _ma_keynr(info,keyinfo,buff,keypos,&max_keynr); if (flag) @@ -262,17 +262,17 @@ err: } - /* Get keynummer of current key and max number of keys in nod */ +/* Get keynummer of current key and max number of keys in nod */ static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key) { - uint nod_flag,keynr,max_key; + uint nod_flag, used_length, keynr, max_key; uchar t_buff[HA_MAX_KEY_BUFF],*end; - end= page+maria_data_on_page(page); - nod_flag=_ma_test_if_nod(page); - page+=2+nod_flag; + _ma_get_used_and_nod(info, page, used_length, nod_flag); + end= page+ used_length; + page+= info->s->keypage_header + nod_flag; if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) { diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c index 4980233fc11..2530ae86a5c 100644 --- a/storage/maria/ma_rt_index.c +++ b/storage/maria/ma_rt_index.c @@ -60,48 +60,48 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int res; uchar *page_buf, *k, *last; int k_len; - uint *saved_key = (uint*) (info->maria_rtree_recursion_state) + level; + uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level; - if (!(page_buf = (uchar*) my_alloca((uint)keyinfo->block_length))) + if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length))) { - my_errno = HA_ERR_OUT_OF_MEM; + my_errno= HA_ERR_OUT_OF_MEM; return -1; } if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); - k_len = keyinfo->keylength - info->s->base.rec_reflength; + k_len= keyinfo->keylength - info->s->base.rec_reflength; - if(info->maria_rtree_recursion_depth >= level) + if (info->maria_rtree_recursion_depth >= level) { k= page_buf + *saved_key; } else { - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); } - last= rt_PAGE_END(page_buf); + last= rt_PAGE_END(info, page_buf); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) + for (; k < last; k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) { if (nod_flag) { /* this is an internal node in the tree */ - if (!(res = maria_rtree_key_cmp(keyinfo->seg, + if (!(res= maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, info->last_rkey_length, nod_cmp_flag))) { - switch ((res = maria_rtree_find_req(info, keyinfo, search_flag, + switch ((res= maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, _ma_kpos(nod_flag, k), level + 1))) { case 0: /* found - exit from recursion */ - *saved_key = k - page_buf; + *saved_key= k - page_buf; goto ok; case 1: /* not found - continue searching */ - info->maria_rtree_recursion_depth = level; + info->maria_rtree_recursion_depth= level; break; default: /* error */ case -1: @@ -115,33 +115,33 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (!maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key, k, info->last_rkey_length, search_flag)) { - uchar *after_key = (uchar*) rt_PAGE_NEXT_KEY(k, k_len, nod_flag); - info->cur_row.lastpos = _ma_dpos(info, 0, after_key); - info->lastkey_length = k_len + info->s->base.rec_reflength; + uchar *after_key= (uchar*) rt_PAGE_NEXT_KEY(k, k_len, nod_flag); + info->cur_row.lastpos= _ma_dpos(info, 0, after_key); + info->lastkey_length= k_len + info->s->base.rec_reflength; memcpy(info->lastkey, k, info->lastkey_length); - info->maria_rtree_recursion_depth = level; - *saved_key = last - page_buf; + info->maria_rtree_recursion_depth= level; + *saved_key= last - page_buf; if (after_key < last) { - info->int_keypos = info->buff; - info->int_maxpos = info->buff + (last - after_key); + info->int_keypos= info->buff; + info->int_maxpos= info->buff + (last - after_key); memcpy(info->buff, after_key, last - after_key); - info->keyread_buff_used = 0; + info->keyread_buff_used= 0; } else { - info->keyread_buff_used = 1; + info->keyread_buff_used= 1; } - res = 0; + res= 0; goto ok; } } } - info->cur_row.lastpos = HA_OFFSET_ERROR; - my_errno = HA_ERR_KEY_NOT_FOUND; - res = 1; + info->cur_row.lastpos= HA_OFFSET_ERROR; + my_errno= HA_ERR_KEY_NOT_FOUND; + res= 1; ok: my_afree((uchar*)page_buf); @@ -149,7 +149,7 @@ ok: err1: my_afree((uchar*)page_buf); - info->cur_row.lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; return -1; } @@ -176,9 +176,9 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key, { my_off_t root; uint nod_cmp_flag; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; - if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; @@ -190,10 +190,10 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key, (minimum bounding rectangle) */ memcpy(info->first_mbr_key, key, keyinfo->keylength); - info->last_rkey_length = key_length; + info->last_rkey_length= key_length; - info->maria_rtree_recursion_depth = -1; - info->keyread_buff_used = 1; + info->maria_rtree_recursion_depth= -1; + info->keyread_buff_used= 1; nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); @@ -221,7 +221,7 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag) { my_off_t root; uint nod_cmp_flag; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; if (info->update & HA_STATE_DELETED) return maria_rtree_find_first(info, keynr, info->lastkey, @@ -252,13 +252,13 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag) key+= keyinfo->keylength; } } - if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } - nod_cmp_flag = ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? + nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ? MBR_WITHIN : MBR_INTERSECT); return maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0); } @@ -276,8 +276,8 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag) 1 Not found */ -static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_length, - my_off_t page, int level) +static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uint key_length, my_off_t page, int level) { uchar *page_buf, *last, *k; uint nod_flag, k_len; @@ -288,39 +288,39 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l return -1; if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); - k_len = keyinfo->keylength - info->s->base.rec_reflength; + k_len= keyinfo->keylength - info->s->base.rec_reflength; if(info->maria_rtree_recursion_depth >= level) { - k = page_buf + *saved_key; + k= page_buf + *saved_key; if (!nod_flag) { /* Only leaf pages contain data references. */ /* Need to check next key with data reference. */ - k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); + k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag); } } else { - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); } - last = rt_PAGE_END(page_buf); + last= rt_PAGE_END(info, page_buf); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) + for (; k < last; k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) { if (nod_flag) { /* this is an internal node in the tree */ - switch ((res = maria_rtree_get_req(info, keyinfo, key_length, + switch ((res= maria_rtree_get_req(info, keyinfo, key_length, _ma_kpos(nod_flag, k), level + 1))) { case 0: /* found - exit from recursion */ - *saved_key = k - page_buf; + *saved_key= k - page_buf; goto ok; case 1: /* not found - continue searching */ - info->maria_rtree_recursion_depth = level; + info->maria_rtree_recursion_depth= level; break; default: case -1: /* error */ @@ -330,33 +330,33 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint key_l else { /* this is a leaf */ - uchar *after_key = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); - info->cur_row.lastpos = _ma_dpos(info, 0, after_key); - info->lastkey_length = k_len + info->s->base.rec_reflength; + uchar *after_key= rt_PAGE_NEXT_KEY(k, k_len, nod_flag); + info->cur_row.lastpos= _ma_dpos(info, 0, after_key); + info->lastkey_length= k_len + info->s->base.rec_reflength; memcpy(info->lastkey, k, info->lastkey_length); - info->maria_rtree_recursion_depth = level; - *saved_key = k - page_buf; + info->maria_rtree_recursion_depth= level; + *saved_key= k - page_buf; if (after_key < last) { - info->int_keypos = (uchar*) saved_key; + info->int_keypos= (uchar*) saved_key; memcpy(info->buff, page_buf, keyinfo->block_length); - info->int_maxpos = rt_PAGE_END(info->buff); - info->keyread_buff_used = 0; + info->int_maxpos= rt_PAGE_END(info, info->buff); + info->keyread_buff_used= 0; } else { - info->keyread_buff_used = 1; + info->keyread_buff_used= 1; } - res = 0; + res= 0; goto ok; } } - info->cur_row.lastpos = HA_OFFSET_ERROR; - my_errno = HA_ERR_KEY_NOT_FOUND; - res = 1; + info->cur_row.lastpos= HA_OFFSET_ERROR; + my_errno= HA_ERR_KEY_NOT_FOUND; + res= 1; ok: my_afree((uchar*)page_buf); @@ -364,7 +364,7 @@ ok: err1: my_afree((uchar*)page_buf); - info->cur_row.lastpos = HA_OFFSET_ERROR; + info->cur_row.lastpos= HA_OFFSET_ERROR; return -1; } @@ -381,16 +381,16 @@ err1: int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length) { my_off_t root; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; - if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; } - info->maria_rtree_recursion_depth = -1; - info->keyread_buff_used = 1; + info->maria_rtree_recursion_depth= -1; + info->keyread_buff_used= 1; return maria_rtree_get_req(info, &keyinfo[keynr], key_length, root, 0); } @@ -408,32 +408,32 @@ int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length) int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length) { my_off_t root; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; if (!info->keyread_buff_used) { - uint k_len = keyinfo->keylength - info->s->base.rec_reflength; + uint k_len= keyinfo->keylength - info->s->base.rec_reflength; /* rt_PAGE_NEXT_KEY(info->int_keypos) */ - uchar *key = info->buff + *(int*)info->int_keypos + k_len + + uchar *key= info->buff + *(int*)info->int_keypos + k_len + info->s->base.rec_reflength; /* rt_PAGE_NEXT_KEY(key) */ - uchar *after_key = key + k_len + info->s->base.rec_reflength; + uchar *after_key= key + k_len + info->s->base.rec_reflength; - info->cur_row.lastpos = _ma_dpos(info, 0, after_key); - info->lastkey_length = k_len + info->s->base.rec_reflength; + info->cur_row.lastpos= _ma_dpos(info, 0, after_key); + info->lastkey_length= k_len + info->s->base.rec_reflength; memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength); - *(int*)info->int_keypos = key - info->buff; + *(int*)info->int_keypos= key - info->buff; if (after_key >= info->int_maxpos) { - info->keyread_buff_used = 1; + info->keyread_buff_used= 1; } return 0; } else { - if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; return -1; @@ -455,27 +455,27 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint nod_flag) { double increase; - double best_incr = DBL_MAX; + double best_incr= DBL_MAX; double perimeter; double best_perimeter; uchar *best_key; - uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - uchar *last = rt_PAGE_END(page_buf); + uchar *k= rt_PAGE_FIRST_KEY(page_buf, nod_flag); + uchar *last= rt_PAGE_END(info, page_buf); LINT_INIT(best_perimeter); LINT_INIT(best_key); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) + for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) { - if ((increase = maria_rtree_perimeter_increase(keyinfo->seg, k, key, key_length, + if ((increase= maria_rtree_perimeter_increase(keyinfo->seg, k, key, key_length, &perimeter)) == -1) return NULL; if ((increase < best_incr)|| (increase == best_incr && perimeter < best_perimeter)) { - best_key = k; + best_key= k; best_perimeter= perimeter; - best_incr = increase; + best_incr= increase; } } return best_key; @@ -490,37 +490,37 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint nod_flag) { double increase; - double best_incr = DBL_MAX; + double best_incr= DBL_MAX; double area; double best_area; uchar *best_key; - uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - uchar *last = rt_PAGE_END(page_buf); + uchar *k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); + uchar *last= rt_PAGE_END(info, page_buf); LINT_INIT(best_area); LINT_INIT(best_key); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) + for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) { /* The following is safe as -1.0 is an exact number */ - if ((increase = maria_rtree_area_increase(keyinfo->seg, k, key, key_length, + if ((increase= maria_rtree_area_increase(keyinfo->seg, k, key, key_length, &area)) == -1.0) return NULL; /* The following should be safe, even if we compare doubles */ if (increase < best_incr) { - best_key = k; - best_area = area; - best_incr = increase; + best_key= k; + best_area= area; + best_incr= increase; } else { /* The following should be safe, even if we compare doubles */ if ((increase == best_incr) && (area < best_area)) { - best_key = k; - best_area = area; - best_incr = increase; + best_key= k; + best_area= area; + best_incr= increase; } } } @@ -552,22 +552,22 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length + HA_MAX_KEY_BUFF))) { - my_errno = HA_ERR_OUT_OF_MEM; + my_errno= HA_ERR_OUT_OF_MEM; DBUG_RETURN(-1); /* purecov: inspected */ } if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); DBUG_PRINT("rtree", ("page: %lu level: %d ins_level: %d nod_flag: %u", (ulong) page, level, ins_level, nod_flag)); if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */ (ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */ { - if ((k = maria_rtree_pick_key(info, keyinfo, key, key_length, page_buf, + if ((k= maria_rtree_pick_key(info, keyinfo, key, key_length, page_buf, nod_flag)) == NULL) goto err1; - switch ((res = maria_rtree_insert_req(info, keyinfo, key, key_length, + switch ((res= maria_rtree_insert_req(info, keyinfo, key, key_length, _ma_kpos(nod_flag, k), new_page, ins_level, level + 1))) { @@ -580,7 +580,7 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } case 1: /* child was split */ { - uchar *new_key = page_buf + keyinfo->block_length + nod_flag; + uchar *new_key= page_buf + keyinfo->block_length + nod_flag; /* set proper MBR for key */ if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length, _ma_kpos(nod_flag, k))) @@ -590,8 +590,8 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, *new_page)) goto err1; - res = maria_rtree_add_key(info, keyinfo, new_key, key_length, - page_buf, new_page); + res= maria_rtree_add_key(info, keyinfo, new_key, key_length, + page_buf, new_page); if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; goto ok; @@ -605,7 +605,7 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } else { - res = maria_rtree_add_key(info, keyinfo, key, key_length, page_buf, + res= maria_rtree_add_key(info, keyinfo, key, key_length, page_buf, new_page); if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; @@ -634,26 +634,27 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, uint key_length, int ins_level) { my_off_t old_root; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; int res; my_off_t new_page; DBUG_ENTER("maria_rtree_insert_level"); - if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((old_root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { - if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) + if ((old_root= _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) DBUG_RETURN(-1); - info->keyread_buff_used = 1; - maria_putint(info->buff, 2, 0); - res = maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL); + info->keyread_buff_used= 1; + _ma_store_page_used(info, info->buff, info->s->keypage_header, 0); + res= maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, + NULL); if (_ma_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff)) DBUG_RETURN(1); - info->s->state.key_root[keynr] = old_root; + info->s->state.key_root[keynr]= old_root; DBUG_RETURN(res); } - switch ((res = maria_rtree_insert_req(info, keyinfo, key, key_length, - old_root, &new_page, ins_level, 0))) + switch ((res= maria_rtree_insert_req(info, keyinfo, key, key_length, + old_root, &new_page, ins_level, 0))) { case 0: /* root was not split */ { @@ -663,22 +664,23 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, { uchar *new_root_buf, *new_key; my_off_t new_root; - uint nod_flag = info->s->base.key_reflength; + uint nod_flag= info->s->base.key_reflength; DBUG_PRINT("rtree", ("root was split, grow a new root")); if (!(new_root_buf= (uchar*) my_alloca((uint)keyinfo->block_length + HA_MAX_KEY_BUFF))) { - my_errno = HA_ERR_OUT_OF_MEM; + my_errno= HA_ERR_OUT_OF_MEM; DBUG_RETURN(-1); /* purecov: inspected */ } - maria_putint(new_root_buf, 2, nod_flag); - if ((new_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == + _ma_store_page_used(info, new_root_buf, info->s->keypage_header, + nod_flag); + if ((new_root= _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) goto err1; - new_key = new_root_buf + keyinfo->block_length + nod_flag; + new_key= new_root_buf + keyinfo->block_length + nod_flag; _ma_kpointer(info, new_key - nod_flag, old_root); if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length, @@ -699,10 +701,10 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, if (_ma_write_keypage(info, keyinfo, new_root, DFLT_INIT_HITS, new_root_buf)) goto err1; - info->s->state.key_root[keynr] = new_root; + info->s->state.key_root[keynr]= new_root; DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u", (ulong) new_root, 0, - _ma_test_if_nod(new_root_buf))); + _ma_test_if_nod(info, new_root_buf))); my_afree((uchar*)new_root_buf); break; @@ -753,13 +755,13 @@ static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t pag if (ReinsertList->n_pages == ReinsertList->m_pages) { ReinsertList->m_pages += REINSERT_BUFFER_INC; - if (!(ReinsertList->pages = (stPageLevel*)my_realloc((uchar*)ReinsertList->pages, + if (!(ReinsertList->pages= (stPageLevel*)my_realloc((uchar*)ReinsertList->pages, ReinsertList->m_pages * sizeof(stPageLevel), MYF(MY_ALLOW_ZERO_PTR)))) goto err1; } /* save page to ReinsertList */ - ReinsertList->pages[ReinsertList->n_pages].offs = page; - ReinsertList->pages[ReinsertList->n_pages].level = level; + ReinsertList->pages[ReinsertList->n_pages].offs= page; + ReinsertList->pages[ReinsertList->n_pages].level= level; ReinsertList->n_pages++; DBUG_RETURN(0); @@ -790,28 +792,28 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page_buf, *last, *k; DBUG_ENTER("maria_rtree_delete_req"); - if (!(page_buf = (uchar*) my_alloca((uint)keyinfo->block_length))) + if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length))) { - my_errno = HA_ERR_OUT_OF_MEM; + my_errno= HA_ERR_OUT_OF_MEM; DBUG_RETURN(-1); /* purecov: inspected */ } if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); DBUG_PRINT("rtree", ("page: %lu level: %d nod_flag: %u", (ulong) page, level, nod_flag)); - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - last = rt_PAGE_END(page_buf); + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); + last= rt_PAGE_END(info, page_buf); - for (i = 0; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag), i++) + for (i= 0; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag), i++) { if (nod_flag) { /* not leaf */ if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN)) { - switch ((res = maria_rtree_delete_req(info, keyinfo, key, key_length, + switch ((res= maria_rtree_delete_req(info, keyinfo, key, key_length, _ma_kpos(nod_flag, k), page_size, ReinsertList, level + 1))) { case 0: /* deleted */ @@ -853,7 +855,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; - *page_size = maria_data_on_page(page_buf); + *page_size= _ma_get_page_used(info, page_buf); } goto ok; @@ -868,8 +870,8 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; - *page_size = maria_data_on_page(page_buf); - res = 0; + *page_size= _ma_get_page_used(info, page_buf); + res= 0; goto ok; } default: /* error */ @@ -883,20 +885,21 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, else { /* leaf */ - if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_EQUAL | MBR_DATA)) + if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, + MBR_EQUAL | MBR_DATA)) { maria_rtree_delete_key(info, page_buf, k, key_length, nod_flag); - *page_size = maria_data_on_page(page_buf); - if (*page_size == 2) + *page_size= _ma_get_page_used(info, page_buf); + if (*page_size == info->s->keypage_header) { /* last key in the leaf */ - res = 2; + res= 2; if (_ma_dispose(info, keyinfo, page, DFLT_INIT_HITS)) goto err1; } else { - res = 0; + res= 0; if (_ma_write_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf)) goto err1; } @@ -904,7 +907,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } } } - res = 1; + res= 1; ok: my_afree((uchar*)page_buf); @@ -929,10 +932,10 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) uint page_size; stPageList ReinsertList; my_off_t old_root; - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; DBUG_ENTER("maria_rtree_delete"); - if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((old_root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) { my_errno= HA_ERR_END_OF_FILE; DBUG_RETURN(-1); /* purecov: inspected */ @@ -940,43 +943,43 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) DBUG_PRINT("rtree", ("starting deletion at root page: %lu", (ulong) old_root)); - ReinsertList.pages = NULL; - ReinsertList.n_pages = 0; - ReinsertList.m_pages = 0; + ReinsertList.pages= NULL; + ReinsertList.n_pages= 0; + ReinsertList.m_pages= 0; switch (maria_rtree_delete_req(info, keyinfo, key, key_length, old_root, &page_size, &ReinsertList, 0)) { case 2: /* empty */ { - info->s->state.key_root[keynr] = HA_OFFSET_ERROR; + info->s->state.key_root[keynr]= HA_OFFSET_ERROR; DBUG_RETURN(0); } case 0: /* deleted */ { uint nod_flag; ulong i; - for (i = 0; i < ReinsertList.n_pages; ++i) + for (i= 0; i < ReinsertList.n_pages; ++i) { uchar *page_buf, *k, *last; - if (!(page_buf = (uchar*) my_alloca((uint)keyinfo->block_length))) + if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length))) { - my_errno = HA_ERR_OUT_OF_MEM; + my_errno= HA_ERR_OUT_OF_MEM; goto err1; } if (!_ma_fetch_keypage(info, keyinfo, ReinsertList.pages[i].offs, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); DBUG_PRINT("rtree", ("reinserting keys from " "page: %lu level: %d nod_flag: %u", (ulong) ReinsertList.pages[i].offs, ReinsertList.pages[i].level, nod_flag)); - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - last = rt_PAGE_END(page_buf); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); + last= rt_PAGE_END(info, page_buf); + for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) { int res; if ((res= @@ -1008,20 +1011,22 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) my_free((uchar*) ReinsertList.pages, MYF(0)); /* check for redundant root (not leaf, 1 child) and eliminate */ - if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((old_root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) goto err1; if (!_ma_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff, 0)) goto err1; - nod_flag = _ma_test_if_nod(info->buff); - page_size = maria_data_on_page(info->buff); - if (nod_flag && (page_size == 2 + key_length + nod_flag)) + nod_flag= _ma_test_if_nod(info, info->buff); + page_size= _ma_get_page_used(info, info->buff); + if (nod_flag && (page_size == info->s->keypage_header + key_length + + nod_flag)) { - my_off_t new_root = _ma_kpos(nod_flag, - rt_PAGE_FIRST_KEY(info->buff, nod_flag)); + my_off_t new_root= _ma_kpos(nod_flag, + rt_PAGE_FIRST_KEY(info, info->buff, + nod_flag)); if (_ma_dispose(info, keyinfo, old_root, DFLT_INIT_HITS)) goto err1; - info->s->state.key_root[keynr] = new_root; + info->s->state.key_root[keynr]= new_root; } info->update= HA_STATE_DELETED; DBUG_RETURN(0); @@ -1031,7 +1036,7 @@ err1: } case 1: /* not found */ { - my_errno = HA_ERR_KEY_NOT_FOUND; + my_errno= HA_ERR_KEY_NOT_FOUND; DBUG_RETURN(-1); /* purecov: inspected */ } default: @@ -1051,35 +1056,35 @@ err1: ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, uint key_length, uint flag) { - MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr; + MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; my_off_t root; - uint i = 0; + uint i= 0; uint nod_flag, k_len; uchar *page_buf, *k, *last; - double area = 0; - ha_rows res = 0; + double area= 0; + ha_rows res= 0; if (flag & MBR_DISJOINT) return info->state->records; - if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) + if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) return HA_POS_ERROR; if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length))) return HA_POS_ERROR; if (!_ma_fetch_keypage(info, keyinfo, root, DFLT_INIT_HITS, page_buf, 0)) goto err1; - nod_flag = _ma_test_if_nod(page_buf); + nod_flag= _ma_test_if_nod(info, page_buf); - k_len = keyinfo->keylength - info->s->base.rec_reflength; + k_len= keyinfo->keylength - info->s->base.rec_reflength; - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); - last = rt_PAGE_END(page_buf); + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); + last= rt_PAGE_END(info, page_buf); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag), i++) + for (; k < last; k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag), i++) { if (nod_flag) { - double k_area = maria_rtree_rect_volume(keyinfo->seg, k, key_length); + double k_area= maria_rtree_rect_volume(keyinfo->seg, k, key_length); /* The following should be safe, even if we compare doubles */ if (k_area == 0) @@ -1124,9 +1129,9 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key, if (nod_flag) { if (i) - res = (ha_rows) (area / i * info->state->records); + res= (ha_rows) (area / i * info->state->records); else - res = HA_POS_ERROR; + res= HA_POS_ERROR; } my_afree((uchar*)page_buf); diff --git a/storage/maria/ma_rt_index.h b/storage/maria/ma_rt_index.h index fe2f62b662c..af2fcabaa44 100644 --- a/storage/maria/ma_rt_index.h +++ b/storage/maria/ma_rt_index.h @@ -19,12 +19,12 @@ #ifdef HAVE_RTREE_KEYS -#define rt_PAGE_FIRST_KEY(page, nod_flag) (page + 2 + nod_flag) +#define rt_PAGE_FIRST_KEY(info, page, nod_flag) (page + info->s->keypage_header + nod_flag) #define rt_PAGE_NEXT_KEY(key, key_length, nod_flag) (key + key_length + \ (nod_flag ? nod_flag : info->s->base.rec_reflength)) -#define rt_PAGE_END(page) (page + maria_data_on_page(page)) +#define rt_PAGE_END(info, page) (page + _ma_get_page_used(info, page)) -#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length) / 3) +#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length - KEYPAGE_CHECKSUM_SIZE) / 3) int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length); diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c index b74d5d06690..c71d7d7d8eb 100644 --- a/storage/maria/ma_rt_key.c +++ b/storage/maria/ma_rt_key.c @@ -32,8 +32,8 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, uint key_length, uchar *page_buf, my_off_t *new_page) { - uint page_size = maria_data_on_page(page_buf); - uint nod_flag = _ma_test_if_nod(page_buf); + uint page_size= _ma_get_page_used(info, page_buf); + uint nod_flag= _ma_test_if_nod(info, page_buf); DBUG_ENTER("maria_rtree_add_key"); if (page_size + key_length + info->s->base.rec_reflength <= @@ -44,8 +44,9 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, { /* save key */ DBUG_ASSERT(_ma_kpos(nod_flag, key) < info->state->key_file_length); - memcpy(rt_PAGE_END(page_buf), key - nod_flag, key_length + nod_flag); - page_size += key_length + nod_flag; + memcpy(rt_PAGE_END(info, page_buf), key - nod_flag, + key_length + nod_flag); + page_size+= key_length + nod_flag; } else { @@ -54,11 +55,11 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, info->s->base.rec_reflength) < info->state->data_file_length + info->s->base.pack_reclength); - memcpy(rt_PAGE_END(page_buf), key, key_length + + memcpy(rt_PAGE_END(info, page_buf), key, key_length + info->s->base.rec_reflength); - page_size += key_length + info->s->base.rec_reflength; + page_size+= key_length + info->s->base.rec_reflength; } - maria_putint(page_buf, page_size, nod_flag); + _ma_store_page_used(info, page_buf, page_size, nod_flag); DBUG_RETURN(0); } @@ -74,18 +75,18 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key, uint key_length, uint nod_flag) { - uint16 page_size = maria_data_on_page(page_buf); + uint16 page_size= _ma_get_page_used(info, page_buf); uchar *key_start; key_start= key - nod_flag; if (!nod_flag) - key_length += info->s->base.rec_reflength; + key_length+= info->s->base.rec_reflength; memmove(key_start, key + key_length, page_size - key_length - (key - page_buf)); page_size-= key_length + nod_flag; - maria_putint(page_buf, page_size, nod_flag); + _ma_store_page_used(info, page_buf, page_size, nod_flag); return 0; } diff --git a/storage/maria/ma_rt_mbr.c b/storage/maria/ma_rt_mbr.c index a224cefac12..4f17ce6d074 100644 --- a/storage/maria/ma_rt_mbr.c +++ b/storage/maria/ma_rt_mbr.c @@ -64,10 +64,10 @@ #define RT_CMP_KORR(type, korr_func, len, nextflag) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(a); \ - bmin = korr_func(b); \ - amax = korr_func(a+len); \ - bmax = korr_func(b+len); \ + amin= korr_func(a); \ + bmin= korr_func(b); \ + amax= korr_func(a+len); \ + bmax= korr_func(b+len); \ RT_CMP(nextflag); \ } @@ -153,7 +153,7 @@ int maria_rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length, end: if (nextflag & MBR_DATA) { - uchar *end = a + keyseg->length; + uchar *end= a + keyseg->length; do { if (*a++ != *b++) @@ -166,8 +166,8 @@ end: #define RT_VOL_KORR(type, korr_func, len, cast) \ { \ type amin, amax; \ - amin = korr_func(a); \ - amax = korr_func(a+len); \ + amin= korr_func(a); \ + amax= korr_func(a+len); \ res *= (cast(amax) - cast(amin)); \ } @@ -184,7 +184,7 @@ end: */ double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) { - double res = 1; + double res= 1; for (; (int)key_length > 0; keyseg += 2) { uint32 keyseg_length; @@ -228,7 +228,7 @@ double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) RT_VOL_GET(double, mi_float8get, 8, (double)); break; case HA_KEYTYPE_END: - key_length = 0; + key_length= 0; break; default: return -1; @@ -243,10 +243,10 @@ double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) #define RT_D_MBR_KORR(type, korr_func, len, cast) \ { \ type amin, amax; \ - amin = korr_func(a); \ - amax = korr_func(a+len); \ - *res++ = cast(amin); \ - *res++ = cast(amax); \ + amin= korr_func(a); \ + amax= korr_func(a+len); \ + *res++= cast(amin); \ + *res++= cast(amax); \ } #define RT_D_MBR_GET(type, get_func, len, cast) \ @@ -254,8 +254,8 @@ double maria_rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length) type amin, amax; \ get_func(amin, a); \ get_func(amax, a+len); \ - *res++ = cast(amin); \ - *res++ = cast(amax); \ + *res++= cast(amin); \ + *res++= cast(amax); \ } @@ -308,7 +308,7 @@ int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res) RT_D_MBR_GET(double, mi_float8get, 8, (double)); break; case HA_KEYTYPE_END: - key_length = 0; + key_length= 0; break; default: return 1; @@ -323,12 +323,12 @@ int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res) #define RT_COMB_KORR(type, korr_func, store_func, len) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(a); \ - bmin = korr_func(b); \ - amax = korr_func(a+len); \ - bmax = korr_func(b+len); \ - amin = min(amin, bmin); \ - amax = max(amax, bmax); \ + amin= korr_func(a); \ + bmin= korr_func(b); \ + amax= korr_func(a+len); \ + bmax= korr_func(b+len); \ + amin= min(amin, bmin); \ + amax= max(amax, bmax); \ store_func(c, amin); \ store_func(c+len, amax); \ } @@ -340,8 +340,8 @@ int maria_rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res) get_func(bmin, b); \ get_func(amax, a+len); \ get_func(bmax, b+len); \ - amin = min(amin, bmin); \ - amax = max(amax, bmax); \ + amin= min(amin, bmin); \ + amax= max(amax, bmax); \ store_func(c, amin); \ store_func(c+len, amax); \ } @@ -415,12 +415,12 @@ int maria_rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c, #define RT_OVL_AREA_KORR(type, korr_func, len) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(a); \ - bmin = korr_func(b); \ - amax = korr_func(a+len); \ - bmax = korr_func(b+len); \ - amin = max(amin, bmin); \ - amax = min(amax, bmax); \ + amin= korr_func(a); \ + bmin= korr_func(b); \ + amax= korr_func(a+len); \ + bmax= korr_func(b+len); \ + amin= max(amin, bmin); \ + amax= min(amax, bmax); \ if (amin >= amax) \ return 0; \ res *= amax - amin; \ @@ -433,8 +433,8 @@ int maria_rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c, get_func(bmin, b); \ get_func(amax, a+len); \ get_func(bmax, b+len); \ - amin = max(amin, bmin); \ - amax = min(amax, bmax); \ + amin= max(amin, bmin); \ + amax= min(amax, bmax); \ if (amin >= amax) \ return 0; \ res *= amax - amin; \ @@ -446,7 +446,7 @@ Calculates overlapping area of two MBRs a & b double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b, uint key_length) { - double res = 1; + double res= 1; for (; (int) key_length > 0 ; keyseg += 2) { uint32 keyseg_length; @@ -505,10 +505,10 @@ double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b, #define RT_AREA_INC_KORR(type, korr_func, len) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(a); \ - bmin = korr_func(b); \ - amax = korr_func(a+len); \ - bmax = korr_func(b+len); \ + amin= korr_func(a); \ + bmin= korr_func(b); \ + amax= korr_func(a+len); \ + bmax= korr_func(b+len); \ a_area *= (((double)amax) - ((double)amin)); \ loc_ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); \ } @@ -599,10 +599,10 @@ safe_end: #define RT_PERIM_INC_KORR(type, korr_func, len) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(a); \ - bmin = korr_func(b); \ - amax = korr_func(a+len); \ - bmax = korr_func(b+len); \ + amin= korr_func(a); \ + bmin= korr_func(b); \ + amax= korr_func(a+len); \ + bmax= korr_func(b+len); \ a_perim+= (((double)amax) - ((double)amin)); \ *ab_perim+= ((double)max(amax, bmax) - (double)min(amin, bmin)); \ } @@ -624,7 +624,7 @@ Calculates MBR_PERIMETER(a+b) - MBR_PERIMETER(a) double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, uint key_length, double *ab_perim) { - double a_perim = 0.0; + double a_perim= 0.0; *ab_perim= 0.0; for (; (int)key_length > 0; keyseg += 2) @@ -690,17 +690,17 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, #define RT_PAGE_MBR_KORR(type, korr_func, store_func, len) \ { \ type amin, amax, bmin, bmax; \ - amin = korr_func(k + inc); \ - amax = korr_func(k + inc + len); \ - k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \ - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \ + amin= korr_func(k + inc); \ + amax= korr_func(k + inc + len); \ + k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \ + for (; k < last; k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \ { \ - bmin = korr_func(k + inc); \ - bmax = korr_func(k + inc + len); \ + bmin= korr_func(k + inc); \ + bmax= korr_func(k + inc + len); \ if (amin > bmin) \ - amin = bmin; \ + amin= bmin; \ if (amax < bmax) \ - amax = bmax; \ + amax= bmax; \ } \ store_func(c, amin); \ c += len; \ @@ -714,15 +714,15 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, type amin, amax, bmin, bmax; \ get_func(amin, k + inc); \ get_func(amax, k + inc + len); \ - k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \ - for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \ + k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag); \ + for (; k < last; k= rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) \ { \ get_func(bmin, k + inc); \ get_func(bmax, k + inc + len); \ if (amin > bmin) \ - amin = bmin; \ + amin= bmin; \ if (amax < bmax) \ - amax = bmax; \ + amax= bmax; \ } \ store_func(c, amin); \ c += len; \ @@ -732,16 +732,16 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, } /* - Calculates key page total MBR = MBR(key1) + MBR(key2) + ... + Calculates key page total MBR= MBR(key1) + MBR(key2) + ... */ int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, uchar *page_buf, uchar *c, uint key_length) { - uint inc = 0; - uint k_len = key_length; - uint nod_flag = _ma_test_if_nod(page_buf); + uint inc= 0; + uint k_len= key_length; + uint nod_flag= _ma_test_if_nod(info, page_buf); uchar *k; - uchar *last = rt_PAGE_END(page_buf); + uchar *last= rt_PAGE_END(info, page_buf); for (; (int)key_length > 0; keyseg += 2) { @@ -753,7 +753,7 @@ int maria_rtree_page_mbr(MARIA_HA *info, HA_KEYSEG *keyseg, uchar *page_buf, return 1; } - k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); + k= rt_PAGE_FIRST_KEY(info, page_buf, nod_flag); switch ((enum ha_base_keytype) keyseg->type) { case HA_KEYTYPE_INT8: diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c index a91eaa47bea..d3381ecf1ad 100644 --- a/storage/maria/ma_rt_split.c +++ b/storage/maria/ma_rt_split.c @@ -32,25 +32,25 @@ typedef struct inline static double *reserve_coords(double **d_buffer, int n_dim) { - double *coords = *d_buffer; - (*d_buffer) += n_dim * 2; + double *coords= *d_buffer; + (*d_buffer)+= n_dim * 2; return coords; } static void mbr_join(double *a, const double *b, int n_dim) { - double *end = a + n_dim * 2; + double *end= a + n_dim * 2; do { if (a[0] > b[0]) - a[0] = b[0]; + a[0]= b[0]; if (a[1] < b[1]) - a[1] = b[1]; + a[1]= b[1]; - a += 2; - b += 2; - }while (a != end); + a+= 2; + b+= 2; + } while (a != end); } /* @@ -58,29 +58,29 @@ Counts the square of mbr which is a join of a and b */ static double mbr_join_square(const double *a, const double *b, int n_dim) { - const double *end = a + n_dim * 2; - double square = 1.0; + const double *end= a + n_dim * 2; + double square= 1.0; do { square *= ((a[1] < b[1]) ? b[1] : a[1]) - ((a[0] > b[0]) ? b[0] : a[0]); - a += 2; - b += 2; - }while (a != end); + a+= 2; + b+= 2; + } while (a != end); return square; } static double count_square(const double *a, int n_dim) { - const double *end = a + n_dim * 2; - double square = 1.0; + const double *end= a + n_dim * 2; + double square= 1.0; do { square *= a[1] - a[0]; - a += 2; - }while (a != end); + a+= 2; + } while (a != end); return square; } @@ -96,25 +96,25 @@ static void pick_seeds(SplitStruct *node, int n_entries, SplitStruct **seed_a, SplitStruct **seed_b, int n_dim) { SplitStruct *cur1; - SplitStruct *lim1 = node + (n_entries - 1); + SplitStruct *lim1= node + (n_entries - 1); SplitStruct *cur2; - SplitStruct *lim2 = node + n_entries; + SplitStruct *lim2= node + n_entries; - double max_d = -DBL_MAX; + double max_d= -DBL_MAX; double d; - for (cur1 = node; cur1 < lim1; ++cur1) + for (cur1= node; cur1 < lim1; cur1++) { - for (cur2=cur1 + 1; cur2 < lim2; ++cur2) + for (cur2=cur1 + 1; cur2 < lim2; cur2++) { - d = mbr_join_square(cur1->coords, cur2->coords, n_dim) - cur1->square - + d= mbr_join_square(cur1->coords, cur2->coords, n_dim) - cur1->square - cur2->square; if (d > max_d) { - max_d = d; - *seed_a = cur1; - *seed_b = cur2; + max_d= d; + *seed_a= cur1; + *seed_b= cur2; } } } @@ -126,12 +126,12 @@ Select next node and group where to add static void pick_next(SplitStruct *node, int n_entries, double *g1, double *g2, SplitStruct **choice, int *n_group, int n_dim) { - SplitStruct *cur = node; - SplitStruct *end = node + n_entries; + SplitStruct *cur= node; + SplitStruct *end= node + n_entries; - double max_diff = -DBL_MAX; + double max_diff= -DBL_MAX; - for (; cur<end; ++cur) + for (; cur < end; cur++) { double diff; double abs_diff; @@ -141,15 +141,15 @@ static void pick_next(SplitStruct *node, int n_entries, double *g1, double *g2, continue; } - diff = mbr_join_square(g1, cur->coords, n_dim) - + diff= mbr_join_square(g1, cur->coords, n_dim) - mbr_join_square(g2, cur->coords, n_dim); - abs_diff = fabs(diff); + abs_diff= fabs(diff); if (abs_diff > max_diff) { - max_diff = abs_diff; - *n_group = 1 + (diff > 0); - *choice = cur; + max_diff= abs_diff; + *n_group= 1 + (diff > 0); + *choice= cur; } } } @@ -159,15 +159,16 @@ Mark not-in-group entries as n_group */ static void mark_all_entries(SplitStruct *node, int n_entries, int n_group) { - SplitStruct *cur = node; - SplitStruct *end = node + n_entries; - for (; cur<end; ++cur) + SplitStruct *cur= node; + SplitStruct *end= node + n_entries; + + for (; cur < end; cur++) { if (cur->n_node) { continue; } - cur->n_node = n_group; + cur->n_node= n_group; } } @@ -181,12 +182,12 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, SplitStruct *cur; SplitStruct *a; SplitStruct *b; - double *g1 = reserve_coords(d_buffer, n_dim); - double *g2 = reserve_coords(d_buffer, n_dim); + double *g1= reserve_coords(d_buffer, n_dim); + double *g2= reserve_coords(d_buffer, n_dim); SplitStruct *next; int next_node; int i; - SplitStruct *end = node + n_entries; + SplitStruct *end= node + n_entries; LINT_INIT(a); LINT_INIT(b); LINT_INIT(next); @@ -197,22 +198,22 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, return 1; } - cur = node; - for (; cur<end; ++cur) + cur= node; + for (; cur < end; cur++) { - cur->square = count_square(cur->coords, n_dim); - cur->n_node = 0; + cur->square= count_square(cur->coords, n_dim); + cur->n_node= 0; } pick_seeds(node, n_entries, &a, &b, n_dim); - a->n_node = 1; - b->n_node = 2; + a->n_node= 1; + b->n_node= 2; copy_coords(g1, a->coords, n_dim); - size1 += key_size; + size1+= key_size; copy_coords(g2, b->coords, n_dim); - size2 += key_size; + size2+= key_size; for (i=n_entries - 2; i>0; --i) @@ -232,15 +233,15 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, pick_next(node, n_entries, g1, g2, &next, &next_node, n_dim); if (next_node == 1) { - size1 += key_size; + size1+= key_size; mbr_join(g1, next->coords, n_dim); } else { - size2 += key_size; + size2+= key_size; mbr_join(g2, next->coords, n_dim); } - next->n_node = next_node; + next->n_node= next_node; } return 0; @@ -262,14 +263,15 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *source_cur, *cur1, *cur2; uchar *new_page; int err_code= 0; - uint nod_flag= _ma_test_if_nod(page); + uint nod_flag= _ma_test_if_nod(info, page); uint full_length= key_length + (nod_flag ? nod_flag : info->s->base.rec_reflength); - int max_keys= (maria_data_on_page(page)-2) / (full_length); + int max_keys= ((_ma_get_page_used(info, page) - info->s->keypage_header) / + (full_length)); DBUG_ENTER("maria_rtree_split_page"); DBUG_PRINT("rtree", ("splitting block")); - n_dim = keyinfo->keysegs / 2; + n_dim= keyinfo->keysegs / 2; if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) * (max_keys + 1 + 4) + @@ -278,66 +280,69 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4)); - next_coord = coord_buf; + next_coord= coord_buf; - stop = task + max_keys; - source_cur = rt_PAGE_FIRST_KEY(page, nod_flag); + stop= task + max_keys; + source_cur= rt_PAGE_FIRST_KEY(info, page, nod_flag); - for (cur = task; cur < stop; ++cur, source_cur = rt_PAGE_NEXT_KEY(source_cur, + for (cur= task; cur < stop; cur++, source_cur= rt_PAGE_NEXT_KEY(source_cur, key_length, nod_flag)) { - cur->coords = reserve_coords(&next_coord, n_dim); - cur->key = source_cur; + cur->coords= reserve_coords(&next_coord, n_dim); + cur->key= source_cur; maria_rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords); } - cur->coords = reserve_coords(&next_coord, n_dim); + cur->coords= reserve_coords(&next_coord, n_dim); maria_rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords); - cur->key = key; + cur->key= key; - old_coord = next_coord; + old_coord= next_coord; if (split_maria_rtree_node(task, max_keys + 1, - maria_data_on_page(page) + full_length + 2, full_length, + _ma_get_page_used(info, page) + full_length + 2, + full_length, rt_PAGE_MIN_SIZE(keyinfo->block_length), 2, 2, &next_coord, n_dim)) { - err_code = 1; + err_code= 1; goto split_err; } - if (!(new_page = (uchar*) my_alloca((uint)keyinfo->block_length))) + if (!(new_page= (uchar*) my_alloca((uint)keyinfo->block_length))) { err_code= -1; goto split_err; } - stop = task + (max_keys + 1); - cur1 = rt_PAGE_FIRST_KEY(page, nod_flag); - cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag); + stop= task + (max_keys + 1); + cur1= rt_PAGE_FIRST_KEY(info, page, nod_flag); + cur2= rt_PAGE_FIRST_KEY(info, new_page, nod_flag); - n1= n2 = 0; - for (cur = task; cur < stop; ++cur) + n1= n2= 0; + for (cur= task; cur < stop; cur++) { uchar *to; if (cur->n_node == 1) { - to = cur1; - cur1 = rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag); - ++n1; + to= cur1; + cur1= rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag); + n1++; } else { - to = cur2; - cur2 = rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag); - ++n2; + to= cur2; + cur2= rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag); + n2++; } if (to != cur->key) memcpy(to - nod_flag, cur->key - nod_flag, full_length); } - maria_putint(page, 2 + n1 * full_length, nod_flag); - maria_putint(new_page, 2 + n2 * full_length, nod_flag); + _ma_store_page_used(info, page, info->s->keypage_header + n1 * full_length, + nod_flag); + _ma_store_page_used(info, new_page, info->s->keypage_header + + n2 * full_length, nod_flag); if ((*new_page_offs= _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) diff --git a/storage/maria/ma_rt_test.c b/storage/maria/ma_rt_test.c index 4360e81c550..e41ebdce500 100644 --- a/storage/maria/ma_rt_test.c +++ b/storage/maria/ma_rt_test.c @@ -122,7 +122,8 @@ static int run_test(const char *filename) /* Define 2*ndims columns for coordinates*/ - for (i=1; i<=2*ndims ;i++){ + for (i=1; i<=2*ndims ;i++) + { recinfo[i].type=FIELD_NORMAL; recinfo[i].length=key_length; rec_length+=key_length; @@ -135,7 +136,8 @@ static int run_test(const char *filename) keyinfo[0].flag=0; keyinfo[0].key_alg=KEYALG; - for (i=0; i<2*ndims; i++){ + for (i=0; i<2*ndims; i++) + { keyinfo[0].seg[i].type= key_type; keyinfo[0].seg[i].flag=0; /* Things like HA_REVERSE_SORT */ keyinfo[0].seg[i].start= (key_length*i)+1; diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 7bbf461096c..460d8367440 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -27,8 +27,6 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int _ma_check_index(MARIA_HA *info, int inx) { - if (inx == -1) /* Use last index */ - inx=info->lastinx; if (inx < 0 || ! maria_is_key_active(info->s->state.key_map, inx)) { my_errno=HA_ERR_WRONG_INDEX; @@ -59,7 +57,7 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, { my_bool last_key; int error,flag; - uint nod_flag; + uint nod_flag, used_length; uchar *keypos,*maxpos; uchar lastkey[HA_MAX_KEY_BUFF],*buff; DBUG_ENTER("_ma_search"); @@ -80,14 +78,14 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, info->keyread_buff, test(!(nextflag & SEARCH_SAVE_BUFF))))) goto err; - DBUG_DUMP("page", buff, maria_data_on_page(buff)); + DBUG_DUMP("page", buff, _ma_get_page_used(info, buff)); flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag, &keypos,lastkey, &last_key); if (flag == MARIA_FOUND_WRONG_KEY) DBUG_RETURN(-1); - nod_flag=_ma_test_if_nod(buff); - maxpos=buff+maria_data_on_page(buff)-1; + _ma_get_used_and_nod(info, buff, used_length, nod_flag); + maxpos= buff + used_length -1; if (flag) { @@ -98,7 +96,7 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (flag >0) { if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) && - keypos == buff+2+nod_flag) + keypos == buff + info->s->keypage_header + nod_flag) DBUG_RETURN(1); /* Bigger than key */ } else if (nextflag & SEARCH_BIGGER && keypos >= maxpos) @@ -157,7 +155,8 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; info->page_changed=0; - info->keyread_buff_used= (info->keyread_buff != buff); /* If we have to reread */ + /* Set marker that buffer was used (Marker for mi_search_next()) */ + info->keyread_buff_used= (info->keyread_buff != buff); DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); @@ -179,17 +178,21 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff __attribute__((unused)), my_bool *last_key) { - reg4 int start,mid,end,save_end; int flag; - uint totlength,nod_flag,not_used[2]; + uint start, mid, end, save_end, totlength, nod_flag, used_length; + uint not_used[2]; DBUG_ENTER("_ma_bin_search"); LINT_INIT(flag); - totlength=keyinfo->keylength+(nod_flag=_ma_test_if_nod(page)); - start=0; mid=1; - save_end=end=(int) ((maria_data_on_page(page)-2-nod_flag)/totlength-1); - DBUG_PRINT("test",("page_length: %d end: %d",maria_data_on_page(page),end)); - page+=2+nod_flag; + _ma_get_used_and_nod(info, page, used_length, nod_flag); + + totlength= keyinfo->keylength + nod_flag; + start=0; + mid=1; + save_end= end= ((used_length - nod_flag - info->s->keypage_header) / + totlength-1); + DBUG_PRINT("test",("page_length: %u end: %u", used_length, end)); + page+= info->s->keypage_header + nod_flag; while (start != end) { @@ -244,14 +247,16 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uchar *page, uchar *buff, my_bool *last_key) { int flag; - uint nod_flag,length,not_used[2]; + uint nod_flag, length, used_length, not_used[2]; uchar t_buff[HA_MAX_KEY_BUFF],*end; DBUG_ENTER("_ma_seq_search"); - LINT_INIT(flag); LINT_INIT(length); - end= page+maria_data_on_page(page); - nod_flag=_ma_test_if_nod(page); - page+=2+nod_flag; + LINT_INIT(flag); + LINT_INIT(length); + + _ma_get_used_and_nod(info, page, used_length, nod_flag); + end= page + used_length; + page+= info->s->keypage_header + nod_flag; *ret_pos=page; t_buff[0]=0; /* Avoid bugs */ while (page < end) @@ -294,7 +299,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, flag is the value returned by ha_key_cmp and as treated as final */ int flag=0, my_flag=-1; - uint nod_flag, length, len, matched, cmplen, kseg_len; + uint nod_flag, used_length, length, len, matched, cmplen, kseg_len; uint prefix_len,suffix_len; int key_len_skip, seg_len_pack, key_len_left; uchar *end; @@ -314,11 +319,11 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, LINT_INIT(saved_vseg); t_buff[0]=0; /* Avoid bugs */ - end= page+maria_data_on_page(page); - nod_flag=_ma_test_if_nod(page); - page+=2+nod_flag; - *ret_pos=page; - kseg= (uchar*) key; + _ma_get_used_and_nod(info, page, used_length, nod_flag); + end= page + used_length; + page+= info->s->keypage_header + nod_flag; + *ret_pos= page; + kseg= key; get_key_pack_length(kseg_len, length_pack, kseg); key_len_skip=length_pack+kseg_len; @@ -974,7 +979,11 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, if (keyseg->flag & HA_NULL_PART) { /* If prefix is used up, switch to rest. */ - if (from == from_end) { from=page; from_end=page_end; } + if (from == from_end) + { + from=page; + from_end=page_end; + } if (!(*key++ = *from++)) continue; /* Null part */ } @@ -1044,8 +1053,11 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, } - /* Get key at position without knowledge of previous key */ - /* Returns pointer to next key */ +/* + @brief Get key at position without knowledge of previous key + + @return pointer to next key +*/ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, uint *return_key_length) @@ -1053,7 +1065,7 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uint nod_flag; DBUG_ENTER("_ma_get_key"); - nod_flag=_ma_test_if_nod(page); + nod_flag=_ma_test_if_nod(info, page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) { bmove((uchar*) key,(uchar*) keypos,keyinfo->keylength+nod_flag); @@ -1061,7 +1073,7 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, } else { - page+=2+nod_flag; + page+= info->s->keypage_header + nod_flag; key[0]=0; /* safety */ while (page <= keypos) { @@ -1080,8 +1092,13 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, } /* _ma_get_key */ - /* Get key at position without knowledge of previous key */ - /* Returns 0 if ok */ +/* + @brief Get key at position without knowledge of previous key + + @return + @retval 0 ok + @retval 1 error +*/ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, @@ -1090,7 +1107,7 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint nod_flag; DBUG_ENTER("_ma_get_prev_key"); - nod_flag=_ma_test_if_nod(page); + nod_flag=_ma_test_if_nod(info, page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) { *return_key_length=keyinfo->keylength; @@ -1100,7 +1117,7 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } else { - page+=2+nod_flag; + page+= info->s->keypage_header + nod_flag; key[0]=0; /* safety */ while (page < keypos) { @@ -1117,9 +1134,12 @@ static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } /* _ma_get_key */ +/* + @brief Get last key from key-page - /* Get last key from key-page */ - /* Return pointer to where key starts */ + @return + @retval pointer to where key starts +*/ uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uchar *lastkey, uchar *endpos, uint *return_key_length) @@ -1130,7 +1150,7 @@ uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page, (long) endpos)); - nod_flag=_ma_test_if_nod(page); + nod_flag=_ma_test_if_nod(info, page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) { lastpos=endpos-keyinfo->keylength-nod_flag; @@ -1140,7 +1160,8 @@ uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, } else { - lastpos=(page+=2+nod_flag); + page+= info->s->keypage_header + nod_flag; + lastpos= page; lastkey[0]=0; while (page < endpos) { @@ -1162,7 +1183,7 @@ uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, } /* _ma_get_last_key */ - /* Calculate length of key */ +/* Calculate length of key */ uint _ma_keylength(MARIA_KEYDEF *keyinfo, register const uchar *key) { @@ -1276,7 +1297,7 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } /* Last used buffer is in info->keyread_buff */ - nod_flag=_ma_test_if_nod(info->keyread_buff); + nod_flag=_ma_test_if_nod(info, info->keyread_buff); if (nextflag & SEARCH_BIGGER) /* Next key */ { @@ -1300,7 +1321,7 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, info->int_keypos, &length); if (!info->int_keypos) DBUG_RETURN(-1); - if (info->int_keypos == info->keyread_buff+2) + if (info->int_keypos == info->keyread_buff + info->s->keypage_header) DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY, nextflag | SEARCH_SAVE_BUFF, pos)); if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY, @@ -1339,20 +1360,23 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, do { - if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->keyread_buff,0)) + if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS, + info->keyread_buff,0)) { info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } - nod_flag=_ma_test_if_nod(info->keyread_buff); - page=info->keyread_buff+2+nod_flag; + nod_flag=_ma_test_if_nod(info, info->keyread_buff); + page= info->keyread_buff + info->s->keypage_header + nod_flag; } while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR); if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page, info->lastkey))) DBUG_RETURN(-1); /* Crashed */ - info->int_keypos=page; info->int_maxpos=info->keyread_buff+maria_data_on_page(info->keyread_buff)-1; + info->int_keypos=page; + info->int_maxpos= (info->keyread_buff + + _ma_get_page_used(info, info->keyread_buff)-1); info->int_nod_flag=nod_flag; info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; @@ -1371,7 +1395,7 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, register my_off_t pos) { uint nod_flag; - uchar *buff,*page; + uchar *buff,*end_of_page; DBUG_ENTER("_ma_search_last"); if (pos == HA_OFFSET_ERROR) @@ -1384,20 +1408,21 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, buff=info->keyread_buff; do { + uint used_length; if (!_ma_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,buff,0)) { info->cur_row.lastpos= HA_OFFSET_ERROR; DBUG_RETURN(-1); } - page= buff+maria_data_on_page(buff); - nod_flag=_ma_test_if_nod(buff); - } while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR); + _ma_get_used_and_nod(info, buff, used_length, nod_flag); + end_of_page= buff + used_length; + } while ((pos= _ma_kpos(nod_flag, end_of_page)) != HA_OFFSET_ERROR); - if (!_ma_get_last_key(info,keyinfo,buff,info->lastkey,page, + if (!_ma_get_last_key(info, keyinfo, buff, info->lastkey, end_of_page, &info->lastkey_length)) DBUG_RETURN(-1); info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length); - info->int_keypos=info->int_maxpos=page; + info->int_keypos= info->int_maxpos= end_of_page; info->int_nod_flag=nod_flag; info->int_keytree_version=keyinfo->version; info->last_search_keypage=info->last_keypage; diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index e367f8c20e3..2b4a4b16923 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -92,7 +92,7 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); _ma_create_index_by_sort() info Sort parameters no_messages Set to 1 if no output - sortbuff_size Size if sortbuffer to allocate + sortbuff_size Size of sortbuffer to allocate RESULT 0 ok @@ -100,10 +100,11 @@ my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); */ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, - ulong sortbuff_size) + size_t sortbuff_size) { int error,maxbuffer,skr; - uint memavl,old_memavl,keys,sort_length; + size_t memavl,old_memavl; + uint keys,sort_length; DYNAMIC_ARRAY buffpek; ha_rows records; uchar **sort_keys; @@ -313,8 +314,9 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) { MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg; int error; - uint memavl,old_memavl,keys,sort_length; - uint idx, maxbuffer; + size_t memavl,old_memavl; + uint sort_length; + ulong idx, maxbuffer, keys; uchar **sort_keys=0; LINT_INIT(keys); @@ -355,19 +357,18 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) while (memavl >= MIN_SORT_MEMORY) { - if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= - (my_off_t) memavl) + if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) keys= idx+1; else { - uint skr; + ulong skr; do { skr= maxbuffer; if (memavl < sizeof(BUFFPEK)*maxbuffer || (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/ (sort_length+sizeof(char*))) <= 1 || - keys < (uint) maxbuffer) + keys < maxbuffer) { _ma_check_print_error(sort_param->sort_info->param, "maria_sort_buffer_size is too small"); @@ -403,8 +404,8 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) } if (sort_param->sort_info->param->testflag & T_VERBOSE) - printf("Key %d - Allocating buffer for %d keys\n", - sort_param->key+1, keys); + printf("Key %d - Allocating buffer for %lu keys\n", + sort_param->key+1, (ulong) keys); sort_param->sort_keys= sort_keys; idx= error= 0; @@ -492,7 +493,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) MARIA_SORT_INFO *sort_info=sort_param->sort_info; HA_CHECK *param=sort_info->param; ulong length, keys; - ulong *rec_per_key_part=param->rec_per_key_part; + double *rec_per_key_part= param->new_rec_per_key_part; int got_error=sort_info->got_error; uint i; MARIA_HA *info=sort_info->info; diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index 41b202491a7..fe1335c39fe 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -24,10 +24,12 @@ #endif LIST *maria_open_list=0; -uchar NEAR maria_file_magic[]= +uchar maria_file_magic[]= { (uchar) 254, (uchar) 254, (uchar) 9, '\001', }; -uchar NEAR maria_pack_file_magic[]= +uchar maria_pack_file_magic[]= { (uchar) 254, (uchar) 254, (uchar) 10, '\001', }; +/* Unique number for this maria instance */ +uchar maria_uuid[MY_UUID_SIZE]; uint maria_quick_table_bits=9; ulong maria_block_size= MARIA_KEY_BLOCK_LENGTH; my_bool maria_flush= 0, maria_single_user= 0; @@ -64,7 +66,7 @@ uchar maria_zero_string[]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; Position is , == , >= , <= , > , < */ -uint NEAR maria_read_vec[]= +uint maria_read_vec[]= { SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER, SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER, @@ -72,7 +74,7 @@ uint NEAR maria_read_vec[]= MBR_CONTAIN, MBR_INTERSECT, MBR_WITHIN, MBR_DISJOINT, MBR_EQUAL }; -uint NEAR maria_readnext_vec[]= +uint maria_readnext_vec[]= { SEARCH_BIGGER, SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_SMALLER diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index d9bd9bca9e0..e99e4653afd 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -42,8 +42,7 @@ static uint rnd(uint max_value); static void fix_length(uchar *record,uint length); static void put_blob_in_record(uchar *blob_pos,char **blob_buffer, ulong *length); -static void copy_key(struct st_maria_info *info,uint inx, - uchar *record,uchar *key); +static void copy_key(MARIA_HA *info, uint inx, uchar *record, uchar *key); static int verbose=0,testflag=0, first_key=0,async_io=0,pagecacheing=0,write_cacheing=0,locking=0, @@ -300,8 +299,6 @@ int main(int argc, char *argv[]) } } } - if (testflag == 2) - goto end; if (write_cacheing) { @@ -311,6 +308,10 @@ int main(int argc, char *argv[]) goto err; } } + + if (testflag == 2) + goto end; + #ifdef REMOVE_WHEN_WE_HAVE_RESIZE if (pagecacheing) resize_pagecache(maria_pagecache, maria_block_size, @@ -453,7 +454,7 @@ int main(int argc, char *argv[]) info.recpos= maria_position(file); int skr=maria_rnext(file,read_record2,0); if ((skr && my_errno != HA_ERR_END_OF_FILE) || - maria_rprev(file,read_record2,-1) || + maria_rprev(file,read_record2,0) || memcmp(read_record,read_record2,reclength) != 0 || info.recpos != maria_position(file)) { @@ -877,7 +878,7 @@ int main(int argc, char *argv[]) goto err; } opt_delete++; -#if 0 +#if TO_BE_REMOVED / /* 179 is ok, 180 causes a difference between runtime and log-applying. diff --git a/storage/maria/ma_test_recovery b/storage/maria/ma_test_recovery index 7c45af1e206..728994a5086 100755 --- a/storage/maria/ma_test_recovery +++ b/storage/maria/ma_test_recovery @@ -107,14 +107,14 @@ do table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' ` $maria_path/maria_chk -dvv $table | grep -v "Creation time:"> $tmp/maria_chk_message.good.txt 2>&1 checksum=`$maria_path/maria_chk -dss $table` - mv $table.MAD $tmp/$table.MAD.good - rm $table.MAI + mv $table.MAD $tmp/$table-good.MAD + mv $table.MAI $tmp/$table-good.MAI apply_log "shouldnotchangelog" - cmp $table.MAD $tmp/$table.MAD.good + cmp $table.MAD $tmp/$table-good.MAD check_table_is_same echo "testing idempotency" apply_log "shouldnotchangelog" - cmp $table.MAD $tmp/$table.MAD.good + cmp $table.MAD $tmp/$table-good.MAD check_table_is_same shift done @@ -145,8 +145,8 @@ do table=`echo $prog | sed -e 's;.*ma_\(test[0-9]\).*;\1;' ` $maria_path/maria_chk -dvv $table | grep -v "Creation time:"> $tmp/maria_chk_message.good.txt 2>&1 checksum=`$maria_path/maria_chk -dss $table` - mv $table.MAD $tmp/$table.MAD.good - rm $table.MAI + mv $table.MAD $tmp/$table-good.MAD + mv $table.MAI $tmp/$table-good.MAI rm maria_log.* maria_log_control echo "TEST WITH $prog $abort_run_args$test_undo (additional aborted work)" $maria_path/$prog $abort_run_args$test_undo diff --git a/storage/maria/ma_test_recovery.expected b/storage/maria/ma_test_recovery.expected index 70339fc69b6..b2ec94663fe 100644 --- a/storage/maria/ma_test_recovery.expected +++ b/storage/maria/ma_test_recovery.expected @@ -31,36 +31,36 @@ applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 11c11 -< Datafile length: 90112 Keyfile length: 204800 +< Datafile length: 114688 Keyfile length: 204800 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 11c11 -< Datafile length: 90112 Keyfile length: 204800 +< Datafile length: 114688 Keyfile length: 204800 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========DIFF END======= TEST WITH ma_test2 -s -M -T -c -b applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 11c11 -< Datafile length: 81920 Keyfile length: 172032 +< Datafile length: 114688 Keyfile length: 155648 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========DIFF END======= testing idempotency applying log Differences in maria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 11c11 -< Datafile length: 81920 Keyfile length: 172032 +< Datafile length: 114688 Keyfile length: 155648 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========DIFF END======= Testing the REDO AND UNDO PHASE TEST WITH ma_test1 -s -M -T -c -N --testflag=1 (commit at end) @@ -182,7 +182,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -195,7 +195,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -208,7 +208,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========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) @@ -329,7 +329,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -342,7 +342,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -355,7 +355,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========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) @@ -476,7 +476,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -489,7 +489,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 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 @@ -502,7 +502,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 90112 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========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) @@ -623,7 +623,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log @@ -636,7 +636,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log @@ -649,7 +649,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========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) @@ -770,7 +770,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log @@ -783,7 +783,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log @@ -796,7 +796,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========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) @@ -917,7 +917,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing idempotency applying log @@ -930,7 +930,7 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 212992 +> Datafile length: 114688 Keyfile length: 212992 ========DIFF END======= testing applying of CLRs to recreate table applying log @@ -943,5 +943,5 @@ Differences in maria_chk -dvv, recovery not yet perfect ! 11c11 < Datafile length: 8192 Keyfile length: 8192 --- -> Datafile length: 81920 Keyfile length: 8192 +> Datafile length: 114688 Keyfile length: 8192 ========DIFF END======= diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index c62b168d008..12f29c8ee1d 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -30,9 +30,9 @@ static int w_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo, static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uchar *key, uchar *curr_buff,uchar *father_buff, uchar *father_keypos,my_off_t father_page); -static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint *return_key_length, - uchar **after_key); +static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uchar *page, uchar *key, + uint *return_key_length, uchar **after_key); int _ma_ck_write_tree(register MARIA_HA *info, uint keynr,uchar *key, uint key_length); int _ma_ck_write_btree(register MARIA_HA *info, uint keynr,uchar *key, @@ -115,7 +115,7 @@ int maria_write(MARIA_HA *info, uchar *record) */ if ((filepos= (*share->write_record_init)(info, record)) == HA_OFFSET_ERROR) - goto err2; + goto err2; } /* Write all keys to indextree */ @@ -277,6 +277,7 @@ err: my_errno=save_errno; err2: save_errno=my_errno; + DBUG_ASSERT(save_errno); DBUG_PRINT("error", ("got error: %d", save_errno)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ @@ -294,10 +295,7 @@ int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length) { DBUG_RETURN(_ma_ck_write_tree(info, keynr, key, key_length)); } - else - { - DBUG_RETURN(_ma_ck_write_btree(info, keynr, key, key_length)); - } + DBUG_RETURN(_ma_ck_write_btree(info, keynr, key, key_length)); } /* _ma_ck_write */ @@ -366,12 +364,18 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, DBUG_ENTER("_ma_enlarge_root"); nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0; - _ma_kpointer(info,info->buff+2,*root); /* if nod */ + /* Store pointer to prev page if nod */ + _ma_kpointer(info, info->buff + info->s->keypage_header, *root); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0, (uchar*) 0, (uchar*) 0, key,&s_temp); - maria_putint(info->buff,t_length+2+nod_flag,nod_flag); - (*keyinfo->store_key)(keyinfo,info->buff+2+nod_flag,&s_temp); - info->keyread_buff_used=info->page_changed=1; /* info->buff is used */ + + _ma_store_keynr(info, info->buff, (keyinfo - info->s->keyinfo)); + _ma_store_page_used(info, info->buff, info->s->keypage_header + + t_length + nod_flag, nod_flag); + (*keyinfo->store_key)(keyinfo, info->buff + info->s->keypage_header + + nod_flag, &s_temp); + /* Mark that info->buff was used */ + info->keyread_buff_used= info->page_changed= 1; if ((*root= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR || _ma_write_keypage(info,keyinfo,*root,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); @@ -379,12 +383,14 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, } /* _ma_enlarge_root */ - /* - Search after a position for a key and store it there - Returns -1 = error - 0 = ok - 1 = key should be stored in higher tree - */ +/* + Search after a position for a key and store it there + + @return + @retval -1 error + @retval 0 ok + @retval 1 key should be stored in higher tree +*/ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, uint comp_flag, uchar *key, uint key_length, my_off_t page, @@ -409,7 +415,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length, comp_flag, &keypos, keybuff, &was_last_key); - nod_flag= _ma_test_if_nod(temp_buff); + nod_flag= _ma_test_if_nod(info, temp_buff); if (flag == 0) { uint tmp_key_length; @@ -442,7 +448,8 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, keyinfo=&info->s->ft2_keyinfo; get_key_full_length_rdonly(off, key); key+=off; - keypos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */ + /* we'll modify key entry 'in vivo' */ + keypos-= keyinfo->keylength + nod_flag; error= _ma_ck_real_write_btree(info, keyinfo, key, 0, &root, comp_flag); _ma_dpointer(info, keypos+HA_FT_WLEN, root); @@ -525,17 +532,17 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key, USE_WHOLE_KEY);); - nod_flag=_ma_test_if_nod(anc_buff); - a_length= maria_data_on_page(anc_buff); + _ma_get_used_and_nod(info, anc_buff, a_length, nod_flag); endpos= anc_buff+ a_length; - prev_key=(key_pos == anc_buff+2+nod_flag ? (uchar*) 0 : key_buff); + prev_key= (key_pos == anc_buff + info->s->keypage_header + nod_flag ? + (uchar*) 0 : key_buff); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (key_pos == endpos ? (uchar*) 0 : key_pos), prev_key, prev_key, key,&s_temp); #ifndef DBUG_OFF - if (key_pos != anc_buff+2+nod_flag && (keyinfo->flag & - (HA_BINARY_PACK_KEY | HA_PACK_KEY))) + if (key_pos != anc_buff + info->s->keypage_header + nod_flag && + (keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY))) { DBUG_DUMP("prev_key",(uchar*) key_buff, _ma_keylength(keyinfo,key_buff)); } @@ -569,11 +576,11 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } (*keyinfo->store_key)(keyinfo,key_pos,&s_temp); a_length+=t_length; - maria_putint(anc_buff,a_length,nod_flag); - if (a_length <= keyinfo->block_length) + _ma_store_page_used(info, anc_buff, a_length, nod_flag); + if (a_length <= (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE) { - if (keyinfo->block_length - a_length < 32 && - keyinfo->flag & HA_FULLTEXT && key_pos == endpos && + if (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE - a_length < 32 && + (keyinfo->flag & HA_FULLTEXT) && key_pos == endpos && info->s->base.key_reflength <= info->s->base.rec_reflength && info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) { @@ -582,7 +589,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, Let's consider converting. We'll compare 'key' and the first key at anc_buff */ - uchar *a=key, *b=anc_buff+2+nod_flag; + uchar *a= key, *b= anc_buff + info->s->keypage_header + nod_flag; uint alen, blen, ft2len=info->s->ft2_keyinfo.keylength; /* the very first key on the page is always unpacked */ DBUG_ASSERT((*b & 128) == 0); @@ -597,25 +604,28 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, ha_compare_text(keyinfo->seg->charset, (uchar*) a, alen, (uchar*) b, blen, 0, 0) == 0) { - /* yup. converting */ + /* Yup. converting */ info->ft1_to_ft2=(DYNAMIC_ARRAY *) my_malloc(sizeof(DYNAMIC_ARRAY), MYF(MY_WME)); my_init_dynamic_array(info->ft1_to_ft2, ft2len, 300, 50); /* - now, adding all keys from the page to dynarray + Now, adding all keys from the page to dynarray if the page is a leaf (if not keys will be deleted later) */ if (!nod_flag) { - /* let's leave the first key on the page, though, because - we cannot easily dispatch an empty page here */ + /* + Let's leave the first key on the page, though, because + we cannot easily dispatch an empty page here + */ b+=blen+ft2len+2; for (a=anc_buff+a_length ; b < a ; b+=ft2len+2) insert_dynamic(info->ft1_to_ft2, b); /* fixing the page's length - it contains only one key now */ - maria_putint(anc_buff,2+blen+ft2len+2,0); + _ma_store_page_used(info, anc_buff, info->s->keypage_header + blen + + ft2len + 2, 0); } /* the rest will be done when we're back from recursion */ } @@ -645,31 +655,33 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, MARIA_KEY_PARAM s_temp; DBUG_ENTER("maria_split_page"); LINT_INIT(after_key); - DBUG_DUMP("buff",(uchar*) buff,maria_data_on_page(buff)); + DBUG_DUMP("buff", buff, _ma_get_page_used(info, buff)); if (info->s->keyinfo+info->lastinx == keyinfo) info->page_changed=1; /* Info->buff is used */ info->keyread_buff_used=1; - nod_flag=_ma_test_if_nod(buff); - key_ref_length=2+nod_flag; + nod_flag=_ma_test_if_nod(info, buff); + key_ref_length= info->s->keypage_header + nod_flag; if (insert_last_key) - key_pos= _ma_find_last_pos(keyinfo,buff,key_buff, &key_length, &after_key); + key_pos= _ma_find_last_pos(info, keyinfo, buff, key_buff, &key_length, + &after_key); else - key_pos= _ma_find_half_pos(nod_flag,keyinfo,buff,key_buff, &key_length, - &after_key); + key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, key_buff, + &key_length, &after_key); if (!key_pos) DBUG_RETURN(-1); length=(uint) (key_pos-buff); - a_length= maria_data_on_page(buff); - maria_putint(buff,length,nod_flag); + a_length= _ma_get_page_used(info, buff); + _ma_store_page_used(info, buff, length, nod_flag); key_pos=after_key; if (nod_flag) { DBUG_PRINT("test",("Splitting nod")); pos=key_pos-nod_flag; - memcpy((uchar*) info->buff+2,(uchar*) pos,(size_t) nod_flag); + memcpy((uchar*) info->buff + info->s->keypage_header, (uchar*) pos, + (size_t) nod_flag); } /* Move middle item to key and pointer to new page */ @@ -688,8 +700,14 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, memcpy((uchar*) info->buff+key_ref_length+t_length,(uchar*) key_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,info->buff+key_ref_length,&s_temp); - maria_putint(info->buff,length+t_length+key_ref_length,nod_flag); - + _ma_store_page_used(info, info->buff, length + t_length + key_ref_length, + nod_flag); + + /* Copy key number */ + info->buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - + KEYPAGE_FLAG_SIZE]= + buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - + KEYPAGE_FLAG_SIZE]; if (_ma_write_keypage(info,keyinfo,new_pos,DFLT_INIT_HITS,info->buff)) DBUG_RETURN(-1); DBUG_DUMP("key",(uchar*) key, _ma_keylength(keyinfo,key)); @@ -697,25 +715,26 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } /* _ma_split_page */ - /* - Calculate how to much to move to split a page in two - Returns pointer to start of key. - key will contain the key. - return_key_length will contain the length of key - after_key will contain the position to where the next key starts - */ +/* + Calculate how to much to move to split a page in two + + Returns pointer to start of key. + key will contain the key. + return_key_length will contain the length of key + after_key will contain the position to where the next key starts +*/ -uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page, - uchar *key, uint *return_key_length, +uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag, MARIA_KEYDEF *keyinfo, + uchar *page, uchar *key, uint *return_key_length, uchar **after_key) { uint keys,length,key_ref_length; uchar *end,*lastpos; DBUG_ENTER("_ma_find_half_pos"); - key_ref_length=2+nod_flag; - length= maria_data_on_page(page)-key_ref_length; - page+=key_ref_length; + key_ref_length= info->s->keypage_header + nod_flag; + length= _ma_get_page_used(info, page) - key_ref_length; + page+= key_ref_length; /* Point to first key */ if (!(keyinfo->flag & (HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) @@ -751,7 +770,8 @@ uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, uchar *page, key will contain the last key */ -static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, +static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo, + uchar *page, uchar *key, uint *return_key_length, uchar **after_key) { @@ -760,8 +780,8 @@ static uchar *_ma_find_last_pos(MARIA_KEYDEF *keyinfo, uchar *page, uchar key_buff[HA_MAX_KEY_BUFF]; DBUG_ENTER("_ma_find_last_pos"); - key_ref_length=2; - length= maria_data_on_page(page)-key_ref_length; + key_ref_length= info->s->keypage_header; + length= _ma_get_page_used(info, page) - key_ref_length; page+=key_ref_length; if (!(keyinfo->flag & (HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY | @@ -818,15 +838,16 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, DBUG_ENTER("_ma_balance_page"); k_length=keyinfo->keylength; - father_length= maria_data_on_page(father_buff); - father_keylength=k_length+info->s->base.key_reflength; - nod_flag=_ma_test_if_nod(curr_buff); + father_length= _ma_get_page_used(info, father_buff); + father_keylength= k_length + info->s->base.key_reflength; + nod_flag=_ma_test_if_nod(info, curr_buff); curr_keylength=k_length+nod_flag; info->page_changed=1; if ((father_key_pos != father_buff+father_length && (info->state->records & 1)) || - father_key_pos == father_buff+2+info->s->base.key_reflength) + father_key_pos == father_buff+ info->s->keypage_header + + info->s->base.key_reflength) { right=1; next_page= _ma_kpos(info->s->base.key_reflength, @@ -846,42 +867,46 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (!_ma_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0)) goto err; - DBUG_DUMP("next",(uchar*) info->buff,maria_data_on_page(info->buff)); + DBUG_DUMP("next", info->buff, _ma_get_page_used(info, info->buff)); /* Test if there is room to share keys */ - left_length= maria_data_on_page(curr_buff); - right_length= maria_data_on_page(buff); - keys=(left_length+right_length-4-nod_flag*2)/curr_keylength; + left_length= _ma_get_page_used(info, curr_buff); + right_length= _ma_get_page_used(info, buff); + keys= ((left_length+right_length-info->s->keypage_header*2-nod_flag*2)/ + curr_keylength); if ((right ? right_length : left_length) + curr_keylength <= - keyinfo->block_length) + (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE) { /* Merge buffs */ - new_left_length=2+nod_flag+(keys/2)*curr_keylength; - new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength; - maria_putint(curr_buff,new_left_length,nod_flag); - maria_putint(buff,new_right_length,nod_flag); + new_left_length= info->s->keypage_header+nod_flag+(keys/2)*curr_keylength; + new_right_length=info->s->keypage_header+nod_flag+(((keys+1)/2)* + curr_keylength); + _ma_store_page_used(info, curr_buff,new_left_length,nod_flag); + _ma_store_page_used(info, buff,new_right_length,nod_flag); if (left_length < new_left_length) { /* Move keys buff -> leaf */ pos=curr_buff+left_length; - memcpy((uchar*) pos,(uchar*) father_key_pos, (size_t) k_length); - memcpy((uchar*) pos+k_length, (uchar*) buff+2, + memcpy(pos,father_key_pos, (size_t) k_length); + memcpy(pos+k_length, buff + info->s->keypage_header, (size_t) (length=new_left_length - left_length - k_length)); - pos=buff+2+length; - memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length); - bmove((uchar*) buff+2,(uchar*) pos+k_length,new_right_length); + pos= buff + info->s->keypage_header + length; + memcpy(father_key_pos, pos, (size_t) k_length); + bmove(buff + info->s->keypage_header, pos + k_length, new_right_length); } else { /* Move keys -> buff */ - bmove_upp((uchar*) buff+new_right_length,(uchar*) buff+right_length, - right_length-2); + bmove_upp(buff + new_right_length, buff + right_length, + right_length - info->s->keypage_header); length=new_right_length-right_length-k_length; - memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length); + memcpy(buff + info->s->keypage_header + length, father_key_pos, + (size_t) k_length); pos=curr_buff+new_left_length; - memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length); - memcpy((uchar*) buff+2,(uchar*) pos+k_length,(size_t) length); + memcpy(father_key_pos, pos, (size_t) k_length); + memcpy(buff + info->s->keypage_header, pos+k_length, + (size_t) length); } if (_ma_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff) || @@ -893,7 +918,13 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, /* curr_buff[] and buff[] are full, lets split and make new nod */ extra_buff=info->buff+info->s->base.max_key_block_length; - new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength; + new_left_length= new_right_length= (info->s->keypage_header + nod_flag + + (keys+1) / 3 * curr_keylength); + /* + 5 is the minum number of keys we can have here. This comes from + the fact that each full page can store at least 2 keys and in this case + we have a 'split' key, ie 2+2+1 = 5 + */ if (keys == 5) /* Too few keys to balance */ new_left_length-=curr_keylength; extra_length=nod_flag+left_length+right_length- @@ -902,28 +933,37 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, left_length, right_length, new_left_length, new_right_length, extra_length)); - maria_putint(curr_buff,new_left_length,nod_flag); - maria_putint(buff,new_right_length,nod_flag); - maria_putint(extra_buff,extra_length+2,nod_flag); + _ma_store_page_used(info, curr_buff,new_left_length,nod_flag); + _ma_store_page_used(info, buff,new_right_length,nod_flag); + /* Copy key number */ + bzero(extra_buff, info->s->keypage_header); + extra_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - + KEYPAGE_FLAG_SIZE]= + buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - + KEYPAGE_FLAG_SIZE]; + _ma_store_page_used(info, extra_buff, extra_length + info->s->keypage_header, + nod_flag); /* move first largest keys to new page */ pos=buff+right_length-extra_length; - memcpy((uchar*) extra_buff+2,pos,(size_t) extra_length); + memcpy(extra_buff + info->s->keypage_header, pos, + (size_t) extra_length); /* Save new parting key */ memcpy(tmp_part_key, pos-k_length,k_length); /* Make place for new keys */ - bmove_upp((uchar*) buff+new_right_length,(uchar*) pos-k_length, - right_length-extra_length-k_length-2); + bmove_upp(buff+ new_right_length, pos - k_length, + right_length - extra_length - k_length - info->s->keypage_header); /* Copy keys from left page */ pos= curr_buff+new_left_length; - memcpy((uchar*) buff+2,(uchar*) pos+k_length, + memcpy(buff + info->s->keypage_header, pos + k_length, (size_t) (length=left_length-new_left_length-k_length)); /* Copy old parting key */ - memcpy((uchar*) buff+2+length,father_key_pos,(size_t) k_length); + memcpy(buff + info->s->keypage_header + length, + father_key_pos, (size_t) k_length); /* Move new parting keys up to caller */ - memcpy((uchar*) (right ? key : father_key_pos),pos,(size_t) k_length); - memcpy((uchar*) (right ? father_key_pos : key),tmp_part_key, k_length); + memcpy((right ? key : father_key_pos),pos,(size_t) k_length); + memcpy((right ? father_key_pos : key),tmp_part_key, k_length); if ((new_pos= _ma_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR) goto err; @@ -970,7 +1010,7 @@ static int keys_compare(bulk_insert_param *param, uchar *key1, uchar *key2) { uint not_used[2]; return ha_key_cmp(param->info->s->keyinfo[param->keynr].seg, - (uchar*) key1, (uchar*) key2, USE_WHOLE_KEY, SEARCH_SAME, + key1, key2, USE_WHOLE_KEY, SEARCH_SAME, not_used); } diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 8c5c11bc3a7..60b83caa2f1 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -830,6 +830,9 @@ static int maria_chk(HA_CHECK *param, char *filename) case HA_ERR_OLD_FILE: _ma_check_print_error(param,"'%s' is a old type of MARIA-table", filename); break; + case HA_ERR_NEW_FILE: + _ma_check_print_error(param,"'%s' uses new features not supported by this version of the MARIA library", filename); + break; case HA_ERR_END_OF_FILE: _ma_check_print_error(param,"Couldn't read complete header from '%s'", filename); break; @@ -1302,6 +1305,8 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) if (share->options & HA_OPTION_DELAY_KEY_WRITE) printf("Keys are only flushed at close\n"); + if (share->options & HA_OPTION_PAGE_CHECKSUM) + printf("Page checksums are used\n"); } printf("Data records: %16s Deleted blocks: %18s\n", llstr(info->state->records,llbuff),llstr(info->state->del,llbuff2)); @@ -1381,7 +1386,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) else buff[0]=0; if (param->testflag & T_VERBOSE) - printf("%11lu %12s %10d", + printf("%11.0g %12s %10d", share->state.rec_per_key_part[keyseg_nr++], buff,keyinfo->block_length); VOID(putchar('\n')); @@ -1402,7 +1407,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) printf(" %-6ld%-3d %-21s", (long) keyseg->start+1,keyseg->length,buff); if (param->testflag & T_VERBOSE) - printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]); + printf("%11.0g", share->state.rec_per_key_part[keyseg_nr++]); VOID(putchar('\n')); } keyseg++; @@ -1681,7 +1686,7 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, HA_CHECK *param=sort_info->param; DBUG_ENTER("sort_record_index"); - nod_flag=_ma_test_if_nod(buff); + nod_flag=_ma_test_if_nod(info, buff); temp_buff=0; if (nod_flag) @@ -1692,9 +1697,9 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info, DBUG_RETURN(-1); } } - used_length= maria_data_on_page(buff); - keypos=buff+2+nod_flag; - endpos=buff+used_length; + used_length= _ma_get_page_used(info, buff); + keypos= buff + info->s->keypage_header + nod_flag; + endpos= buff + used_length; for ( ;; ) { _sanity(__FILE__,__LINE__); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index e4c8c3efcdc..5351ffdab16 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -25,13 +25,16 @@ #else #include <my_no_pthread.h> #endif - #include "ma_loghandler.h" #include "ma_control_file.h" +/* For testing recovery */ +#define IDENTICAL_PAGES_AFTER_RECOVERY 1 +/* Do extra sanity checking */ +#define SANITY_CHECKS 1 + #define MAX_NONMAPPED_INSERTS 1000 #define MARIA_MAX_TREE_LEVELS 32 -#define SANITY_CHECKS struct st_transaction; @@ -79,11 +82,12 @@ typedef struct st_maria_state_info ulong unique; /* Unique number for this process */ ulong update_count; /* Updated for each write lock */ ulong status; - ulong *rec_per_key_part; + double *rec_per_key_part; + ulong *nulls_per_key_part; ha_checksum checksum; /* Table checksum */ my_off_t *key_root; /* Start of key trees */ my_off_t key_del; /* delete links for index pages */ - my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ + my_off_t records_at_analyze; /* Rows when calculating rec_per_key */ ulong sec_index_changed; /* Updated when new sec_index */ ulong sec_index_used; /* which extra index are in use */ @@ -108,18 +112,19 @@ typedef struct st_maria_state_info #define MARIA_STATE_INFO_SIZE \ (24 + LSN_STORE_SIZE*2 + 4 + 11*8 + 4*4 + 8 + 3*4 + 5*8) -#define MARIA_STATE_KEY_SIZE 8 +#define MARIA_STATE_KEY_SIZE (8 + 4) #define MARIA_STATE_KEYBLOCK_SIZE 8 -#define MARIA_STATE_KEYSEG_SIZE 4 +#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_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) -#define MARIA_BASE_INFO_SIZE (5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) +#define MARIA_BASE_INFO_SIZE (MY_UUID_SIZE + 5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) #define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ /* Internal management bytes needed to store 2 keys on an index page */ -#define MARIA_INDEX_MIN_OVERHEAD_SIZE (4 + (TRANSID_SIZE+1) * 2) +#define MARIA_INDEX_OVERHEAD_SIZE (TRANSID_SIZE * 2) +#define MARIA_DELETE_KEY_NR 255 /* keynr for deleted blocks */ /* Basic information of the Maria table. This is stored on disk @@ -171,9 +176,12 @@ typedef struct st_ma_base_info uint default_rec_buff_size; /* Extra number of bytes the row format require in the record buffer */ uint extra_rec_buff_size; + /* Tuning flags that can be ignored by older Maria versions */ + uint extra_options; /* The following are from the header */ uint key_parts, all_key_parts; + uchar uuid[MY_UUID_SIZE]; /** @brief If false, we disable logging, versioning, transaction etc. Observe difference with MARIA_SHARE::now_transactional @@ -233,6 +241,7 @@ typedef struct st_maria_share MARIA_COLUMNDEF *columndef; /* Pointer to column information */ MARIA_PACK pack; /* Data about packed records */ MARIA_BLOB *blobs; /* Pointer to blobs */ + uint16 *column_nr; /* Original column order */ char *unique_file_name; /* realpath() of index file */ char *data_file_name; /* Resolved path names from symlinks */ char *index_file_name; @@ -247,38 +256,38 @@ typedef struct st_maria_share /* Called when the last instance of the table is closed */ my_bool (*once_end)(struct st_maria_share *); /* Is called for every open of the table */ - my_bool (*init)(struct st_maria_info *); + my_bool (*init)(MARIA_HA *); /* Is called for every close of the table */ - void (*end)(struct st_maria_info *); + void (*end)(MARIA_HA *); /* Called when we want to read a record from a specific position */ - int (*read_record)(struct st_maria_info *, uchar *, MARIA_RECORD_POS); + int (*read_record)(MARIA_HA *, uchar *, MARIA_RECORD_POS); /* Initialize a scan */ - my_bool (*scan_init)(struct st_maria_info *); + my_bool (*scan_init)(MARIA_HA *); /* Read next record while scanning */ - int (*scan)(struct st_maria_info *, uchar *, MARIA_RECORD_POS, my_bool); + int (*scan)(MARIA_HA *, uchar *, MARIA_RECORD_POS, my_bool); /* End scan */ - void (*scan_end)(struct st_maria_info *); + void (*scan_end)(MARIA_HA *); /* Pre-write of row (some handlers may do the actual write here) */ - MARIA_RECORD_POS (*write_record_init)(struct st_maria_info *, const uchar *); + MARIA_RECORD_POS (*write_record_init)(MARIA_HA *, const uchar *); /* Write record (or accept write_record_init) */ - my_bool (*write_record)(struct st_maria_info *, const uchar *); + my_bool (*write_record)(MARIA_HA *, const uchar *); /* Called when write failed */ - my_bool (*write_record_abort)(struct st_maria_info *); - my_bool (*update_record)(struct st_maria_info *, MARIA_RECORD_POS, + my_bool (*write_record_abort)(MARIA_HA *); + my_bool (*update_record)(MARIA_HA *, MARIA_RECORD_POS, const uchar *, const uchar *); - my_bool (*delete_record)(struct st_maria_info *, const uchar *record); - my_bool (*compare_record)(struct st_maria_info *, const uchar *); + my_bool (*delete_record)(MARIA_HA *, const uchar *record); + my_bool (*compare_record)(MARIA_HA *, const uchar *); /* calculate checksum for a row */ - ha_checksum(*calc_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_checksum)(MARIA_HA *, const uchar *); /* Calculate checksum for a row during write. May be 0 if we calculate the checksum in write_record_init() */ - ha_checksum(*calc_write_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_write_checksum)(MARIA_HA *, const uchar *); /* calculate checksum for a row during check table */ - ha_checksum(*calc_check_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_check_checksum)(MARIA_HA *, const uchar *); /* Compare a row in memory with a row on disk */ - my_bool (*compare_unique)(struct st_maria_info *, MARIA_UNIQUEDEF *, + my_bool (*compare_unique)(MARIA_HA *, MARIA_UNIQUEDEF *, const uchar *record, MARIA_RECORD_POS pos); /* Mapings to read/write the data file */ size_t (*file_read)(MARIA_HA *, uchar *, size_t, my_off_t, myf); @@ -293,6 +302,7 @@ typedef struct st_maria_share ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ uint unique_name_length; + uint keypage_header; uint32 ftparsers; /* Number of distinct ftparsers + 1 */ PAGECACHE_FILE kfile; /* Shared keyfile */ @@ -396,7 +406,7 @@ typedef struct st_maria_block_scan } MARIA_BLOCK_SCAN; -struct st_maria_info +struct st_maria_handler { MARIA_SHARE *s; /* Shared between open:s */ struct st_transaction *trn; /* Pointer to active transaction */ @@ -424,7 +434,7 @@ struct st_maria_info uchar *update_field_data; /* Used by update in rows-in-block */ uint int_nod_flag; /* -""- */ uint32 int_keytree_version; /* -""- */ - int (*read_record) (struct st_maria_info *, uchar*, MARIA_RECORD_POS); + int (*read_record)(MARIA_HA *, uchar*, MARIA_RECORD_POS); invalidator_by_filename invalidator; /* query cache invalidator */ ulong this_unique; /* uniq filenumber or thread */ ulong last_unique; /* last unique number */ @@ -513,10 +523,32 @@ struct st_maria_info #define READING_NEXT 1 #define READING_HEADER 2 -#define maria_data_on_page(x) ((uint) mi_uint2korr(x) & 32767) -#define maria_putint(x,y,nod) { uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y);\ - mi_int2store(x,boh); } -#define _ma_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0) +/* Number of bytes on key pages to indicate used size */ +#define KEYPAGE_USED_SIZE 2 +#define KEYPAGE_KEYID_SIZE 1 +#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) + +#define _ma_get_page_used(info,x) \ + (((uint) mi_uint2korr(x + (info)->s->keypage_header - KEYPAGE_USED_SIZE)) & \ + 32767) +#define _ma_store_page_used(info,x,y,nod) \ +{ uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y); \ + mi_int2store(x + (info)->s->keypage_header - KEYPAGE_USED_SIZE, boh); } +#define _ma_test_if_nod(info,x) \ + (x[(info)->s->keypage_header-KEYPAGE_USED_SIZE] & 128 ? \ + (info)->s->base.key_reflength : 0) +#define _ma_get_used_and_nod(info,buff,length,nod) \ +{ \ + nod= 0; \ + length= mi_uint2korr((buff) + (info)->s->keypage_header - \ + KEYPAGE_USED_SIZE); \ + if (length & 32768) {length&= 32767; nod= (info)->s->base.key_reflength; } \ +} +#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 maria_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \ DBUG_PRINT("error", ("Marked table crashed")); \ }while(0) @@ -559,7 +591,7 @@ struct st_maria_info { length=mi_uint2korr((key)+1)+3; } \ } -#define maria_max_key_length() ((maria_block_size - MARIA_INDEX_MIN_OVERHEAD_SIZE)/2) +#define maria_max_key_length() ((maria_block_size - MAX_KEYPAGE_HEADER_SIZE)/2 - MARIA_INDEX_OVERHEAD_SIZE) #define get_pack_length(length) ((length) >= 255 ? 3 : 1) #define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */ @@ -610,8 +642,9 @@ extern pthread_mutex_t THR_LOCK_maria; /* Some extern variables */ extern LIST *maria_open_list; -extern uchar NEAR maria_file_magic[], NEAR maria_pack_file_magic[]; -extern uint NEAR maria_read_vec[], NEAR maria_readnext_vec[]; +extern uchar maria_file_magic[], maria_pack_file_magic[]; +extern uchar maria_uuid[MY_UUID_SIZE]; +extern uint maria_read_vec[], maria_readnext_vec[]; extern uint maria_quick_table_bits; extern const char *maria_data_root; extern uchar maria_zero_string[]; @@ -671,7 +704,8 @@ extern int _ma_insert(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, extern int _ma_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, uchar *buff, uchar *key_buff, my_bool insert_last); -extern uchar *_ma_find_half_pos(uint nod_flag, MARIA_KEYDEF *keyinfo, +extern uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag, + MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uint *return_key_length, uchar ** after_key); @@ -714,7 +748,7 @@ extern int _ma_decrement_open_count(MARIA_HA *info); extern int _ma_check_index(MARIA_HA *info, int inx); extern int _ma_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, my_off_t pos); -extern int _ma_bin_search(struct st_maria_info *info, MARIA_KEYDEF *keyinfo, +extern int _ma_bin_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff, my_bool *was_last_key); @@ -877,14 +911,16 @@ uint _ma_state_info_write(MARIA_SHARE *share, uint pWrite); uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite); uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state); uint _ma_base_info_write(File file, MARIA_BASE_INFO *base); -int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg); +my_bool _ma_keyseg_write(File file, const HA_KEYSEG *keyseg); uchar *_ma_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg); -uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef); +my_bool _ma_keydef_write(File file, MARIA_KEYDEF *keydef); uchar *_ma_keydef_read(uchar *ptr, MARIA_KEYDEF *keydef); -uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef); +my_bool _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef); uchar *_ma_uniquedef_read(uchar *ptr, MARIA_UNIQUEDEF *keydef); -uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef); +my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef); uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef); +my_bool _ma_column_nr_write(File file, uint16 *offsets, uint columns); +uchar *_ma_column_nr_read(uchar *ptr, uint16 *offsets, uint columns); ulong _ma_calc_total_blob_length(MARIA_HA *info, const uchar *record); ha_checksum _ma_checksum(MARIA_HA *info, const uchar *buf); ha_checksum _ma_static_checksum(MARIA_HA *info, const uchar *buf); @@ -943,7 +979,7 @@ int _ma_flush_table_files_after_repair(HA_CHECK *param, MARIA_HA *info); int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param); int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, - ulong); + size_t); int _ma_sync_table_files(const MARIA_HA *info); int _ma_initialize_data_file(MARIA_SHARE *share, File dfile); int _ma_update_create_rename_lsn(MARIA_SHARE *share, diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index 88df230b5d4..b7b8a042435 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -860,7 +860,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) ha_rows record_count; HUFF_COUNTS *count,*end_count; TREE_ELEMENT *element; - ha_checksum(*calc_checksum) (struct st_maria_info *, const uchar *); + ha_checksum(*calc_checksum)(MARIA_HA *, const uchar *); DBUG_ENTER("get_statistic"); reclength= mrg->file[0]->s->base.reclength; @@ -873,8 +873,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) /* Check how to calculate checksum */ if (mrg->file[0]->s->data_file_type == STATIC_RECORD) calc_checksum= _ma_static_checksum; - else - calc_checksum= _ma_checksum; + else + calc_checksum= _ma_checksum; mrg_reset(mrg); while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE) |