diff options
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; |