diff options
author | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-10-09 21:09:50 +0300 |
---|---|---|
committer | unknown <monty@mysql.com/narttu.mysql.fi> | 2007-10-09 21:09:50 +0300 |
commit | 496741d5761f14dba39c7cfd01c31bcc0fe810b1 (patch) | |
tree | 4d91944237ccddf915e51bf77eac8aad2cf2353f | |
parent | d097806323618aef56bcfb1968b036be2aa8491a (diff) | |
download | mariadb-git-496741d5761f14dba39c7cfd01c31bcc0fe810b1.tar.gz |
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''
64 files changed, 1870 insertions, 1135 deletions
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index f6ff44c7d56..5948f4de828 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -515,7 +515,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) If this behaviour is ever changed, Docs should be notified. */ - struct rand_struct rand_st; + struct my_rnd_struct rand_st; for (; argc > 0 ; argv++,argc--) { @@ -827,7 +827,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) time_t start_time; /* Do initialization the same way as we do in mysqld */ start_time=time((time_t*) 0); - randominit(&rand_st,(ulong) start_time,(ulong) start_time/2); + my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2); if (argc < 2) { diff --git a/include/maria.h b/include/maria.h index 1d7778f7c3d..49259915d16 100644 --- a/include/maria.h +++ b/include/maria.h @@ -110,7 +110,7 @@ extern "C" { typedef ulonglong MARIA_RECORD_POS; -typedef struct st_maria_isaminfo /* Struct from h_info */ +typedef struct st_maria_info { ha_rows records; /* Records in database */ ha_rows deleted; /* Deleted records in database */ @@ -126,7 +126,7 @@ typedef struct st_maria_isaminfo /* Struct from h_info */ time_t check_time; time_t update_time; ulong record_offset; - ulong *rec_per_key; /* for sql optimizing */ + double *rec_per_key; /* for sql optimizing */ ulong reclength; /* Recordlength */ ulong mean_reclength; /* Mean recordlength (if packed) */ char *data_file_name, *index_file_name; @@ -156,9 +156,9 @@ typedef struct st_maria_create_info my_bool with_auto_increment, transactional; } MARIA_CREATE_INFO; -struct st_maria_info; /* For referense */ struct st_maria_share; -typedef struct st_maria_info MARIA_HA; +struct st_maria_handler; /* For referense */ +typedef struct st_maria_handler MARIA_HA; struct st_maria_s_param; typedef struct st_maria_keydef /* Key definition with open & info */ @@ -178,7 +178,7 @@ typedef struct st_maria_keydef /* Key definition with open & info */ HA_KEYSEG *seg, *end; struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ - int (*bin_search)(struct st_maria_info *info, + int (*bin_search)(MARIA_HA *info, struct st_maria_keydef *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff, my_bool *was_last_key); @@ -189,8 +189,8 @@ typedef struct st_maria_keydef /* Key definition with open & info */ const uchar *key, struct st_maria_s_param *s_temp); void (*store_key)(struct st_maria_keydef *keyinfo, uchar *key_pos, struct st_maria_s_param *s_temp); - int (*ck_insert)(struct st_maria_info *inf, uint k_nr, uchar *k, uint klen); - int (*ck_delete)(struct st_maria_info *inf, uint k_nr, uchar *k, uint klen); + int (*ck_insert)(MARIA_HA *inf, uint k_nr, uchar *k, uint klen); + int (*ck_delete)(MARIA_HA *inf, uint k_nr, uchar *k, uint klen); } MARIA_KEYDEF; @@ -222,9 +222,10 @@ struct st_maria_bit_buff; typedef struct st_maria_columndef /* column information */ { - uint64 offset; /* Offset to position in row */ enum en_fieldtype type; + uint32 offset; /* Offset to position in row */ uint16 length; /* length of field */ + uint16 column_nr; /* Intern variable (size of total storage area for the row) */ uint16 fill_length; uint16 null_pos; /* Position for null marker */ @@ -257,34 +258,34 @@ extern PAGECACHE maria_pagecache_var, *maria_pagecache; extern int maria_init(void); extern void maria_end(void); -extern int maria_close(struct st_maria_info *file); -extern int maria_delete(struct st_maria_info *file, const uchar *buff); -extern struct st_maria_info *maria_open(const char *name, int mode, +extern int maria_close(MARIA_HA *file); +extern int maria_delete(MARIA_HA *file, const uchar *buff); +extern MARIA_HA *maria_open(const char *name, int mode, uint wait_if_locked); -extern struct st_maria_info *maria_clone(struct st_maria_share *share, int mode); +extern MARIA_HA *maria_clone(struct st_maria_share *share, int mode); extern int maria_panic(enum ha_panic_function function); -extern int maria_rfirst(struct st_maria_info *file, uchar *buf, int inx); -extern int maria_rkey(struct st_maria_info *file, uchar *buf, int inx, +extern int maria_rfirst(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rkey(MARIA_HA *file, uchar *buf, int inx, const uchar *key, key_part_map keypart_map, enum ha_rkey_function search_flag); -extern int maria_rlast(struct st_maria_info *file, uchar *buf, int inx); -extern int maria_rnext(struct st_maria_info *file, uchar *buf, int inx); -extern int maria_rnext_same(struct st_maria_info *info, uchar *buf); -extern int maria_rprev(struct st_maria_info *file, uchar *buf, int inx); -extern int maria_rrnd(struct st_maria_info *file, uchar *buf, +extern int maria_rlast(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rnext(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rnext_same(MARIA_HA *info, uchar *buf); +extern int maria_rprev(MARIA_HA *file, uchar *buf, int inx); +extern int maria_rrnd(MARIA_HA *file, uchar *buf, MARIA_RECORD_POS pos); -extern int maria_scan_init(struct st_maria_info *file); -extern int maria_scan(struct st_maria_info *file, uchar *buf); -extern void maria_scan_end(struct st_maria_info *file); -extern int maria_rsame(struct st_maria_info *file, uchar *record, int inx); -extern int maria_rsame_with_pos(struct st_maria_info *file, uchar *record, +extern int maria_scan_init(MARIA_HA *file); +extern int maria_scan(MARIA_HA *file, uchar *buf); +extern void maria_scan_end(MARIA_HA *file); +extern int maria_rsame(MARIA_HA *file, uchar *record, int inx); +extern int maria_rsame_with_pos(MARIA_HA *file, uchar *record, int inx, MARIA_RECORD_POS pos); -extern int maria_update(struct st_maria_info *file, const uchar *old, +extern int maria_update(MARIA_HA *file, const uchar *old, uchar *new_record); -extern int maria_write(struct st_maria_info *file, uchar *buff); -extern MARIA_RECORD_POS maria_position(struct st_maria_info *file); -extern int maria_status(struct st_maria_info *info, MARIA_INFO *x, uint flag); -extern int maria_lock_database(struct st_maria_info *file, int lock_type); +extern int maria_write(MARIA_HA *file, uchar *buff); +extern MARIA_RECORD_POS maria_position(MARIA_HA *file); +extern int maria_status(MARIA_HA *info, MARIA_INFO *x, uint flag); +extern int maria_lock_database(MARIA_HA *file, int lock_type); extern int maria_create(const char *name, enum data_file_type record_type, uint keys, MARIA_KEYDEF *keydef, uint columns, MARIA_COLUMNDEF *columndef, @@ -292,16 +293,16 @@ extern int maria_create(const char *name, enum data_file_type record_type, MARIA_CREATE_INFO *create_info, uint flags); extern int maria_delete_table(const char *name); extern int maria_rename(const char *from, const char *to); -extern int maria_extra(struct st_maria_info *file, +extern int maria_extra(MARIA_HA *file, enum ha_extra_function function, void *extra_arg); -extern int maria_reset(struct st_maria_info *file); -extern ha_rows maria_records_in_range(struct st_maria_info *info, int inx, +extern int maria_reset(MARIA_HA *file); +extern ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key, key_range *max_key); -extern int maria_is_changed(struct st_maria_info *info); -extern int maria_delete_all_rows(struct st_maria_info *info); +extern int maria_is_changed(MARIA_HA *info); +extern int maria_delete_all_rows(MARIA_HA *info); extern uint maria_get_pointer_length(ulonglong file_length, uint def); -extern int maria_commit(struct st_maria_info *info); -extern int maria_begin(struct st_maria_info *info); +extern int maria_commit(MARIA_HA *info); +extern int maria_begin(MARIA_HA *info); /* this is used to pass to mysql_mariachk_table */ @@ -402,7 +403,7 @@ int maria_change_to_newfile(const char *filename, const char *old_ext, const char *new_ext, myf myflags); void maria_lock_memory(HA_CHECK *param); int maria_update_state_info(HA_CHECK *param, MARIA_HA *info, uint update); -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); int maria_filecopy(HA_CHECK *param, File to, File from, my_off_t start, diff --git a/include/my_base.h b/include/my_base.h index 2ab1123ce76..f69d0dce977 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -293,6 +293,7 @@ enum ha_base_keytype { #define HA_OPTION_CREATE_FROM_ENGINE 256 #define HA_OPTION_RELIES_ON_SQL_LAYER 512 #define HA_OPTION_NULL_FIELDS 1024 +#define HA_OPTION_PAGE_CHECKSUM 2048 #define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ @@ -302,6 +303,7 @@ enum ha_base_keytype { #define HA_PACK_RECORD 2 /* Request packed record format */ #define HA_CREATE_TMP_TABLE 4 #define HA_CREATE_CHECKSUM 8 +#define HA_CREATE_PAGE_CHECKSUM 16 #define HA_CREATE_DELAY_KEY_WRITE 64 #define HA_CREATE_RELIES_ON_SQL_LAYER 128 @@ -348,12 +350,15 @@ enum ha_base_keytype { */ #define HA_STATUS_AUTO 64 - /* Errorcodes given by functions */ +/* + Errorcodes given by handler functions + + opt_sum_query() assumes these codes are > 1 + Do not add error numbers before HA_ERR_FIRST. + If necessary to add lower numbers, change HA_ERR_FIRST accordingly. +*/ +#define HA_ERR_FIRST 120 /* Copy of first error nr.*/ -/* opt_sum_query() assumes these codes are > 1 */ -/* Do not add error numbers before HA_ERR_FIRST. */ -/* If necessary to add lower numbers, change HA_ERR_FIRST accordingly. */ -#define HA_ERR_FIRST 120 /*Copy first error nr.*/ #define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */ #define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */ #define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */ @@ -374,7 +379,7 @@ enum ha_base_keytype { #define HA_WRONG_CREATE_OPTION 140 /* Wrong create option */ #define HA_ERR_FOUND_DUPP_UNIQUE 141 /* Dupplicate unique on write */ #define HA_ERR_UNKNOWN_CHARSET 142 /* Can't open charset */ -#define HA_ERR_WRONG_MRG_TABLE_DEF 143 /* conflicting MyISAM tables in MERGE */ +#define HA_ERR_WRONG_MRG_TABLE_DEF 143 /* conflicting tables in MERGE */ #define HA_ERR_CRASHED_ON_REPAIR 144 /* Last (automatic?) repair failed */ #define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */ #define HA_ERR_LOCK_WAIT_TIMEOUT 146 @@ -389,28 +394,33 @@ enum ha_base_keytype { #define HA_ERR_NO_SUCH_TABLE 155 /* The table does not exist in engine */ #define HA_ERR_TABLE_EXIST 156 /* The table existed in storage engine */ #define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */ -#define HA_ERR_NULL_IN_SPATIAL 158 /* NULLs are not supported in spatial index */ +/* NULLs are not supported in spatial index */ +#define HA_ERR_NULL_IN_SPATIAL 158 #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ #define HA_ERR_NO_PARTITION_FOUND 160 /* There's no partition in table for given value */ #define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ -#define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr. */ -#define HA_ERR_FOREIGN_DUPLICATE_KEY 163 /* Upholding foreign key constraints - would lead to a duplicate key - error in some other table. */ -#define HA_ERR_TABLE_NEEDS_UPGRADE 164 /* The table changed in storage engine */ -#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */ +#define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr */ +/* + Upholding foreign key constraints would lead to a duplicate key error + in some other table. +*/ +#define HA_ERR_FOREIGN_DUPLICATE_KEY 163 +/* The table changed in storage engine */ +#define HA_ERR_TABLE_NEEDS_UPGRADE 164 +#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */ #define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */ #define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */ #define HA_ERR_GENERIC 168 /* Generic error */ -#define HA_ERR_RECORD_IS_THE_SAME 169 /* row not actually updated : - new values same as the old values */ - -#define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this - statement */ -#define HA_ERR_LAST 170 /*Copy last error nr.*/ -/* Add error numbers before HA_ERR_LAST and change it accordingly. */ +/* row not actually updated: new values same as the old values */ +#define HA_ERR_RECORD_IS_THE_SAME 169 +/* It is not possible to log this statement */ +#define HA_ERR_LOGGING_IMPOSSIBLE 170 +#define HA_ERR_NEW_FILE 171 /* New file format */ +#define HA_ERR_LAST 171 /* Copy of last error nr */ + +/* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) /* Other constants */ diff --git a/include/my_sys.h b/include/my_sys.h index ca44f9ed39b..65a8c9fdeda 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -902,6 +902,18 @@ int my_getpagesize(void); int my_msync(int, void *, size_t, int); +#define MY_UUID_SIZE 16 +void my_uuid_init(ulong seed1, ulong seed2); +void my_uuid(uchar *guid); + +struct my_rnd_struct { + unsigned long seed1,seed2,max_value; + double max_value_dbl; +}; + +void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2); +double my_rnd(struct my_rnd_struct *rand_st); + /* character sets */ extern uint get_charset_number(const char *cs_name, uint cs_flags); extern uint get_collation_number(const char *name); diff --git a/include/myisamchk.h b/include/myisamchk.h index 78350b60bb0..30b986a835a 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -128,9 +128,10 @@ typedef struct st_handler_check_param ha_checksum key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_record_checksum; - ulong use_buffers, read_buffer_length, write_buffer_length; - ulong sort_buffer_length, sort_key_blocks; + size_t use_buffers, read_buffer_length, write_buffer_length; + size_t sort_buffer_length, sort_key_blocks; ulong rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; + double new_rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; uint out_flag, warning_printed, error_printed, verbose; uint opt_sort_key, total_files, max_level; uint testflag, key_cache_block_size, pagecache_block_size; diff --git a/include/mysql_com.h b/include/mysql_com.h index ae57e84a696..f05cf8e1068 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -365,11 +365,7 @@ void my_net_set_read_timeout(NET *net, uint timeout); struct sockaddr; int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen, unsigned int timeout); - -struct rand_struct { - unsigned long seed1,seed2,max_value; - double max_value_dbl; -}; +struct my_rnd_struct; #ifdef __cplusplus } @@ -417,10 +413,8 @@ extern "C" { implemented in sql/password.c */ -void randominit(struct rand_struct *, unsigned long seed1, - unsigned long seed2); -double my_rnd(struct rand_struct *); -void create_random_string(char *to, unsigned int length, struct rand_struct *rand_st); +void create_random_string(char *to, unsigned int length, + struct my_rnd_struct *rand_st); void hash_password(unsigned long *to, const char *password, unsigned int password_len); void make_scrambled_password_323(char *to, const char *password); diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 70b67cee28e..118f4d2dde5 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -68,7 +68,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ mf_iocache2.lo my_seek.lo my_sleep.lo \ my_pread.lo mf_cache.lo md5.lo sha1.lo \ my_getopt.lo my_gethostbyname.lo my_port.lo \ - my_rename.lo my_chsize.lo my_sync.lo + my_rename.lo my_chsize.lo my_sync.lo my_rnd.lo sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 8c1cb5f3a2f..8a029ef5d16 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -596,14 +596,14 @@ Error 1146 Table 'test.t3' doesn't exist checksum table t1, t2, t3; Table Checksum test.t1 3442722830 -test.t2 2948697075 +test.t2 3442722830 test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist checksum table t1, t2, t3 extended; Table Checksum -test.t1 2948697075 -test.t2 2948697075 +test.t1 3442722830 +test.t2 3442722830 test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist @@ -665,6 +665,25 @@ checksum table t2; Table Checksum test.t2 984116287 drop table t1, t2; +CREATE TABLE t1 ( +twenty int(4), +hundred int(4) NOT NULL +) CHECKSUM=1; +INSERT INTO t1 VALUES (11,91); +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +checksum table t1; +Table Checksum +test.t1 3235292310 +checksum table t1 extended; +Table Checksum +test.t1 3235292310 +alter table t1 engine=myisam; +checksum table t1; +Table Checksum +test.t1 3235292310 +drop table t1; show variables like 'maria_stats_method'; Variable_name Value maria_stats_method nulls_unequal @@ -1836,23 +1855,39 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC TRANSACTIONAL=0 drop table t1; create table t1 (a int) row_format=dynamic transactional=1; +Warnings: +Note 1475 Row format set to PAGE because of TRANSACTIONAL=1 option show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL -) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC TRANSACTIONAL=1 +) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=1 alter table t1 row_format=PAGE; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=1 +alter table t1 row_format=DYNAMIC; +Warnings: +Note 1475 Row format set to PAGE because of TRANSACTIONAL=1 option +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=1 alter table t1 transactional=0; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=0 +alter table t1 row_format=DYNAMIC; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC TRANSACTIONAL=0 drop table t1; create table t1 (a int) row_format=PAGE; show create table t1; @@ -1861,6 +1896,19 @@ t1 CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE drop table t1; +create table t1 (a int) row_format=PAGE TRANSACTIONAL=DEFAULT; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE +alter table t1 row_format=DYNAMIC; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +drop table t1; create table t1 (a int) row_format=page; insert delayed into t1 values(1); ERROR HY000: Table storage engine for 't1' doesn't have this option diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test index a98e2a8acf4..06e5a4d5b45 100644 --- a/mysql-test/t/maria.test +++ b/mysql-test/t/maria.test @@ -638,6 +638,22 @@ checksum table t1; checksum table t2; drop table t1, t2; +CREATE TABLE t1 ( + twenty int(4), + hundred int(4) NOT NULL +) CHECKSUM=1; +INSERT INTO t1 VALUES (11,91); +check table t1 extended; +checksum table t1; +checksum table t1 extended; +alter table t1 row_format=static; +checksum table t1; +alter table t1 row_format=packed; +checksum table t1; +alter table t1 engine=myisam; +checksum table t1; +drop table t1; + # # maria_stats_method variable. # @@ -1130,12 +1146,21 @@ create table t1 (a int) row_format=dynamic transactional=1; show create table t1; alter table t1 row_format=PAGE; show create table t1; +alter table t1 row_format=DYNAMIC; +show create table t1; alter table t1 transactional=0; show create table t1; +alter table t1 row_format=DYNAMIC; +show create table t1; drop table t1; create table t1 (a int) row_format=PAGE; show create table t1; drop table t1; +create table t1 (a int) row_format=PAGE TRANSACTIONAL=DEFAULT; +show create table t1; +alter table t1 row_format=DYNAMIC; +show create table t1; +drop table t1; # Verify that INSERT DELAYED is disabled only for transactional tables create table t1 (a int) row_format=page; diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 3d3047b3a9c..3c9cd9ac6dd 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -34,6 +34,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_vle.c my_atomic.c lf_hash.c \ lf_dynarray.c lf_alloc-pin.c \ my_fopen.c my_fstream.c my_getsystime.c \ + my_rnd.c my_uuid.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ my_symlink.c my_symlink2.c \ diff --git a/mysys/my_rnd.c b/mysys/my_rnd.c new file mode 100644 index 00000000000..e1aca222954 --- /dev/null +++ b/mysys/my_rnd.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2007 MySQL AB & Michael Widenius + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <mysys_priv.h> +#include <m_string.h> + +/* + Initialize random generator + + NOTES + MySQL's password checks depends on this, so don't do any changes + that changes the random numbers that are generated! +*/ + +void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2) +{ +#ifdef HAVE_purify + bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */ +#endif + rand_st->max_value= 0x3FFFFFFFL; + rand_st->max_value_dbl=(double) rand_st->max_value; + rand_st->seed1=seed1%rand_st->max_value ; + rand_st->seed2=seed2%rand_st->max_value; +} + + +/* + Generate random number. + + SYNOPSIS + my_rnd() + rand_st INOUT Structure used for number generation + + RETURN VALUE + generated pseudo random number +*/ + +double my_rnd(struct my_rnd_struct *rand_st) +{ + rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value; + rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value; + return (((double) rand_st->seed1)/rand_st->max_value_dbl); +} diff --git a/mysys/my_uuid.c b/mysys/my_uuid.c new file mode 100644 index 00000000000..3c3cd8836fc --- /dev/null +++ b/mysys/my_uuid.c @@ -0,0 +1,169 @@ +/* Copyright (C) 2007 MySQL AB, Sergei Golubchik & Michael Widenius + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + implements Universal Unique Identifiers (UUIDs), as in + DCE 1.1: Remote Procedure Call, + Open Group Technical Standard Document Number C706, October 1997, + (supersedes C309 DCE: Remote Procedure Call 8/1994, + which was basis for ISO/IEC 11578:1996 specification) + + A UUID has the following structure: + + Field NDR Data Type Octet # Note + time_low unsigned long 0-3 The low field of the + timestamp. + time_mid unsigned short 4-5 The middle field of + the timestamp. + time_hi_and_version unsigned short 6-7 The high field of the + timestamp multiplexed + with the version number. + clock_seq_hi_and_reserved unsigned small 8 The high field of the + clock sequence multi- + plexed with the variant. + clock_seq_low unsigned small 9 The low field of the + clock sequence. + node character 10-15 The spatially unique node + identifier. +*/ + +#include "mysys_priv.h" +#include <m_string.h> + +static my_bool my_uuid_inited= 0; +static struct my_rnd_struct uuid_rand; +static uint nanoseq; +static ulonglong uuid_time= 0; +static uchar uuid_suffix[2+6]; /* clock_seq and node */ + +#ifdef THREAD +pthread_mutex_t LOCK_uuid_generator; +#endif + +/* + Number of 100-nanosecond intervals between + 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 +*/ + +#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10) +#define UUID_VERSION 0x1000 +#define UUID_VARIANT 0x8000 + + +/* Helper function */ + +static void set_clock_seq() +{ + uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT; + int2store(uuid_suffix, clock_seq); +} + + +/** + Init structures needed for my_uuid + + @func my_uuid_init() + @param seed1 Seed for random generator + @param seed2 Seed for random generator + + @note + Seed1 & seed2 should NOT depend on clock. This is to be able to + generate a random mac address according to UUID specs. +*/ + +void my_uuid_init(ulong seed1, ulong seed2) +{ + uchar *mac= uuid_suffix+2; + ulonglong now; + + if (my_uuid_inited) + return; + my_uuid_inited= 1; + now= my_getsystime(); + nanoseq= 0; + + if (my_gethwaddr(mac)) + { + uint i; + /* + Generating random "hardware addr" + + Specs explicitly specify that node identifier should NOT + correlate with a clock_seq value, so we use a separate + randominit() here. + */ + /* purecov: begin inspected */ + my_rnd_init(&uuid_rand, (ulong) (seed2+ now/2), (seed1 + now)+random()); + for (i=0; i < sizeof(mac); i++) + mac[i]= (uchar)(my_rnd(&uuid_rand)*255); + /* purecov: end */ + } + my_rnd_init(&uuid_rand, (ulong) (seed1 + now), + (ulong) (now/2+ seed2 + getpid())); + set_clock_seq(); + pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); +} + + +/** + Create a global unique identifier (uuid) + + @func my_uuid() + @param to Store uuid here. Must be of size MY_uuid_SIZE (16) +*/ + +void my_uuid(uchar *to) +{ + ulonglong tv; + uint32 time_low; + uint16 time_mid, time_hi_and_version; + + DBUG_ASSERT(my_uuid_inited); + + pthread_mutex_lock(&LOCK_uuid_generator); + tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq; + if (unlikely(tv < uuid_time)) + set_clock_seq(); + else if (unlikely(tv == uuid_time)) + { + /* special protection for low-res system clocks */ + nanoseq++; + tv++; + } + else + { + if (nanoseq && likely(tv-nanoseq >= uuid_time)) + { + tv-=nanoseq; + nanoseq=0; + } + } + uuid_time=tv; + pthread_mutex_unlock(&LOCK_uuid_generator); + + time_low= (uint32) (tv & 0xFFFFFFFF); + time_mid= (uint16) ((tv >> 32) & 0xFFFF); + time_hi_and_version= (uint16) ((tv >> 48) | UUID_VERSION); + + /* + Note, that the standard does NOT specify byte ordering in + multi-byte fields. it's implementation defined (but must be + the same for all fields). + */ + int4store(to, time_low); + int2store(to+4, time_mid); + int2store(to+6, time_hi_and_version); + bmove(to+8, uuid_suffix, sizeof(uuid_suffix)); +} diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index e68ba2fe8ce..ce0f6fb5d2e 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -17,12 +17,12 @@ #pragma implementation #endif -#include "listener.h" - #include <my_global.h> #include <mysql.h> -#include <violite.h> +#include <my_sys.h> +#include "listener.h" +#include <violite.h> #include <sys/stat.h> #ifndef __WIN__ #include <sys/un.h> diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index bf08f963aa3..de611878bb4 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -17,13 +17,12 @@ #pragma implementation #endif -#include "mysql_connection.h" - -#include <m_string.h> -#include <m_string.h> #include <my_global.h> #include <mysql.h> #include <my_sys.h> +#include "mysql_connection.h" + +#include <m_string.h> #include <violite.h> #include "command.h" @@ -88,7 +87,7 @@ bool Mysql_connection::init() { ulong seed1= (ulong) &rand_st + rand(); ulong seed2= (ulong) rand() + (ulong) time(0); - randominit(&rand_st, seed1, seed2); + my_rnd_init(&rand_st, seed1, seed2); } /* Fill scramble - server's random message used for handshake */ diff --git a/server-tools/instance-manager/mysql_connection.h b/server-tools/instance-manager/mysql_connection.h index 56bbf76e146..933dd820372 100644 --- a/server-tools/instance-manager/mysql_connection.h +++ b/server-tools/instance-manager/mysql_connection.h @@ -17,7 +17,6 @@ #define INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H #include "thread_registry.h" -#include <mysql_com.h> #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #pragma interface @@ -55,7 +54,7 @@ private: Thread_registry *thread_registry; User_map *user_map; NET net; - struct rand_struct rand_st; + struct my_rnd_struct rand_st; char scramble[SCRAMBLE_LENGTH + 1]; uint status; ulong client_capabilities; diff --git a/sql/handler.h b/sql/handler.h index feb551670a3..c498dd6e7af 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -327,6 +327,7 @@ enum enum_binlog_command { #define HA_CREATE_USED_CONNECTION (1L << 18) #define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19) #define HA_CREATE_USED_TRANSACTIONAL (1L << 20) +#define HA_CREATE_USED_PAGE_CHECKSUM (1L << 21) typedef ulonglong my_xid; // this line is the same as in log_event.h #define MYSQL_XID_PREFIX "MySQLXid" @@ -786,6 +787,7 @@ typedef struct st_ha_create_information bool frm_only; /* 1 if no ha_create_table() */ bool varchar; /* 1 if table has a VARCHAR */ enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */ + enum ha_choice page_checksum; /* If we have page_checksums */ } HA_CREATE_INFO; diff --git a/sql/item_func.cc b/sql/item_func.cc index 5a41aa3e9da..557f01e2c65 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2132,7 +2132,7 @@ void Item_func_rand::seed_random(Item *arg) args[0] is a constant. */ uint32 tmp= (uint32) arg->val_int(); - randominit(rand, (uint32) (tmp*0x10001L+55555555L), + my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L), (uint32) (tmp*0x10000001L)); } @@ -2152,7 +2152,7 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref) No need to send a Rand log event if seed was given eg: RAND(seed), as it will be replicated in the query as such. */ - if (!rand && !(rand= (struct rand_struct*) + if (!rand && !(rand= (struct my_rnd_struct*) thd->stmt_arena->alloc(sizeof(*rand)))) return TRUE; diff --git a/sql/item_func.h b/sql/item_func.h index 347a4a1f084..f02b35d2e80 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -664,7 +664,7 @@ public: class Item_func_rand :public Item_real_func { - struct rand_struct *rand; + struct my_rnd_struct *rand; public: Item_func_rand(Item *a) :Item_real_func(a), rand(0) {} Item_func_rand() :Item_real_func() {} diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index a376504512f..ca43bd6011a 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3303,7 +3303,7 @@ err: which was basis for ISO/IEC 11578:1996 specification) */ -static struct rand_struct uuid_rand; +static struct my_rnd_struct uuid_rand; static uint nanoseq; static ulonglong uuid_time=0; static char clock_seq_and_node_str[]="-0000-000000000000"; @@ -3351,9 +3351,9 @@ String *Item_func_uuid::val_str(String *str) generating random "hardware addr" and because specs explicitly specify that it should NOT correlate with a clock_seq value (initialized random below), we use a separate - randominit() here + my_rnd_init() here */ - randominit(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id); + my_rnd_init(&uuid_rand, tmp + (ulong) thd, tmp + (ulong)global_query_id); for (i=0; i < (int)sizeof(mac); i++) mac[i]=(uchar)(my_rnd(&uuid_rand)*255); /* purecov: end */ @@ -3364,7 +3364,7 @@ String *Item_func_uuid::val_str(String *str) *--s=_dig_vec_lower[mac[i] & 15]; *--s=_dig_vec_lower[mac[i] >> 4]; } - randominit(&uuid_rand, tmp + (ulong) server_start_time, + my_rnd_init(&uuid_rand, tmp + (ulong) server_start_time, tmp + (ulong) thd->status_var.bytes_sent); set_clock_seq_str(); } diff --git a/sql/lex.h b/sql/lex.h index 5f24b06cf05..aab2182b097 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -381,6 +381,7 @@ static SYMBOL symbols[] = { { "PACK_KEYS", SYM(PACK_KEYS_SYM)}, { "PARSER", SYM(PARSER_SYM)}, { "PAGE", SYM(PAGE_SYM)}, + { "PAGE_CHECKSUM", SYM(PAGE_CHECKSUM_SYM)}, { "PARTIAL", SYM(PARTIAL)}, { "PARTITION", SYM(PARTITION_SYM)}, { "PARTITIONING", SYM(PARTITIONING_SYM)}, @@ -513,7 +514,8 @@ static SYMBOL symbols[] = { { "SUSPEND", SYM(SUSPEND_SYM)}, { "TABLE", SYM(TABLE_SYM)}, { "TABLES", SYM(TABLES)}, - { "TABLESPACE", SYM(TABLESPACE)}, + { "TABLESPACE", SYM(TABLESPACE)}, + { "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)}, { "TEMPORARY", SYM(TEMPORARY)}, { "TEMPTABLE", SYM(TEMPTABLE_SYM)}, { "TERMINATED", SYM(TERMINATED)}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 683a6553632..b52bdf90a69 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1810,7 +1810,7 @@ extern SHOW_VAR status_vars[]; extern struct system_variables global_system_variables; extern struct system_variables max_system_variables; extern struct system_status_var global_status_var; -extern struct rand_struct sql_rand; +extern struct my_rnd_struct sql_rand; extern const char *opt_date_time_formats[]; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2b47be2cddc..4b802c83eb6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -610,7 +610,7 @@ static char **defaults_argv; static char *opt_bin_logname; static my_socket unix_sock,ip_sock; -struct rand_struct sql_rand; // used by sql_class.cc:THD::THD() +struct my_rnd_struct sql_rand; // used by sql_class.cc:THD::THD() #ifndef EMBEDDED_LIBRARY struct passwd *user_info; @@ -3239,7 +3239,7 @@ static int init_server_components() query_cache_set_min_res_unit(query_cache_min_res_unit); query_cache_init(); query_cache_resize(query_cache_size); - randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); + my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); reset_floating_point_exceptions(); init_thr_lock(); #ifdef HAVE_REPLICATION diff --git a/sql/password.c b/sql/password.c index 1ff67888ea4..43430f37f96 100644 --- a/sql/password.c +++ b/sql/password.c @@ -69,41 +69,12 @@ /* New (MySQL 3.21+) random generation structure initialization SYNOPSIS - randominit() + my_rnd_init() rand_st OUT Structure to initialize seed1 IN First initialization parameter seed2 IN Second initialization parameter */ -void randominit(struct rand_struct *rand_st, ulong seed1, ulong seed2) -{ /* For mysql 3.21.# */ -#ifdef HAVE_purify - bzero((char*) rand_st,sizeof(*rand_st)); /* Avoid UMC varnings */ -#endif - rand_st->max_value= 0x3FFFFFFFL; - rand_st->max_value_dbl=(double) rand_st->max_value; - rand_st->seed1=seed1%rand_st->max_value ; - rand_st->seed2=seed2%rand_st->max_value; -} - - -/* - Generate random number. - SYNOPSIS - my_rnd() - rand_st INOUT Structure used for number generation - RETURN VALUE - generated pseudo random number -*/ - -double my_rnd(struct rand_struct *rand_st) -{ - rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value; - rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value; - return (((double) rand_st->seed1)/rand_st->max_value_dbl); -} - - /* Generate binary hash from raw text string Used for Pre-4.1 password handling @@ -164,7 +135,7 @@ void make_scrambled_password_323(char *to, const char *password) void scramble_323(char *to, const char *message, const char *password) { - struct rand_struct rand_st; + struct my_rnd_struct rand_st; ulong hash_pass[2], hash_message[2]; if (password && password[0]) @@ -173,7 +144,7 @@ void scramble_323(char *to, const char *message, const char *password) const char *message_end= message + SCRAMBLE_LENGTH_323; hash_password(hash_pass,password, (uint) strlen(password)); hash_password(hash_message, message, SCRAMBLE_LENGTH_323); - randominit(&rand_st,hash_pass[0] ^ hash_message[0], + my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1]); for (; message < message_end; message++) *to++= (char) (floor(my_rnd(&rand_st)*31)+64); @@ -206,13 +177,13 @@ my_bool check_scramble_323(const char *scrambled, const char *message, ulong *hash_pass) { - struct rand_struct rand_st; + struct my_rnd_struct rand_st; ulong hash_message[2]; char buff[16],*to,extra; /* Big enough for check */ const char *pos; hash_password(hash_message, message, SCRAMBLE_LENGTH_323); - randominit(&rand_st,hash_pass[0] ^ hash_message[0], + my_rnd_init(&rand_st,hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1]); to=buff; DBUG_ASSERT(sizeof(buff) > SCRAMBLE_LENGTH_323); @@ -293,7 +264,8 @@ void make_password_from_salt_323(char *to, const ulong *salt) rand_st INOUT structure used for number generation */ -void create_random_string(char *to, uint length, struct rand_struct *rand_st) +void create_random_string(char *to, uint length, + struct my_rnd_struct *rand_st) { char *end= to + length; /* Use pointer arithmetics as it is faster way to do so. */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 53651f92001..d83b3f51ce0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -446,7 +446,7 @@ THD::THD() tablespace_op=FALSE; tmp= sql_rnd_with_mutex(); - randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id); + my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id); substitute_null_with_insert_id = FALSE; thr_lock_info_init(&lock_info); /* safety: will be reset after start */ thr_lock_owner_init(&main_lock_id, &lock_info); diff --git a/sql/sql_class.h b/sql/sql_class.h index 0a518e860e5..8d55d06c3ec 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -993,7 +993,7 @@ public: String packet; // dynamic buffer for network I/O String convert_buffer; // buffer for charset conversions struct sockaddr_in remote; // client socket address - struct rand_struct rand; // used for authentication + struct my_rnd_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars struct system_status_var *initial_status_var; /* used by show status */ diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc index ebd424f00f0..53babf517c1 100644 --- a/sql/sql_crypt.cc +++ b/sql/sql_crypt.cc @@ -38,7 +38,7 @@ SQL_CRYPT::SQL_CRYPT(const char *password) void SQL_CRYPT::crypt_init(ulong *rand_nr) { uint i; - randominit(&rand,rand_nr[0],rand_nr[1]); + my_rnd_init(&rand,rand_nr[0],rand_nr[1]); for (i=0 ; i<=255; i++) decode_buff[i]= (char) i; diff --git a/sql/sql_crypt.h b/sql/sql_crypt.h index f3db9adde25..7d803245b0b 100644 --- a/sql/sql_crypt.h +++ b/sql/sql_crypt.h @@ -20,7 +20,7 @@ class SQL_CRYPT :public Sql_alloc { - struct rand_struct rand,org_rand; + struct my_rnd_struct rand,org_rand; char decode_buff[256],encode_buff[256]; uint shift; void crypt_init(ulong *seed); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8906c5654c7..1c1b86d11a7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -70,6 +70,9 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), grant_names, NULL}; #endif +/* Match the values of enum ha_choice */ +static const char *ha_choice_values[] = {"", "0", "1"}; + static void store_key_options(THD *thd, String *packet, TABLE *table, KEY *key_info); @@ -1153,6 +1156,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, key_info= table->key_info; bzero((char*) &create_info, sizeof(create_info)); + /* Allow update_create_info to update row type */ + create_info.row_type= share->row_type; file->update_create_info(&create_info); primary_key= share->primary_key; @@ -1337,19 +1342,25 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); + /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ if (share->db_create_options & HA_OPTION_CHECKSUM) packet->append(STRING_WITH_LEN(" CHECKSUM=1")); + if (share->page_checksum != HA_CHOICE_UNDEF) + { + packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM=")); + packet->append(ha_choice_values[(uint) share->page_checksum], 1); + } if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1")); - if (share->row_type != ROW_TYPE_DEFAULT) + if (create_info.row_type != ROW_TYPE_DEFAULT) { packet->append(STRING_WITH_LEN(" ROW_FORMAT=")); - packet->append(ha_row_type[(uint) share->row_type]); + packet->append(ha_row_type[(uint) create_info.row_type]); } if (share->transactional != HA_CHOICE_UNDEF) { packet->append(STRING_WITH_LEN(" TRANSACTIONAL=")); - packet->append(share->transactional == HA_CHOICE_YES ? "1" : "0", 1); + packet->append(ha_choice_values[(uint) share->transactional], 1); } if (table->s->key_block_size) { @@ -3001,8 +3012,12 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, ptr=strmov(ptr," pack_keys=1"); if (share->db_create_options & HA_OPTION_NO_PACK_KEYS) ptr=strmov(ptr," pack_keys=0"); + /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ if (share->db_create_options & HA_OPTION_CHECKSUM) ptr=strmov(ptr," checksum=1"); + if (share->page_checksum != HA_CHOICE_UNDEF) + ptr= strxmov(ptr, " page_checksum=", + ha_choice_values[(uint) share->page_checksum], NullS); if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE) ptr=strmov(ptr," delay_key_write=1"); if (share->row_type != ROW_TYPE_DEFAULT) @@ -3015,6 +3030,9 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, show_table->part_info->no_parts > 0) ptr= strmov(ptr, " partitioned"); #endif + if (share->transactional != HA_CHOICE_UNDEF) + ptr= strxmov(ptr, " transactional=", + ha_choice_values[(uint) share->transactional], NullS); table->field[19]->store(option_buff+1, (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1), cs); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 22b1d7701e7..98b64551de7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7082,10 +7082,9 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, for (uint i= 0; i < t->s->fields; i++ ) { Field *f= t->field[i]; -#ifdef NOT_YET - if (f->is_real_null(0)) + if (! thd->variables.old_mode && + f->is_real_null(0)) continue; -#endif if ((f->type() == MYSQL_TYPE_BLOB) || (f->type() == MYSQL_TYPE_VARCHAR)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8def8a43249..e6b0aeb6430 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -470,6 +470,7 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, enum enum_tx_isolation tx_isolation; enum Cast_target cast_type; enum Item_udftype udf_type; + enum ha_choice choice; CHARSET_INFO *charset; thr_lock_type lock_type; interval_type interval, interval_time_st; @@ -858,6 +859,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token OWNER_SYM %token PACK_KEYS_SYM %token PAGE_SYM +%token PAGE_CHECKSUM_SYM %token PARAM_MARKER %token PARSER_SYM %token PARTIAL /* SQL-2003-N */ @@ -993,6 +995,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TABLESPACE %token TABLE_REF_PRIORITY %token TABLE_SYM /* SQL-2003-R */ +%token TABLE_CHECKSUM_SYM %token TEMPORARY /* SQL-2003-N */ %token TEMPTABLE_SYM %token TERMINATED @@ -1126,6 +1129,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <ulonglong_number> ulonglong_num real_ulonglong_num size_number +%type <choice> choice + %type <p_elem_value> part_bit_expr @@ -4335,6 +4340,12 @@ create_table_option: Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS; } | CHECKSUM_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; } + | TABLE_CHECKSUM_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; } + | PAGE_CHECKSUM_SYM opt_equal choice + { + Lex->create_info.used_fields|= HA_CREATE_USED_PAGE_CHECKSUM; + Lex->create_info.page_checksum= $3; + } | DELAY_KEY_WRITE_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE; Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; } | ROW_FORMAT_SYM opt_equal row_types { Lex->create_info.row_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; } | UNION_SYM opt_equal '(' table_list ')' @@ -4366,11 +4377,10 @@ create_table_option: Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE; Lex->create_info.key_block_size= $3; } - | TRANSACTIONAL_SYM opt_equal ulong_num + | TRANSACTIONAL_SYM opt_equal choice { Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL; - Lex->create_info.transactional= ($3 != 0 ? HA_CHOICE_YES : - HA_CHOICE_NO); + Lex->create_info.transactional= $3; } ; @@ -8000,6 +8010,11 @@ dec_num: | FLOAT_NUM ; +choice: + ulong_num { $$= $1 != 0 ? HA_CHOICE_YES : HA_CHOICE_NO; } + | DEFAULT { $$= HA_CHOICE_UNDEF; } + ; + procedure_clause: /* empty */ | PROCEDURE ident /* Procedure name */ @@ -10046,6 +10061,7 @@ keyword_sp: | ONE_SYM {} | PACK_KEYS_SYM {} | PAGE_SYM {} + | PAGE_CHECKSUM_SYM {} | PARTIAL {} | PARTITIONING_SYM {} | PARTITIONS_SYM {} @@ -10108,6 +10124,7 @@ keyword_sp: | SUBPARTITIONS_SYM {} | SUPER_SYM {} | SUSPEND_SYM {} + | TABLE_CHECKSUM_SYM {} | TABLES {} | TABLESPACE {} | TEMPORARY {} diff --git a/sql/table.cc b/sql/table.cc index e8add38640c..abdb635f899 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -655,7 +655,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (!head[32]) // New frm file in 3.23 { share->avg_row_length= uint4korr(head+34); - share->transactional= (ha_choice) head[39]; + share->transactional= (ha_choice) (head[39] & 3); + share->page_checksum= (ha_choice) ((head[39] >> 2) & 3); share->row_type= (row_type) head[40]; share->table_charset= get_charset((uint) head[38],MYF(0)); share->null_field_first= 1; @@ -2373,7 +2374,8 @@ File create_frm(THD *thd, const char *name, const char *db, int4store(fileinfo+34,create_info->avg_row_length); fileinfo[38]= (create_info->default_table_charset ? create_info->default_table_charset->number : 0); - fileinfo[39]= (uchar) create_info->transactional; + fileinfo[39]= (uchar) ((uint) create_info->transactional | + ((uint) create_info->page_checksum << 2)); fileinfo[40]= (uchar) create_info->row_type; /* Next few bytes where for RAID support */ fileinfo[41]= 0; diff --git a/sql/table.h b/sql/table.h index 47b2cbd3075..cd3d12614fb 100644 --- a/sql/table.h +++ b/sql/table.h @@ -204,6 +204,7 @@ typedef struct st_table_share enum row_type row_type; /* How rows are stored */ enum tmp_table_type tmp_table; enum ha_choice transactional; + enum ha_choice page_checksum; uint ref_count; /* How many TABLE objects uses this */ uint open_count; /* Number of tables in open list */ 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 <lf.h> @@ -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; i<key_parts; i++) { - if (!(share->state.rec_per_key_part[i]=param->rec_per_key_part[i])) + if (!(share->state.rec_per_key_part[i]=param->new_rec_per_key_part[i])) share->state.changed|= STATE_NOT_ANALYZED; } } @@ -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 (; cur<end; ++cur) + for (; cur < end; cur++) { double diff; double abs_diff; @@ -141,15 +141,15 @@ static void pick_next(SplitStruct *node, int n_entries, double *g1, double *g2, continue; } - diff = mbr_join_square(g1, cur->coords, n_dim) - + diff= mbr_join_square(g1, cur->coords, n_dim) - mbr_join_square(g2, cur->coords, n_dim); - abs_diff = fabs(diff); + abs_diff= fabs(diff); if (abs_diff > max_diff) { - max_diff = abs_diff; - *n_group = 1 + (diff > 0); - *choice = cur; + max_diff= abs_diff; + *n_group= 1 + (diff > 0); + *choice= cur; } } } @@ -159,15 +159,16 @@ Mark not-in-group entries as n_group */ static void mark_all_entries(SplitStruct *node, int n_entries, int n_group) { - SplitStruct *cur = node; - SplitStruct *end = node + n_entries; - for (; cur<end; ++cur) + SplitStruct *cur= node; + SplitStruct *end= node + n_entries; + + for (; cur < end; cur++) { if (cur->n_node) { continue; } - cur->n_node = n_group; + cur->n_node= n_group; } } @@ -181,12 +182,12 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, SplitStruct *cur; SplitStruct *a; SplitStruct *b; - double *g1 = reserve_coords(d_buffer, n_dim); - double *g2 = reserve_coords(d_buffer, n_dim); + double *g1= reserve_coords(d_buffer, n_dim); + double *g2= reserve_coords(d_buffer, n_dim); SplitStruct *next; int next_node; int i; - SplitStruct *end = node + n_entries; + SplitStruct *end= node + n_entries; LINT_INIT(a); LINT_INIT(b); LINT_INIT(next); @@ -197,22 +198,22 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, return 1; } - cur = node; - for (; cur<end; ++cur) + cur= node; + for (; cur < end; cur++) { - cur->square = count_square(cur->coords, n_dim); - cur->n_node = 0; + cur->square= count_square(cur->coords, n_dim); + cur->n_node= 0; } pick_seeds(node, n_entries, &a, &b, n_dim); - a->n_node = 1; - b->n_node = 2; + a->n_node= 1; + b->n_node= 2; copy_coords(g1, a->coords, n_dim); - size1 += key_size; + size1+= key_size; copy_coords(g2, b->coords, n_dim); - size2 += key_size; + size2+= key_size; for (i=n_entries - 2; i>0; --i) @@ -232,15 +233,15 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries, pick_next(node, n_entries, g1, g2, &next, &next_node, n_dim); if (next_node == 1) { - size1 += key_size; + size1+= key_size; mbr_join(g1, next->coords, n_dim); } else { - size2 += key_size; + size2+= key_size; mbr_join(g2, next->coords, n_dim); } - next->n_node = next_node; + next->n_node= next_node; } return 0; @@ -262,14 +263,15 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *source_cur, *cur1, *cur2; uchar *new_page; int err_code= 0; - uint nod_flag= _ma_test_if_nod(page); + uint nod_flag= _ma_test_if_nod(info, page); uint full_length= key_length + (nod_flag ? nod_flag : info->s->base.rec_reflength); - int max_keys= (maria_data_on_page(page)-2) / (full_length); + int max_keys= ((_ma_get_page_used(info, page) - info->s->keypage_header) / + (full_length)); DBUG_ENTER("maria_rtree_split_page"); DBUG_PRINT("rtree", ("splitting block")); - n_dim = keyinfo->keysegs / 2; + n_dim= keyinfo->keysegs / 2; if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) * (max_keys + 1 + 4) + @@ -278,66 +280,69 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4)); - next_coord = coord_buf; + next_coord= coord_buf; - stop = task + max_keys; - source_cur = rt_PAGE_FIRST_KEY(page, nod_flag); + stop= task + max_keys; + source_cur= rt_PAGE_FIRST_KEY(info, page, nod_flag); - for (cur = task; cur < stop; ++cur, source_cur = rt_PAGE_NEXT_KEY(source_cur, + for (cur= task; cur < stop; cur++, source_cur= rt_PAGE_NEXT_KEY(source_cur, key_length, nod_flag)) { - cur->coords = reserve_coords(&next_coord, n_dim); - cur->key = source_cur; + cur->coords= reserve_coords(&next_coord, n_dim); + cur->key= source_cur; maria_rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords); } - cur->coords = reserve_coords(&next_coord, n_dim); + cur->coords= reserve_coords(&next_coord, n_dim); maria_rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords); - cur->key = key; + cur->key= key; - old_coord = next_coord; + old_coord= next_coord; if (split_maria_rtree_node(task, max_keys + 1, - maria_data_on_page(page) + full_length + 2, full_length, + _ma_get_page_used(info, page) + full_length + 2, + full_length, rt_PAGE_MIN_SIZE(keyinfo->block_length), 2, 2, &next_coord, n_dim)) { - err_code = 1; + err_code= 1; goto split_err; } - if (!(new_page = (uchar*) my_alloca((uint)keyinfo->block_length))) + if (!(new_page= (uchar*) my_alloca((uint)keyinfo->block_length))) { err_code= -1; goto split_err; } - stop = task + (max_keys + 1); - cur1 = rt_PAGE_FIRST_KEY(page, nod_flag); - cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag); + stop= task + (max_keys + 1); + cur1= rt_PAGE_FIRST_KEY(info, page, nod_flag); + cur2= rt_PAGE_FIRST_KEY(info, new_page, nod_flag); - n1= n2 = 0; - for (cur = task; cur < stop; ++cur) + n1= n2= 0; + for (cur= task; cur < stop; cur++) { uchar *to; if (cur->n_node == 1) { - to = cur1; - cur1 = rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag); - ++n1; + to= cur1; + cur1= rt_PAGE_NEXT_KEY(cur1, key_length, nod_flag); + n1++; } else { - to = cur2; - cur2 = rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag); - ++n2; + to= cur2; + cur2= rt_PAGE_NEXT_KEY(cur2, key_length, nod_flag); + n2++; } if (to != cur->key) memcpy(to - nod_flag, cur->key - nod_flag, full_length); } - maria_putint(page, 2 + n1 * full_length, nod_flag); - maria_putint(new_page, 2 + n2 * full_length, nod_flag); + _ma_store_page_used(info, page, info->s->keypage_header + n1 * full_length, + nod_flag); + _ma_store_page_used(info, new_page, info->s->keypage_header + + n2 * full_length, nod_flag); if ((*new_page_offs= _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR) diff --git a/storage/maria/ma_rt_test.c b/storage/maria/ma_rt_test.c index 4360e81c550..e41ebdce500 100644 --- a/storage/maria/ma_rt_test.c +++ b/storage/maria/ma_rt_test.c @@ -122,7 +122,8 @@ static int run_test(const char *filename) /* Define 2*ndims columns for coordinates*/ - for (i=1; i<=2*ndims ;i++){ + for (i=1; i<=2*ndims ;i++) + { recinfo[i].type=FIELD_NORMAL; recinfo[i].length=key_length; rec_length+=key_length; @@ -135,7 +136,8 @@ static int run_test(const char *filename) keyinfo[0].flag=0; keyinfo[0].key_alg=KEYALG; - for (i=0; i<2*ndims; i++){ + for (i=0; i<2*ndims; i++) + { keyinfo[0].seg[i].type= key_type; keyinfo[0].seg[i].flag=0; /* Things like HA_REVERSE_SORT */ keyinfo[0].seg[i].start= (key_length*i)+1; diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 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 <my_no_pthread.h> #endif - #include "ma_loghandler.h" #include "ma_control_file.h" +/* For testing recovery */ +#define IDENTICAL_PAGES_AFTER_RECOVERY 1 +/* Do extra sanity checking */ +#define SANITY_CHECKS 1 + #define MAX_NONMAPPED_INSERTS 1000 #define MARIA_MAX_TREE_LEVELS 32 -#define SANITY_CHECKS struct st_transaction; @@ -79,11 +82,12 @@ typedef struct st_maria_state_info ulong unique; /* Unique number for this process */ ulong update_count; /* Updated for each write lock */ ulong status; - ulong *rec_per_key_part; + double *rec_per_key_part; + ulong *nulls_per_key_part; ha_checksum checksum; /* Table checksum */ my_off_t *key_root; /* Start of key trees */ my_off_t key_del; /* delete links for index pages */ - my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ + my_off_t records_at_analyze; /* Rows when calculating rec_per_key */ ulong sec_index_changed; /* Updated when new sec_index */ ulong sec_index_used; /* which extra index are in use */ @@ -108,18 +112,19 @@ typedef struct st_maria_state_info #define MARIA_STATE_INFO_SIZE \ (24 + LSN_STORE_SIZE*2 + 4 + 11*8 + 4*4 + 8 + 3*4 + 5*8) -#define MARIA_STATE_KEY_SIZE 8 +#define MARIA_STATE_KEY_SIZE (8 + 4) #define MARIA_STATE_KEYBLOCK_SIZE 8 -#define MARIA_STATE_KEYSEG_SIZE 4 +#define MARIA_STATE_KEYSEG_SIZE 12 #define MARIA_STATE_EXTRA_SIZE (MARIA_MAX_KEY*MARIA_STATE_KEY_SIZE + MARIA_MAX_KEY*HA_MAX_KEY_SEG*MARIA_STATE_KEYSEG_SIZE) #define MARIA_KEYDEF_SIZE (2+ 5*2) #define MARIA_UNIQUEDEF_SIZE (2+1+1) #define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) #define MARIA_COLUMNDEF_SIZE (6+2+2+2+2+2+1+1) -#define MARIA_BASE_INFO_SIZE (5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) +#define MARIA_BASE_INFO_SIZE (MY_UUID_SIZE + 5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16) #define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ /* Internal management bytes needed to store 2 keys on an index page */ -#define MARIA_INDEX_MIN_OVERHEAD_SIZE (4 + (TRANSID_SIZE+1) * 2) +#define MARIA_INDEX_OVERHEAD_SIZE (TRANSID_SIZE * 2) +#define MARIA_DELETE_KEY_NR 255 /* keynr for deleted blocks */ /* Basic information of the Maria table. This is stored on disk @@ -171,9 +176,12 @@ typedef struct st_ma_base_info uint default_rec_buff_size; /* Extra number of bytes the row format require in the record buffer */ uint extra_rec_buff_size; + /* Tuning flags that can be ignored by older Maria versions */ + uint extra_options; /* The following are from the header */ uint key_parts, all_key_parts; + uchar uuid[MY_UUID_SIZE]; /** @brief If false, we disable logging, versioning, transaction etc. Observe difference with MARIA_SHARE::now_transactional @@ -233,6 +241,7 @@ typedef struct st_maria_share MARIA_COLUMNDEF *columndef; /* Pointer to column information */ MARIA_PACK pack; /* Data about packed records */ MARIA_BLOB *blobs; /* Pointer to blobs */ + uint16 *column_nr; /* Original column order */ char *unique_file_name; /* realpath() of index file */ char *data_file_name; /* Resolved path names from symlinks */ char *index_file_name; @@ -247,38 +256,38 @@ typedef struct st_maria_share /* Called when the last instance of the table is closed */ my_bool (*once_end)(struct st_maria_share *); /* Is called for every open of the table */ - my_bool (*init)(struct st_maria_info *); + my_bool (*init)(MARIA_HA *); /* Is called for every close of the table */ - void (*end)(struct st_maria_info *); + void (*end)(MARIA_HA *); /* Called when we want to read a record from a specific position */ - int (*read_record)(struct st_maria_info *, uchar *, MARIA_RECORD_POS); + int (*read_record)(MARIA_HA *, uchar *, MARIA_RECORD_POS); /* Initialize a scan */ - my_bool (*scan_init)(struct st_maria_info *); + my_bool (*scan_init)(MARIA_HA *); /* Read next record while scanning */ - int (*scan)(struct st_maria_info *, uchar *, MARIA_RECORD_POS, my_bool); + int (*scan)(MARIA_HA *, uchar *, MARIA_RECORD_POS, my_bool); /* End scan */ - void (*scan_end)(struct st_maria_info *); + void (*scan_end)(MARIA_HA *); /* Pre-write of row (some handlers may do the actual write here) */ - MARIA_RECORD_POS (*write_record_init)(struct st_maria_info *, const uchar *); + MARIA_RECORD_POS (*write_record_init)(MARIA_HA *, const uchar *); /* Write record (or accept write_record_init) */ - my_bool (*write_record)(struct st_maria_info *, const uchar *); + my_bool (*write_record)(MARIA_HA *, const uchar *); /* Called when write failed */ - my_bool (*write_record_abort)(struct st_maria_info *); - my_bool (*update_record)(struct st_maria_info *, MARIA_RECORD_POS, + my_bool (*write_record_abort)(MARIA_HA *); + my_bool (*update_record)(MARIA_HA *, MARIA_RECORD_POS, const uchar *, const uchar *); - my_bool (*delete_record)(struct st_maria_info *, const uchar *record); - my_bool (*compare_record)(struct st_maria_info *, const uchar *); + my_bool (*delete_record)(MARIA_HA *, const uchar *record); + my_bool (*compare_record)(MARIA_HA *, const uchar *); /* calculate checksum for a row */ - ha_checksum(*calc_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_checksum)(MARIA_HA *, const uchar *); /* Calculate checksum for a row during write. May be 0 if we calculate the checksum in write_record_init() */ - ha_checksum(*calc_write_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_write_checksum)(MARIA_HA *, const uchar *); /* calculate checksum for a row during check table */ - ha_checksum(*calc_check_checksum)(struct st_maria_info *, const uchar *); + ha_checksum(*calc_check_checksum)(MARIA_HA *, const uchar *); /* Compare a row in memory with a row on disk */ - my_bool (*compare_unique)(struct st_maria_info *, MARIA_UNIQUEDEF *, + my_bool (*compare_unique)(MARIA_HA *, MARIA_UNIQUEDEF *, const uchar *record, MARIA_RECORD_POS pos); /* Mapings to read/write the data file */ 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) diff --git a/storage/myisam/mi_dbug.c b/storage/myisam/mi_dbug.c index 0808a7e85dd..659abdce131 100644 --- a/storage/myisam/mi_dbug.c +++ b/storage/myisam/mi_dbug.c @@ -92,7 +92,7 @@ void _mi_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; |