From 496741d5761f14dba39c7cfd01c31bcc0fe810b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 Oct 2007 21:09:50 +0300 Subject: Moved randomize and my_rnd under mysys Added my_uuid Added pre-support for PAGE_CHECKSUM Added syntax for CREATE ... PAGE_CHECKSUM=# TABLE_CHECKSUM=# Reserved place for page checksums on index, bitmap and block pages Added index number to header of index pages Added linked list for free directory entries (speeds up inserts with BLOCK format) Calculate checksums in original column order (fixes bug with checksum on rows with BLOCK format) Cleaned up all index handling to use 'info->s->keypage_header' (variable size) as the header for index pages (before this was '2') Added 0xffffffff to end of index and block data bases and 0xfffffffe at end of bitmap pages when page checksums are not enabled Added _ma_get_page_used() and _ma_get_used_and_node() to simplify index page header handling rec_per_key_part is now in double precision Reserved place in index file for my_guid and nulls_per_key_part Give error HA_ERR_NEW_FILE if trying to open a Maria file with new, not yet supported extensions Lots of renames to increase readability: randomize() -> my_rnd_init() st_maria_info -> st_maria_handler st_maria_info -> MARIA_HA st_maria_isaminfo -> st_maria_info rand_struct -> my_rand_struct rec_per_key_rows -> records_at_analyze client/mysqladmin.cc: rand_struct -> my_rrnd_struct include/maria.h: st_maria_info -> MARIA_HA st_maria_isaminfo -> st_maria_info Changed analyze statistics to be of double precission Changed offset to field to be 32bits instead of 64 (safe as a record without blobs can't be that big) include/my_base.h: Added HA_OPTION_PAGE_CHECKSUM & HA_CREATE_PAGE_CHECKSUM Fixed comments Added HA_ERR_NEW_FILE include/my_sys.h: Added prototypes and structures for my_uuid() and my_rnd() include/myisamchk.h: Changed some buffers to size_t Added possibility to have key statistics with double precission include/mysql_com.h: Move rand functions to mysys libmysql/Makefile.shared: Added my_rnd mysql-test/r/maria.result: Updated results mysql-test/t/maria.test: More tests for checksum mysys/Makefile.am: Added my_rnd.c and my_uuid.c server-tools/instance-manager/listener.cc: Fixed include order (my_global.h should always be first) server-tools/instance-manager/mysql_connection.cc: Fixed include order (my_global.h should always be first) Use my_rnd_init() server-tools/instance-manager/mysql_connection.h: rand_struct -> my_rand_struct sql/handler.h: Added flag for page checksums sql/item_func.cc: Use new my_rnd() interface sql/item_func.h: Use new my_rnd() interface sql/item_strfunc.cc: Use new my_rnd() interface sql/lex.h: Added PAGE_CHECKSUM and TABLE_CHECKSUM sql/mysql_priv.h: Use new my_rnd() interface sql/mysqld.cc: Use new my_rnd() interface sql/password.c: Move my_rnd() to mysys Use new my_rnd() interface sql/sql_class.cc: Use new my_rnd() interface sql/sql_class.h: Use new my_rnd() interface sql/sql_crypt.cc: Use new my_rnd() interface sql/sql_crypt.h: Use new my_rnd() interface sql/sql_show.cc: Simpler handling of ha_choice_values Added PAGE_CHECKSUM sql/sql_table.cc: Enable correct checksum handling (for now) if not running in compatible mode sql/sql_yacc.yy: Added table option PAGE_CHECKSUM Added future compatible table option TABLE_CHECKSUM (alias for CHECKSUM) Added 'choice' target to simplify code sql/table.cc: Store flag for PAGE_CHECKSUM sql/table.h: Added support for PAGE_CHECKSUM storage/maria/ha_maria.cc: Remove protection for incompatbile frm and MAI (Slow, not needed test) Rec_per_key is now in double Remember row type for table Give warning if one Maria uses another row type than requested Removed some old ASK_MONTY entries (added comments instead) Added handling of PAGE_CHECKSUM flags storage/maria/ma_bitmap.c: Added page checksums to bitmap pages Added special bitmap marker for bitmap pages (Used to find bugs when running without page checksums) storage/maria/ma_blockrec.c: Added a free-link list over directory entries. This makes insert of small rows faster as we don't have to scan the whole directory to find a not used entry. Moved SANITY_CHECKS to maria_def.h Simplify code by introducing dir_entry_pos() Added support for PAGE_CHECKSUM storage/maria/ma_blockrec.h: Added DIR_FREE_SIZE (linked list of free directory entries) Added PAGE_CHECKSUM Added 'dir_entry_pos()' storage/maria/ma_check.c: Check that index pages has correct index number Calculate rec_per_key with double precission Simplify code by using '_ma_get_used_and_node()' Check free directory list Remove wrong end \n from messages maria_data_on_page() -> _ma_get_page_used() maria_putint() -> _ma_store_page_used() rec_per_key_rows -> records_at_analyze storage/maria/ma_checksum.c: Calculate checksum in original column order storage/maria/ma_create.c: Store original column order in index file Reserve place for nulls_per_key_part (future) Added support for PAGE_CHECKSUM storage/maria/ma_dbug.c: Fixed wrong debug output of key of type 'ulong' storage/maria/ma_delete.c: maria_data_on_page() -> _ma_get_used_and_node() maria_data_on_page() -> _ma_get_page_used() maria_putint() -> _ma_store_page_used() Added page header (index key number) to all index pages Reserved page for checksum on index pages Use keypage_header storage/maria/ma_ft_update.c: maria_putint() -> _ma_store_page_used() Store key number at start of page storage/maria/ma_loghandler.h: st_maria_info -> MARIA_HA storage/maria/ma_open.c: rec_per_key is now in double precission Added 'nulls_per_key_part' Added 'extra_options' (flags for future) Added support for PAGE_CHECKSUM Give error HA_ERR_NEW_FILE when using unsupported maria extensions Added comments Add maria_uuid to index file Added functions to store and read column_nr map. Changed some functions to return my_bool instead of uint storage/maria/ma_page.c: Added checks that pages has correct key nr Store 0xffffffff in checksum position if page checksums are not enabled Moved key-page-delete link to take into account keypage header storage/maria/ma_preload.c: Remove old MyISAM dependent code When scanning pages, only add pages to page cache for the requested index storage/maria/ma_range.c: maria_data_on_page() -> _ma_get_used_and_node() Use keypage_header storage/maria/ma_rt_index.c: Fixed indentation storage/maria/ma_rt_index.h: Added support for dynamic index page header Reserved place for PAGE_CHECKSUM storage/maria/ma_rt_key.c: Fixed indentation maria_data_on_page() -> _ma_get_page_used() maria_putint() -> maria_store_page_used() storage/maria/ma_rt_mbr.c: Fixed indentation storage/maria/ma_rt_split.c: Fixed indentation maria_data_on_page () -> _ma_get_page_used() storage/maria/ma_rt_test.c: Fixed indentation storage/maria/ma_search.c: Remove support of using -1 as 'last used index' to _ma_check_index() maria_data_on_page() -> _ma_get_page_used() maria_data_on_page() -> _ma_get_used_and_node() Use keypage_header storage/maria/ma_sort.c: Changed some buffers to size_t Changed rec_per_key_part to double storage/maria/ma_static.c: Removed NEAR Added maria_uuid storage/maria/ma_test2.c: Moevd testflag == 2 to correct place Remove test of reading with index number -1 (not supported anymore) storage/maria/ma_test_recovery.expected: Updated results storage/maria/ma_test_recovery: Changed tmp table names so that one can run maria_chk on them storage/maria/ma_write.c: Fixed indentation Use keypage_header Store index number on index pages maria_putint() -> _ma_store_page_used() maria_data_on_page() -> ma_get_used_and_node() maria_data_on_page() -> _ma_get_page_used() Added PAGE_CHECKSUM Added Maria handler to some functions Removed some not needed casts storage/maria/maria_chk.c: Added error handling for HA_ERR_NEW_FILE Added information about page checksums rec_per_key_part changed to double maria_data_on_page() -> _ma_get_page_used() Use keypage_header storage/maria/maria_def.h: Added IDENTICAL_PAGES_AFTER_RECOVERY and SANITY_CHECKS Changed rec_per_key_part to double Added nulls_per_key_part rec_per_key_rows -> records_at_analyze st_maria_info -> MARIA_HA Reserve place for new statistics variables, uuid, checksums per page etc. Removed NEAR tags Changed some prototypes to use my_bool and size_t storage/maria/maria_pack.c: st_maria_info -> MARIA_HA Fixed indentation storage/myisam/mi_dbug.c: Fix wrong debug output for ULONG mysys/my_rnd.c: New BitKeeper file ``mysys/my_rnd.c'' mysys/my_uuid.c: New BitKeeper file ``mysys/my_uuid.c'' --- storage/maria/ha_maria.cc | 90 +++------ storage/maria/ma_bitmap.c | 49 +++-- storage/maria/ma_blockrec.c | 286 ++++++++++++++++++-------- storage/maria/ma_blockrec.h | 26 ++- storage/maria/ma_check.c | 178 ++++++++++++----- storage/maria/ma_checksum.c | 25 ++- storage/maria/ma_create.c | 52 +++-- storage/maria/ma_dbug.c | 2 +- storage/maria/ma_delete.c | 166 +++++++++------- storage/maria/ma_ft_update.c | 7 +- storage/maria/ma_loghandler.h | 12 +- storage/maria/ma_open.c | 99 ++++++--- storage/maria/ma_page.c | 39 ++-- storage/maria/ma_preload.c | 66 ++---- storage/maria/ma_range.c | 12 +- storage/maria/ma_rt_index.c | 343 ++++++++++++++++---------------- storage/maria/ma_rt_index.h | 6 +- storage/maria/ma_rt_key.c | 21 +- storage/maria/ma_rt_mbr.c | 120 +++++------ storage/maria/ma_rt_split.c | 167 ++++++++-------- storage/maria/ma_rt_test.c | 6 +- storage/maria/ma_search.c | 129 +++++++----- storage/maria/ma_sort.c | 25 +-- storage/maria/ma_static.c | 10 +- storage/maria/ma_test2.c | 13 +- storage/maria/ma_test_recovery | 12 +- storage/maria/ma_test_recovery.expected | 52 ++--- storage/maria/ma_write.c | 232 ++++++++++++--------- storage/maria/maria_chk.c | 17 +- storage/maria/maria_def.h | 116 +++++++---- storage/maria/maria_pack.c | 6 +- 31 files changed, 1396 insertions(+), 988 deletions(-) (limited to 'storage/maria') diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 678b88063db..6cecb95cac9 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -372,8 +372,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, @@ -725,9 +726,6 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command, 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 @@ -753,39 +751,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)); @@ -817,16 +782,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; } @@ -1918,9 +1873,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); @@ -2112,6 +2070,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(); } @@ -2161,7 +2123,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)); @@ -2175,18 +2146,13 @@ 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 */ -#endif create_info.transactional= (row_type == BLOCK_RECORD && ha_create_info->transactional != HA_CHOICE_NO); @@ -2198,6 +2164,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 684f5e16ffa..5bda329ceab 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 @@ -452,10 +455,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 ; @@ -541,14 +540,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); @@ -1425,6 +1440,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, @@ -2065,9 +2081,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 3ec18d229c2..1e2cda8e8e1 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 @@ -599,17 +605,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. @@ -646,7 +677,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 */ } } @@ -824,60 +861,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; @@ -1082,8 +1135,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) @@ -1172,7 +1225,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 @@ -1202,22 +1255,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; } @@ -1269,7 +1331,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); @@ -1302,8 +1364,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) @@ -1407,7 +1468,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; @@ -1509,6 +1570,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, @@ -2330,7 +2394,7 @@ static my_bool write_block_record(MARIA_HA *info, (uint) (log_array_pos - log_array), log_array, log_data); if (log_array != tmp_log_array) - my_free((uchar*) log_array, MYF(0)); + my_free(log_array, MYF(0)); if (error) goto disk_err; } @@ -2510,6 +2574,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, @@ -2710,8 +2775,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) { @@ -2820,9 +2884,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 @@ -2838,33 +2902,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; @@ -3118,7 +3223,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; @@ -3135,8 +3240,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 @@ -3258,7 +3362,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); } @@ -4079,8 +4183,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"); @@ -4634,7 +4738,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; @@ -4643,7 +4747,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, @@ -4664,25 +4767,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) @@ -4698,7 +4803,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) @@ -4916,6 +5021,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 30dffe1c0c0..f9adc6a830e 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 fa1c812daf7..79b267b6bd5 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -264,7 +264,8 @@ static int check_k_link(HA_CHECK *param, register MARIA_HA *info, { uint block_size= info->s->block_size; ha_rows records; - char llbuff[21], llbuff2[21], *buff; + char llbuff[21], llbuff2[21]; + uchar *buff; DBUG_ENTER("check_k_link"); records= (ha_rows) (info->state->key_file_length / block_size); @@ -313,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; } @@ -418,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]; @@ -444,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++) { @@ -454,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; } @@ -627,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 */ @@ -742,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, @@ -755,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) @@ -771,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", @@ -1388,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. @@ -1399,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; @@ -1417,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, @@ -1454,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))); } @@ -1665,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; @@ -1831,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) @@ -2424,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, @@ -2620,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) @@ -2666,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))) @@ -2775,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; @@ -2912,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++) { @@ -2924,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; } @@ -2990,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; @@ -3004,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) @@ -3200,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. */ @@ -3377,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; @@ -3392,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; @@ -4656,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) @@ -4672,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) { @@ -4681,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; @@ -4698,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)) @@ -4792,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; @@ -5079,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; istate.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; } } @@ -5246,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]; @@ -5271,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 ba1d9a13b42..db31d62fb8e 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); @@ -900,6 +918,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)); @@ -911,9 +930,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 56da6fd3ed3..b7c036c3f30 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -176,8 +176,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) @@ -187,11 +187,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)) @@ -209,13 +212,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, @@ -228,7 +232,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, @@ -238,7 +242,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) { @@ -338,14 +342,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)) @@ -375,7 +379,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; @@ -384,7 +389,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)); @@ -407,7 +412,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; @@ -415,14 +420,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+ @@ -432,18 +439,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 @@ -464,20 +475,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, @@ -491,11 +501,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 */ @@ -521,22 +532,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")); @@ -557,14 +568,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 */ @@ -579,7 +591,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 */ @@ -588,9 +600,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)) @@ -601,21 +613,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), @@ -626,21 +639,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; @@ -659,12 +674,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)) @@ -688,7 +704,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, @@ -696,22 +712,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); @@ -730,11 +746,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); @@ -745,14 +763,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 b13984d88ef..7e8c87caaa4 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; /* Length of CRC at end of pages */ #define CRC_LENGTH 4 @@ -228,7 +228,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); @@ -263,7 +263,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 @@ -298,11 +298,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, struct st_translog_parts *parts); 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, struct st_translog_parts *parts); diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 6852d5b4a6d..4a15d6e338a 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) char *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(name_buff, strlen(name_buff), maria_pagecache); @@ -314,10 +316,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) && @@ -441,7 +444,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, @@ -449,6 +455,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, @@ -465,7 +472,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); @@ -595,6 +604,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) { /* @@ -666,6 +679,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)) @@ -693,7 +708,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; @@ -771,7 +786,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)); @@ -914,7 +929,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; @@ -1095,10 +1110,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; } } @@ -1135,7 +1153,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; @@ -1154,10 +1174,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; } @@ -1199,6 +1221,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; @@ -1215,7 +1239,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; @@ -1241,6 +1265,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; @@ -1257,7 +1282,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; @@ -1284,7 +1309,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; @@ -1320,7 +1345,7 @@ char *_ma_keydef_read(char *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; @@ -1370,7 +1395,7 @@ char *_ma_keyseg_read(char *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; @@ -1394,12 +1419,12 @@ char *_ma_uniquedef_read(char *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; @@ -1407,12 +1432,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; } char *_ma_columndef_read(char *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; @@ -1420,9 +1446,36 @@ char *_ma_columndef_read(char *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 f749414474f..484d9230725 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; - char buff[8]; + char 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= 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); } info->s->state.changed|= STATE_NOT_SORTED_PAGES; DBUG_PRINT("exit",("Pos: %ld",(long) pos)); 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 (; curcoords, 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 (; curn_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 (; cursquare = 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 8cb3e56e646..a41346f2460 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 2851a3a09dd..68564b44312 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -93,7 +93,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 @@ -101,10 +101,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; @@ -314,8 +315,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); @@ -356,19 +358,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"); @@ -404,8 +405,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; @@ -493,7 +494,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 935be09850c..72d2c8e9777 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(char *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)) { @@ -872,7 +873,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 926943b11b3..e776ea9d73c 100644 --- a/storage/maria/ma_test_recovery.expected +++ b/storage/maria/ma_test_recovery.expected @@ -39,36 +39,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) @@ -218,7 +218,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 @@ -231,7 +231,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 @@ -244,7 +244,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) @@ -393,7 +393,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 @@ -406,7 +406,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 @@ -419,7 +419,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) @@ -568,7 +568,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 @@ -581,7 +581,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 @@ -594,7 +594,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) @@ -743,7 +743,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 @@ -756,7 +756,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 @@ -769,7 +769,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) @@ -918,7 +918,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 @@ -931,7 +931,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 @@ -944,7 +944,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) @@ -1093,7 +1093,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 @@ -1106,7 +1106,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 @@ -1119,5 +1119,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 b034d71ef9d..4a0854dd785 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 */ @@ -280,6 +280,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 */ @@ -297,10 +298,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 */ @@ -369,12 +367,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); @@ -382,12 +386,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, @@ -412,7 +418,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; @@ -445,7 +451,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); @@ -528,17 +535,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)); } @@ -572,11 +579,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)) { @@ -585,7 +592,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); @@ -600,25 +607,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, (char*) 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 */ } @@ -648,31 +658,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 */ @@ -691,8 +703,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)); @@ -700,25 +718,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))) @@ -754,7 +773,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) { @@ -763,8 +783,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 | @@ -821,15 +841,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, @@ -849,42 +870,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) || @@ -896,7 +921,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- @@ -905,28 +936,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; @@ -973,7 +1013,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 e6ac0dcfc50..dc483ff547f 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 bac83db4f51..42cf3f48cf5 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -25,13 +25,16 @@ #else #include #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 */ uint (*file_read)(MARIA_HA *, uchar *, uint, 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); char *_ma_keyseg_read(char *ptr, HA_KEYSEG *keyseg); -uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef); +my_bool _ma_keydef_write(File file, MARIA_KEYDEF *keydef); char *_ma_keydef_read(char *ptr, MARIA_KEYDEF *keydef); -uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef); +my_bool _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *keydef); char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *keydef); -uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef); +my_bool _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef); char *_ma_columndef_read(char *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); @@ -940,7 +976,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 83f88fcb0dc..79c85b8be29 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) -- cgit v1.2.1