diff options
author | Monty <monty@mariadb.org> | 2019-08-08 23:04:05 +0300 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2019-08-23 11:26:04 +0200 |
commit | 6c50875a380aabb9da8926b785524e813e98a82d (patch) | |
tree | 8ce40297412f1bcd62830f4e52e308d9f4c8ea57 | |
parent | afe969ba05faece41fdef1275e9b9c510081805b (diff) | |
download | mariadb-git-6c50875a380aabb9da8926b785524e813e98a82d.tar.gz |
MDEV-20279 Increase Aria index length limit
Limit increased from 1000 to 2000.
Avoiding stack overflow by only storing keys and pages on the stack in
recursive functions if there is plenty of space on it.
Other things:
- Use less stack space for b-tree operations as we now only allocate as
much space as needed instead of always allocating HA_MAX_KEY_LENGTH.
- Replaced most usage of my_safe_alloca() in Aria with the stack_alloc
interface.
- Moved my_setstacksize() to mysys/my_pthread.c
35 files changed, 732 insertions, 338 deletions
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 <my_stack_alloc.h> + /* 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 <my_check_opt.h> - -#include <stdarg.h> +#include <my_stack_alloc.h> #include <my_getopt.h> #ifdef HAVE_SYS_VADVISE_H #include <sys/vadvise.h> @@ -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 <myisamchk.h> #include <my_bit.h> #include <m_ctype.h> -#include <stdarg.h> #include <my_getopt.h> #include <my_check_opt.h> #include <my_handler_errors.h> @@ -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 |