diff --git a/include/maria.h b/include/maria.h index 60b981fd1a9..bb3ca905eab 100644 --- a/include/maria.h +++ b/include/maria.h @@ -186,6 +186,7 @@ typedef struct st_maria_keydef /* Key definition with open & info */ uint16 keylength; /* Tot length of keyparts (auto) */ uint16 minlength; /* min length of (packed) key (auto) */ uint16 maxlength; /* max length of (packed) key (auto) */ + uint16 max_store_length; /* Size to store key + overhead */ uint32 write_comp_flag; /* compare flag for write key (auto) */ uint32 version; /* For concurrent read/write */ uint32 ftkey_nr; /* full-text index number */ diff --git a/include/my_pthread.h b/include/my_pthread.h index ff892863800..17813047ce5 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -312,6 +312,8 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex); #endif #endif +size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize); + /* The defines set_timespec and set_timespec_nsec should be used for calculating an absolute time at which diff --git a/include/my_stack_alloc.h b/include/my_stack_alloc.h new file mode 100644 index 00000000000..6f6305f248d --- /dev/null +++ b/include/my_stack_alloc.h @@ -0,0 +1,114 @@ +/* Copyright 2019 MariaDB corporation AB + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#ifndef _my_stack_alloc_h +#define _my_stack_alloc_h + +/* + Do allocation trough alloca if there is enough stack available. + If not, use my_malloc() instead. + + The idea is that to be able to alloc as much as possible trough the + stack. To ensure this, we have two different limits, on for big + blocks and one for small blocks. This will enable us to continue to + do allocation for small blocks even when there is less stack space + available. + This is for example used by Aria when traversing the b-tree and the code + needs to allocate one b-tree page and a few keys for each recursion. Even + if there is not space to allocate the b-tree pages on stack we can still + continue to allocate the keys. +*/ + +/* + Default suggested allocations +*/ + +/* Allocate big blocks as long as there is this much left */ +#define STACK_ALLOC_BIG_BLOCK 1024*64 + +/* Allocate small blocks as long as there is this much left */ +#define STACK_ALLOC_SMALL_BLOCK 1024*32 + +struct st_stack_alloc +{ + void **stack_ends_here; /* Set on init */ + size_t stack_for_big_blocks; + size_t stack_for_small_blocks; + size_t small_block_size; +}; +typedef struct st_stack_alloc STACK_ALLOC; + + +/* + Initialize STACK_ALLOC structure +*/ + +static inline void init_stack_alloc(STACK_ALLOC *alloc, + size_t stack_for_big_blocks, + size_t stack_for_small_blocks, + size_t small_block_size) +{ + alloc->stack_ends_here= &my_thread_var->stack_ends_here; + alloc->stack_for_big_blocks= stack_for_big_blocks; + alloc->stack_for_small_blocks= stack_for_small_blocks; + alloc->small_block_size= small_block_size; +} + + +/* + Allocate a block on stack or trough malloc. + The 'must_be_freed' variable will be set to 1 if malloc was called. + 'must_be_freed' must be a variable on the stack! +*/ + +#ifdef HAVE_ALLOCA +#define alloc_on_stack(alloc, res, must_be_freed, size) \ +{ \ + size_t stack_left= available_stack_size(&(must_be_freed), \ + *(alloc)->stack_ends_here); \ + if (stack_left > (size_t) (size) && \ + ((alloc)->stack_for_big_blocks < stack_left - (size) || \ + (((alloc)->stack_for_small_blocks < stack_left - (size)) && \ + ((alloc)->small_block_size <= (size_t) (size))))) \ + { \ + (must_be_freed)= 0; \ + (res)= alloca(size); \ + } \ + else \ + { \ + (must_be_freed)= 1; \ + (res)= my_malloc(size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ + } \ +} +#else +#define alloc_on_stack(alloc, res, must_be_freed, size) \ + { \ + (must_be_freed)= 1; \ + (res)= my_malloc(size, MYF(MY_THREAD_SPECIFIC | MY_WME)); \ + } +#endif /* HAVE_ALLOCA */ + + +/* + Free memory allocated by stack_alloc +*/ + +static inline void stack_alloc_free(void *res, my_bool must_be_freed) +{ + if (must_be_freed) + my_free(res); +} +#endif /* _my_stack_alloc_h */ diff --git a/include/myisam.h b/include/myisam.h index 216f041c8a9..d283712a1e0 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -309,6 +309,8 @@ extern int mi_make_backup_of_index(struct st_myisam_info *info, #define MYISAMCHK_VERIFY 2 /* Verify, run repair if failure */ typedef uint mi_bit_type; +typedef struct st_sort_key_blocks SORT_KEY_BLOCKS; +typedef struct st_sort_ftbuf SORT_FT_BUF; typedef struct st_mi_bit_buff { /* Used for packing of record */ diff --git a/include/myisamchk.h b/include/myisamchk.h index 5876d67ca5f..d734df505fb 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -20,6 +20,8 @@ #ifndef _myisamchk_h #define _myisamchk_h +#include + /* Flags used by xxxxchk.c or/and ha_xxxx.cc that are NOT passed to xxxcheck.c follows: @@ -33,15 +35,6 @@ #define O_NEW_DATA 2U #define O_DATA_LOST 4U -typedef struct st_sort_key_blocks /* Used when sorting */ -{ - uchar *buff, *end_pos; - uchar lastkey[HA_MAX_POSSIBLE_KEY_BUFF]; - uint last_length; - int inited; -} SORT_KEY_BLOCKS; - - /* MARIA/MYISAM supports several statistics collection methods. Currently statistics collection method is not stored in @@ -111,6 +104,7 @@ typedef struct st_handler_check_param my_bool retry_repair, force_sort, calc_checksum, static_row_size; char temp_filename[FN_REFLEN]; IO_CACHE read_cache; + STACK_ALLOC stack_alloc; enum_handler_stats_method stats_method; /* For reporting progress */ uint stage, max_stage; @@ -125,14 +119,6 @@ typedef struct st_handler_check_param } HA_CHECK; -typedef struct st_sort_ftbuf -{ - uchar *buf, *end; - int count; - uchar lastkey[HA_MAX_KEY_BUFF]; -} SORT_FT_BUF; - - typedef struct st_buffpek { my_off_t file_pos; /* Where we are in the sort file */ uchar *base, *key; /* Key pointers */ diff --git a/mysql-test/suite/maria/maria-ucs2.result b/mysql-test/suite/maria/maria-ucs2.result index 1a54ab78081..83eaf88e660 100644 --- a/mysql-test/suite/maria/maria-ucs2.result +++ b/mysql-test/suite/maria/maria-ucs2.result @@ -16,8 +16,6 @@ Table Op Msg_type Msg_text test.t1 check status OK SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR ALTER TABLE t1 MODIFY a VARCHAR(800) CHARSET `ucs2`; -Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK @@ -25,12 +23,12 @@ SHOW CREATE table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(800) CHARACTER SET ucs2 DEFAULT NULL, - KEY `a` (`a`(500)) + KEY `a` (`a`) ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 DROP TABLE t1; -CREATE TABLE t1 (a VARCHAR(800),KEY(a)) ENGINE=Aria CHARACTER SET ucs2; +CREATE TABLE t1 (a VARCHAR(1200),KEY(a)) ENGINE=Aria CHARACTER SET ucs2; Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes INSERT INTO t1 VALUES (REPEAT('abc ',200)); CHECK TABLE t1; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/maria/maria-ucs2.test b/mysql-test/suite/maria/maria-ucs2.test index e4f8bc8dd27..7dab000a1c9 100644 --- a/mysql-test/suite/maria/maria-ucs2.test +++ b/mysql-test/suite/maria/maria-ucs2.test @@ -37,7 +37,7 @@ DROP TABLE t1; # Issue was too long key # -CREATE TABLE t1 (a VARCHAR(800),KEY(a)) ENGINE=Aria CHARACTER SET ucs2; +CREATE TABLE t1 (a VARCHAR(1200),KEY(a)) ENGINE=Aria CHARACTER SET ucs2; INSERT INTO t1 VALUES (REPEAT('abc ',200)); CHECK TABLE t1; DROP TABLE t1; diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index 7a4283c4cc5..908df15aa0d 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -351,13 +351,13 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e)); -ERROR 42000: Specified key was too long; max key length is 1000 bytes +CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), f varchar(255), g varchar(255), h varchar(255), i varchar(255), KEY t1 (a, b, c, d, e, f, g, h, i)); +ERROR 42000: Specified key was too long; max key length is 2000 bytes CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b)); ERROR 42000: Too many key parts specified; max 32 parts allowed -CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255)); -ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e); -ERROR 42000: Specified key was too long; max key length is 1000 bytes +CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), f varchar(255), g varchar(255), h varchar(255), i varchar(255)); +ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e, f, g, h, i); +ERROR 42000: Specified key was too long; max key length is 2000 bytes DROP TABLE t1; CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a)); INSERT into t1 values (0,null,0), (0,null,1), (0,null,2), (0,null,3), (1,1,4); @@ -1594,7 +1594,7 @@ a b drop table t1; create table t1 (v varchar(65530), key(v)); Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes drop table if exists t1; set statement sql_mode = 'NO_ENGINE_SUBSTITUTION' for create table t1 (v varchar(65536)); @@ -1866,34 +1866,34 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a varchar(2048), key `a` (a)); Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2048) DEFAULT NULL, - KEY `a` (`a`(1000)) + KEY `a` (`a`(2000)) ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 drop table t1; create table t1 (a varchar(2048), key `a` (a) key_block_size=1024); Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2048) DEFAULT NULL, - KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192 + KEY `a` (`a`(2000)) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 drop table t1; create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024; Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192 + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=1024 alter table t1 key_block_size=2048; show create table t1; @@ -1902,7 +1902,7 @@ t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192 + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=2048 alter table t1 add c int, add key (c); show create table t1; @@ -1912,7 +1912,7 @@ t1 CREATE TABLE `t1` ( `b` varchar(2048) DEFAULT NULL, `c` int(11) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192, KEY `c` (`c`) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=2048 alter table t1 key_block_size=4096; @@ -1923,7 +1923,7 @@ t1 CREATE TABLE `t1` ( `b` varchar(2048) DEFAULT NULL, `c` int(11) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192, KEY `c` (`c`) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=4096 alter table t1 key_block_size=0; @@ -1934,7 +1934,7 @@ t1 CREATE TABLE `t1` ( `b` varchar(2048) DEFAULT NULL, `c` int(11) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192, KEY `c` (`c`) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 alter table t1 add d int, add key (d); @@ -1946,33 +1946,33 @@ t1 CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, KEY `a` (`a`) KEY_BLOCK_SIZE=8192, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(2000)) KEY_BLOCK_SIZE=8192, KEY `c` (`c`) KEY_BLOCK_SIZE=8192, KEY `d` (`d`) ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 drop table t1; create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192; Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, KEY `a` (`a`), - KEY `b` (`b`(1000)) + KEY `b` (`b`(2000)) ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=8192 drop table t1; create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192; Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, KEY `a` (`a`), - KEY `b` (`b`(1000)) + KEY `b` (`b`(2000)) ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 KEY_BLOCK_SIZE=8192 drop table t1; create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384; @@ -1995,12 +1995,12 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000); Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2048) DEFAULT NULL, - KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192 + KEY `a` (`a`(2000)) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 drop table t1; create table t1 (a int not null, key `a` (a) key_block_size=1025); diff --git a/mysql-test/suite/maria/maria.test b/mysql-test/suite/maria/maria.test index d5b9d839699..920443d4338 100644 --- a/mysql-test/suite/maria/maria.test +++ b/mysql-test/suite/maria/maria.test @@ -373,12 +373,12 @@ drop table t1; # --error 1071 -CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), KEY t1 (a, b, c, d, e)); +CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), f varchar(255), g varchar(255), h varchar(255), i varchar(255), KEY t1 (a, b, c, d, e, f, g, h, i)); --error 1070 CREATE TABLE t1 (a varchar(1), b varchar(1), key (a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b,a,b)); -CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255)); +CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), d varchar(255), e varchar(255), f varchar(255), g varchar(255), h varchar(255), i varchar(255)); --error 1071 -ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e); +ALTER TABLE t1 ADD INDEX t1 (a, b, c, d, e, f, g, h, i); DROP TABLE t1; # diff --git a/mysql-test/suite/maria/maria3.result b/mysql-test/suite/maria/maria3.result index ba8b64f9514..09ce22411eb 100644 --- a/mysql-test/suite/maria/maria3.result +++ b/mysql-test/suite/maria/maria3.result @@ -17,12 +17,12 @@ t1 CREATE TABLE `t1` ( drop table t1; create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000); Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2048) DEFAULT NULL, - KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192 + KEY `a` (`a`(2000)) KEY_BLOCK_SIZE=8192 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=0 drop table t1; create table t1 (a int not null, key `a` (a) key_block_size=1025); diff --git a/mysql-test/suite/maria/max_length.result b/mysql-test/suite/maria/max_length.result index 93478e033f4..b4ca61392cc 100644 --- a/mysql-test/suite/maria/max_length.result +++ b/mysql-test/suite/maria/max_length.result @@ -2,13 +2,30 @@ drop table if exists t1,t2; Warnings: Note 1051 Unknown table 'test.t1' Note 1051 Unknown table 'test.t2' -create table t1 (id int(10) unsigned not null auto_increment primary key, v varchar(1000), b blob) row_format=page max_rows=2 engine=aria; -create table t2 (id int(10) unsigned not null auto_increment primary key, v varchar(1000), b blob) row_format=page max_rows=20000000 engine=aria; +create table t1 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob) row_format=page max_rows=2 engine=aria; +create table t2 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob, key(v)) row_format=page max_rows=20000000 engine=aria; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `v` varchar(2000) DEFAULT NULL, + `b` blob DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=2 PAGE_CHECKSUM=1 ROW_FORMAT=PAGE +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `v` varchar(2000) DEFAULT NULL, + `b` blob DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `v` (`v`) +) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=20000000 PAGE_CHECKSUM=1 ROW_FORMAT=PAGE lock tables t1 write,t2 write; show table status like "t_"; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary t1 Aria 10 Page 0 0 8192 268320768 8192 0 1 # # # latin1_swedish_ci NULL max_rows=2 row_format=PAGE 536862720 N -t2 Aria 10 Page 0 0 8192 17592186011648 8192 0 1 # # # latin1_swedish_ci NULL max_rows=20000000 row_format=PAGE 536862720 N +t2 Aria 10 Page 0 0 8192 17592186011648 8192 0 1 # # # latin1_swedish_ci NULL max_rows=20000000 row_format=PAGE 137438945280 N insert into t1 values(null, repeat("ab",100),repeat("def",1000)); insert into t1 values(null, repeat("de",200),repeat("ghi",2000)); insert into t1 values(null, repeat("fe",300),repeat("ghi",3000)); diff --git a/mysql-test/suite/maria/max_length.test b/mysql-test/suite/maria/max_length.test index fdfe2aae4ac..4ebe48b4979 100644 --- a/mysql-test/suite/maria/max_length.test +++ b/mysql-test/suite/maria/max_length.test @@ -7,8 +7,10 @@ drop table if exists t1,t2; -create table t1 (id int(10) unsigned not null auto_increment primary key, v varchar(1000), b blob) row_format=page max_rows=2 engine=aria; -create table t2 (id int(10) unsigned not null auto_increment primary key, v varchar(1000), b blob) row_format=page max_rows=20000000 engine=aria; +create table t1 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob) row_format=page max_rows=2 engine=aria; +create table t2 (id int(10) unsigned not null auto_increment primary key, v varchar(2000), b blob, key(v)) row_format=page max_rows=20000000 engine=aria; +show create table t1; +show create table t2; lock tables t1 write,t2 write; --replace_column 12 # 13 # 14 # show table status like "t_"; diff --git a/mysql-test/suite/maria/mrr.result b/mysql-test/suite/maria/mrr.result index 5c709fb34e5..2ebf10cf1af 100644 --- a/mysql-test/suite/maria/mrr.result +++ b/mysql-test/suite/maria/mrr.result @@ -392,8 +392,6 @@ col_varchar_1024_latin1_key varchar(1024) DEFAULT NULL, PRIMARY KEY (pk), KEY col_varchar_1024_latin1_key (col_varchar_1024_latin1_key) ) ENGINE=Aria; -Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes INSERT INTO t1 VALUES (1,'z'), (2,'abcdefjhjkl'), (3,'in'), (4,'abcdefjhjkl'), (6,'abcdefjhjkl'), (11,'zx'), (12,'abcdefjhjm'), (13,'jn'), (14,'abcdefjhjp'), (16,'abcdefjhjr'); @@ -407,7 +405,7 @@ WHERE table1.col_varchar_1024_latin1_key = table2.col_varchar_10_latin1 AND table1.pk<>0 ; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table2 ALL NULL NULL NULL NULL 2 Using where -1 SIMPLE table1 ref PRIMARY,col_varchar_1024_latin1_key col_varchar_1024_latin1_key 1003 test.table2.col_varchar_10_latin1 2 Using where +1 SIMPLE table1 ref PRIMARY,col_varchar_1024_latin1_key col_varchar_1024_latin1_key 1027 test.table2.col_varchar_10_latin1 2 Using index condition(BKA); Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT count(*) FROM t1 AS table1, t2 AS table2 WHERE @@ -425,12 +423,12 @@ set join_buffer_size=10240; CREATE TABLE t1 ( f2 varchar(32) COLLATE latin1_swedish_ci, f3 int(11), -f4 varchar(1024) COLLATE utf8_bin, -f5 varchar(1024) COLLATE latin1_bin, +f4 varchar(2048) COLLATE utf8_bin, +f5 varchar(2048) COLLATE latin1_bin, KEY (f5) ) ENGINE=Aria TRANSACTIONAL=0 ; Warnings: -Warning 1071 Specified key was too long; max key length is 1000 bytes +Warning 1071 Specified key was too long; max key length is 2000 bytes # Fill the table with some data SELECT alias2.* , alias1.f2 FROM diff --git a/mysql-test/suite/maria/mrr.test b/mysql-test/suite/maria/mrr.test index 6c6a8c4e7b6..f3addd6c0f5 100644 --- a/mysql-test/suite/maria/mrr.test +++ b/mysql-test/suite/maria/mrr.test @@ -144,8 +144,8 @@ set join_buffer_size=10240; CREATE TABLE t1 ( f2 varchar(32) COLLATE latin1_swedish_ci, f3 int(11), - f4 varchar(1024) COLLATE utf8_bin, - f5 varchar(1024) COLLATE latin1_bin, + f4 varchar(2048) COLLATE utf8_bin, + f5 varchar(2048) COLLATE latin1_bin, KEY (f5) ) ENGINE=Aria TRANSACTIONAL=0 ; diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index e2795ed7bb9..ac6d3f87de3 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -405,3 +405,66 @@ int pthread_dummy(int ret) { return ret; } + + +/* + pthread_attr_setstacksize() without so much platform-dependency + + Return: The actual stack size if possible. +*/ + +size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + size_t guard_size __attribute__((unused))= 0; + +#if defined(__ia64__) || defined(__ia64) + /* + On IA64, half of the requested stack size is used for "normal stack" + and half for "register stack". The space measured by check_stack_overrun + is the "normal stack", so double the request to make sure we have the + caller-expected amount of normal stack. + + NOTE: there is no guarantee that the register stack can't grow faster + than normal stack, so it's very unclear that we won't dump core due to + stack overrun despite check_stack_overrun's efforts. Experimentation + shows that in the execution_constants test, the register stack grows + less than half as fast as normal stack, but perhaps other scenarios are + less forgiving. If it turns out that more space is needed for the + register stack, that could be forced (rather inefficiently) by using a + multiplier higher than 2 here. + */ + stacksize *= 2; +#endif + + /* + On many machines, the "guard space" is subtracted from the requested + stack size, and that space is quite large on some platforms. So add + it to our request, if we can find out what it is. + */ +#ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE + if (pthread_attr_getguardsize(attr, &guard_size)) + guard_size = 0; /* if can't find it out, treat as 0 */ +#endif /* HAVE_PTHREAD_ATTR_GETGUARDSIZE */ + + pthread_attr_setstacksize(attr, stacksize + guard_size); + + /* Retrieve actual stack size if possible */ +#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE + { + size_t real_stack_size= 0; + /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */ + if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 && + real_stack_size > guard_size) + { + real_stack_size -= guard_size; + if (real_stack_size < stacksize) + stacksize= real_stack_size; + } + } +#endif /* HAVE_PTHREAD_ATTR_GETSTACKSIZE */ + +#if defined(__ia64__) || defined(__ia64) + stacksize /= 2; +#endif + return stacksize; +} diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7bd3e045cb3..689258158a1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2884,75 +2884,6 @@ extern "C" char *my_demangle(const char *mangled_name, int *status) #endif -/* - pthread_attr_setstacksize() without so much platform-dependency - - Return: The actual stack size if possible. -*/ - -#ifndef EMBEDDED_LIBRARY -static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize) -{ - size_t guard_size __attribute__((unused))= 0; - -#if defined(__ia64__) || defined(__ia64) - /* - On IA64, half of the requested stack size is used for "normal stack" - and half for "register stack". The space measured by check_stack_overrun - is the "normal stack", so double the request to make sure we have the - caller-expected amount of normal stack. - - NOTE: there is no guarantee that the register stack can't grow faster - than normal stack, so it's very unclear that we won't dump core due to - stack overrun despite check_stack_overrun's efforts. Experimentation - shows that in the execution_constants test, the register stack grows - less than half as fast as normal stack, but perhaps other scenarios are - less forgiving. If it turns out that more space is needed for the - register stack, that could be forced (rather inefficiently) by using a - multiplier higher than 2 here. - */ - stacksize *= 2; -#endif - - /* - On many machines, the "guard space" is subtracted from the requested - stack size, and that space is quite large on some platforms. So add - it to our request, if we can find out what it is. - */ -#ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE - if (pthread_attr_getguardsize(attr, &guard_size)) - guard_size = 0; /* if can't find it out, treat as 0 */ -#endif - - pthread_attr_setstacksize(attr, stacksize + guard_size); - - /* Retrieve actual stack size if possible */ -#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE - { - size_t real_stack_size= 0; - /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */ - if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 && - real_stack_size > guard_size) - { - real_stack_size -= guard_size; - if (real_stack_size < stacksize) - { - if (global_system_variables.log_warnings) - sql_print_warning("Asked for %zu thread stack, but got %zu", - stacksize, real_stack_size); - stacksize= real_stack_size; - } - } - } -#endif /* !EMBEDDED_LIBRARY */ - -#if defined(__ia64__) || defined(__ia64) - stacksize /= 2; -#endif - return stacksize; -} -#endif - #ifdef DBUG_ASSERT_AS_PRINTF extern "C" void mariadb_dbug_assert_failed(const char *assert_expr, const char *file, @@ -5580,7 +5511,13 @@ int mysqld_main(int argc, char **argv) new_thread_stack_size= my_setstacksize(&connection_attrib, (size_t)my_thread_stack_size); if (new_thread_stack_size != my_thread_stack_size) + { + if ((new_thread_stack_size < my_thread_stack_size) && + global_system_variables.log_warnings) + sql_print_warning("Asked for %llu thread stack, but got %llu", + my_thread_stack_size, new_thread_stack_size); SYSVAR_AUTOSIZE(my_thread_stack_size, new_thread_stack_size); + } (void) thr_setconcurrency(concurrency); // 10 by default diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6ea50f21675..df889aa9f71 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1093,11 +1093,8 @@ double ha_maria::scan_time() splitting algorithms depends on this. (With only one key on a page we also can't use any compression, which may make the index file much larger) - We use HA_MAX_KEY_LENGTH as this is a stack restriction imposed by the - handler interface. If we want to increase this, we have also to - increase HA_MARIA_KEY_BUFF and MARIA_MAX_KEY_BUFF as the buffer needs - to take be able to store the extra lenght bytes that is part of the stored - key. + We use MARIA_MAX_KEY_LENGTH to limit the key size as we don't want to use + too much stack when searching in the b_tree. We also need to reserve place for a record pointer (8) and 3 bytes per key segment to store the length of the segment + possible null bytes. @@ -2805,6 +2802,9 @@ int ha_maria::external_lock(THD *thd, int lock_type) F_UNLCK : F_EXTRA_LCK)); if (!file->s->base.born_transactional) file->state= &file->s->state.state; // Restore state if clone + + /* Remember stack end for this thread */ + aria_init_stack_alloc(file); DBUG_RETURN(result); } diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index a267a482074..05a0baacd07 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2458,12 +2458,16 @@ static my_bool free_full_pages(MARIA_HA *info, MARIA_ROW *row) /* Compact events by removing filler and tail events */ uchar *new_block= 0; uchar *end, *to, *compact_extent_info; - my_bool res; + my_bool result, buff_alloced; uint extents_count; - if (!(compact_extent_info= my_alloca(row->extents_count * - ROW_EXTENT_SIZE))) - DBUG_RETURN(1); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + row->extents_count * ROW_EXTENT_SIZE); + if (!(compact_extent_info= res)) + DBUG_RETURN(1); + } to= compact_extent_info; for (end= extents + row->extents_count * ROW_EXTENT_SIZE ; @@ -2501,7 +2505,7 @@ static my_bool free_full_pages(MARIA_HA *info, MARIA_ROW *row) No ranges. This happens in the rear case when we have a allocated place for a blob on a tail page but it did fit into the main page. */ - my_afree(compact_extent_info); + stack_alloc_free(compact_extent_info, buff_alloced); DBUG_RETURN(0); } extents_count= (uint) (extents_length / ROW_EXTENT_SIZE); @@ -2510,14 +2514,14 @@ static my_bool free_full_pages(MARIA_HA *info, MARIA_ROW *row) log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); log_array[TRANSLOG_INTERNAL_PARTS + 1].str= compact_extent_info; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= extents_length; - res= translog_write_record(&lsn, LOGREC_REDO_FREE_BLOCKS, info->trn, - info, - (translog_size_t) (sizeof(log_data) + - extents_length), - TRANSLOG_INTERNAL_PARTS + 2, log_array, - log_data, NULL); - my_afree(compact_extent_info); - if (res) + result= translog_write_record(&lsn, LOGREC_REDO_FREE_BLOCKS, info->trn, + info, + (translog_size_t) (sizeof(log_data) + + extents_length), + TRANSLOG_INTERNAL_PARTS + 2, log_array, + log_data, NULL); + stack_alloc_free(compact_extent_info, buff_alloced); + if (result) DBUG_RETURN(1); } @@ -5192,14 +5196,16 @@ my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *org_rec_buff, *old_record; size_t org_rec_buff_size; int error; + my_bool buff_alloced; DBUG_ENTER("_ma_cmp_block_unique"); - /* - Don't allocate more than 16K on the stack to ensure we don't get - stack overflow. - */ - if (!(old_record= my_safe_alloca(info->s->base.reclength))) - DBUG_RETURN(1); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + info->s->base.reclength); + if (!(old_record= res)) + DBUG_RETURN(1); + } /* Don't let the compare destroy blobs that may be in use */ org_rec_buff= info->rec_buff; @@ -5220,7 +5226,7 @@ my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, info->rec_buff_size= org_rec_buff_size; } DBUG_PRINT("exit", ("result: %d", error)); - my_safe_afree(old_record, info->s->base.reclength); + stack_alloc_free(old_record, buff_alloced); DBUG_RETURN(error != 0); } diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index e2c0fa79a3d..719eb330801 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -46,8 +46,7 @@ #include "trnman.h" #include "ma_key_recover.h" #include - -#include +#include #include #ifdef HAVE_SYS_VADVISE_H #include @@ -78,11 +77,11 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a); static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo, const uchar *key); static int sort_insert_key(MARIA_SORT_PARAM *sort_param, - reg1 SORT_KEY_BLOCKS *key_block, + reg1 MA_SORT_KEY_BLOCKS *key_block, const uchar *key, my_off_t prev_block); static int sort_delete_record(MARIA_SORT_PARAM *sort_param); /*static int _ma_flush_pending_blocks(HA_CHECK *param);*/ -static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, +static MA_SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, uint buffer_length); static ha_checksum maria_byte_checksum(const uchar *buf, uint length); static void set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share); @@ -127,6 +126,10 @@ void maria_chk_init(HA_CHECK *param) param->pagecache_block_size= KEY_CACHE_BLOCK_SIZE; param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; param->max_stage= 1; + init_stack_alloc(¶m->stack_alloc, + STACK_ALLOC_BIG_BLOCK, + STACK_ALLOC_SMALL_BLOCK, + 4096); } @@ -863,7 +866,8 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, MARIA_SHARE *share= info->s; char llbuff[22]; uint diff_pos[2]; - uchar tmp_key_buff[MARIA_MAX_KEY_BUFF]; + uchar *tmp_key_buff; + my_bool temp_buff_alloced; MARIA_KEY tmp_key; DBUG_ENTER("chk_index"); DBUG_DUMP("buff", anc_page->buff, anc_page->size); @@ -872,11 +876,17 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (keyinfo->flag & (HA_SPATIAL | HA_RTREE_INDEX)) DBUG_RETURN(0); - if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length))) { - _ma_check_print_error(param,"Not enough memory for keyblock"); - DBUG_RETURN(-1); + void *res; + alloc_on_stack(¶m->stack_alloc, res, temp_buff_alloced, + (keyinfo->block_length + keyinfo->max_store_length)); + if (!(temp_buff= res)) + { + _ma_check_print_error(param,"Not enough memory for keyblock"); + DBUG_RETURN(-1); + } } + tmp_key_buff= temp_buff+ keyinfo->block_length; if (keyinfo->flag & HA_NOSAME) { @@ -1068,10 +1078,10 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo, (uint) (keypos - anc_page->buff)); goto err; } - my_afree(temp_buff); + stack_alloc_free(temp_buff, temp_buff_alloced); DBUG_RETURN(0); err: - my_afree(temp_buff); + stack_alloc_free(temp_buff, temp_buff_alloced); DBUG_RETURN(1); } /* chk_index */ @@ -3227,6 +3237,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, MARIA_SHARE *share= info->s; MARIA_KEY key; MARIA_PAGE page; + my_bool buff_alloced; DBUG_ENTER("sort_one_index"); /* cannot walk over R-tree indices */ @@ -3235,12 +3246,15 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, param->new_file_pos+=keyinfo->block_length; key.keyinfo= keyinfo; - if (!(buff= (uchar*) my_alloca((uint) keyinfo->block_length + - keyinfo->maxlength + - MARIA_INDEX_OVERHEAD_SIZE))) { - _ma_check_print_error(param,"Not enough memory for key block"); - DBUG_RETURN(-1); + void *res; + alloc_on_stack(¶m->stack_alloc, res, buff_alloced, + keyinfo->block_length + keyinfo->max_store_length); + if (!(buff= res)) + { + _ma_check_print_error(param,"Not enough memory for keyblock"); + DBUG_RETURN(-1); + } } key.data= buff + keyinfo->block_length; @@ -3306,10 +3320,10 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, _ma_check_print_error(param,"Can't write indexblock, error: %d",my_errno); goto err; } - my_afree(buff); + stack_alloc_free(buff, buff_alloced); DBUG_RETURN(0); err: - my_afree(buff); + stack_alloc_free(buff, buff_alloced); DBUG_RETURN(1); } /* sort_one_index */ @@ -4472,6 +4486,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, (void) pthread_attr_init(&thr_attr); (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + (void) my_setstacksize(&thr_attr, my_thread_stack_size); for (i=0 ; i < sort_info.total_keys ; i++) { @@ -5581,11 +5596,11 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a) int _ma_sort_ft_buf_flush(MARIA_SORT_PARAM *sort_param) { MARIA_SORT_INFO *sort_info=sort_param->sort_info; - SORT_KEY_BLOCKS *key_block=sort_info->key_block; + MA_SORT_KEY_BLOCKS *key_block=sort_info->key_block; MARIA_SHARE *share=sort_info->info->s; uint val_off, val_len; int error; - SORT_FT_BUF *maria_ft_buf=sort_info->ft_buf; + MA_SORT_FT_BUF *maria_ft_buf=sort_info->ft_buf; uchar *from, *to; val_len=share->ft2_keyinfo.keylength; @@ -5629,8 +5644,8 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, { uint a_len, val_off, val_len, error; MARIA_SORT_INFO *sort_info= sort_param->sort_info; - SORT_FT_BUF *ft_buf= sort_info->ft_buf; - SORT_KEY_BLOCKS *key_block= sort_info->key_block; + MA_SORT_FT_BUF *ft_buf= sort_info->ft_buf; + MA_SORT_KEY_BLOCKS *key_block= sort_info->key_block; MARIA_SHARE *share= sort_info->info->s; val_len=HA_FT_WLEN+share->rec_reflength; @@ -5646,8 +5661,8 @@ static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param, share->rec_reflength) && (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))) - ft_buf= (SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length + - sizeof(SORT_FT_BUF), MYF(MY_WME)); + ft_buf= (MA_SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length + + sizeof(MA_SORT_FT_BUF), MYF(MY_WME)); if (!ft_buf) { @@ -5731,7 +5746,7 @@ static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo, /* Insert a key in sort-key-blocks */ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, - register SORT_KEY_BLOCKS *key_block, + register MA_SORT_KEY_BLOCKS *key_block, const uchar *key, my_off_t prev_block) { @@ -5913,7 +5928,7 @@ int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param) { uint nod_flag,length; my_off_t filepos; - SORT_KEY_BLOCKS *key_block; + MA_SORT_KEY_BLOCKS *key_block; MARIA_SORT_INFO *sort_info= sort_param->sort_info; myf myf_rw=sort_info->param->myf_rw; MARIA_HA *info=sort_info->info; @@ -5965,14 +5980,14 @@ err: /* alloc space and pointers for key_blocks */ -static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, +static MA_SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, uint buffer_length) { reg1 uint i; - SORT_KEY_BLOCKS *block; + MA_SORT_KEY_BLOCKS *block; DBUG_ENTER("alloc_key_blocks"); - if (!(block= (SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+ + if (!(block= (MA_SORT_KEY_BLOCKS*) my_malloc((sizeof(MA_SORT_KEY_BLOCKS)+ buffer_length+IO_SIZE)*blocks, MYF(0)))) { diff --git a/storage/maria/ma_check.h b/storage/maria/ma_check.h new file mode 100644 index 00000000000..1c2a971098d --- /dev/null +++ b/storage/maria/ma_check.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2019 MariaDB Corporation AB + + 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., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1335 USA +*/ + +/* + Types that are different in Aria from those used by MyISAM check tables + in myisamchk.h +*/ + +typedef struct st_sort_key_blocks /* Used when sorting */ +{ + uchar *buff, *end_pos; + uchar lastkey[MARIA_MAX_POSSIBLE_KEY_BUFF]; + uint last_length; + int inited; +} MA_SORT_KEY_BLOCKS; + +typedef struct st_sort_ftbuf +{ + uchar *buf, *end; + int count; + uchar lastkey[MARIA_MAX_KEY_BUFF]; +} MA_SORT_FT_BUF; diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index e46f2048aee..f683c64f346 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -75,7 +75,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, uint max_field_lengths, extra_header_size, column_nr; uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; - char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr; + char kfilename[FN_REFLEN], klinkname[FN_REFLEN], *klinkname_ptr= 0; char dfilename[FN_REFLEN], dlinkname[FN_REFLEN], *dlinkname_ptr= 0; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 7377f3bf5ad..3e3689cfd35 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -158,13 +158,21 @@ my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key) { MARIA_SHARE *share= info->s; int res; + my_bool buff_alloced; LSN lsn= LSN_IMPOSSIBLE; my_off_t new_root= share->state.key_root[key->keyinfo->key_nr]; - uchar key_buff[MARIA_MAX_KEY_BUFF], *save_key_data; + uchar *key_buff, *save_key_data; MARIA_KEY org_key; DBUG_ENTER("_ma_ck_delete"); LINT_INIT_STRUCT(org_key); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + key->keyinfo->max_store_length); + if (!(key_buff= res)) + DBUG_RETURN(1); + } save_key_data= key->data; if (share->now_transactional) @@ -190,6 +198,8 @@ my_bool _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key) _ma_fast_unlock_key_del(info); } _ma_unpin_all_pages_and_finalize_row(info, lsn); + + stack_alloc_free(key_buff, buff_alloced); DBUG_RETURN(res != 0); } /* _ma_ck_delete */ @@ -198,7 +208,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, my_off_t *root) { int error; - my_bool result= 0; + my_bool result= 0, buff_alloced; my_off_t old_root; uchar *root_buff; MARIA_KEYDEF *keyinfo= key->keyinfo; @@ -210,13 +220,15 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, _ma_set_fatal_error(info->s, HA_ERR_CRASHED); DBUG_RETURN(1); } - if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MARIA_MAX_KEY_BUFF*2))) + { - DBUG_PRINT("error",("Couldn't allocate memory")); - my_errno=ENOMEM; - DBUG_RETURN(1); + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + (keyinfo->block_length + keyinfo->max_store_length*2)); + if (!(root_buff= res)) + DBUG_RETURN(1); } + DBUG_PRINT("info",("root_page: %lu", (ulong) (old_root / keyinfo->block_length))); if (_ma_fetch_keypage(&page, info, keyinfo, old_root, @@ -261,7 +273,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, } } err: - my_afree(root_buff); + stack_alloc_free(root_buff, buff_alloced); DBUG_PRINT("exit",("Return: %d",result)); DBUG_RETURN(result); } /* _ma_ck_real_delete */ @@ -284,9 +296,8 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, { int flag,ret_value,save_flag; uint nod_flag, page_flag; - my_bool last_key; - uchar *leaf_buff,*keypos; - uchar lastkey[MARIA_MAX_KEY_BUFF]; + my_bool last_key, buff_alloced= 0, lastkey_alloced; + uchar *leaf_buff=0, *keypos, *lastkey; MARIA_KEY_PARAM s_temp; MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; @@ -294,12 +305,20 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, DBUG_ENTER("d_search"); DBUG_DUMP("page", anc_page->buff, anc_page->size); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, lastkey_alloced, + keyinfo->max_store_length); + if (!(lastkey= res)) + DBUG_RETURN(1); + } + flag=(*keyinfo->bin_search)(key, anc_page, comp_flag, &keypos, lastkey, &last_key); if (flag == MARIA_FOUND_WRONG_KEY) { DBUG_PRINT("error",("Found wrong key")); - DBUG_RETURN(-1); + goto err; } page_flag= anc_page->flag; nod_flag= anc_page->node; @@ -344,14 +363,14 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, &kpos))) { _ma_set_fatal_error(share, HA_ERR_CRASHED); - DBUG_RETURN(-1); + goto err; } root= _ma_row_pos_from_key(&tmp_key); if (subkeys == -1) { /* the last entry in sub-tree */ if (_ma_dispose(info, root, 1)) - DBUG_RETURN(-1); + goto err; /* fall through to normal delete */ } else @@ -378,22 +397,21 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS); } - DBUG_PRINT("exit",("Return: %d",ret_value)); - DBUG_RETURN(ret_value); + goto end; } } } - leaf_buff=0; if (nod_flag) { /* Read left child page */ leaf_page.pos= _ma_kpos(nod_flag,keypos); - if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MARIA_MAX_KEY_BUFF*2))) + { - DBUG_PRINT("error", ("Couldn't allocate memory")); - my_errno=ENOMEM; - DBUG_RETURN(-1); + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + (keyinfo->block_length + keyinfo->max_store_length*2)); + if (!(leaf_buff= res)) + goto err; } if (_ma_fetch_keypage(&leaf_page, info,keyinfo, leaf_page.pos, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, leaf_buff, @@ -439,7 +457,7 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, _ma_log_delete(anc_page, s_temp.key_pos, s_temp.changed_length, s_temp.move_length, 0, KEY_OP_DEBUG_LOG_DEL_CHANGE_1)) - DBUG_RETURN(-1); + goto err; if (!nod_flag) { /* On leaf page */ @@ -448,12 +466,15 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, (uint) keyinfo->underflow_block_length)) { /* Page will be written by caller if we return 1 */ - DBUG_RETURN(1); + ret_value= 1; + goto end; } if (_ma_write_keypage(anc_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS)) - DBUG_RETURN(-1); - DBUG_RETURN(0); + goto err; + + ret_value= 0; /* Return ok */ + goto end; } save_flag=1; /* Mark that anc_buff is changed */ ret_value= del(info, key, anc_page, &leaf_page, @@ -506,12 +527,16 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, { DBUG_DUMP("page", anc_page->buff, anc_page->size); } - my_afree(leaf_buff); + +end: + stack_alloc_free(leaf_buff, buff_alloced); + stack_alloc_free(lastkey, lastkey_alloced); DBUG_PRINT("exit",("Return: %d",ret_value)); DBUG_RETURN(ret_value); err: - my_afree(leaf_buff); + stack_alloc_free(leaf_buff, buff_alloced); + stack_alloc_free(lastkey, lastkey_alloced); DBUG_PRINT("exit",("Error: %d",my_errno)); DBUG_RETURN (-1); } /* d_search */ @@ -550,8 +575,9 @@ static int del(MARIA_HA *info, MARIA_KEY *key, { int ret_value,length; uint a_length, page_flag, nod_flag, leaf_length, new_leaf_length; - uchar keybuff[MARIA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; + uchar *keybuff,*endpos,*next_buff,*key_start, *prev_key; uchar *anc_buff; + my_bool buff_alloced= 0, keybuff_alloced; MARIA_KEY_PARAM s_temp; MARIA_KEY tmp_key; MARIA_SHARE *share= info->s; @@ -564,6 +590,14 @@ static int del(MARIA_HA *info, MARIA_KEY *key, keypos)); DBUG_DUMP("leaf_buff", leaf_page->buff, leaf_page->size); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, keybuff_alloced, + keyinfo->max_store_length); + if (!(keybuff= res)) + DBUG_RETURN(1); + } + page_flag= leaf_page->flag; leaf_length= leaf_page->size; nod_flag= leaf_page->node; @@ -574,14 +608,20 @@ static int del(MARIA_HA *info, MARIA_KEY *key, next_buff= 0; if (!(key_start= _ma_get_last_key(&tmp_key, leaf_page, endpos))) - DBUG_RETURN(-1); + goto err; if (nod_flag) { next_page.pos= _ma_kpos(nod_flag,endpos); - if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MARIA_MAX_KEY_BUFF*2))) - DBUG_RETURN(-1); + + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + (keyinfo->block_length + keyinfo->max_store_length*2)); + if (!(next_buff= res)) + goto err; + } + if (_ma_fetch_keypage(&next_page, info, keyinfo, next_page.pos, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, next_buff, 0)) ret_value= -1; @@ -634,7 +674,8 @@ static int del(MARIA_HA *info, MARIA_KEY *key, DFLT_INIT_HITS)) goto err; } - my_afree(next_buff); + stack_alloc_free(next_buff, buff_alloced); + stack_alloc_free(keybuff, keybuff_alloced); DBUG_ASSERT(leaf_page->size <= share->max_index_block_size); DBUG_RETURN(ret_value); } @@ -712,13 +753,15 @@ static int del(MARIA_HA *info, MARIA_KEY *key, goto err; DBUG_ASSERT(leaf_page->size <= share->max_index_block_size); + stack_alloc_free(next_buff, buff_alloced); + stack_alloc_free(keybuff, keybuff_alloced); DBUG_RETURN(new_leaf_length <= (info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : (uint) keyinfo->underflow_block_length)); -err: - if (next_buff) - my_afree(next_buff); +err: + stack_alloc_free(next_buff, buff_alloced); + stack_alloc_free(keybuff, keybuff_alloced); DBUG_RETURN(-1); } /* del */ @@ -761,13 +804,13 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint next_buff_length, new_buff_length, key_reflength; uint unchanged_leaf_length, new_leaf_length, new_anc_length; uint anc_page_flag, page_flag; - uchar anc_key_buff[MARIA_MAX_KEY_BUFF], leaf_key_buff[MARIA_MAX_KEY_BUFF]; + uchar *anc_key_buff, *leaf_key_buff; uchar *endpos, *next_keypos, *anc_pos, *half_pos, *prev_key; uchar *anc_buff, *leaf_buff; uchar *after_key, *anc_end_pos; MARIA_KEY_PARAM key_deleted, key_inserted; MARIA_SHARE *share= info->s; - my_bool first_key; + my_bool first_key, buff_alloced; MARIA_KEY tmp_key, anc_key, leaf_key; MARIA_PAGE next_page; DBUG_ENTER("underflow"); @@ -777,6 +820,15 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo, DBUG_DUMP("anc_buff", anc_page->buff, anc_page->size); DBUG_DUMP("leaf_buff", leaf_page->buff, leaf_page->size); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->max_store_length*2); + if (!(anc_key_buff= res)) + DBUG_RETURN(1); + leaf_key_buff= anc_key_buff+ keyinfo->max_store_length; + } + anc_page_flag= anc_page->flag; anc_buff= anc_page->buff; leaf_buff= leaf_page->buff; @@ -1035,6 +1087,7 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(leaf_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS)) goto err; + stack_alloc_free(anc_key_buff, buff_alloced); DBUG_RETURN(new_anc_length <= ((info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : (uint) keyinfo->underflow_block_length))); @@ -1264,11 +1317,13 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS)) goto err; + stack_alloc_free(anc_key_buff, buff_alloced); DBUG_RETURN(new_anc_length <= ((info->quick_mode ? MARIA_MIN_KEYBLOCK_LENGTH : (uint) keyinfo->underflow_block_length))); err: + stack_alloc_free(anc_key_buff, buff_alloced); DBUG_RETURN(-1); } /* underflow */ diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index ae6fc57c114..a8b33ea9657 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -249,16 +249,23 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const uchar *record) uchar *rec_buff; int error; ulong reclength,reclength2,extra; + my_bool buff_alloced; extra= (ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER)+MARIA_SPLIT_LENGTH+ MARIA_DYN_DELETE_BLOCK_HEADER+1); reclength= (info->s->base.pack_reclength + _ma_calc_total_blob_length(info,record)+ extra); - if (!(rec_buff=(uchar*) my_safe_alloca(reclength))) + { - my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ - return(1); + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, reclength); + if (!(rec_buff= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ + return(1); + } } + reclength2= _ma_rec_pack(info, rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), record); @@ -275,7 +282,7 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const uchar *record) rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), reclength2); err: - my_safe_afree(rec_buff, reclength); + stack_alloc_free(rec_buff, buff_alloced); return(error != 0); } @@ -287,6 +294,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, uchar *rec_buff; int error; ulong reclength,reclength2,extra; + my_bool buff_alloced; extra= (ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER)+MARIA_SPLIT_LENGTH+ MARIA_DYN_DELETE_BLOCK_HEADER); @@ -299,10 +307,15 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, return 1; } #endif - if (!(rec_buff=(uchar*) my_safe_alloca(reclength))) + { - my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ - return(1); + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, reclength); + if (!(rec_buff= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ + return(1); + } } reclength2= _ma_rec_pack(info, rec_buff+ ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), @@ -317,7 +330,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos, rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER), reclength2); err: - my_safe_afree(rec_buff, reclength); + stack_alloc_free(rec_buff, buff_alloced); return(error != 0); } @@ -1579,11 +1592,16 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, { uchar *old_rec_buff,*old_record; size_t old_rec_buff_size; - my_bool error; + my_bool error, buff_alloced; DBUG_ENTER("_ma_cmp_dynamic_unique"); - if (!(old_record= my_safe_alloca(info->s->base.reclength))) - DBUG_RETURN(1); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + info->s->base.reclength); + if (!(old_record= res)) + DBUG_RETURN(1); + } /* Don't let the compare destroy blobs that may be in use */ old_rec_buff= info->rec_buff; @@ -1603,7 +1621,7 @@ my_bool _ma_cmp_dynamic_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, info->rec_buff= old_rec_buff; info->rec_buff_size= old_rec_buff_size; } - my_safe_afree(old_record, info->s->base.reclength); + stack_alloc_free(old_record, buff_alloced); DBUG_RETURN(error); } @@ -1617,7 +1635,7 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info, my_off_t filepos; uchar *buffer; MARIA_BLOCK_INFO block_info; - my_bool error= 1; + my_bool error= 1, buff_alloced= 0; size_t UNINIT_VAR(buffer_length); DBUG_ENTER("_ma_cmp_dynamic_record"); @@ -1638,8 +1656,13 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info, { buffer_length= (info->s->base.pack_reclength + _ma_calc_total_blob_length(info,record)); - if (!(buffer=(uchar*) my_safe_alloca(buffer_length))) - DBUG_RETURN(1); + + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, buffer_length); + if (!(buffer= res)) + DBUG_RETURN(1); + } } if (!(reclength= _ma_rec_pack(info,buffer,record))) goto err; @@ -1691,8 +1714,7 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info, my_errno=0; error= 0; err: - if (buffer != info->rec_buff) - my_safe_afree(buffer, buffer_length); + stack_alloc_free(buffer, buff_alloced); DBUG_PRINT("exit", ("result: %d", error)); DBUG_RETURN(error); } diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c index 6d40f804880..f0b04e020c2 100644 --- a/storage/maria/ma_info.c +++ b/storage/maria/ma_info.c @@ -31,7 +31,7 @@ MARIA_RECORD_POS maria_position(MARIA_HA *info) uint maria_max_key_length() { uint tmp= (_ma_max_key_length() - 8 - HA_MAX_KEY_SEG*3); - return MY_MIN(HA_MAX_KEY_LENGTH, tmp); + return MY_MIN(MARIA_MAX_KEY_LENGTH, tmp); } /* Get information about the table */ diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index cf17d88f6e9..4995d3832ea 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -716,6 +716,12 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, disk_pos=_ma_keydef_read(disk_pos, keyinfo); keyinfo->key_nr= i; + /* Calculate length to store a key + nod flag and transaction info */ + keyinfo->max_store_length= (keyinfo->maxlength + + share->base.key_reflength); + if (share->base.born_transactional) + keyinfo->max_store_length+= MARIA_INDEX_OVERHEAD_SIZE; + /* See ma_delete.cc::underflow() */ if (!(keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY))) keyinfo->underflow_block_length= keyinfo->block_length/3; @@ -1170,6 +1176,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, mysql_mutex_unlock(&THR_LOCK_maria); m_info->open_flags= open_flags; + aria_init_stack_alloc(m_info); DBUG_PRINT("exit", ("table: %p name: %s",m_info, name)); DBUG_RETURN(m_info); diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c index a90efc4ca38..b7bbbdaf630 100644 --- a/storage/maria/ma_rt_index.c +++ b/storage/maria/ma_rt_index.c @@ -66,12 +66,19 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int key_data_length; uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level; MARIA_PAGE page; + my_bool buff_alloced; - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length))) { - my_errno= HA_ERR_OUT_OF_MEM; - return -1; + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length); + if (!(page_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + return(-1); + } } + if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, page_buf, 0)) @@ -165,11 +172,11 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, res= 1; ok: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); return res; err: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); info->cur_row.lastpos= HA_OFFSET_ERROR; return -1; } @@ -329,10 +336,20 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uint nod_flag, key_data_length; int res; uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level; + my_bool buff_alloced; MARIA_PAGE page; - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length))) - return -1; + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length); + if (!(page_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + return(-1); + } + } + if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, page_buf, 0)) @@ -422,11 +439,11 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo, res= 1; ok: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); return res; err: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); info->cur_row.lastpos= HA_OFFSET_ERROR; return -1; } @@ -603,18 +620,24 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key, uint nod_flag; uint key_length= key->data_length; int res; + my_bool buff_alloced; uchar *page_buf, *k; MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; DBUG_ENTER("maria_rtree_insert_req"); - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length + - MARIA_MAX_KEY_BUFF))) { - my_errno= HA_ERR_OUT_OF_MEM; - DBUG_RETURN(-1); /* purecov: inspected */ + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length + keyinfo->max_store_length); + if (!(page_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + DBUG_RETURN(-1); /* purecov: inspected */ + } } + if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, page_buf, 0)) goto err; @@ -695,7 +718,7 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key, } ok: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); DBUG_RETURN(res); err: @@ -765,6 +788,7 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level, case 1: /* root was split, grow a new root; very rare */ { uchar *new_root_buf, *new_key_buff; + my_bool new_root_buf_alloced; my_off_t new_root; uint nod_flag= share->base.key_reflength; MARIA_PINNED_PAGE tmp_page_link, *page_link; @@ -773,14 +797,19 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level, page_link= &tmp_page_link; DBUG_PRINT("rtree", ("root was split, grow a new root")); - if (!(new_root_buf= (uchar*) my_alloca((uint) keyinfo->block_length + - MARIA_MAX_KEY_BUFF))) + { - my_errno= HA_ERR_OUT_OF_MEM; - DBUG_RETURN(-1); /* purecov: inspected */ + void *res; + alloc_on_stack(&info->stack_alloc, res, new_root_buf_alloced, + keyinfo->block_length + keyinfo->max_store_length); + if (!(new_root_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + DBUG_RETURN(-1); /* purecov: inspected */ + } } - bzero(new_root_buf, share->block_size); + bzero(new_root_buf, keyinfo->block_length); _ma_store_keypage_flag(share, new_root_buf, KEYPAGE_FLAG_ISNOD); _ma_store_keynr(share, new_root_buf, keyinfo->key_nr); _ma_store_page_used(share, new_root_buf, share->keypage_header); @@ -805,14 +834,12 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level, _ma_kpointer(info, new_key_buff - nod_flag, old_root); if (maria_rtree_set_key_mbr(info, &new_key, old_root)) goto err; - if (maria_rtree_add_key(&new_key, &page, NULL) - == -1) + if (maria_rtree_add_key(&new_key, &page, NULL) == -1) goto err; _ma_kpointer(info, new_key_buff - nod_flag, new_page); if (maria_rtree_set_key_mbr(info, &new_key, new_page)) goto err; - if (maria_rtree_add_key(&new_key, &page, NULL) - == -1) + if (maria_rtree_add_key(&new_key, &page, NULL) == -1) goto err; if (_ma_write_keypage(&page, write_lock, DFLT_INIT_HITS)) goto err; @@ -820,10 +847,10 @@ int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level, DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u", (ulong) new_root, 0, page.node)); - my_afree(new_root_buf); + stack_alloc_free(new_root_buf, new_root_buf_alloced); break; err: - my_afree(new_root_buf); + stack_alloc_free(new_root_buf, new_root_buf_alloced); DBUG_RETURN(-1); /* purecov: inspected */ } default: @@ -922,17 +949,24 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key, ulong i; uint nod_flag; int res; + my_bool buff_alloced; uchar *page_buf, *last, *k; MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; DBUG_ENTER("maria_rtree_delete_req"); - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length))) { - my_errno= HA_ERR_OUT_OF_MEM; - DBUG_RETURN(-1); /* purecov: inspected */ + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length); + if (!(page_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + DBUG_RETURN(-1); + } } + if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, page_buf, 0)) goto err; @@ -1072,11 +1106,11 @@ static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key, res= 1; ok: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); DBUG_RETURN(res); err: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); DBUG_RETURN(-1); /* purecov: inspected */ } @@ -1121,6 +1155,8 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; uint key_data_length= key->data_length; + my_bool buff_alloced= 0; + uchar *page_buf= 0; DBUG_ENTER("maria_rtree_real_delete"); if ((old_root= share->state.key_root[keyinfo->key_nr]) == @@ -1147,9 +1183,9 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, { uint nod_flag; ulong i; - uchar *page_buf; MARIA_PAGE page; MARIA_KEY tmp_key; + tmp_key.keyinfo= key->keyinfo; tmp_key.data_length= key->data_length; tmp_key.ref_length= key->ref_length; @@ -1157,10 +1193,15 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, if (ReinsertList.n_pages) { - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length))) { - my_errno= HA_ERR_OUT_OF_MEM; - goto err; + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length); + if (!(page_buf= res)) + { + my_errno= HA_ERR_OUT_OF_MEM; + goto err; + } } for (i= 0; i < ReinsertList.n_pages; ++i) @@ -1186,10 +1227,7 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, if ((res= maria_rtree_insert_level(info, &tmp_key, ReinsertList.pages[i].level, root)) == -1) - { - my_afree(page_buf); goto err; - } if (res) { uint j; @@ -1205,13 +1243,8 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, } page_mark_changed(info, &page); if (_ma_dispose(info, page.pos, 0)) - { - my_afree(page_buf); goto err; - } } - my_afree(page_buf); - my_free(ReinsertList.pages); } /* check for redundant root (not leaf, 1 child) and eliminate */ @@ -1243,9 +1276,13 @@ my_bool maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, default: goto err; /* purecov: inspected */ } + my_free(ReinsertList.pages); + stack_alloc_free(page_buf, buff_alloced); DBUG_RETURN(0); err: + my_free(ReinsertList.pages); + stack_alloc_free(page_buf, buff_alloced); DBUG_RETURN(1); } @@ -1268,14 +1305,22 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag) MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; + my_bool buff_alloced; if (flag & MBR_DISJOINT) return HA_POS_ERROR; if ((root= share->state.key_root[key->keyinfo->key_nr]) == HA_OFFSET_ERROR) return HA_POS_ERROR; - if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length))) - return HA_POS_ERROR; + + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->block_length); + if (!(page_buf= res)) + return(HA_POS_ERROR); + } + if (_ma_fetch_keypage(&page, info, keyinfo, root, PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, page_buf, 0)) @@ -1343,11 +1388,11 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag) res= HA_POS_ERROR; } - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); return res; err: - my_afree(page_buf); + stack_alloc_free(page_buf, buff_alloced); return HA_POS_ERROR; } diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c index 1eb0ffb5b89..3387a9d82ab 100644 --- a/storage/maria/ma_rt_split.c +++ b/storage/maria/ma_rt_split.c @@ -378,7 +378,7 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page, double *next_coord; int n_dim; uchar *source_cur, *cur1, *cur2; - uchar *new_page_buff, *log_internal_copy, *log_internal_copy_ptr, + uchar *new_page_buff= 0, *log_internal_copy, *log_internal_copy_ptr, *log_key_copy= NULL; int err_code= 0; uint new_page_length; @@ -390,15 +390,21 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page, int max_keys= ((org_length - share->keypage_header) / (full_length)); MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link; MARIA_KEYDEF *keyinfo= key->keyinfo; + my_bool new_page_buff_alloced= 0, coord_buf_alloced= 0; DBUG_ENTER("maria_rtree_split_page"); DBUG_PRINT("rtree", ("splitting block")); n_dim= keyinfo->keysegs / 2; - if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) * - (max_keys + 1 + 4) + - sizeof(SplitStruct) * (max_keys + 1)))) - DBUG_RETURN(-1); /* purecov: inspected */ + { + void *res; + size_t length= (n_dim * 2 * sizeof(double) * + (max_keys + 1 + 4) + + sizeof(SplitStruct) * (max_keys + 1)); + alloc_on_stack(&info->stack_alloc, res, coord_buf_alloced, length); + if (!(coord_buf= res)) + DBUG_RETURN(-1); + } task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4)); @@ -433,14 +439,19 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page, } /* Allocate buffer for new page and piece of log record */ - if (!(new_page_buff= (uchar*) my_alloca((uint)keyinfo->block_length + - (transactional ? - (max_keys * (2 + 2) + - 1 + 2 + 1 + 2) : 0)))) { - err_code= -1; - goto split_err; + void *res; + size_t len= (keyinfo->block_length + + (transactional ? (max_keys * (2 + 2) + 1 + 2 + 1 + 2) : 0)); + + alloc_on_stack(&info->stack_alloc, res, new_page_buff_alloced, len); + if (!(new_page_buff= res)) + { + err_code= -1; + goto split_err; + } } + log_internal_copy= log_internal_copy_ptr= new_page_buff + keyinfo->block_length; bzero(new_page_buff, share->block_size); @@ -538,9 +549,9 @@ int maria_rtree_split_page(const MARIA_KEY *key, MARIA_PAGE *page, } DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs)); - my_afree(new_page_buff); split_err: - my_afree(coord_buf); + stack_alloc_free(new_page_buff, new_page_buff_alloced); + stack_alloc_free(coord_buf, coord_buf_alloced); DBUG_RETURN(err_code); } diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 63035925653..b5ed64a6843 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -114,11 +114,11 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, MARIA_PINNED_PAGE **res_page_link, uchar **res_page_buff) { - my_bool last_key_not_used; + my_bool last_key_not_used, buff_alloced; int error,flag; uint page_flag, nod_flag, used_length; uchar *keypos,*maxpos; - uchar lastkey[MARIA_MAX_KEY_BUFF]; + uchar *lastkey; MARIA_KEYDEF *keyinfo= key->keyinfo; MARIA_PAGE page; MARIA_PINNED_PAGE *page_link; @@ -138,6 +138,14 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, DBUG_RETURN(1); /* Search at upper levels */ } + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->max_store_length); + if (!(lastkey= res)) + DBUG_RETURN(1); + } + if (_ma_fetch_keypage(&page, info, keyinfo, pos, PAGECACHE_LOCK_READ, DFLT_INIT_HITS, 0, 0)) goto err; @@ -164,16 +172,17 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, if ((error= _ma_search_no_save(info, key, nextflag, _ma_kpos(nod_flag,keypos), res_page_link, res_page_buff)) <= 0) - DBUG_RETURN(error); + goto ret_error; + error= 1; /* Default return value */ if (flag >0) { if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) && keypos == page.buff + info->s->keypage_header + nod_flag) - DBUG_RETURN(1); /* Bigger than key */ + goto ret_error; /* Bigger than key */ } else if (nextflag & SEARCH_BIGGER && keypos >= maxpos) - DBUG_RETURN(1); /* Smaller than key */ + goto ret_error; /* Smaller than key */ } else { @@ -188,7 +197,7 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, _ma_kpos(nod_flag,keypos), res_page_link, res_page_buff)) >= 0 || my_errno != HA_ERR_KEY_NOT_FOUND) - DBUG_RETURN(error); + goto ret_error; } } @@ -233,6 +242,7 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key, *res_page_link= page_link; *res_page_buff= page.buff; + stack_alloc_free(lastkey, buff_alloced); DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos)); DBUG_RETURN(0); @@ -240,7 +250,11 @@ err: DBUG_PRINT("exit",("Error: %d",my_errno)); info->cur_row.lastpos= HA_OFFSET_ERROR; info->page_changed=1; - DBUG_RETURN (-1); + error= -1; + +ret_error: + stack_alloc_free(lastkey, buff_alloced); + DBUG_RETURN(error); } diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index 3a7981c81b4..091ac7e9278 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -870,7 +870,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), record_type= DYNAMIC_RECORD; break; case 'k': - if (key_length < 4 || key_length > HA_MAX_KEY_LENGTH) + if (key_length < 4 || key_length > MARIA_MAX_KEY_LENGTH) { fprintf(stderr,"Wrong key length\n"); exit(1); diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 07be8333794..1e43454454b 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -620,9 +620,8 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, my_bool insert_last) { int error,flag; - uchar *temp_buff,*keypos; - uchar keybuff[MARIA_MAX_KEY_BUFF]; - my_bool was_last_key; + uchar *temp_buff,*keypos,*keybuff; + my_bool was_last_key, buff_alloced; my_off_t next_page, dup_key_pos; MARIA_SHARE *share= info->s; MARIA_KEYDEF *keyinfo= key->keyinfo; @@ -630,9 +629,15 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, DBUG_ENTER("w_search"); DBUG_PRINT("enter", ("page: %lu", (ulong) (page_pos/keyinfo->block_length))); - if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MARIA_MAX_KEY_BUFF*2))) - DBUG_RETURN(-1); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + (keyinfo->block_length + keyinfo->max_store_length*3)); + if (!(temp_buff= res)) + DBUG_RETURN(1); + } + keybuff= temp_buff + (keyinfo->block_length + keyinfo->max_store_length*2); + if (_ma_fetch_keypage(&page, info, keyinfo, page_pos, PAGECACHE_LOCK_WRITE, DFLT_INIT_HITS, temp_buff, 0)) goto err; @@ -692,7 +697,7 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, DFLT_INIT_HITS)) goto err; } - my_afree(temp_buff); + stack_alloc_free(temp_buff, buff_alloced); DBUG_RETURN(error); } } @@ -742,10 +747,10 @@ static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key, DFLT_INIT_HITS)) goto err; } - my_afree(temp_buff); + stack_alloc_free(temp_buff, buff_alloced); DBUG_RETURN(error); err: - my_afree(temp_buff); + stack_alloc_free(temp_buff, buff_alloced); DBUG_PRINT("exit",("Error: %d",my_errno)); DBUG_RETURN(-1); } /* w_search */ @@ -1243,15 +1248,23 @@ static int _ma_balance_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, { MARIA_PINNED_PAGE tmp_page_link, *new_page_link= &tmp_page_link; MARIA_SHARE *share= info->s; - my_bool right; + my_bool right, buff_alloced; uint k_length,father_length,father_keylength,nod_flag,curr_keylength; uint right_length,left_length,new_right_length,new_left_length,extra_length; uint keys, tmp_length, extra_buff_length; uchar *pos, *extra_buff, *parting_key; - uchar tmp_part_key[MARIA_MAX_KEY_BUFF]; + uchar *tmp_part_key; MARIA_PAGE next_page, extra_page, *left_page, *right_page; DBUG_ENTER("_ma_balance_page"); + { + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + keyinfo->max_store_length); + if (!(tmp_part_key= res)) + DBUG_RETURN(-1); + } + k_length= keyinfo->keylength; father_length= father_page->size; father_keylength= k_length + share->base.key_reflength; @@ -1463,6 +1476,7 @@ static int _ma_balance_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, _ma_write_keypage(father_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS)) goto err; + stack_alloc_free(tmp_part_key, buff_alloced); DBUG_RETURN(0); } @@ -1633,9 +1647,11 @@ static int _ma_balance_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, DFLT_INIT_HITS)) goto err; + stack_alloc_free(tmp_part_key, buff_alloced); DBUG_RETURN(1); /* Middle key up */ err: + stack_alloc_free(tmp_part_key, buff_alloced); DBUG_RETURN(-1); } /* _ma_balance_page */ diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 907aab91141..30ac9d5eca9 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -2012,9 +2011,10 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param, MARIA_HA *info= ma_page->info; MARIA_SHARE *share= info->s; uint page_flag, nod_flag,used_length; + my_bool buff_alloced; uchar *temp_buff,*keypos,*endpos; my_off_t next_page,rec_pos; - uchar lastkey[MARIA_MAX_KEY_BUFF]; + uchar *lastkey; char llbuff[22]; MARIA_SORT_INFO *sort_info= sort_param->sort_info; HA_CHECK *param=sort_info->param; @@ -2023,20 +2023,27 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param, const MARIA_KEYDEF *keyinfo= ma_page->keyinfo; DBUG_ENTER("sort_record_index"); + temp_buff=0; page_flag= ma_page->flag; nod_flag= ma_page->node; - temp_buff=0; tmp_key.keyinfo= (MARIA_KEYDEF*) keyinfo; - tmp_key.data= lastkey; - if (nod_flag) { - if (!(temp_buff= (uchar*) my_alloca(tmp_key.keyinfo->block_length))) + void *res; + alloc_on_stack(&info->stack_alloc, res, buff_alloced, + (nod_flag ? keyinfo->block_length : 0) + + ALIGN_SIZE(keyinfo->max_store_length)); + if (!(lastkey= res)) { _ma_check_print_error(param,"Not Enough memory"); DBUG_RETURN(-1); } + if (nod_flag) + temp_buff= lastkey + ALIGN_SIZE(keyinfo->max_store_length); } + + tmp_key.data= lastkey; + used_length= ma_page->size; keypos= ma_page->buff + share->keypage_header + nod_flag; endpos= ma_page->buff + used_length; @@ -2091,12 +2098,11 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param, _ma_check_print_error(param,"%d when updating keyblock",my_errno); goto err; } - if (temp_buff) - my_afree(temp_buff); + stack_alloc_free(lastkey, buff_alloced); DBUG_RETURN(0); + err: - if (temp_buff) - my_afree(temp_buff); + stack_alloc_free(lastkey, buff_alloced); DBUG_RETURN(1); } /* sort_record_index */ diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 56718731b45..110339ba722 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -48,6 +48,9 @@ /* maria_open() flag, specific for maria_pack */ #define HA_OPEN_IGNORE_MOVED_STATE (1U << 30) +typedef struct st_sort_key_blocks MA_SORT_KEY_BLOCKS; +typedef struct st_sort_ftbuf MA_SORT_FT_BUF; + extern PAGECACHE maria_pagecache_var, *maria_pagecache; int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map, PAGECACHE *key_cache); @@ -62,8 +65,8 @@ typedef struct st_maria_sort_info MARIA_HA *info, *new_info; HA_CHECK *param; char *buff; - SORT_KEY_BLOCKS *key_block, *key_block_end; - SORT_FT_BUF *ft_buf; + MA_SORT_KEY_BLOCKS *key_block, *key_block_end; + MA_SORT_FT_BUF *ft_buf; my_off_t filelength, dupp, buff_length; pgcache_page_no_t page; ha_rows max_records; @@ -221,6 +224,10 @@ typedef struct st_maria_state_info #define MARIA_FILE_CREATE_RENAME_LSN_OFFSET 4 #define MARIA_FILE_CREATE_TRID_OFFSET (4 + LSN_STORE_SIZE*3 + 11*8) +#define MARIA_MAX_KEY_LENGTH 2000 +#define MARIA_MAX_KEY_BUFF (MARIA_MAX_KEY_LENGTH+HA_MAX_KEY_SEG*6+8+8 + \ + MARIA_MAX_PACK_TRANSID_SIZE) +#define MARIA_MAX_POSSIBLE_KEY_BUFF (MARIA_MAX_KEY_LENGTH + 24+ 6+6) #define MARIA_STATE_KEY_SIZE (8 + 4) #define MARIA_STATE_KEYBLOCK_SIZE 8 #define MARIA_STATE_KEYSEG_SIZE 12 @@ -228,7 +235,6 @@ typedef struct st_maria_state_info #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_MAX_KEY_BUFF (HA_MAX_KEY_BUFF + MARIA_MAX_PACK_TRANSID_SIZE) #define MARIA_COLUMNDEF_SIZE (2*7+1+1+4) #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 */ @@ -245,6 +251,8 @@ typedef struct st_maria_state_info #define MA_EXTRA_OPTIONS_ENCRYPTED (1 << 0) #define MA_EXTRA_OPTIONS_INSERT_ORDER (1 << 1) +#include "ma_check.h" + /* Basic information of the Maria table. This is stored on disk and not changed (unless we do DLL changes). @@ -615,6 +623,7 @@ struct st_maria_handler MARIA_STATUS_INFO *state_start; /* State at start of transaction */ MARIA_USED_TABLES *used_tables; struct ms3_st *s3; + STACK_ALLOC stack_alloc; MARIA_ROW cur_row; /* The active row that we just read */ MARIA_ROW new_row; /* Storage for a row during update */ MARIA_KEY last_key; /* Last found key */ @@ -1459,3 +1468,18 @@ static inline void unmap_file(MARIA_HA *info __attribute__((unused))) _ma_unmap_file(info); #endif } + +static inline void aria_init_stack_alloc(MARIA_HA *info) +{ +#ifndef DEBUG_STACK_ALLOC + init_stack_alloc(&info->stack_alloc, + STACK_ALLOC_BIG_BLOCK, + STACK_ALLOC_SMALL_BLOCK, + 4096); +#else + /* + Force all allocation to go trough malloc to more easily find corruptions + */ + init_stack_alloc(&info->stack_alloc, 10000000, 10000000, 4096); +#endif /* DEBUG_STACK_ALLOC */ +} diff --git a/storage/maria/s3_func.c b/storage/maria/s3_func.c index 8600b0ec7db..25f13d92741 100644 --- a/storage/maria/s3_func.c +++ b/storage/maria/s3_func.c @@ -533,7 +533,7 @@ int aria_copy_from_s3(ms3_st *s3_client, const char *aws_bucket, char table_name[FN_REFLEN], aws_path[FN_REFLEN+100]; char filename[FN_REFLEN]; char *aws_path_end, *end; - File file; + File file= -1; S3_BLOCK block; my_off_t index_file_size, data_file_size; uint offset; diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index f4b3ae39676..8ca100ed45f 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -46,7 +46,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uint aligned_key_start, block_length, res; uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; - char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr; + char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr= 0; char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr= 0; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 7fc8a8eba4f..06dd864fcfd 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -612,7 +612,24 @@ typedef struct st_mi_block_info /* Parameter to _mi_get_block_info */ uint offset; } MI_BLOCK_INFO; - /* bits in return from _mi_get_block_info */ + +typedef struct st_sort_key_blocks /* Used when sorting */ +{ + uchar *buff, *end_pos; + uchar lastkey[HA_MAX_POSSIBLE_KEY_BUFF]; + uint last_length; + int inited; +} SORT_KEY_BLOCKS; + + +typedef struct st_sort_ftbuf +{ + uchar *buf, *end; + int count; + uchar lastkey[HA_MAX_KEY_BUFF]; +} SORT_FT_BUF; + +/* bits in return from _mi_get_block_info */ #define BLOCK_FIRST 1U #define BLOCK_LAST 2U