summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/maria.h5
-rw-r--r--include/my_base.h1
-rw-r--r--include/my_handler.h3
-rw-r--r--include/pagecache.h4
-rw-r--r--mysql-test/include/ps_conv.inc2
-rw-r--r--mysql-test/r/maria-connect.result23
-rw-r--r--mysql-test/r/maria.result73
-rw-r--r--mysql-test/r/ps_2myisam.result2
-rw-r--r--mysql-test/r/ps_3innodb.result2
-rw-r--r--mysql-test/r/ps_4heap.result2
-rw-r--r--mysql-test/r/ps_5merge.result4
-rw-r--r--mysql-test/r/ps_7ndb.result2
-rw-r--r--mysql-test/r/ps_maria.result2
-rw-r--r--mysql-test/t/maria-connect.test39
-rw-r--r--mysql-test/t/maria.test42
-rw-r--r--mysys/mf_iocache.c1
-rw-r--r--mysys/mf_tempfile.c1
-rw-r--r--mysys/my_error.c5
-rw-r--r--mysys/my_handler.c66
-rw-r--r--mysys/my_init.c1
-rw-r--r--mysys/my_open.c73
-rw-r--r--mysys/my_symlink2.c4
-rw-r--r--sql-bench/example9
-rw-r--r--sql/handler.cc8
-rw-r--r--sql/handler.h7
-rw-r--r--sql/lex.h2
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/sql_show.cc9
-rw-r--r--sql/sql_table.cc3
-rw-r--r--sql/sql_yacc.yy11
-rw-r--r--sql/table.cc8
-rw-r--r--sql/table.h1
-rw-r--r--storage/maria/ha_maria.cc31
-rw-r--r--storage/maria/ma_bitmap.c13
-rw-r--r--storage/maria/ma_blockrec.c54
-rw-r--r--storage/maria/ma_check.c570
-rw-r--r--storage/maria/ma_close.c4
-rw-r--r--storage/maria/ma_create.c4
-rw-r--r--storage/maria/ma_delete_all.c54
-rw-r--r--storage/maria/ma_dynrec.c5
-rw-r--r--storage/maria/ma_info.c1
-rw-r--r--storage/maria/ma_init.c1
-rw-r--r--storage/maria/ma_loghandler.c4
-rw-r--r--storage/maria/ma_open.c8
-rwxr-xr-xstorage/maria/ma_pagecache.c14
-rwxr-xr-xstorage/maria/ma_test_all.sh21
-rw-r--r--storage/maria/ma_update.c3
-rw-r--r--storage/maria/maria_chk.c42
-rw-r--r--storage/maria/maria_def.h11
-rw-r--r--storage/myisam/ft_stopwords.c17
50 files changed, 944 insertions, 332 deletions
diff --git a/include/maria.h b/include/maria.h
index fbf4bc68c29..c7c32ff0e78 100644
--- a/include/maria.h
+++ b/include/maria.h
@@ -327,17 +327,18 @@ typedef struct st_maria_sort_info
pthread_mutex_t mutex;
pthread_cond_t cond;
#endif
- MARIA_HA *info;
+ MARIA_HA *info, *new_info;
HA_CHECK *param;
char *buff;
SORT_KEY_BLOCKS *key_block, *key_block_end;
SORT_FT_BUF *ft_buf;
my_off_t filelength, dupp, buff_length;
+ ulonglong page;
ha_rows max_records;
uint current_key, total_keys;
uint got_error, threads_running;
myf myf_rw;
- enum data_file_type new_data_file_type;
+ enum data_file_type new_data_file_type, org_data_file_type;
} MARIA_SORT_INFO;
typedef struct st_maria_sort_param
diff --git a/include/my_base.h b/include/my_base.h
index 38376adfe85..952c325f911 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -47,6 +47,7 @@
#define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */
#define HA_OPEN_FROM_SQL_LAYER 64
#define HA_OPEN_MMAP 128 /* open memory mapped */
+#define HA_OPEN_COPY 256 /* Open copy (for repair) */
/* The following is parameter to ha_rkey() how to use key */
diff --git a/include/my_handler.h b/include/my_handler.h
index 13dcd01a332..1a1235d0588 100644
--- a/include/my_handler.h
+++ b/include/my_handler.h
@@ -110,7 +110,8 @@ extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
uint *diff_pos);
extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a);
-
+extern void my_handler_error_register(void);
+extern void my_handler_error_unregister(void);
/*
Inside an in-memory data record, memory pointers to pieces of the
record (like BLOBs) are stored in their native byte order and in
diff --git a/include/pagecache.h b/include/pagecache.h
index 12906676959..f505dec0fe9 100644
--- a/include/pagecache.h
+++ b/include/pagecache.h
@@ -34,7 +34,9 @@ enum pagecache_page_type
/* the page does not contain LSN */
PAGECACHE_PLAIN_PAGE,
/* the page contain LSN (maria tablespace page) */
- PAGECACHE_LSN_PAGE
+ PAGECACHE_LSN_PAGE,
+ /* Page type used when scanning file and we don't care about the type */
+ PAGECACHE_READ_UNKNOWN_PAGE
};
/*
diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc
index 0dd819f6e62..b0c0f9bd9e0 100644
--- a/mysql-test/include/ps_conv.inc
+++ b/mysql-test/include/ps_conv.inc
@@ -52,7 +52,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+eval create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/maria-connect.result b/mysql-test/r/maria-connect.result
new file mode 100644
index 00000000000..e232f564d10
--- /dev/null
+++ b/mysql-test/r/maria-connect.result
@@ -0,0 +1,23 @@
+set global storage_engine=maria;
+set session storage_engine=maria;
+drop table if exists t1;
+SET SQL_WARNINGS=1;
+RESET MASTER;
+set binlog_format=statement;
+CREATE TABLE t1 (a int primary key);
+insert t1 values (1),(2),(3);
+insert t1 values (4),(2),(5);
+ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
+select * from t1;
+a
+1
+2
+3
+4
+SHOW BINLOG EVENTS FROM 102;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 102 Query 1 200 use `test`; CREATE TABLE t1 (a int primary key)
+master-bin.000001 200 Query 1 291 use `test`; insert t1 values (1),(2),(3)
+master-bin.000001 291 Query 1 382 use `test`; insert t1 values (4),(2),(5)
+drop table t1;
+set binlog_format=default;
diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result
index 3ec9af0fffa..a1c49fdfe4f 100644
--- a/mysql-test/r/maria.result
+++ b/mysql-test/r/maria.result
@@ -2,25 +2,6 @@ set global storage_engine=maria;
set session storage_engine=maria;
drop table if exists t1,t2;
SET SQL_WARNINGS=1;
-RESET MASTER;
-set binlog_format=statement;
-CREATE TABLE t1 (a int primary key);
-insert t1 values (1),(2),(3);
-insert t1 values (4),(2),(5);
-ERROR 23000: Duplicate entry '2' for key 'PRIMARY'
-select * from t1;
-a
-1
-2
-3
-4
-SHOW BINLOG EVENTS FROM 102;
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 102 Query 1 200 use `test`; CREATE TABLE t1 (a int primary key)
-master-bin.000001 200 Query 1 291 use `test`; insert t1 values (1),(2),(3)
-master-bin.000001 291 Query 1 382 use `test`; insert t1 values (4),(2),(5)
-drop table t1;
-set binlog_format=default;
CREATE TABLE t1 (
STRING_DATA char(255) default NULL,
KEY string_data (STRING_DATA)
@@ -618,7 +599,7 @@ t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
alter table t1 enable keys;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+t1 1 a 1 a A NULL NULL NULL YES BTREE
alter table t1 engine=heap;
alter table t1 disable keys;
Warnings:
@@ -853,19 +834,19 @@ _id
DELETE FROM t1 WHERE _id < 8;
SHOW TABLE STATUS LIKE 't1';
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
-t1 MARIA 10 Paged 2 # # # # 0 # # # # # #
+t1 MARIA 10 Page 2 # # # # 0 # # # # # #
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
-test.t1 optimize status Table is already up to date
+test.t1 optimize status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
SHOW TABLE STATUS LIKE 't1';
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
-t1 MARIA 10 Paged 2 # # # # 0 # # # # # #
+t1 MARIA 10 Page 2 # # # # 0 # # # # # #
SELECT _id FROM t1;
_id
8
@@ -912,7 +893,7 @@ _id
DELETE FROM t1 WHERE _id < 8;
SHOW TABLE STATUS LIKE 't1';
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
-t1 MARIA 10 Paged 2 # # # # 0 # # # # # #
+t1 MARIA 10 Page 2 # # # # 0 # # # # # #
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
test.t1 check status OK
@@ -924,7 +905,7 @@ Table Op Msg_type Msg_text
test.t1 check status OK
SHOW TABLE STATUS LIKE 't1';
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
-t1 MARIA 10 Paged 2 # # # # 0 # # # # # #
+t1 MARIA 10 Page 2 # # # # 0 # # # # # #
SELECT _id FROM t1;
_id
8
@@ -1598,7 +1579,7 @@ alter table t1 disable keys;
alter table t1 enable keys;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a A 8 NULL NULL YES BTREE disabled
+t1 1 a 1 a A 8 NULL NULL YES BTREE
drop table t1;
show create table t1;
show create table t1;
@@ -1811,3 +1792,43 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
+create table t1 (a int) transactional=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 TRANSACTIONAL=0
+drop table t1;
+create table t1 (a int) row_format=dynamic transactional=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC TRANSACTIONAL=0
+drop table t1;
+create table t1 (a int) row_format=dynamic transactional=1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC TRANSACTIONAL=1
+alter table t1 row_format=PAGE;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=1
+alter table t1 transactional=0;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE TRANSACTIONAL=0
+drop table t1;
+create table t1 (a int) row_format=PAGE;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MARIA DEFAULT CHARSET=latin1 ROW_FORMAT=PAGE
+drop table t1;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 2bfd6d31ac9..9330ac2853e 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1756,7 +1756,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 607a0426bd7..4972942e6f3 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1739,7 +1739,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index f4eec0c610c..bb17d0d161c 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1740,7 +1740,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 38e4626d59c..1ed2136151b 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1676,7 +1676,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
@@ -4690,7 +4690,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index 432a07df9d0..af693de986b 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -1739,7 +1739,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/r/ps_maria.result b/mysql-test/r/ps_maria.result
index 9268c44eecd..b1ea905c406 100644
--- a/mysql-test/r/ps_maria.result
+++ b/mysql-test/r/ps_maria.result
@@ -1756,7 +1756,7 @@ set @arg14= 'abc';
set @arg14= NULL ;
set @arg15= CAST('abc' as binary) ;
set @arg15= NULL ;
-create table t5 as select
+create table t5 engine = MyISAM as select
8 as const01, @arg01 as param01,
8.0 as const02, @arg02 as param02,
80.00000000000e-1 as const03, @arg03 as param03,
diff --git a/mysql-test/t/maria-connect.test b/mysql-test/t/maria-connect.test
new file mode 100644
index 00000000000..aedfa92e278
--- /dev/null
+++ b/mysql-test/t/maria-connect.test
@@ -0,0 +1,39 @@
+#
+# Test that can't be run with --extern
+#
+
+-- source include/have_maria.inc
+
+let $default=`select @@global.storage_engine`;
+set global storage_engine=maria;
+set session storage_engine=maria;
+
+# Initialise
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+SET SQL_WARNINGS=1;
+
+#
+# UNIQUE key test
+#
+# as long as maria cannot rollback, binlog should contain both inserts
+#
+RESET MASTER;
+set binlog_format=statement;
+CREATE TABLE t1 (a int primary key);
+insert t1 values (1),(2),(3);
+--error 1582
+insert t1 values (4),(2),(5);
+select * from t1;
+SHOW BINLOG EVENTS FROM 102;
+drop table t1;
+set binlog_format=default;
+
+# End of 5.2 tests
+
+--disable_result_log
+--disable_query_log
+eval set global storage_engine=$default;
+--enable_result_log
+--enable_query_log
diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test
index 763abbd9d25..25000abd426 100644
--- a/mysql-test/t/maria.test
+++ b/mysql-test/t/maria.test
@@ -16,22 +16,6 @@ drop table if exists t1,t2;
SET SQL_WARNINGS=1;
#
-# UNIQUE key test
-#
-# as long as maria cannot rollback, binlog should contain both inserts
-#
-RESET MASTER;
-set binlog_format=statement;
-CREATE TABLE t1 (a int primary key);
-insert t1 values (1),(2),(3);
---error 1582
-insert t1 values (4),(2),(5);
-select * from t1;
-SHOW BINLOG EVENTS FROM 102;
-drop table t1;
-set binlog_format=default;
-
-#
# Test problem with CHECK TABLE;
#
@@ -597,10 +581,7 @@ insert t1 select * from t2;
show keys from t1;
alter table t1 enable keys;
show keys from t1;
-#TODO after we have repair: delete the following --disable-warnings
---disable_warnings
alter table t1 engine=heap;
---enable_warnings
alter table t1 disable keys;
show keys from t1;
drop table t1,t2;
@@ -1072,10 +1053,10 @@ create table t1 (a int not null, key key_block_size=1024 (a));
--error 1064
create table t1 (a int not null, key `a` key_block_size=1024 (a));
-
#
# Test of changing MI_KEY_BLOCK_LENGTH
#
+
CREATE TABLE t1 (
c1 INT,
c2 VARCHAR(300),
@@ -1116,6 +1097,27 @@ DELETE FROM t1 WHERE c1 >= 10;
CHECK TABLE t1;
DROP TABLE t1;
+#
+# Test that TRANSACTIONAL is preserved
+#
+
+create table t1 (a int) transactional=0;
+show create table t1;
+drop table t1;
+create table t1 (a int) row_format=dynamic transactional=0;
+show create table t1;
+drop table t1;
+create table t1 (a int) row_format=dynamic transactional=1;
+show create table t1;
+alter table t1 row_format=PAGE;
+show create table t1;
+alter table t1 transactional=0;
+show create table t1;
+drop table t1;
+create table t1 (a int) row_format=PAGE;
+show create table t1;
+drop table t1;
+
# End of 5.2 tests
--disable_result_log
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index e40490776f8..8b8ba540a4e 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1696,6 +1696,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
my_bool append_cache;
my_off_t pos_in_file;
DBUG_ENTER("my_b_flush_io_cache");
+ DBUG_PRINT("enter", ("cache: 0x%lx", (long) info));
if (!(append_cache = (info->type == SEQ_READ_APPEND)))
need_append_buffer_lock=0;
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index 6c412157937..a820d09a2c6 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -107,6 +107,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
if (org_file >= 0 && file < 0)
{
int tmp=my_errno;
+ close(org_file);
(void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
my_errno=tmp;
}
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 48392fe84c3..00c78b64e0e 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -84,11 +84,6 @@ int my_error(int nr, myf MyFlags, ...)
if (nr <= meh_p->meh_last)
break;
-#ifdef SHARED_LIBRARY
- if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
- init_glob_errs();
-#endif
-
/* get the error message string. Default, if NULL or empty string (""). */
if (! (format= (meh_p && (nr >= meh_p->meh_first)) ?
meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format)
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 757cbe490f8..bf75d992f9d 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -19,6 +19,7 @@
#include <m_ctype.h>
#include <my_base.h>
#include <my_handler.h>
+#include <my_sys.h>
int ha_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
uchar *b, uint b_length, my_bool part_key,
@@ -563,3 +564,68 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
return keyseg;
}
+
+/*
+ Errors a handler can give you
+*/
+
+static const char *handler_error_messages[]=
+{
+ "Didn't find key on read or update",
+ "Duplicate key on write or update",
+ "Undefined handler error 122",
+ "Someone has changed the row since it was read (while the table was locked to prevent it)",
+ "Wrong index given to function",
+ "Undefined handler error 125",
+ "Index file is crashed",
+ "Record file is crashed",
+ "Out of memory in engine",
+ "Undefined handler error 129",
+ "Incorrect file format",
+ "Command not supported by database",
+ "Old database file",
+ "No record read before update",
+ "Record was already deleted (or record file crashed)",
+ "No more room in record file",
+ "No more room in index file",
+ "No more records (read after end of file)",
+ "Unsupported extension used for table",
+ "Too big row",
+ "Wrong create options",
+ "Duplicate unique key or constraint on write or update",
+ "Unknown character set used in table",
+ "Conflicting table definitions in sub-tables of MERGE table",
+ "Table is crashed and last repair failed",
+ "Table was marked as crashed and should be repaired",
+ "Lock timed out; Retry transaction",
+ "Lock table is full; Restart program with a larger locktable",
+ "Updates are not allowed under a read only transactions",
+ "Lock deadlock; Retry transaction",
+ "Foreign key constraint is incorrectly formed",
+ "Cannot add a child row",
+ "Cannot delete a parent row",
+ "Unknown handler error"
+};
+
+
+/*
+ Register handler error messages for usage with my_error()
+
+ NOTES
+ This is safe to call multiple times as my_error_register()
+ will ignore calls to register already registered error numbers.
+*/
+
+
+void my_handler_error_register(void)
+{
+ my_error_register(handler_error_messages, HA_ERR_FIRST,
+ HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
+}
+
+
+void my_handler_error_unregister(void)
+{
+ my_error_unregister(HA_ERR_FIRST,
+ HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
+}
diff --git a/mysys/my_init.c b/mysys/my_init.c
index e8a55fdc1e6..2023a7da223 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -77,6 +77,7 @@ my_bool my_init(void)
mysys_usage_id++;
my_umask= 0660; /* Default umask for new files */
my_umask_dir= 0700; /* Default umask for new directories */
+ init_glob_errs();
#if defined(THREAD) && defined(SAFE_MUTEX)
safe_mutex_global_init(); /* Must be called early */
#endif
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 6fe7883b99b..b4bb7e25810 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -71,6 +71,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
#else
fd = open((my_string) FileName, Flags);
#endif
+
DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN,
EE_FILENOTFOUND, MyFlags));
} /* my_open */
@@ -124,61 +125,65 @@ int my_close(File fd, myf MyFlags)
SYNOPSIS
my_register_filename()
- fd
- FileName
- type_file_type
+ fd File number opened, -1 if error on open
+ FileName File name
+ type_file_type How file was created
+ error_message_number Error message number if caller got error (fd == -1)
+ MyFlags Flags for my_close()
+
+ RETURN
+ -1 error
+ # Filenumber
+
*/
File my_register_filename(File fd, const char *FileName, enum file_type
type_of_file, uint error_message_number, myf MyFlags)
{
+ DBUG_ENTER("my_register_filename");
if ((int) fd >= 0)
{
if ((uint) fd >= my_file_limit)
{
#if defined(THREAD) && !defined(HAVE_PREAD)
- (void) my_close(fd,MyFlags);
- my_errno=EMFILE;
- if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
- my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- return(-1);
-#endif
+ my_errno= EMFILE;
+#else
thread_safe_increment(my_file_opened,&THR_LOCK_open);
- return(fd); /* safeguard */
+ DBUG_RETURN(fd); /* safeguard */
+#endif
}
- pthread_mutex_lock(&THR_LOCK_open);
- if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags)))
+ else
{
- my_file_opened++;
- my_file_info[fd].type = type_of_file;
+ pthread_mutex_lock(&THR_LOCK_open);
+ if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags)))
+ {
+ my_file_opened++;
+ my_file_info[fd].type = type_of_file;
#if defined(THREAD) && !defined(HAVE_PREAD)
- pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
#endif
+ pthread_mutex_unlock(&THR_LOCK_open);
+ DBUG_PRINT("exit",("fd: %d",fd));
+ DBUG_RETURN(fd);
+ }
pthread_mutex_unlock(&THR_LOCK_open);
- DBUG_PRINT("exit",("fd: %d",fd));
- return(fd);
+ my_errno= ENOMEM;
}
- pthread_mutex_unlock(&THR_LOCK_open);
(void) my_close(fd, MyFlags);
- fd= -1;
- my_errno=ENOMEM;
}
else
- my_errno=errno;
- DBUG_PRINT("error",("Got error %d on open",my_errno));
- if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) {
- if (my_errno == EMFILE) {
- DBUG_PRINT("error",("print err: %d",EE_OUT_OF_FILERESOURCES));
- my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- } else {
- DBUG_PRINT("error",("print err: %d",error_message_number));
- my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- }
+ my_errno= errno;
+
+ DBUG_PRINT("error",("Got error %d on open", my_errno));
+ if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
+ {
+ if (my_errno == EMFILE)
+ error_message_number= EE_OUT_OF_FILERESOURCES;
+ DBUG_PRINT("error",("print err: %d",error_message_number));
+ my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG),
+ FileName, my_errno);
}
- return(fd);
+ DBUG_RETURN(-1);
}
#ifdef __WIN__
diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c
index 279672be11c..932f2b6424f 100644
--- a/mysys/my_symlink2.c
+++ b/mysys/my_symlink2.c
@@ -33,7 +33,9 @@ File my_create_with_symlink(const char *linkname, const char *filename,
int create_link;
char abs_linkname[FN_REFLEN];
DBUG_ENTER("my_create_with_symlink");
- DBUG_PRINT("enter", ("linkname: %s filename: %s", linkname, filename));
+ DBUG_PRINT("enter",
+ ("linkname: %s filename: %s", linkname ? linkname : "NULL",
+ filename));
if (my_disable_symlinks)
{
diff --git a/sql-bench/example b/sql-bench/example
index df2a9b8be69..cb39fad819e 100644
--- a/sql-bench/example
+++ b/sql-bench/example
@@ -6,15 +6,14 @@ machine="Linux-x64"
# InnoDB tests
-./run-all-tests --suffix=-innodb --comments="Engine=InnoDB --innodb_log_file_size=100M" --create-options="ENGINE=InnoDB" --hw="$hw" --optimization="$optimization" --machine="$machine" --log
-
-./run-all-tests --suffix=_fast-innodb --comments="Engine=InnoDB --innodb_log_file_size=100M" --create-options="ENGINE=InnoDB" --hw="$hw" --optimization="$optimization" --machine="$machine" --fast --log
+./run-all-tests --suffix=-innodb --comments="Engine=InnoDB --innodb_buffer_pool_size=256M --innodb_additional_mem_pool_size=20M --innodb_log_file_size=1000M --innodb_log_buffer_size=16M --innodb_lock_wait_timeout=50 --innodb_flush_log_at_trx_commit=1 --innodb_flush_method=O_DIRECT --innodb_log_files_in_group=2 --skip-innodb-doblewrite" --create-options="ENGINE=InnoDB" --hw="$hw" --optimization="$optimization" --machine="$machine" --log
+./run-all-tests --suffix=_fast-innodb --comments="Engine=InnoDB --innodb_buffer_pool_size=256M --innodb_additional_mem_pool_size=20M --innodb_log_file_size=1000M --innodb_log_buffer_size=16M --innodb_lock_wait_timeout=50 --innodb_flush_log_at_trx_commit=1 --innodb_flush_method=O_DIRECT --innodb_log_files_in_group=2 --skip-innodb-doblewrite" --create-options="ENGINE=InnoDB" --hw="$hw" --optimization="$optimization" --machine="$machine" --fast --log
# MyISAM tests
-./run-all-tests --suffix=-myisam --comments="Engine=MyISAM key_buffer_size=16M" --create-options="ENGINE=myisam" --hw="$hw" --optimization="$optimization" --machine="$machine" --log
+./run-all-tests --suffix=-myisam --comments="Engine=MyISAM key_buffer_size=256M" --create-options="ENGINE=myisam" --hw="$hw" --optimization="$optimization" --machine="$machine" --log
-./run-all-tests --suffix=_fast-myisam --comments="Engine=MyISAM key_buffer_size=16M" --create-options="ENGINE=myisam" --hw="$hw" --optimization="$optimization" --machine="$machine" --fast --log
+./run-all-tests --suffix=_fast-myisam --comments="Engine=MyISAM key_buffer_size=256M" --create-options="ENGINE=myisam" --hw="$hw" --optimization="$optimization" --machine="$machine" --fast --log
compare-results --relative output/RUN-mysql-myisam-* output/RUN-mysql_fast-myisam* output/RUN-mysql*
diff --git a/sql/handler.cc b/sql/handler.cc
index b32098bfc78..f3c71887e9a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -68,7 +68,7 @@ static const LEX_STRING sys_table_aliases[]=
};
const char *ha_row_type[] = {
- "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "?","?","?"
+ "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE","?","?","?"
};
const char *tx_isolation_names[] =
@@ -281,7 +281,8 @@ handler *get_ha_partition(partition_info *part_info)
0 OK
!= 0 Error
*/
-static int ha_init_errors(void)
+
+int ha_init_errors(void)
{
#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
const char **errmsgs;
@@ -495,9 +496,6 @@ int ha_init()
int error= 0;
DBUG_ENTER("ha_init");
- if (ha_init_errors())
- DBUG_RETURN(1);
-
DBUG_ASSERT(total_ha < MAX_HA);
/*
Check if there is a transaction-capable storage engine besides the
diff --git a/sql/handler.h b/sql/handler.h
index d488ca5f07e..b5679147d8a 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -268,7 +268,7 @@ enum legacy_db_type
enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
- ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT, ROW_TYPE_PAGES };
+ ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT, ROW_TYPE_PAGE };
enum enum_binlog_func {
BFN_RESET_LOGS= 1,
@@ -311,6 +311,7 @@ enum enum_binlog_command {
#define HA_CREATE_USED_PASSWORD (1L << 17)
#define HA_CREATE_USED_CONNECTION (1L << 18)
#define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19)
+#define HA_CREATE_USED_TRANSACTIONAL (1L << 20)
typedef ulonglong my_xid; // this line is the same as in log_event.h
#define MYSQL_XID_PREFIX "MySQLXid"
@@ -741,6 +742,7 @@ class partition_info;
struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)
+enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES };
typedef struct st_ha_create_information
{
@@ -763,6 +765,8 @@ typedef struct st_ha_create_information
uint options; /* OR of HA_CREATE_ options */
uint merge_insert_method;
uint extra_size; /* length of extra data segment */
+ /* 0 not used, 1 if not transactional, 2 if transactional */
+ enum ha_choice transactional;
bool table_existed; /* 1 in create if table existed */
bool frm_only; /* 1 if no ha_create_table() */
bool varchar; /* 1 if table has a VARCHAR */
@@ -1661,6 +1665,7 @@ static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
}
/* basic stuff */
+int ha_init_errors(void);
int ha_init(void);
int ha_end(void);
int ha_initialize_handlerton(st_plugin_int *plugin);
diff --git a/sql/lex.h b/sql/lex.h
index 45155da7692..28271bf46d9 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -379,6 +379,7 @@ static SYMBOL symbols[] = {
{ "OWNER", SYM(OWNER_SYM)},
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
{ "PARSER", SYM(PARSER_SYM)},
+ { "PAGE", SYM(PAGE_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
@@ -528,6 +529,7 @@ static SYMBOL symbols[] = {
{ "TO", SYM(TO_SYM)},
{ "TRAILING", SYM(TRAILING)},
{ "TRANSACTION", SYM(TRANSACTION_SYM)},
+ { "TRANSACTIONAL", SYM(TRANSACTIONAL_SYM)},
{ "TRIGGER", SYM(TRIGGER_SYM)},
{ "TRIGGERS", SYM(TRIGGERS_SYM)},
{ "TRUE", SYM(TRUE_SYM)},
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a49e4005c67..fd77317509b 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3350,6 +3350,10 @@ server.");
using_update_log=1;
}
+ /* Allow storage engine to give real error messages */
+ if (ha_init_errors())
+ DBUG_RETURN(1);
+
if (plugin_init(opt_bootstrap))
{
sql_print_error("Failed to init plugins.");
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 250d9d917eb..9ae38d5dcec 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1371,6 +1371,11 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
packet->append(ha_row_type[(uint) share->row_type]);
}
+ if (share->transactional != HA_CHOICE_UNDEF)
+ {
+ packet->append(STRING_WITH_LEN(" TRANSACTIONAL="));
+ packet->append(share->transactional == HA_CHOICE_YES ? "1" : "0", 1);
+ }
if (table->s->key_block_size)
{
char *end;
@@ -2910,8 +2915,8 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
case ROW_TYPE_COMPACT:
tmp_buff= "Compact";
break;
- case ROW_TYPE_PAGES:
- tmp_buff= "Paged";
+ case ROW_TYPE_PAGE:
+ tmp_buff= "Page";
break;
}
table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 0697fdd79b4..a037fc6f727 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5653,6 +5653,8 @@ view_err:
create_info->default_table_charset= table->s->table_charset;
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
create_info->key_block_size= table->s->key_block_size;
+ if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
+ create_info->transactional= table->s->transactional;
if (!create_info->tablespace && create_info->storage_media != HA_SM_MEMORY)
{
@@ -6916,7 +6918,6 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
lex->col_list.empty();
lex->alter_info.reset();
bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type= 0;
create_info.row_type=ROW_TYPE_NOT_USED;
create_info.default_table_charset=default_charset_info;
/* Force alter table to recreate table */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 9c062407921..0653863cc73 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -720,6 +720,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token OUT_SYM /* SQL-2003-R */
%token OWNER_SYM
%token PACK_KEYS_SYM
+%token PAGE_SYM
%token PARAM_MARKER
%token PARSER_SYM
%token PARTIAL /* SQL-2003-N */
@@ -872,6 +873,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TO_SYM /* SQL-2003-R */
%token TRAILING /* SQL-2003-R */
%token TRANSACTION_SYM
+%token TRANSACTIONAL_SYM
%token TRIGGERS_SYM
%token TRIGGER_SYM /* SQL-2003-R */
%token TRIM /* SQL-2003-N */
@@ -4213,6 +4215,12 @@ create_table_option:
Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE;
Lex->create_info.key_block_size= $3;
}
+ | TRANSACTIONAL_SYM opt_equal ulong_num
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
+ Lex->create_info.transactional= ($3 != 0 ? HA_CHOICE_YES :
+ HA_CHOICE_NO);
+ }
;
default_charset:
@@ -4273,6 +4281,7 @@ row_types:
| COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
| REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; }
| COMPACT_SYM { $$= ROW_TYPE_COMPACT; };
+ | PAGE_SYM { $$= ROW_TYPE_PAGE; };
merge_insert_types:
NO_SYM { $$= MERGE_INSERT_DISABLED; }
@@ -9786,6 +9795,7 @@ keyword_sp:
| ONE_SHOT_SYM {}
| ONE_SYM {}
| PACK_KEYS_SYM {}
+ | PAGE_SYM {}
| PARTIAL {}
| PARTITIONING_SYM {}
| PARTITIONS_SYM {}
@@ -9855,6 +9865,7 @@ keyword_sp:
| TEXT_SYM {}
| THAN_SYM {}
| TRANSACTION_SYM {}
+ | TRANSACTIONAL_SYM {}
| TRIGGERS_SYM {}
| TIMESTAMP {}
| TIMESTAMP_ADD {}
diff --git a/sql/table.cc b/sql/table.cc
index ed3cac85214..316d99a85b5 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -460,7 +460,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
if (!head[32]) // New frm file in 3.23
{
share->avg_row_length= uint4korr(head+34);
- share-> row_type= (row_type) head[40];
+ share->transactional= (ha_choice) head[39];
+ share->row_type= (row_type) head[40];
share->table_charset= get_charset((uint) head[38],MYF(0));
share->null_field_first= 1;
}
@@ -2111,7 +2112,9 @@ File create_frm(THD *thd, const char *name, const char *db,
int2store(fileinfo+16,reclength);
int4store(fileinfo+18,create_info->max_rows);
int4store(fileinfo+22,create_info->min_rows);
+ /* fileinfo[26] is set in mysql_create_frm() */
fileinfo[27]=2; // Use long pack-fields
+ /* fileinfo[28 & 29] is set to key_info_length in mysql_create_frm() */
create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers
int2store(fileinfo+30,create_info->table_options);
fileinfo[32]=0; // No filename anymore
@@ -2119,8 +2122,9 @@ File create_frm(THD *thd, const char *name, const char *db,
int4store(fileinfo+34,create_info->avg_row_length);
fileinfo[38]= (create_info->default_table_charset ?
create_info->default_table_charset->number : 0);
+ fileinfo[39]= (uchar) create_info->transactional;
fileinfo[40]= (uchar) create_info->row_type;
- /* Next few bytes were for RAID support */
+ /* Next few bytes where for RAID support */
fileinfo[41]= 0;
fileinfo[42]= 0;
fileinfo[43]= 0;
diff --git a/sql/table.h b/sql/table.h
index fc2f25f3aa8..fc9f1b7caa4 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -175,6 +175,7 @@ typedef struct st_table_share
handlerton *db_type; /* table_type for handler */
enum row_type row_type; /* How rows are stored */
enum tmp_table_type tmp_table;
+ enum ha_choice transactional;
uint ref_count; /* How many TABLE objects uses this */
uint open_count; /* Number of tables in open list */
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index f7fd417836a..0c83d73c3ef 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -436,32 +436,38 @@ volatile int *_ma_killed_ptr(HA_CHECK *param)
void _ma_check_print_error(HA_CHECK *param, const char *fmt, ...)
{
+ va_list args;
+ DBUG_ENTER("_ma_check_print_error");
param->error_printed |= 1;
param->out_flag |= O_DATA_LOST;
- va_list args;
va_start(args, fmt);
_ma_check_print_msg(param, "error", fmt, args);
va_end(args);
+ DBUG_VOID_RETURN;
}
void _ma_check_print_info(HA_CHECK *param, const char *fmt, ...)
{
va_list args;
+ DBUG_ENTER("_ma_check_print_info");
va_start(args, fmt);
_ma_check_print_msg(param, "info", fmt, args);
va_end(args);
+ DBUG_VOID_RETURN;
}
void _ma_check_print_warning(HA_CHECK *param, const char *fmt, ...)
{
+ va_list args;
+ DBUG_ENTER("_ma_check_print_warning");
param->warning_printed= 1;
param->out_flag |= O_DATA_LOST;
- va_list args;
va_start(args, fmt);
_ma_check_print_msg(param, "warning", fmt, args);
va_end(args);
+ DBUG_VOID_RETURN;
}
}
@@ -1065,16 +1071,6 @@ int ha_maria::repair(THD *thd, HA_CHECK &param, bool do_optimize)
param.out_flag= 0;
strmov(fixed_name, file->s->open_file_name);
-#ifndef TO_BE_FIXED
- /* QQ: Until we have repair for block format, lie that it succeded */
- if (file->s->data_file_type == BLOCK_RECORD)
- {
- if (do_optimize)
- DBUG_RETURN(analyze(thd, (HA_CHECK_OPT*) 0));
- DBUG_RETURN(HA_ADMIN_OK);
- }
-#endif
-
// Don't lock tables if we have used LOCK TABLE
if (!thd->locked_tables &&
maria_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK))
@@ -1099,7 +1095,9 @@ int ha_maria::repair(THD *thd, HA_CHECK &param, bool do_optimize)
local_testflag |= T_STATISTICS;
param.testflag |= T_STATISTICS; // We get this for free
statistics_done= 1;
- if (thd->variables.maria_repair_threads > 1)
+ /* TODO: Remove BLOCK_RECORD test when parallel works with blocks */
+ if (thd->variables.maria_repair_threads > 1 &&
+ file->s->data_file_type != BLOCK_RECORD)
{
char buf[40];
/* TODO: respect maria_repair_threads variable */
@@ -1954,7 +1952,7 @@ enum row_type ha_maria::get_row_type() const
switch (file->s->data_file_type) {
case STATIC_RECORD: return ROW_TYPE_FIXED;
case DYNAMIC_RECORD: return ROW_TYPE_DYNAMIC;
- case BLOCK_RECORD: return ROW_TYPE_PAGES;
+ case BLOCK_RECORD: return ROW_TYPE_PAGE;
case COMPRESSED_RECORD: return ROW_TYPE_COMPRESSED;
default: return ROW_TYPE_NOT_USED;
}
@@ -1963,6 +1961,8 @@ enum row_type ha_maria::get_row_type() const
static enum data_file_type maria_row_type(HA_CREATE_INFO *info)
{
+ if (info->transactional == HA_CHOICE_YES)
+ return BLOCK_RECORD;
switch (info->row_type) {
case ROW_TYPE_FIXED: return STATIC_RECORD;
case ROW_TYPE_DYNAMIC: return DYNAMIC_RECORD;
@@ -2007,7 +2007,8 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
share->avg_row_length);
create_info.data_file_name= ha_create_info->data_file_name;
create_info.index_file_name= ha_create_info->index_file_name;
- create_info.transactional= row_type == BLOCK_RECORD;
+ create_info.transactional= (row_type == BLOCK_RECORD &&
+ ha_create_info->transactional != HA_CHOICE_NO);
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= HA_CREATE_TMP_TABLE;
diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c
index e1308bce487..f6a8172935f 100644
--- a/storage/maria/ma_bitmap.c
+++ b/storage/maria/ma_bitmap.c
@@ -106,6 +106,19 @@
put on disk even if they are not in the page cache).
- When explicitely requested (for example on backup or after recvoery,
to simplify things)
+
+ The flow of writing a row is that:
+ - Lock the bitmap
+ - Decide which data pages we will write to
+ - Mark them full in the bitmap page so that other threads do not try to
+ use the same data pages as us
+ - We unlock the bitmap
+ - Write the data pages
+ - Lock the bitmap
+ - Correct the bitmap page with the true final occupation of the data
+ pages (that is, we marked pages full but when we are done we realize
+ we didn't fill them)
+ - Unlock the bitmap.
*/
#include "maria_def.h"
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index c747aaeb6cb..0ed8c1f7232 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -1778,7 +1778,7 @@ static my_bool write_block_record(MARIA_HA *info,
ulong length;
ulong data_length= (tmp_data - info->rec_buff);
-#ifdef SANITY_CHECK
+#ifdef SANITY_CHECKS
if (cur_block->sub_blocks == 1)
goto crashed; /* no reserved full or tails */
#endif
@@ -1814,8 +1814,8 @@ static my_bool write_block_record(MARIA_HA *info,
FULL_PAGE_SIZE(block_size))) &&
cur_block->page_count)
{
-#ifdef SANITY_CHECK
- if ((cur_block == end_block) || (cur_block->used & BLOCKUSED_BIT))
+#ifdef SANITY_CHECKS
+ if ((cur_block == end_block) || (cur_block->used & BLOCKUSED_USED))
goto crashed;
#endif
data_length-= length;
@@ -1829,7 +1829,7 @@ static my_bool write_block_record(MARIA_HA *info,
/* Skip empty filler block */
cur_block++;
}
-#ifdef SANITY_CHECK
+#ifdef SANITY_CHECKS
if ((cur_block >= end_block))
goto crashed;
#endif
@@ -2548,11 +2548,6 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
PAGECACHE_PIN_LEFT_PINNED,
PAGECACHE_WRITE_DELAY, &page_link.link))
DBUG_RETURN(1);
-
- /* Change the lock used when we read the page */
- page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK;
- set_dynamic(&info->pinned_pages, (void*) &page_link,
- info->pinned_pages.elements-1);
}
else
{
@@ -2564,7 +2559,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
pagerange_store(log_data + FILEID_STORE_SIZE, 1);
page_store(log_data+ FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE, page);
pagerange_store(log_data + FILEID_STORE_SIZE + PAGERANGE_STORE_SIZE +
- PAGERANGE_STORE_SIZE, 1);
+ PAGE_STORE_SIZE, 1);
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
if (translog_write_record(!info->trn->rec_lsn ? &info->trn->rec_lsn : &lsn,
@@ -2573,8 +2568,24 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
sizeof(log_data), TRANSLOG_INTERNAL_PARTS + 1,
log_array))
DBUG_RETURN(1);
+
+ /* Write the empty page (needed only for REPAIR to work) */
+ buff[PAGE_TYPE_OFFSET]= UNALLOCATED_PAGE;
+ if (pagecache_write(share->pagecache,
+ &info->dfile, page, 0,
+ buff, share->page_type,
+ PAGECACHE_LOCK_WRITE_TO_READ,
+ PAGECACHE_PIN_LEFT_PINNED,
+ PAGECACHE_WRITE_DELAY, &page_link.link))
+ DBUG_RETURN(1);
+
DBUG_ASSERT(empty_space >= info->s->bitmap.sizes[0]);
}
+ /* Change the lock used when we read the page */
+ page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK;
+ set_dynamic(&info->pinned_pages, (void*) &page_link,
+ info->pinned_pages.elements-1);
+
DBUG_PRINT("info", ("empty_space: %u", empty_space));
DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space));
}
@@ -2794,7 +2805,8 @@ static byte *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent,
extent->extent+= ROW_EXTENT_SIZE;
extent->page= uint5korr(extent->extent);
page_count= uint2korr(extent->extent+ROW_EXTENT_PAGE_SIZE);
- DBUG_ASSERT(page_count != 0);
+ if (!page_count)
+ goto crashed;
extent->tail= page_count & TAIL_BIT;
extent->page_count= (page_count & ~TAIL_BIT);
extent->first_extent= 0;
@@ -2817,7 +2829,8 @@ static byte *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent,
if (!extent->tail)
{
/* Full data page */
- DBUG_ASSERT((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == BLOB_PAGE);
+ if ((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != BLOB_PAGE)
+ goto crashed;
extent->page++; /* point to next page */
extent->page_count--;
*end_of_data= buff + share->block_size;
@@ -2826,7 +2839,8 @@ static byte *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent,
}
/* Found tail. page_count is in this case the position in the tail page */
- DBUG_ASSERT((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == TAIL_PAGE);
+ if ((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != TAIL_PAGE)
+ goto crashed;
*(extent->tail_positions++)= ma_recordpos(extent->page,
extent->page_count);
info->cur_row.tail_count++; /* For maria_chk */
@@ -2948,7 +2962,6 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
MARIA_COLUMNDEF *column, *end_column;
DBUG_ENTER("_ma_read_block_record2");
- LINT_INIT(field_lengths);
LINT_INIT(field_length_data);
LINT_INIT(blob_buffer);
@@ -2994,6 +3007,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
}
extent.first_extent= 1;
+ field_lengths= 0;
if (share->base.max_field_lengths)
{
get_key_length(field_lengths, data);
@@ -3028,7 +3042,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
Read row extents (note that first extent was already read into
info->cur_row.extents above)
*/
- if (row_extents)
+ if (row_extents > 1)
{
if (read_long_data(info, info->cur_row.extents + ROW_EXTENT_SIZE,
(row_extents - 1) * ROW_EXTENT_SIZE,
@@ -3053,7 +3067,7 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record,
}
/* Read array of field lengths. This may be stored in several extents */
- if (share->base.max_field_lengths)
+ if (field_lengths)
{
field_length_data= info->cur_row.field_lengths;
if (read_long_data(info, field_length_data, field_lengths, &extent,
@@ -3459,6 +3473,8 @@ restart_bitmap_scan:
DBUG_PRINT("error", ("Wrong page header"));
DBUG_RETURN((my_errno= HA_ERR_WRONG_IN_RECORD));
}
+ DBUG_PRINT("info", ("Page %lu has %u rows",
+ (ulong) page, info->scan.number_of_rows));
info->scan.dir= (info->scan.page_buff + block_size -
PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE);
info->scan.dir_end= (info->scan.dir -
@@ -3471,7 +3487,8 @@ restart_bitmap_scan:
for (data+= 6; data < info->scan.bitmap_end; data+= 6)
{
bits= uint6korr(data);
- if (bits && ((bits & LL(04444444444444444)) != LL(04444444444444444)))
+ /* Skip not allocated pages and blob / full tail pages */
+ if (bits && bits != LL(07777777777777777))
break;
}
bit_pos= 0;
@@ -3483,8 +3500,11 @@ restart_bitmap_scan:
filepos= (my_off_t) info->scan.bitmap_page * block_size;
if (unlikely(filepos >= info->state->data_file_length))
{
+ DBUG_PRINT("info", ("Found end of file"));
DBUG_RETURN((my_errno= HA_ERR_END_OF_FILE));
}
+ DBUG_PRINT("info", ("Reading bitmap at %lu",
+ (ulong) info->scan.bitmap_page));
if (!(pagecache_read(share->pagecache, &info->dfile,
info->scan.bitmap_page,
0, info->scan.bitmap_buff, PAGECACHE_PLAIN_PAGE,
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 8f10c98d0ee..9d017bc6ad5 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -42,7 +42,6 @@
#include "ma_ftdefs.h"
#include <myisamchk.h>
-#include <m_ctype.h>
#include <stdarg.h>
#include <my_getopt.h>
#ifdef HAVE_SYS_VADVISE_H
@@ -86,6 +85,12 @@ static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks,
static ha_checksum maria_byte_checksum(const byte *buf, uint length);
static void set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share);
static void restore_data_file_type(MARIA_SHARE *share);
+static void change_data_file_descriptor(MARIA_HA *info, File new_file);
+static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info,
+ MARIA_HA *info, byte *record);
+static void copy_data_file_state(MARIA_STATE_INFO *to,
+ MARIA_STATE_INFO *from);
+
void maria_chk_init(HA_CHECK *param)
{
@@ -837,7 +842,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
}
(*key_checksum)+= maria_byte_checksum((byte*) key,
- key_length- info->s->rec_reflength);
+ key_length- info->s->rec_reflength);
record= _ma_dpos(info,0,key+key_length);
if (keyinfo->flag & HA_FULLTEXT) /* special handling for ft2 */
{
@@ -1262,18 +1267,21 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend,
}
else
{
- info->cur_row.checksum= _ma_checksum(info,record);
+ ha_checksum checksum= 0;
+ if (info->s->calc_checksum)
+ checksum= (*info->s->calc_checksum)(info, record);
+
if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE))
{
if (_ma_rec_check(info,record, info->rec_buff,block_info.rec_len,
- test(info->s->calc_checksum)))
+ test(info->s->calc_checksum), checksum))
{
_ma_check_print_error(param,"Found wrong packed record at %s",
llstr(start_recpos,llbuff));
got_error= 1;
}
}
- param->glob_crc+= info->cur_row.checksum;
+ param->glob_crc+= checksum;
}
if (! got_error)
@@ -1506,8 +1514,11 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, byte *record,
}
if (info->s->calc_checksum)
{
- info->cur_row.checksum= _ma_checksum(info, record);
- param->glob_crc+= info->cur_row.checksum;
+ ha_checksum checksum= (*info->s->calc_checksum)(info, record);
+ if (info->cur_row.checksum != (checksum & 255))
+ _ma_check_print_error(param, "Page %9s: Row %3d has wrong checksum",
+ llstr(page_pos, llbuff), row);
+ param->glob_crc+= checksum;
}
if (info->cur_row.extents_count)
{
@@ -1571,6 +1582,8 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
my_bool full_dir;
uint offset_page, offset;
+ LINT_INIT(full_dir);
+
if (_ma_scan_init_block_record(info))
{
_ma_check_print_error(param, "got error %d when initializing scan",
@@ -1648,13 +1661,12 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
llstr(pos, llbuff), page_type);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err;
+ continue;
}
switch ((enum en_page_type) page_type) {
case UNALLOCATED_PAGE:
case MAX_PAGE_TYPE:
- DBUG_PRINT("warning",
- ("Found page with wrong page type: %d", page_type));
- DBUG_ASSERT(0);
+ DBUG_ASSERT(0); /* Impossible */
break;
case HEAD_PAGE:
row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET];
@@ -1907,13 +1919,28 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend)
} /* maria_chk_data_link */
- /* Recover old table by reading each record and writing all keys */
- /* Save new datafile-name in temp_filename */
+/*
+ Recover old table by reading each record and writing all keys
+
+ NOTES
+ Save new datafile-name in temp_filename
+
+ IMPLEMENTATION (for hard repair with block format)
+ - Create new, unrelated MARIA_HA of the table
+ - Create new datafile and associate it with new handler
+ - Reset all statistic information in new handler
+ - Copy all data to new handler with normal write operations
+ - Move state of new handler to old handler
+ - Close new handler
+ - Close data file in old handler
+ - Rename old data file to new data file.
+ - Reopen data file in old handler
+*/
int maria_repair(HA_CHECK *param, register MARIA_HA *info,
my_string name, int rep_quick)
{
- int error,got_error;
+ int error, got_error= 1;
uint i;
ha_rows start_records,new_header_length;
my_off_t del;
@@ -1922,6 +1949,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
char llbuff[22],llbuff2[22];
MARIA_SORT_INFO sort_info;
MARIA_SORT_PARAM sort_param;
+ my_bool block_record, scan_inited= 0;
+ enum data_file_type org_data_file_type= info->s->data_file_type;
DBUG_ENTER("maria_repair");
bzero((char *)&sort_info, sizeof(sort_info));
@@ -1929,9 +1958,11 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
start_records=info->state->records;
new_header_length=(param->testflag & T_UNPACK) ? 0L :
share->pack.header_length;
- got_error=1;
new_file= -1;
sort_param.sort_info=&sort_info;
+ block_record= org_data_file_type == BLOCK_RECORD;
+ sort_info.info= sort_info.new_info= info;
+ bzero(&info->rec_cache,sizeof(info->rec_cache));
if (!(param->testflag & T_SILENT))
{
@@ -1943,28 +1974,6 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|=T_CALC_CHECKSUM;
- if (init_io_cache(&param->read_cache, info->dfile.file,
- (uint) param->read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
- {
- bzero(&info->rec_cache,sizeof(info->rec_cache));
- goto err;
- }
- if (!rep_quick)
- if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
- WRITE_CACHE, new_header_length, 1,
- MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- info->opt_flag|=WRITE_CACHE_USED;
- if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength,
- MYF(0))) ||
- _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
- info->s->base.default_rec_buff_size))
- {
- _ma_check_print_error(param, "Not enough memory for extra record");
- goto err;
- }
-
if (!rep_quick)
{
/* Get real path for data file */
@@ -1983,11 +1992,71 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
new_header_length, "datafile-header"))
goto err;
info->s->state.dellink= HA_OFFSET_ERROR;
- info->rec_cache.file=new_file;
- if (param->testflag & T_UNPACK)
- restore_data_file_type(share);
+ info->rec_cache.file= new_file;
+ if (share->data_file_type == BLOCK_RECORD ||
+ ((param->testflag & T_UNPACK) &&
+ share->state.header.org_data_file_type == BLOCK_RECORD))
+ {
+ MARIA_HA *new_info;
+ if (!(sort_info.new_info= maria_open(info->s->unique_file_name, O_RDWR,
+ HA_OPEN_COPY | HA_OPEN_FOR_REPAIR)))
+ goto err;
+ new_info= sort_info.new_info;
+ change_data_file_descriptor(new_info, new_file);
+ maria_lock_database(new_info, F_EXTRA_LCK);
+ if ((param->testflag & T_UNPACK) &&
+ share->data_file_type == COMPRESSED_RECORD)
+ {
+ (*new_info->s->once_end)(new_info->s);
+ (*new_info->s->end)(new_info);
+ restore_data_file_type(new_info->s);
+ _ma_setup_functions(new_info->s);
+ if ((*new_info->s->once_init)(new_info->s, new_file) ||
+ (*new_info->s->init)(new_info))
+ goto err;
+ }
+ _ma_reset_status(sort_info.new_info);
+ if (_ma_initialize_data_file(sort_info.new_info->s, new_file))
+ goto err;
+ block_record= 1;
+ }
+ }
+
+ if (org_data_file_type != BLOCK_RECORD)
+ {
+ /* We need a read buffer to read rows in big blocks */
+ if (init_io_cache(&param->read_cache, info->dfile.file,
+ (uint) param->read_buffer_length,
+ READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)))
+ goto err;
}
- sort_info.info=info;
+ if (sort_info.new_info->s->data_file_type != BLOCK_RECORD)
+ {
+ /* When writing to not block records, we need a write buffer */
+ if (!rep_quick)
+ if (init_io_cache(&info->rec_cache, new_file,
+ (uint) param->write_buffer_length,
+ WRITE_CACHE, new_header_length, 1,
+ MYF(MY_WME | MY_WAIT_IF_FULL)))
+ goto err;
+ info->opt_flag|=WRITE_CACHE_USED;
+ }
+ else
+ {
+ scan_inited= 1;
+ if (maria_scan_init(sort_info.info))
+ goto err;
+ }
+
+ if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength,
+ MYF(0))) ||
+ _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
+ info->s->base.default_rec_buff_size))
+ {
+ _ma_check_print_error(param, "Not enough memory for extra record");
+ goto err;
+ }
+
sort_info.param = param;
sort_param.read_cache=param->read_cache;
sort_param.pos=sort_param.max_pos=share->pack.header_length;
@@ -2030,9 +2099,14 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
maria_lock_memory(param); /* Everything is alloced */
+ sort_info.org_data_file_type= info->s->data_file_type;
+
/* Re-create all keys, which are set in key_map. */
while (!(error=sort_get_next_record(&sort_param)))
{
+ if (block_record && _ma_sort_write_record(&sort_param))
+ goto err;
+
if (writekeys(&sort_param))
{
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
@@ -2058,7 +2132,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
}
continue;
}
- if (_ma_sort_write_record(&sort_param))
+
+ if (!block_record && _ma_sort_write_record(&sort_param))
goto err;
}
if (error > 0 || maria_write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
@@ -2081,35 +2156,58 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
{
_ma_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
_ma_check_print_error(param,"Run recovery again without -q");
- got_error=1;
param->retry_repair=1;
param->testflag|=T_RETRY_WITHOUT_QUICK;
goto err;
}
+
if (param->testflag & T_SAFE_REPAIR)
{
/* Don't repair if we loosed more than one row */
- if (info->state->records+1 < start_records)
+ if (sort_info.new_info->state->records+1 < start_records)
{
info->state->records=start_records;
- got_error=1;
goto err;
}
}
if (!rep_quick)
{
- my_close(info->dfile.file, MYF(0));
- info->dfile.file= new_file;
- info->state->data_file_length=sort_param.filepos;
+ if (sort_info.new_info != sort_info.info)
+ {
+ MARIA_STATE_INFO save_state= sort_info.new_info->s->state;
+ if (maria_close(sort_info.new_info))
+ {
+ _ma_check_print_error(param, "Got error %d on close", my_errno);
+ goto err;
+ }
+ copy_data_file_state(&info->s->state, &save_state);
+ new_file= -1;
+ }
+ else
+ info->state->data_file_length= sort_param.filepos;
share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
+
+ /* Replace the actual file with the temporary file */
+ if (new_file >= 0)
+ my_close(new_file, MYF(MY_WME));
+ my_close(info->dfile.file, MYF(MY_WME));
+ info->dfile.file= new_file= -1;
+ if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT,
+ DATA_TMP_EXT,
+ (param->testflag & T_BACKUP_DATA ?
+ MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
+ _ma_open_datafile(info, share, -1))
+ {
+ goto err;
+ }
}
else
{
- info->state->data_file_length=sort_param.max_pos;
+ info->state->data_file_length= sort_param.max_pos;
}
if (param->testflag & T_CALC_CHECKSUM)
- info->state->checksum=param->glob_crc;
+ info->state->checksum= param->glob_crc;
if (!(param->testflag & T_SILENT))
{
@@ -2127,25 +2225,19 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
- if (!got_error)
- {
- /* Replace the actual file with the temporary file */
- if (new_file >= 0)
- {
- my_close(new_file,MYF(0));
- info->dfile.file= new_file= -1;
- if (maria_change_to_newfile(share->data_file_name,MARIA_NAME_DEXT,
- DATA_TMP_EXT, (param->testflag & T_BACKUP_DATA ?
- MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
- _ma_open_datafile(info,share,-1))
- got_error=1;
- }
- }
+ if (scan_inited)
+ maria_scan_end(sort_info.info);
+
if (got_error)
{
if (! param->error_printed)
_ma_check_print_error(param,"%d for record at pos %s",my_errno,
llstr(sort_param.start_recpos,llbuff));
+ if (sort_info.new_info && sort_info.new_info != sort_info.info)
+ {
+ sort_info.new_info->dfile.file= -1;
+ maria_close(sort_info.new_info);
+ }
if (new_file >= 0)
{
VOID(my_close(new_file,MYF(0)));
@@ -2595,7 +2687,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
uint i;
ulong length;
ha_rows start_records;
- my_off_t new_header_length,del;
+ my_off_t new_header_length, org_header_length, del;
File new_file;
MARIA_SORT_PARAM sort_param;
MARIA_SHARE *share=info->s;
@@ -2606,11 +2698,15 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
ulonglong key_map=share->state.key_map;
DBUG_ENTER("maria_repair_by_sort");
+ bzero((char*)&sort_info,sizeof(sort_info));
+ bzero((char *)&sort_param, sizeof(sort_param));
+
start_records=info->state->records;
got_error=1;
new_file= -1;
- new_header_length=(param->testflag & T_UNPACK) ? 0 :
- share->pack.header_length;
+ org_header_length= share->pack.header_length;
+ new_header_length= (param->testflag & T_UNPACK) ? 0 : org_header_length;
+
if (!(param->testflag & T_SILENT))
{
printf("- recovering (with sort) MARIA-table '%s'\n",name);
@@ -2621,15 +2717,13 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|=T_CALC_CHECKSUM;
- bzero((char*)&sort_info,sizeof(sort_info));
- bzero((char *)&sort_param, sizeof(sort_param));
if (!(sort_info.key_block=
alloc_key_blocks(param,
(uint) param->sort_key_blocks,
- share->base.max_key_block_length))
- || init_io_cache(&param->read_cache, info->dfile.file,
- (uint) param->read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) ||
+ share->base.max_key_block_length)) ||
+ init_io_cache(&param->read_cache, info->dfile.file,
+ (uint) param->read_buffer_length,
+ READ_CACHE, org_header_length, 1, MYF(MY_WME)) ||
(! rep_quick &&
init_io_cache(&info->rec_cache, info->dfile.file,
(uint) param->write_buffer_length,
@@ -2639,6 +2733,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks;
info->opt_flag|=WRITE_CACHE_USED;
info->rec_cache.file= info->dfile.file; /* for sort_delete_record */
+ sort_info.org_data_file_type= info->s->data_file_type;
if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength,
MYF(0))) ||
@@ -2694,8 +2789,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
key_map= ~key_map; /* Create the missing keys */
}
- sort_info.info=info;
- sort_info.param = param;
+ sort_info.info= sort_info.new_info= info;
+ sort_info.param= param;
set_data_file_type(&sort_info, share);
sort_param.filepos=new_header_length;
@@ -2707,9 +2802,9 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
sort_param.wordlist=NULL;
init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
- if (share->data_file_type == DYNAMIC_RECORD)
+ if (sort_info.org_data_file_type == DYNAMIC_RECORD)
length=max(share->base.min_pack_length+1,share->base.min_block_length);
- else if (share->data_file_type == COMPRESSED_RECORD)
+ else if (sort_info.org_data_file_type == COMPRESSED_RECORD)
length=share->base.min_block_length;
else
length=share->base.pack_reclength;
@@ -2747,7 +2842,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if ((!(param->testflag & T_SILENT)))
printf ("- Fixing index %d\n",sort_param.key+1);
- sort_param.max_pos=sort_param.pos=share->pack.header_length;
+ sort_param.max_pos= sort_param.pos= org_header_length;
keyseg=sort_param.seg;
bzero((char*) sort_param.unique,sizeof(sort_param.unique));
sort_param.key_length=share->rec_reflength;
@@ -2845,8 +2940,9 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
share->state.version=(ulong) time((time_t*) 0);
my_close(info->dfile.file, MYF(0));
info->dfile.file= new_file;
- share->data_file_type=sort_info.new_data_file_type;
- share->pack.header_length=(ulong) new_header_length;
+ share->data_file_type= sort_info.new_data_file_type;
+ org_header_length= (ulong) new_header_length;
+ sort_info.org_data_file_type= info->s->data_file_type;
sort_param.fix_datafile=0;
}
else
@@ -2874,11 +2970,11 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
if (rep_quick & T_FORCE_UNIQUENESS)
{
- my_off_t skr=info->state->data_file_length+
- (share->options & HA_OPTION_COMPRESS_RECORD ?
- MEMMAP_EXTRA_MARGIN : 0);
+ my_off_t skr= (info->state->data_file_length +
+ (sort_info.org_data_file_type == COMPRESSED_RECORD) ?
+ MEMMAP_EXTRA_MARGIN : 0);
#ifdef USE_RELOC
- if (share->data_file_type == STATIC_RECORD &&
+ if (sort_info.org_data_file_type == STATIC_RECORD &&
skr < share->base.reloc*share->base.min_pack_length)
skr=share->base.reloc*share->base.min_pack_length;
#endif
@@ -3073,6 +3169,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
pthread_cond_init(&sort_info.cond, 0);
+ sort_info.org_data_file_type= info->s->data_file_type;
+
if (!(sort_info.key_block=
alloc_key_blocks(param, (uint) param->sort_key_blocks,
share->base.max_key_block_length)) ||
@@ -3140,8 +3238,8 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
key_map= ~key_map; /* Create the missing keys */
}
- sort_info.info=info;
- sort_info.param = param;
+ sort_info.info= sort_info.new_info= info;
+ sort_info.param= param;
set_data_file_type(&sort_info, share);
sort_info.dupp=0;
@@ -3149,9 +3247,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
param->read_cache.end_of_file=sort_info.filelength=
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
- if (share->data_file_type == DYNAMIC_RECORD)
+ if (sort_info.org_data_file_type == DYNAMIC_RECORD)
rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
- else if (share->data_file_type == COMPRESSED_RECORD)
+ else if (sort_info.org_data_file_type == COMPRESSED_RECORD)
rec_length=share->base.min_block_length;
else
rec_length=share->base.pack_reclength;
@@ -3367,8 +3465,6 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
*/
my_close(info->dfile.file, MYF(0));
info->dfile.file= new_file;
-
- share->data_file_type=sort_info.new_data_file_type;
share->pack.header_length=(ulong) new_header_length;
}
else
@@ -3385,11 +3481,11 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
if (rep_quick & T_FORCE_UNIQUENESS)
{
- my_off_t skr=info->state->data_file_length+
- (share->options & HA_OPTION_COMPRESS_RECORD ?
- MEMMAP_EXTRA_MARGIN : 0);
+ my_off_t skr= (info->state->data_file_length +
+ (sort_info.org_data_file_type == COMPRESSED_RECORD) ?
+ MEMMAP_EXTRA_MARGIN : 0);
#ifdef USE_RELOC
- if (share->data_file_type == STATIC_RECORD &&
+ if (sort_info.org_data_file_type == STATIC_RECORD &&
skr < share->base.reloc*share->base.min_pack_length)
skr=share->base.reloc*share->base.min_pack_length;
#endif
@@ -3574,27 +3670,28 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, byte *key)
sort_get_next_record()
sort_param Information about and for the sort process
- NOTE
-
+ NOTES
Dynamic Records With Non-Quick Parallel Repair
- For non-quick parallel repair we use a synchronized read/write
- cache. This means that one thread is the master who fixes the data
- file by reading each record from the old data file and writing it
- to the new data file. By doing this the records in the new data
- file are written contiguously. Whenever the write buffer is full,
- it is copied to the read buffer. The slaves read from the read
- buffer, which is not associated with a file. Thus read_cache.file
- is -1. When using _mi_read_cache(), the slaves must always set
- flag to READING_NEXT so that the function never tries to read from
- file. This is safe because the records are contiguous. There is no
- need to read outside the cache. This condition is evaluated in the
- variable 'parallel_flag' for quick reference. read_cache.file must
- be >= 0 in every other case.
+ For non-quick parallel repair we use a synchronized read/write
+ cache. This means that one thread is the master who fixes the data
+ file by reading each record from the old data file and writing it
+ to the new data file. By doing this the records in the new data
+ file are written contiguously. Whenever the write buffer is full,
+ it is copied to the read buffer. The slaves read from the read
+ buffer, which is not associated with a file. Thus read_cache.file
+ is -1. When using _mi_read_cache(), the slaves must always set
+ flag to READING_NEXT so that the function never tries to read from
+ file. This is safe because the records are contiguous. There is no
+ need to read outside the cache. This condition is evaluated in the
+ variable 'parallel_flag' for quick reference. read_cache.file must
+ be >= 0 in every other case.
RETURN
-1 end of file
0 ok
+ sort_param->filepos points to record position.
+ sort_param->record contains record
> 0 error
*/
@@ -3615,10 +3712,61 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
if (*_ma_killed_ptr(param))
DBUG_RETURN(1);
- switch (share->data_file_type) {
+ switch (sort_info->org_data_file_type) {
case BLOCK_RECORD:
- DBUG_ASSERT(0);
+ {
+ for (;;)
+ {
+ int flag;
+
+ if (info != sort_info->new_info)
+ {
+ /* Safe scanning */
+ flag= _ma_safe_scan_block_record(sort_info, info,
+ sort_param->record);
+ }
+ else
+ {
+ /* Scan on clean table */
+ flag= _ma_scan_block_record(info, sort_param->record,
+ info->cur_row.nextpos, 1);
+ }
+ if (!flag)
+ {
+ if (sort_param->calc_checksum)
+ {
+ ha_checksum checksum;
+ checksum= (*info->s->calc_check_checksum)(info, sort_param->record);
+ if (info->s->calc_checksum &&
+ info->cur_row.checksum != (checksum & 255))
+ {
+ if (param->testflag & T_VERBOSE)
+ {
+ char llbuff[22];
+ record_pos_to_txt(info, sort_param->filepos, llbuff);
+ _ma_check_print_info(param,
+ "Found record with wrong checksum at %s",
+ llbuff);
+ }
+ continue;
+ }
+ info->cur_row.checksum= checksum;
+ param->glob_crc+= checksum;
+ }
+ sort_param->filepos= info->cur_row.lastpos;
+ DBUG_RETURN(0);
+ }
+ if (flag == HA_ERR_END_OF_FILE)
+ {
+ sort_param->max_pos= sort_info->filelength;
+ DBUG_RETURN(-1);
+ }
+ /* Retry only if wrong record, not if disk error */
+ if (flag != HA_ERR_WRONG_IN_RECORD)
+ DBUG_RETURN(flag);
+ }
break;
+ }
case STATIC_RECORD:
for (;;)
{
@@ -3656,6 +3804,8 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
{
byte *to;
LINT_INIT(to);
+ ha_checksum checksum= 0;
+
pos=sort_param->pos;
searching=(sort_param->fix_datafile && (param->testflag & T_EXTEND));
parallel_flag= (sort_param->read_cache.file < 0) ? READING_NEXT : 0;
@@ -3925,14 +4075,14 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
if (sort_param->read_cache.error < 0)
DBUG_RETURN(1);
if (sort_param->calc_checksum)
- info->cur_row.checksum= _ma_checksum(info, sort_param->record);
+ checksum= (info->s->calc_check_checksum)(info, sort_param->record);
if ((param->testflag & (T_EXTEND | T_REP)) || searching)
{
if (_ma_rec_check(info, sort_param->record, sort_param->rec_buff,
sort_param->find_length,
(param->testflag & T_QUICK) &&
sort_param->calc_checksum &&
- test(info->s->calc_checksum)))
+ test(info->s->calc_checksum), checksum))
{
_ma_check_print_info(param,"Found wrong packed record at %s",
llstr(sort_param->start_recpos,llbuff));
@@ -3940,7 +4090,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
}
}
if (sort_param->calc_checksum)
- param->glob_crc+= info->cur_row.checksum;
+ param->glob_crc+= checksum;
DBUG_RETURN(0);
}
if (!searching)
@@ -4014,8 +4164,9 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
if (sort_param->calc_checksum)
{
- info->cur_row.checksum= (*info->s->calc_checksum)(info,
- sort_param->record);
+ info->cur_row.checksum= (*info->s->calc_check_checksum)(info,
+ sort_param->
+ record);
param->glob_crc+= info->cur_row.checksum;
}
DBUG_RETURN(0);
@@ -4048,8 +4199,8 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
byte *from;
byte block_buff[8];
MARIA_SORT_INFO *sort_info=sort_param->sort_info;
- HA_CHECK *param=sort_info->param;
- MARIA_HA *info=sort_info->info;
+ HA_CHECK *param= sort_info->param;
+ MARIA_HA *info= sort_info->new_info;
MARIA_SHARE *share=info->s;
DBUG_ENTER("_ma_sort_write_record");
@@ -4057,7 +4208,11 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
{
switch (sort_info->new_data_file_type) {
case BLOCK_RECORD:
- DBUG_ASSERT(0);
+ if ((sort_param->filepos= (*share->write_record_init)(info,
+ sort_param->
+ record)) ==
+ HA_OFFSET_ERROR)
+ DBUG_RETURN(1);
break;
case STATIC_RECORD:
if (my_b_write(&info->rec_cache,sort_param->record,
@@ -4090,7 +4245,9 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
from=sort_info->buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER);
}
/* We can use info->checksum here as only one thread calls this */
- info->cur_row.checksum= _ma_checksum(info,sort_param->record);
+ info->cur_row.checksum= (*info->s->calc_check_checksum)(info,
+ sort_param->
+ record);
reclength= _ma_rec_pack(info,from,sort_param->record);
flag=0;
@@ -4147,7 +4304,7 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
} /* _ma_sort_write_record */
- /* Compare two keys from _ma_create_index_by_sort */
+/* Compare two keys from _ma_create_index_by_sort */
static int sort_key_cmp(MARIA_SORT_PARAM *sort_param, const void *a,
const void *b)
@@ -4505,7 +4662,8 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
}
}
if (sort_param->calc_checksum)
- param->glob_crc-=(*info->s->calc_checksum)(info, sort_param->record);
+ param->glob_crc-=(*info->s->calc_check_checksum)(info,
+ sort_param->record);
}
error= (flush_io_cache(&info->rec_cache) ||
(*info->s->delete_record)(info, sort_param->record));
@@ -4514,7 +4672,8 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
DBUG_RETURN(error);
} /* sort_delete_record */
- /* Fix all pending blocks and flush everything to disk */
+
+/* Fix all pending blocks and flush everything to disk */
int _ma_flush_pending_blocks(MARIA_SORT_PARAM *sort_param)
{
@@ -4786,9 +4945,9 @@ end:
int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile)
{
- MARIA_HA *info=sort_info->info;
+ MARIA_HA *info=sort_info->new_info;
- if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
+ if (info->s->data_file_type == COMPRESSED_RECORD && fix_datafile)
{
char buff[MEMMAP_EXTRA_MARGIN];
bzero(buff,sizeof(buff));
@@ -5101,6 +5260,9 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows,
*/
if (! maria_is_any_key_active(key_map))
return FALSE; /* Can't use sort */
+ /* QQ: Remove this when maria_repair_by_sort() works with block format */
+ if (info->s->data_file_type == BLOCK_RECORD)
+ return FALSE;
for (i=0 ; i < share->base.keys ; i++,key++)
{
if (!force && maria_too_big_key_for_sort(key,rows))
@@ -5119,7 +5281,8 @@ set_data_file_type(MARIA_SORT_INFO *sort_info, MARIA_SHARE *share)
MARIA_SHARE tmp;
sort_info->new_data_file_type= share->state.header.org_data_file_type;
/* Set delete_function for sort_delete_record() */
- memcpy((char*) &tmp, share, sizeof(*share));
+ tmp= *share;
+ tmp.state.header.data_file_type= tmp.state.header.org_data_file_type;
tmp.options= ~HA_OPTION_COMPRESS_RECORD;
_ma_setup_functions(&tmp);
share->delete_record=tmp.delete_record;
@@ -5132,6 +5295,161 @@ static void restore_data_file_type(MARIA_SHARE *share)
mi_int2store(share->state.header.options,share->options);
share->state.header.data_file_type=
share->state.header.org_data_file_type;
- share->data_file_type= share->state.header.data_file_type=
+ share->data_file_type= share->state.header.data_file_type;
share->pack.header_length= 0;
}
+
+
+static void change_data_file_descriptor(MARIA_HA *info, File new_file)
+{
+ my_close(info->dfile.file, MYF(0));
+ info->dfile.file= info->s->bitmap.file.file= new_file;
+}
+
+
+/*
+ Copy all states that has to do with the data file
+
+ NOTES
+ This is done to copy the state from the data file generated from
+ repair to the original handler
+*/
+
+static void copy_data_file_state(MARIA_STATE_INFO *to,
+ MARIA_STATE_INFO *from)
+{
+ to->state.records= from->state.records;
+ to->state.del= from->state.del;
+ to->state.empty= from->state.empty;
+ to->state.data_file_length= from->state.data_file_length;
+ to->split= from->split;
+ to->dellink= from->dellink;
+ to->first_bitmap_with_space= from->first_bitmap_with_space;
+}
+
+
+/*
+ Read 'safely' next record while scanning table.
+
+ SYNOPSIS
+ _ma_safe_scan_block_record()
+ info Maria handler
+ record Store found here
+
+ NOTES
+ - One must have called mi_scan() before this
+
+ Differences compared to _ma_scan_block_records() are:
+ - We read all blocks, not only blocks marked by the bitmap to be safe
+ - In case of errors, next read will read next record.
+ - More sanity checks
+
+ RETURN
+ 0 ok
+ HA_ERR_END_OF_FILE End of file
+ # error number
+*/
+
+
+static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info,
+ MARIA_HA *info, byte *record)
+{
+ uint record_pos= info->cur_row.nextpos;
+ ulonglong page= sort_info->page;
+ DBUG_ENTER("_ma_safe_scan_block_record");
+
+ for (;;)
+ {
+ /* Find next row in current page */
+ if (likely(record_pos < info->scan.number_of_rows))
+ {
+ uint length, offset;
+ byte *data, *end_of_data;
+ char llbuff[22];
+
+ while (!(offset= uint2korr(info->scan.dir)))
+ {
+ info->scan.dir-= DIR_ENTRY_SIZE;
+ record_pos++;
+ if (info->scan.dir < info->scan.dir_end)
+ {
+ _ma_check_print_info(sort_info->param,
+ "Wrong directory on page: %s",
+ llstr(page, llbuff));
+ goto read_next_page;
+ }
+ }
+ /* found row */
+ info->cur_row.lastpos= info->scan.row_base_page + record_pos;
+ info->cur_row.nextpos= record_pos + 1;
+ data= info->scan.page_buff + offset;
+ length= uint2korr(info->scan.dir + 2);
+ end_of_data= data + length;
+ info->scan.dir-= DIR_ENTRY_SIZE; /* Point to previous row */
+
+ if (end_of_data > info->scan.dir_end ||
+ offset < PAGE_HEADER_SIZE || length < info->s->base.min_block_length)
+ {
+ _ma_check_print_info(sort_info->param,
+ "Wrong directory entry %3u at page %s",
+ record_pos, llstr(page, llbuff));
+ record_pos++;
+ continue;
+ }
+ else
+ {
+ DBUG_PRINT("info", ("rowid: %lu", (ulong) info->cur_row.lastpos));
+ DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
+ }
+ }
+
+read_next_page:
+ /* Read until we find next head page */
+ for (;;)
+ {
+ uint page_type;
+ char llbuff[22];
+
+ sort_info->page++; /* In case of errors */
+ page++;
+ if (!(page % info->s->bitmap.pages_covered))
+ page++; /* Skip bitmap */
+ if ((page + 1) * info->s->block_size > sort_info->filelength)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ if (!(pagecache_read(info->s->pagecache,
+ &info->dfile,
+ page, 0, info->scan.page_buff,
+ PAGECACHE_READ_UNKNOWN_PAGE,
+ PAGECACHE_LOCK_LEFT_UNLOCKED, 0)))
+ DBUG_RETURN(my_errno);
+
+ page_type= (info->scan.page_buff[PAGE_TYPE_OFFSET] &
+ PAGE_TYPE_MASK);
+ if (page_type == HEAD_PAGE)
+ {
+ if ((info->scan.number_of_rows=
+ (uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) != 0)
+ break;
+ _ma_check_print_info(sort_info->param,
+ "Wrong head page at %s",
+ llstr(page * info->s->block_size, llbuff));
+ }
+ else if (page_type >= MAX_PAGE_TYPE)
+ {
+ _ma_check_print_info(sort_info->param,
+ "Found wrong page type: %d at %s",
+ page_type, llstr(page * info->s->block_size,
+ llbuff));
+ }
+ }
+
+ /* New head page */
+ info->scan.dir= (info->scan.page_buff + info->s->block_size -
+ PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE);
+ info->scan.dir_end= (info->scan.dir -
+ (info->scan.number_of_rows - 1) *
+ DIR_ENTRY_SIZE);
+ info->scan.row_base_page= ma_recordpos(page, 0);
+ record_pos= 0;
+ }
+}
diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c
index dc60ce8aa83..e73629c3c87 100644
--- a/storage/maria/ma_close.c
+++ b/storage/maria/ma_close.c
@@ -124,8 +124,6 @@ int maria_close(register MARIA_HA *info)
my_free((gptr) info,MYF(0));
if (error)
- {
- DBUG_RETURN(my_errno=error);
- }
+ DBUG_RETURN(my_errno= error);
DBUG_RETURN(0);
} /* maria_close */
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index d8660dd41cb..280321d40ec 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -798,7 +798,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
goto err;
errpos=3;
- if (_ma_initialize_data_file(dfile, &share))
+ if (_ma_initialize_data_file(&share, dfile))
goto err;
}
DBUG_PRINT("info", ("write state info and base info"));
@@ -1082,7 +1082,7 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr)
/* Initialize data file */
-int _ma_initialize_data_file(File dfile, MARIA_SHARE *share)
+int _ma_initialize_data_file(MARIA_SHARE *share, File dfile)
{
if (share->data_file_type == BLOCK_RECORD)
{
diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c
index 2d85b347662..b18b1105391 100644
--- a/storage/maria/ma_delete_all.c
+++ b/storage/maria/ma_delete_all.c
@@ -20,9 +20,7 @@
int maria_delete_all_rows(MARIA_HA *info)
{
- uint i;
MARIA_SHARE *share=info->s;
- MARIA_STATE_INFO *state=&share->state;
DBUG_ENTER("maria_delete_all_rows");
if (share->options & HA_OPTION_READ_ONLY_DATA)
@@ -35,18 +33,7 @@ int maria_delete_all_rows(MARIA_HA *info)
if (_ma_mark_file_changed(info))
goto err;
- info->state->records=info->state->del=state->split=0;
- state->changed= 0; /* File is optimized */
- state->dellink = HA_OFFSET_ERROR;
- state->sortkey= (ushort) ~0;
- info->state->key_file_length=share->base.keystart;
- info->state->data_file_length=0;
- info->state->empty=info->state->key_empty=0;
- info->state->checksum=0;
-
- state->key_del= HA_OFFSET_ERROR;
- for (i=0 ; i < share->base.keys ; i++)
- state->key_root[i]= HA_OFFSET_ERROR;
+ _ma_reset_status(info);
/*
If we are using delayed keys or if the user has done changes to the tables
@@ -67,7 +54,7 @@ int maria_delete_all_rows(MARIA_HA *info)
my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
- if (_ma_initialize_data_file(info->dfile.file, info->s))
+ if (_ma_initialize_data_file(info->s, info->dfile.file))
goto err;
/*
@@ -104,4 +91,39 @@ err:
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(my_errno=save_errno);
}
-} /* maria_delete */
+} /* maria_delete_all_rows */
+
+
+/*
+ Reset status information
+
+ SYNOPSIS
+ _ma_reset_status()
+ maria Maria handler
+
+ DESCRIPTION
+ Resets data and index file information as if the file would be empty
+ Files are not touched.
+*/
+
+void _ma_reset_status(MARIA_HA *info)
+{
+ MARIA_SHARE *share= info->s;
+ MARIA_STATE_INFO *state= &share->state;
+ uint i;
+
+ info->state->records= info->state->del= state->split= 0;
+ state->changed= 0; /* File is optimized */
+ state->dellink= HA_OFFSET_ERROR;
+ state->sortkey= (ushort) ~0;
+ info->state->key_file_length= share->base.keystart;
+ info->state->data_file_length= 0;
+ info->state->empty= info->state->key_empty= 0;
+ info->state->checksum= 0;
+
+ /* Drop the delete key chain. */
+ state->key_del= HA_OFFSET_ERROR;
+ /* Clear all keys */
+ for (i=0 ; i < share->base.keys ; i++)
+ state->key_root[i]= HA_OFFSET_ERROR;
+}
diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
index ebf84032106..9281378fd33 100644
--- a/storage/maria/ma_dynrec.c
+++ b/storage/maria/ma_dynrec.c
@@ -1018,7 +1018,8 @@ uint _ma_rec_pack(MARIA_HA *info, register byte *to, register const byte *from)
*/
my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
- ulong packed_length, my_bool with_checksum)
+ ulong packed_length, my_bool with_checksum,
+ ha_checksum checksum)
{
uint length,new_length,flag,bit,i;
char *pos,*end,*packpos,*to;
@@ -1124,7 +1125,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, byte *rec_buff,
if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) ||
(bit != 1 && (flag & ~(bit - 1))))
goto err;
- if (with_checksum && ((uchar) info->cur_row.checksum != (uchar) *to))
+ if (with_checksum && ((uchar) checksum != (uchar) *to))
{
DBUG_PRINT("error",("wrong checksum for row"));
goto err;
diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c
index a04fba4e0d8..cfb4580a72f 100644
--- a/storage/maria/ma_info.c
+++ b/storage/maria/ma_info.c
@@ -135,6 +135,7 @@ void _ma_report_error(int errcode, const char *file_name)
file_name+= length - 64;
}
}
+
my_error(errcode, MYF(ME_NOREFRESH), file_name);
DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c
index 19b835a837f..ab62d1bfaa0 100644
--- a/storage/maria/ma_init.c
+++ b/storage/maria/ma_init.c
@@ -45,6 +45,7 @@ int maria_init(void)
pthread_mutex_init(&THR_LOCK_maria,MY_MUTEX_INIT_SLOW);
_ma_init_block_record_data();
loghandler_init();
+ my_handler_error_register();
}
return 0;
}
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index f398ec90897..b029297d2d0 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -4143,12 +4143,12 @@ my_bool translog_write_record(LSN *lsn,
{
uint i;
uint len= 0;
-#ifdef HAVE_PURIFY
+#ifdef HAVE_purify
ha_checksum checksum= 0;
#endif
for (i= TRANSLOG_INTERNAL_PARTS; i < part_no; i++)
{
-#ifdef HAVE_PURIFY
+#ifdef HAVE_purify
/* Find unitialized bytes early */
checksum+= my_checksum(checksum, parts_data[i].str,
parts_data[i].length);
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index b8ce6d123e7..79ff25e3c2f 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -260,7 +260,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
my_realpath(name_buff, fn_format(org_name,name,"",MARIA_NAME_IEXT,
MY_UNPACK_FILENAME),MYF(0));
pthread_mutex_lock(&THR_LOCK_maria);
- if (!(old_info=_ma_test_if_reopen(name_buff)))
+ old_info= 0;
+ if ((open_flags & HA_OPEN_COPY) ||
+ !(old_info=_ma_test_if_reopen(name_buff)))
{
share= &share_buff;
bzero((gptr) &share_buff,sizeof(share_buff));
@@ -586,6 +588,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->base.null_bytes +
share->base.pack_bytes +
test(share->options & HA_OPTION_CHECKSUM));
+ if (open_flags & HA_OPEN_COPY)
+ share->base.transactional= 0; /* Repair: no logging */
if (share->base.transactional)
share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE;
share->base.default_rec_buff_size= max(share->base.pack_reclength,
@@ -858,6 +862,8 @@ void _ma_setup_functions(register MARIA_SHARE *share)
}
share->file_read= _ma_nommap_pread;
share->file_write= _ma_nommap_pwrite;
+ share->calc_check_checksum= share->calc_checksum;
+
if (!(share->options & HA_OPTION_CHECKSUM) &&
share->data_file_type != COMPRESSED_RECORD)
share->calc_checksum= share->calc_write_checksum= 0;
diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c
index 53a24e36861..ca47230cfbd 100755
--- a/storage/maria/ma_pagecache.c
+++ b/storage/maria/ma_pagecache.c
@@ -315,7 +315,8 @@ struct st_pagecache_block_link
#ifndef DBUG_OFF
/* debug checks */
static my_bool info_check_pin(PAGECACHE_BLOCK_LINK *block,
- enum pagecache_page_pin mode)
+ enum pagecache_page_pin mode
+ __attribute__((unused)))
{
struct st_my_thread_var *thread= my_thread_var;
PAGECACHE_PIN_INFO *info= info_find(block->pin_list, thread);
@@ -373,6 +374,7 @@ static my_bool info_check_pin(PAGECACHE_BLOCK_LINK *block,
1 - Error
*/
+#ifdef NOT_USED
static my_bool info_check_lock(PAGECACHE_BLOCK_LINK *block,
enum pagecache_page_lock lock,
enum pagecache_page_pin pin)
@@ -440,7 +442,8 @@ error:
page_cache_page_pin_str[pin]));
DBUG_RETURN(1);
}
-#endif
+#endif /* NOT_USED */
+#endif /* !DBUG_OFF */
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
@@ -2858,8 +2861,10 @@ restart:
(pin == PAGECACHE_PIN)),
&page_st);
DBUG_ASSERT(block->type == PAGECACHE_EMPTY_PAGE ||
- block->type == type);
- block->type= type;
+ block->type == type || type == PAGECACHE_READ_UNKNOWN_PAGE);
+ if (type != PAGECACHE_READ_UNKNOWN_PAGE ||
+ block->type == PAGECACHE_EMPTY_PAGE)
+ block->type= type;
if (((block->status & PCBLOCK_ERROR) == 0) && (page_st != PAGE_READ))
{
DBUG_PRINT("info", ("read block 0x%lx", (ulong)block));
@@ -3223,6 +3228,7 @@ restart:
}
DBUG_ASSERT(block->type == PAGECACHE_EMPTY_PAGE ||
+ block->type == PAGECACHE_READ_UNKNOWN_PAGE ||
block->type == type);
block->type= type;
diff --git a/storage/maria/ma_test_all.sh b/storage/maria/ma_test_all.sh
index 8ee326a9c69..a7c8df827ff 100755
--- a/storage/maria/ma_test_all.sh
+++ b/storage/maria/ma_test_all.sh
@@ -8,6 +8,9 @@ silent="-s"
suffix=""
#set -x -v -e
+# Delete temporary files
+rm -f *.TMD
+
run_tests()
{
row_type=$1
@@ -120,6 +123,11 @@ run_repair_tests()
./maria_chk$suffix -se test1
./maria_chk$suffix -rqos --correct-checksum test1
./maria_chk$suffix -se test1
+ ./ma_test2$suffix $silent -c -d1 $row_type
+ ./maria_chk$suffix -s --parallel-recover test2
+ ./maria_chk$suffix -se test2
+ ./maria_chk$suffix -s --parallel-recover --quick test2
+ ./maria_chk$suffix -se test2
}
run_pack_tests()
@@ -147,6 +155,15 @@ run_pack_tests()
./maria_chk$suffix -es test1
./maria_chk$suffix -rus test1
./maria_chk$suffix -es test1
+
+ ./ma_test2$suffix $silent -c -d1 $row_type
+ ./maria_chk$suffix -s --parallel-recover test2
+ ./maria_chk$suffix -se test2
+ ./maria_chk$suffix -s --parallel-recover --unpack test2
+ ./maria_chk$suffix -se test2
+ ./maria_pack$suffix --force -s test1
+ ./maria_chk$suffix -s --parallel-recover --unpack test2
+ ./maria_chk$suffix -se test2
}
echo "Running tests with dynamic row format"
@@ -161,9 +178,13 @@ run_pack_tests -S
echo "Running tests with block row format"
run_tests -M
+run_repair_tests -M
+run_pack_tests -M
echo "Running tests with block row format and transactions"
run_tests "-M -T"
+run_repair_tests "-M -T"
+run_pack_tests "-M -T"
#
# Tests that gives warnings
diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c
index 737c7c909b4..913959717fc 100644
--- a/storage/maria/ma_update.c
+++ b/storage/maria/ma_update.c
@@ -147,6 +147,7 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
if (share->calc_checksum)
{
info->cur_row.checksum= (*share->calc_checksum)(info,newrec);
+ info->state->checksum+= (info->cur_row.checksum - old_checksum);
/* Store new checksum in index file header */
key_changed|= HA_STATE_CHANGED;
}
@@ -173,8 +174,6 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
if (auto_key_changed)
set_if_bigger(info->s->state.auto_increment,
ma_retrieve_auto_increment(info, newrec));
- if (share->calc_checksum)
- info->state->checksum+= (info->cur_row.checksum - old_checksum);
/*
We can't yet have HA_STATE_AKTIV here, as block_record dosn't support
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index 0b82a71f736..e7e0f5d40b5 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -676,14 +676,7 @@ get_one_option(int optid,
check_param.testflag|= T_UPDATE_STATE;
break;
case '#':
- if (argument == disabled_my_option)
- {
- DBUG_POP();
- }
- else
- {
- DBUG_PUSH(argument ? argument : "d:t:o,/tmp/maria_chk.trace");
- }
+ DBUG_SET_INITIAL(argument ? argument : "d:t:o,/tmp/maria_chk.trace");
break;
case 'V':
print_version();
@@ -862,16 +855,25 @@ static int maria_chk(HA_CHECK *param, my_string filename)
share->r_locks=0;
maria_block_size= share->base.block_size;
- if (share->data_file_type == BLOCK_RECORD &&
- (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_FAST | T_STATISTICS |
- T_CHECK | T_CHECK_ONLY_CHANGED)))
+ if (share->data_file_type == BLOCK_RECORD ||
+ ((param->testflag & T_UNPACK) &&
+ share->state.header.org_data_file_type == BLOCK_RECORD))
{
- _ma_check_print_error(param,
- "Record format used by '%s' is is not yet supported with repair/check",
- filename);
- param->error_printed= 0;
- error= 1;
- goto end2;
+ if (param->testflag & T_SORT_RECORDS)
+ {
+ _ma_check_print_error(param,
+ "Record format used by '%s' is is not yet supported with repair/check",
+ filename);
+ param->error_printed= 0;
+ error= 1;
+ goto end2;
+ }
+ /* We can't do parallell repair with BLOCK_RECORD yet */
+ if (param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL))
+ {
+ param->testflag&= ~(T_REP_BY_SORT | T_REP_PARALLEL);
+ param->testflag|= T_REP;
+ }
}
/*
@@ -1757,11 +1759,14 @@ void _ma_check_print_info(HA_CHECK *param __attribute__((unused)),
const char *fmt,...)
{
va_list args;
+ DBUG_ENTER("_ma_check_print_info");
+ DBUG_PRINT("enter", ("format: %s", fmt));
va_start(args,fmt);
VOID(vfprintf(stdout, fmt, args));
VOID(fputc('\n',stdout));
va_end(args);
+ DBUG_VOID_RETURN;
}
/* VARARGS */
@@ -1770,6 +1775,7 @@ void _ma_check_print_warning(HA_CHECK *param, const char *fmt,...)
{
va_list args;
DBUG_ENTER("_ma_check_print_warning");
+ DBUG_PRINT("enter", ("format: %s", fmt));
fflush(stdout);
if (!param->warning_printed && !param->error_printed)
@@ -1795,7 +1801,7 @@ void _ma_check_print_error(HA_CHECK *param, const char *fmt,...)
{
va_list args;
DBUG_ENTER("_ma_check_print_error");
- DBUG_PRINT("enter",("format: %s",fmt));
+ DBUG_PRINT("enter", ("format: %s", fmt));
fflush(stdout);
if (!param->warning_printed && !param->error_printed)
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index d9e31e800c4..bd48a5288d5 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -30,6 +30,7 @@
#define MAX_NONMAPPED_INSERTS 1000
#define MARIA_MAX_TREE_LEVELS 32
+#define SANITY_CHECKS
struct st_transaction;
@@ -261,7 +262,9 @@ typedef struct st_maria_share
Calculate checksum for a row during write. May be 0 if we calculate
the checksum in write_record_init()
*/
- ha_checksum(*calc_write_checksum) (struct st_maria_info *, const byte *);
+ ha_checksum(*calc_write_checksum)(struct st_maria_info *, const byte *);
+ /* calculate checksum for a row during check table */
+ ha_checksum(*calc_check_checksum)(struct st_maria_info *, const byte *);
/* Compare a row in memory with a row on disk */
my_bool (*compare_unique)(struct st_maria_info *, MARIA_UNIQUEDEF *,
const byte *record, MARIA_RECORD_POS pos);
@@ -746,7 +749,7 @@ extern ulong _ma_rec_unpack(MARIA_HA *info, byte *to, byte *from,
ulong reclength);
extern my_bool _ma_rec_check(MARIA_HA *info, const char *record,
byte *packpos, ulong packed_length,
- my_bool with_checkum);
+ my_bool with_checkum, ha_checksum checksum);
extern int _ma_write_part_record(MARIA_HA *info, my_off_t filepos,
ulong length, my_off_t next_filepos,
byte ** record, ulong *reclength,
@@ -871,6 +874,7 @@ void _ma_update_status(void *param);
void _ma_restore_status(void *param);
void _ma_copy_status(void *to, void *from);
my_bool _ma_check_status(void *param);
+void _ma_reset_status(MARIA_HA *maria);
extern MARIA_HA *_ma_test_if_reopen(char *filename);
my_bool _ma_check_table_is_closed(const char *name, const char *where);
@@ -904,9 +908,8 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param);
int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
ulong);
int _ma_sync_table_files(const MARIA_HA *info);
-int _ma_initialize_data_file(File dfile, MARIA_SHARE *share);
+int _ma_initialize_data_file(MARIA_SHARE *share, File dfile);
void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn);
extern PAGECACHE *maria_log_pagecache;
-
diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c
index 1b6cff5e903..b95e0f4d857 100644
--- a/storage/myisam/ft_stopwords.c
+++ b/storage/myisam/ft_stopwords.c
@@ -51,10 +51,11 @@ static int ft_add_stopword(const char *w)
int ft_init_stopwords()
{
+ DBUG_ENTER("ft_init_stopwords");
if (!stopwords3)
{
if (!(stopwords3=(TREE *)my_malloc(sizeof(TREE),MYF(0))))
- return -1;
+ DBUG_RETURN(-1);
init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp,
0,
(ft_stopword_file ? (tree_element_free)&FT_STOPWORD_free : 0),
@@ -70,10 +71,10 @@ int ft_init_stopwords()
int error=-1;
if (!*ft_stopword_file)
- return 0;
+ DBUG_RETURN(0);
if ((fd=my_open(ft_stopword_file, O_RDONLY, MYF(MY_WME))) == -1)
- return -1;
+ DBUG_RETURN(-1);
len=(uint)my_seek(fd, 0L, MY_SEEK_END, MYF(0));
my_seek(fd, 0L, MY_SEEK_SET, MYF(0));
if (!(start=buffer=my_malloc(len+1, MYF(MY_WME))))
@@ -90,7 +91,7 @@ err1:
my_free(buffer, MYF(0));
err0:
my_close(fd, MYF(MY_WME));
- return error;
+ DBUG_RETURN(error);
}
else
{
@@ -100,13 +101,14 @@ err0:
for (;*sws;sws++)
{
if (ft_add_stopword(*sws))
- return -1;
+ DBUG_RETURN(-1);
}
ft_stopword_file="(built-in)"; /* for SHOW VARIABLES */
}
- return 0;
+ DBUG_RETURN(0);
}
+
int is_stopword(char *word, uint len)
{
FT_STOPWORD sw;
@@ -118,6 +120,8 @@ int is_stopword(char *word, uint len)
void ft_free_stopwords()
{
+ DBUG_ENTER("ft_free_stopwords");
+
if (stopwords3)
{
delete_tree(stopwords3); /* purecov: inspected */
@@ -125,4 +129,5 @@ void ft_free_stopwords()
stopwords3=0;
}
ft_stopword_file= 0;
+ DBUG_VOID_RETURN;
}