diff options
65 files changed, 736 insertions, 429 deletions
diff --git a/.bzrignore b/.bzrignore index 5bdb136c0c6..acbf0040063 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3063,3 +3063,5 @@ libmysqld/sql_tablespace.cc sql/link_sources ylwrap libmysql_r/link_sources +storage/maria/unittest/page_cache_test_file_1 +storage/maria/unittest/pagecache_debug.log diff --git a/include/maria.h b/include/maria.h index 9f6672d482c..8baacfc9c13 100644 --- a/include/maria.h +++ b/include/maria.h @@ -255,7 +255,7 @@ extern my_bool maria_delay_key_write; extern my_off_t maria_max_temp_length; extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size; extern PAGECACHE maria_pagecache_var, *maria_pagecache; - +extern MY_TMPDIR *maria_tmpdir; /* Prototypes for maria-functions */ diff --git a/include/my_base.h b/include/my_base.h index 684e3633fe3..2b60ff552a4 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -422,7 +422,8 @@ enum ha_base_keytype { #define HA_ERR_LOGGING_IMPOSSIBLE 170 #define HA_ERR_NEW_FILE 171 /* New file format */ #define HA_ERR_INITIALIZATION 172 /* Error during initialization */ -#define HA_ERR_LAST 172 /* Copy of last error nr */ +#define HA_ERR_FILE_TOO_SHORT 173 /* File too short */ +#define HA_ERR_LAST 173 /* Copy of last error nr */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_sys.h b/include/my_sys.h index c884dd741f6..f8f3411f337 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -546,6 +546,7 @@ my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */ *(info)->current_pos) typedef uint32 ha_checksum; +extern ha_checksum my_crc_dbug_check; /* Define the type of function to be passed to process_default_option_files */ typedef int (*Process_option_func)(void *ctx, const char *group_name, @@ -858,6 +859,7 @@ extern int unpackfrm(uchar **, size_t *, const uchar *); extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem, size_t count); +extern void my_debug_put_break_here(void); extern void my_sleep(ulong m_seconds); extern ulong crc32(ulong crc, const uchar *buf, uint len); extern uint my_set_max_open_files(uint files); diff --git a/include/myisamchk.h b/include/myisamchk.h index 30b986a835a..3c5d59884be 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -128,6 +128,7 @@ typedef struct st_handler_check_param ha_checksum key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_key_crc[HA_MAX_POSSIBLE_KEY]; ha_checksum tmp_record_checksum; + ulonglong org_key_map; size_t use_buffers, read_buffer_length, write_buffer_length; size_t sort_buffer_length, sort_key_blocks; ulong rec_per_key_part[HA_MAX_KEY_SEG * HA_MAX_POSSIBLE_KEY]; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index d0b67e90afb..e7910ee9e32 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1440,7 +1440,7 @@ insert t2 select * from t1; insert t3 select * from t1; checksum table t1, t2, t3, t4 quick; Table Checksum -test.t1 2948697075 +test.t1 3442722830 test.t2 NULL test.t3 NULL test.t4 NULL @@ -1448,17 +1448,17 @@ Warnings: Error 1146 Table 'test.t4' doesn't exist checksum table t1, t2, t3, t4; Table Checksum -test.t1 2948697075 -test.t2 2948697075 -test.t3 2948697075 +test.t1 3442722830 +test.t2 3442722830 +test.t3 3442722830 test.t4 NULL Warnings: Error 1146 Table 'test.t4' doesn't exist checksum table t1, t2, t3, t4 extended; Table Checksum -test.t1 2948697075 -test.t2 2948697075 -test.t3 2948697075 +test.t1 3442722830 +test.t2 3442722830 +test.t3 3442722830 test.t4 NULL Warnings: Error 1146 Table 'test.t4' doesn't exist diff --git a/mysql-test/r/mix2_myisam.result b/mysql-test/r/mix2_myisam.result index cabc4de8d21..e0a3d1af089 100644 --- a/mysql-test/r/mix2_myisam.result +++ b/mysql-test/r/mix2_myisam.result @@ -1232,34 +1232,34 @@ insert t5 select * from t1; insert t6 select * from t1; checksum table t1, t2, t3, t4, t5, t6, t7 quick; Table Checksum -test.t1 2948697075 +test.t1 3442722830 test.t2 NULL test.t3 NULL test.t4 NULL -test.t5 2948697075 +test.t5 3442722830 test.t6 NULL test.t7 NULL Warnings: Error 1146 Table 'test.t7' doesn't exist checksum table t1, t2, t3, t4, t5, t6, t7; Table Checksum -test.t1 2948697075 -test.t2 2948697075 -test.t3 2948697075 -test.t4 2948697075 -test.t5 2948697075 -test.t6 2948697075 +test.t1 3442722830 +test.t2 3442722830 +test.t3 3442722830 +test.t4 3442722830 +test.t5 3442722830 +test.t6 3442722830 test.t7 NULL Warnings: Error 1146 Table 'test.t7' doesn't exist checksum table t1, t2, t3, t4, t5, t6, t7 extended; Table Checksum -test.t1 2948697075 -test.t2 2948697075 -test.t3 2948697075 -test.t4 2948697075 -test.t5 2948697075 -test.t6 2948697075 +test.t1 3442722830 +test.t2 3442722830 +test.t3 3442722830 +test.t4 3442722830 +test.t5 3442722830 +test.t6 3442722830 test.t7 NULL Warnings: Error 1146 Table 'test.t7' doesn't exist diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 73661897ee1..cb9c3355f7a 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2; +drop table if exists t1,t2,t3; SET SQL_WARNINGS=1; CREATE TABLE t1 ( STRING_DATA char(255) default NULL, @@ -551,22 +551,22 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, ""); insert t2 select * from t1; checksum table t1, t2, t3 quick; Table Checksum -test.t1 2948697075 +test.t1 3442722830 test.t2 NULL test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist checksum table t1, t2, t3; Table Checksum -test.t1 2948697075 -test.t2 2948697075 +test.t1 3442722830 +test.t2 3442722830 test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist checksum table t1, t2, t3 extended; Table Checksum -test.t1 2948697075 -test.t2 2948697075 +test.t1 3442722830 +test.t2 3442722830 test.t3 NULL Warnings: Error 1146 Table 'test.t3' doesn't exist diff --git a/mysql-test/r/old-mode.result b/mysql-test/r/old-mode.result new file mode 100644 index 00000000000..df2c0b6fee0 --- /dev/null +++ b/mysql-test/r/old-mode.result @@ -0,0 +1,14 @@ +drop table if exists t1,t2; +create table t1 (a int, b varchar(200), c text not null) checksum=1; +create table t2 (a int, b varchar(200), c text not null) checksum=0; +insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, ""); +insert t2 select * from t1; +checksum table t1, t2; +Table Checksum +test.t1 3442722830 +test.t2 2948697075 +checksum table t1, t2 extended; +Table Checksum +test.t1 2948697075 +test.t2 2948697075 +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index b06fd536f45..5c6fe0fc887 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -4,7 +4,7 @@ # Initialise --disable_warnings -drop table if exists t1,t2; +drop table if exists t1,t2,t3; --enable_warnings SET SQL_WARNINGS=1; diff --git a/mysql-test/t/old-mode-master.opt b/mysql-test/t/old-mode-master.opt new file mode 100644 index 00000000000..840ee0dedcf --- /dev/null +++ b/mysql-test/t/old-mode-master.opt @@ -0,0 +1 @@ +--old=1 diff --git a/mysql-test/t/old-mode.test b/mysql-test/t/old-mode.test new file mode 100644 index 00000000000..4fa21f761ca --- /dev/null +++ b/mysql-test/t/old-mode.test @@ -0,0 +1,16 @@ +# +# Test 'old' mode +# + +# Initialise +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +create table t1 (a int, b varchar(200), c text not null) checksum=1; +create table t2 (a int, b varchar(200), c text not null) checksum=0; +insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, ""); +insert t2 select * from t1; +checksum table t1, t2; +checksum table t1, t2 extended; +drop table t1,t2; diff --git a/mysys/checksum.c b/mysys/checksum.c index 4f86f6845f0..0cc9801c2b1 100644 --- a/mysys/checksum.c +++ b/mysys/checksum.c @@ -18,6 +18,8 @@ #include <my_sys.h> #include <zlib.h> +ha_checksum my_crc_dbug_check= 1; /* Unlikely number */ + /* Calculate a long checksum for a memoryblock. @@ -34,9 +36,13 @@ ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) const uchar *end=pos+length; for ( ; pos != end ; pos++) crc=((crc << 8) + *((uchar*) pos)) + (crc >> (8*sizeof(ha_checksum)-8)); - return crc; #else - return (ha_checksum)crc32((uint)crc, pos, length); + crc= (ha_checksum) crc32((uint)crc, pos, length); +#endif /* NOT_USED */ + DBUG_PRINT("info", ("crc: %lu", (ulong) crc)); +#ifndef DBUG_OFF + if (crc == my_crc_dbug_check) + my_debug_put_break_here(); #endif + return crc; } - diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index a847d722023..ff9c5a42f81 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -333,6 +333,7 @@ static void _lf_pinbox_real_free(LF_PINS *pins) struct st_lf_alloc_node *first, *last= NULL; LF_PINBOX *pinbox= pins->pinbox; + LINT_INIT(first); npins= pinbox->pins_in_array+1; #ifdef HAVE_ALLOCA diff --git a/mysys/my_handler.c b/mysys/my_handler.c index f7cf4f310d7..2b1c91a43e2 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -626,7 +626,8 @@ static const char *handler_error_messages[]= "Record is the same", "It is not possible to log this statement", "The table is of a new format not supported by this version", - "Got a fatal error during initialzaction of handler" + "Got a fatal error during initialzaction of handler", + "File to short; Expected more data in file" }; diff --git a/mysys/my_init.c b/mysys/my_init.c index 8ddc6092f79..850333e0100 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -78,7 +78,10 @@ my_bool my_init(void) my_umask= 0660; /* Default umask for new files */ my_umask_dir= 0700; /* Default umask for new directories */ init_glob_errs(); - my_progname_short= my_progname + dirname_length(my_progname); + my_progname_short= "unknown"; + if (my_progname) + my_progname_short= my_progname + dirname_length(my_progname); + #if defined(THREAD) && defined(SAFE_MUTEX) safe_mutex_global_init(); /* Must be called early */ #endif @@ -233,6 +236,13 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", my_init_done=0; } /* my_end */ +#ifndef DBUG_OFF +/* Dummy tag function for debugging */ + +void my_debug_put_break_here(void) +{ +} +#endif #ifdef __WIN__ diff --git a/mysys/my_pread.c b/mysys/my_pread.c index de7a2b611ed..821d8636d8e 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -15,6 +15,7 @@ #include "mysys_priv.h" #include "mysys_err.h" +#include "my_base.h" #include <errno.h> #ifdef HAVE_PREAD #include <unistd.h> @@ -63,7 +64,11 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, pthread_mutex_unlock(&my_file_info[Filedes].mutex); #else if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count))) - my_errno= errno ? errno : -1; + { + my_errno= errno; + if (errno == 0 || (errno == -1 && (MyFlags & (MY_NABP | MY_FNABP)))) + my_errno= HA_ERR_FILE_TOO_SHORT; + } #endif if (error || readbytes != Count) { diff --git a/mysys/my_read.c b/mysys/my_read.c index f3e8a4b300e..ee91620e163 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -15,9 +15,9 @@ #include "mysys_priv.h" #include "mysys_err.h" +#include <my_base.h> #include <errno.h> - /* Read a chunk of bytes from a file with retry's if needed @@ -46,7 +46,9 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) errno= 0; /* Linux doesn't reset this */ if ((readbytes= read(Filedes, Buffer, Count)) != Count) { - my_errno= errno ? errno : -1; + my_errno= errno; + if (errno == 0 || (errno == -1 && (MyFlags & (MY_NABP | MY_FNABP)))) + my_errno= HA_ERR_FILE_TOO_SHORT; DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", (int) readbytes, (ulong) Count, Filedes, my_errno)); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 731d49474f7..c95522b114d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -340,6 +340,7 @@ static char *default_storage_engine_str; static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; static I_List<THD> thread_cache; static double long_query_time; +static ulong opt_my_crc_dbug_check; static pthread_cond_t COND_thread_cache, COND_flush_thread_cache; @@ -5119,7 +5120,7 @@ enum options_mysqld OPT_SECURE_FILE_PRIV, OPT_MIN_EXAMINED_ROW_LIMIT, OPT_LOG_SLOW_SLAVE_STATEMENTS, - OPT_OLD_MODE + OPT_DEBUG_CRC, OPT_OLD_MODE }; @@ -5244,6 +5245,10 @@ struct my_option my_long_options[] = #ifndef DBUG_OFF {"debug", '#', "Debug log.", (uchar**) &default_dbug_option, (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-crc-break", OPT_DEBUG_CRC, + "Call my_debug_put_break_here() if crc matches this number (for debug).", + (uchar**) &opt_my_crc_dbug_check, (uchar**) &opt_my_crc_dbug_check, + 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~(ulong) 0L, 0, 0, 0}, #endif {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).", (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, @@ -7893,6 +7898,7 @@ static void get_options(int *argc,char **argv) /* Set global variables based on startup options */ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); + my_crc_dbug_check= opt_my_crc_dbug_check; /* long_query_time is in microseconds */ global_system_variables.long_query_time= max_system_variables.long_query_time= diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e440aeaa588..ad0ba27651f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4683,8 +4683,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, (see SQLCOM_GRANT case, mysql_execute_command() function) and set db_is_pattern according to 'dont_check_global_grants' value. */ - bool db_is_pattern= (test(want_access & GRANT_ACL) && - dont_check_global_grants); + bool db_is_pattern= ((want_access & GRANT_ACL) && dont_check_global_grants); #endif ulong dummy; DBUG_ENTER("check_access"); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 287c183c830..46e443d33f7 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1211,7 +1211,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ? maria_get_mask_all_keys_active(share->base.keys) : share->state.key_map); - uint testflag= param.testflag; + uint save_testflag= param.testflag; if (maria_test_if_sort_rep(file, file->state->records, key_map, 0) && (local_testflag & T_REP_BY_SORT)) { @@ -1226,6 +1226,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) /* TODO: respect maria_repair_threads variable */ my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map)); thd->proc_info= buf; + param.testflag|= T_REP_PARALLEL; error= maria_repair_parallel(¶m, file, fixed_name, param.testflag & T_QUICK); thd->proc_info= "Repair done"; // to reset proc_info, as @@ -1234,6 +1235,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) else { thd->proc_info= "Repair by sorting"; + param.testflag|= T_REP_BY_SORT; error= maria_repair_by_sort(¶m, file, fixed_name, param.testflag & T_QUICK); } @@ -1241,7 +1243,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) else { thd->proc_info= "Repair with keycache"; - param.testflag &= ~T_REP_BY_SORT; + param.testflag &= ~(T_REP_BY_SORT | T_REP_PARALLEL); error= maria_repair(¶m, file, fixed_name, param.testflag & T_QUICK); /** @todo RECOVERY BUG we do things with the index file @@ -1249,7 +1251,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) record and bumped create_rename_lsn. Is it ok? */ } - param.testflag= testflag; + param.testflag= save_testflag; optimize_done= 1; } if (!error) @@ -2410,13 +2412,14 @@ static int ha_maria_init(void *p) maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES; bzero(maria_log_pagecache, sizeof(*maria_log_pagecache)); maria_data_root= mysql_real_data_home; + maria_tmpdir= &mysql_tmpdir_list; /* For REDO */ res= maria_init() || ma_control_file_create_or_open() || - (init_pagecache(maria_pagecache, + !init_pagecache(maria_pagecache, pagecache_buffer_size, pagecache_division_limit, - pagecache_age_threshold, MARIA_KEY_BLOCK_LENGTH) == 0) || - (init_pagecache(maria_log_pagecache, + pagecache_age_threshold, MARIA_KEY_BLOCK_LENGTH, 0) || + !init_pagecache(maria_log_pagecache, TRANSLOG_PAGECACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE) == 0) || + TRANSLOG_PAGE_SIZE, 0) || translog_init(maria_data_root, TRANSLOG_FILE_SIZE, MYSQL_VERSION_ID, server_id, maria_log_pagecache, TRANSLOG_DEFAULT_FLAGS) || diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index f4abbc2c1c5..36218351b7b 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -5045,7 +5045,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &page_link.link))) { - if (my_errno != -1) /* If not read outside of file */ + if (my_errno != HA_ERR_FILE_TOO_SHORT) /* If not read outside of file */ { pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, @@ -5487,7 +5487,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_WRITE, &page_link.link))) { - if (my_errno != -1) /* If not read outside of file */ + if (my_errno != HA_ERR_FILE_TOO_SHORT) /* If not read outside of file */ { pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, diff --git a/storage/maria/ma_cache.c b/storage/maria/ma_cache.c index 6b1f9ec3fae..0cd4a356f70 100644 --- a/storage/maria/ma_cache.c +++ b/storage/maria/ma_cache.c @@ -97,8 +97,8 @@ int _ma_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length, DBUG_PRINT("error", ("Error %d reading next-multi-part block (Got %d bytes)", my_errno, (int) read_length)); - if (!my_errno || my_errno == -1) - my_errno=HA_ERR_WRONG_IN_RECORD; + if (!my_errno || my_errno == HA_ERR_FILE_TOO_SHORT) + my_errno= HA_ERR_WRONG_IN_RECORD; DBUG_RETURN(1); } bzero(buff+read_length,MARIA_BLOCK_INFO_HEADER_LENGTH - in_buff_length - diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index f30ebebd6e7..d3e472c3ebb 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -2051,6 +2051,11 @@ static void initialize_variables_for_repair(HA_CHECK *param, if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) param->testflag|= T_CALC_CHECKSUM; param->glob_crc= 0; + if (rep_quick) + param->testflag|= T_QUICK; + else + param->testflag&= ~T_QUICK; + param->org_key_map= info->s->state.key_map; sort_param->sort_info= sort_info; sort_param->fix_datafile= (my_bool) (! rep_quick); @@ -2872,7 +2877,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, double *rec_per_key_part; char llbuff[22]; MARIA_SORT_INFO sort_info; - ulonglong key_map=share->state.key_map; + ulonglong key_map= share->state.key_map; myf sync_dir= ((share->now_transactional && !share->temporary) ? MY_SYNC_DIR : 0); my_bool scan_inited= 0; @@ -3005,9 +3010,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, for (sort_param.key=0 ; sort_param.key < share->base.keys ; rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++) { - sort_param.read_cache=param->read_cache; sort_param.keyinfo=share->keyinfo+sort_param.key; - sort_param.seg=sort_param.keyinfo->seg; if (! maria_is_key_active(key_map, sort_param.key)) { /* Remember old statistics for key */ @@ -3020,6 +3023,9 @@ 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.read_cache=param->read_cache; + sort_param.seg=sort_param.keyinfo->seg; sort_param.max_pos= sort_param.pos= org_header_length; keyseg=sort_param.seg; bzero((char*) sort_param.unique,sizeof(sort_param.unique)); @@ -3364,9 +3370,6 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, printf("Data records: %s\n", llstr(start_records,llbuff)); } - if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - param->testflag|=T_CALC_CHECKSUM; - if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, FLUSH_FORCE_WRITE, FLUSH_IGNORE_CHANGED)) goto err; @@ -4815,14 +4818,17 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, /* Save pointer to previous block */ if (nod_flag) + { + _ma_store_keypage_flag(info, anc_buff, KEYPAGE_FLAG_ISNOD); _ma_kpointer(info,key_block->end_pos,prev_block); + } t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0,lastkey,lastkey,key, &s_temp); (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp); a_length+=t_length; - _ma_store_page_used(info, anc_buff, a_length, nod_flag); + _ma_store_page_used(info, anc_buff, a_length); key_block->end_pos+=t_length; if (a_length <= keyinfo->block_length) { @@ -4832,7 +4838,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, } /* Fill block with end-zero and write filled block */ - _ma_store_page_used(info, anc_buff, key_block->last_length, nod_flag); + _ma_store_page_used(info, anc_buff, key_block->last_length); bzero(anc_buff+key_block->last_length, keyinfo->block_length- key_block->last_length); key_file_length=info->state->key_file_length; @@ -5812,8 +5818,7 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) if (translog_inited && !maria_in_recovery && info->s->base.born_transactional) { - my_bool now_transactional= info->s->now_transactional; - info->s->now_transactional= 1; + my_bool save_now_transactional= info->s->now_transactional; /* For now this record is only informative. It could serve when applying @@ -5833,15 +5838,21 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) record). */ LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 1]; - uchar log_data[FILEID_STORE_SIZE + 4]; + uchar log_data[FILEID_STORE_SIZE + 4 + 8]; LSN lsn; - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); + /* testflag gives an idea of what REPAIR did (in particular T_QUICK or not: did it touch the data file or not?). */ int4store(log_data + FILEID_STORE_SIZE, param->testflag); + /* org_key_map is used when recreating index after a load data infile */ + int8store(log_data + FILEID_STORE_SIZE + 4, param->org_key_map); + + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); + + info->s->now_transactional= 1; if (unlikely(translog_write_record(&lsn, LOGREC_REDO_REPAIR_TABLE, &dummy_transaction_object, info, sizeof(log_data), @@ -5857,7 +5868,7 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) */ if (_ma_update_create_rename_lsn(share, lsn, TRUE)) return 1; - info->s->now_transactional= now_transactional; + info->s->now_transactional= save_now_transactional; } return 0; } diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 12e2f2e426d..58203de0568 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -176,6 +176,7 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key, struct st_msg_to_write_hook_for_undo_key msg; enum translog_record_type log_type= LOGREC_UNDO_KEY_DELETE; + info->key_delete_undo_lsn[keynr]= info->trn->undo_lsn; lsn_store(log_data, info->trn->undo_lsn); key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keynr); log_pos= log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + KEY_NR_STORE_SIZE; @@ -436,7 +437,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, anc_page_link->changed= 1; anc_buff_length-= tmp; - _ma_store_page_used(info, anc_buff, anc_buff_length, nod_flag); + _ma_store_page_used(info, anc_buff, anc_buff_length); /* Log initial changes on pages @@ -622,7 +623,7 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, } /* Remove last key from leaf page */ - _ma_store_page_used(info, leaf_buff, key_start-leaf_buff, nod_flag); + _ma_store_page_used(info, leaf_buff, key_start-leaf_buff); if (info->s->now_transactional && _ma_log_suffix(info, leaf_page, leaf_buff, leaf_length, @@ -659,11 +660,10 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key)) goto err; _ma_kpointer(info,keypos - share->base.key_reflength,next_block); - _ma_store_page_used(info, anc_buff, a_length + length, - share->base.key_reflength); + _ma_store_page_used(info, anc_buff, a_length + length); if (info->s->now_transactional && - _ma_log_add(info, anc_page, anc_buff, a_length + length, + _ma_log_add(info, anc_page, anc_buff, a_length, key_start, s_temp.changed_length, s_temp.move_length, 1)) goto err; @@ -704,7 +704,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, int t_length; uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag; uint next_buff_length, new_buff_length, key_reflength, key_length; - uint unchanged_leaf_length, new_leaf_length; + uint unchanged_leaf_length, new_leaf_length, new_anc_length; my_off_t next_page; uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF]; uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*prev_key; @@ -778,7 +778,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, memcpy(buff, leaf_buff,(size_t) leaf_length); (*keyinfo->store_key)(keyinfo, buff+leaf_length, &key_inserted); buff_length= (uint) (endpos-buff); - _ma_store_page_used(info, buff, buff_length, nod_flag); + _ma_store_page_used(info, buff, buff_length); /* remove key from anc_buff */ if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key, @@ -786,8 +786,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, &key_deleted))) goto err; - anc_length-=s_length; - _ma_store_page_used(info, anc_buff, anc_length, key_reflength); + new_anc_length= anc_length - s_length; + _ma_store_page_used(info, anc_buff, new_anc_length); if (buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { @@ -827,7 +827,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, */ MARIA_KEY_PARAM anc_key_inserted; - anc_end_pos= anc_buff + anc_length; + anc_end_pos= anc_buff + new_anc_length; DBUG_PRINT("test",("anc_buff: 0x%lx anc_end_pos: 0x%lx", (long) anc_buff, (long) anc_end_pos)); if (!first_key && @@ -838,7 +838,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, goto err; new_leaf_length= (uint) (half_pos-buff); memcpy(leaf_buff, buff, (size_t) new_leaf_length); - _ma_store_page_used(info, leaf_buff, new_leaf_length, nod_flag); + _ma_store_page_used(info, leaf_buff, new_leaf_length); /* Correct new keypointer to leaf_page */ half_pos=after_key; @@ -857,8 +857,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted); - anc_length+= t_length; - _ma_store_page_used(info, anc_buff, anc_length, key_reflength); + new_anc_length+= t_length; + _ma_store_page_used(info, anc_buff, new_anc_length); /* Store key first in new page */ if (nod_flag) @@ -874,7 +874,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, bmove(buff+p_length+t_length, half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,buff+p_length, &key_inserted); new_buff_length= length + t_length + p_length; - _ma_store_page_used(info, buff, new_buff_length, nod_flag); + _ma_store_page_used(info, buff, new_buff_length); if (info->s->now_transactional) { @@ -889,7 +889,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (_ma_log_add(info, anc_page, anc_buff, anc_length, keypos, anc_key_inserted.move_length + - min(anc_key_inserted.changed_length - + max(anc_key_inserted.changed_length - anc_key_inserted.move_length, key_deleted.changed_length), anc_key_inserted.move_length - @@ -940,8 +940,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, leaf_buff)) goto err; - DBUG_RETURN(anc_length <= ((info->quick_mode ? MARIA_MIN_BLOCK_LENGTH : - (uint) keyinfo->underflow_block_length))); + DBUG_RETURN(new_anc_length <= ((info->quick_mode ? MARIA_MIN_BLOCK_LENGTH : + (uint) keyinfo->underflow_block_length))); } DBUG_PRINT("test",("use left page")); @@ -988,7 +988,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, key_inserted.move_length); new_buff_length= buff_length + leaf_length - p_length + t_length; - _ma_store_page_used(info, buff, new_buff_length, nod_flag); + _ma_store_page_used(info, buff, new_buff_length); /* remove key from anc_buff */ if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key, @@ -996,8 +996,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, &key_deleted))) goto err; - anc_length-=s_length; - _ma_store_page_used(info, anc_buff, anc_length, key_reflength); + new_anc_length= anc_length - s_length; + _ma_store_page_used(info, anc_buff, new_anc_length); if (new_buff_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) @@ -1049,9 +1049,9 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, _ma_kpointer(info,leaf_key+key_length,leaf_page); /* Save key in anc_buff */ - DBUG_DUMP("anc_buff",anc_buff,anc_length); + DBUG_DUMP("anc_buff", anc_buff, new_anc_length); DBUG_DUMP("key_to_anc",leaf_key,key_length); - anc_end_pos= anc_buff + anc_length; + anc_end_pos= anc_buff + new_anc_length; t_length=(*keyinfo->pack_key)(keyinfo,key_reflength, keypos == anc_end_pos ? (uchar*) 0 : keypos, @@ -1063,8 +1063,8 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, else bmove(keypos,keypos-t_length,(uint) (anc_end_pos-keypos)+t_length); (*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted); - anc_length+= t_length; - _ma_store_page_used(info, anc_buff, anc_length, key_reflength); + new_anc_length+= t_length; + _ma_store_page_used(info, anc_buff, new_anc_length); /* Store first key on new page */ if (nod_flag) @@ -1082,9 +1082,9 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, bmove(leaf_buff+p_length+t_length, half_pos, (size_t) length); (*keyinfo->store_key)(keyinfo,leaf_buff+p_length, &key_inserted); new_leaf_length= length + t_length + p_length; - _ma_store_page_used(info, leaf_buff, new_leaf_length, nod_flag); + _ma_store_page_used(info, leaf_buff, new_leaf_length); new_buff_length= (uint) (endpos - buff); - _ma_store_page_used(info, buff, new_buff_length, nod_flag); + _ma_store_page_used(info, buff, new_buff_length); if (info->s->now_transactional) { @@ -1099,7 +1099,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (_ma_log_add(info, anc_page, anc_buff, anc_length, keypos, anc_key_inserted.move_length + - min(anc_key_inserted.changed_length - + max(anc_key_inserted.changed_length - anc_key_inserted.move_length, key_deleted.changed_length), anc_key_inserted.move_length - @@ -1136,7 +1136,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, if (_ma_write_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_LEFT_WRITELOCKED, DFLT_INIT_HITS, buff)) goto err; - DBUG_RETURN(anc_length <= (uint) + DBUG_RETURN(new_anc_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)/2); err: @@ -1262,6 +1262,7 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag, uint pack_length; uint diff= (next_length-prev_length); + /* keypos points to data of next key (after key length) */ bmove(keypos - diff, lastkey + prev_length, diff); rest_length+= diff; pack_length= prev_length ? get_pack_length(rest_length): 0; @@ -1323,14 +1324,15 @@ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, uint move_length) { LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 9], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 9 + 7], *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 3]; uint translog_parts; uint offset= (uint) (key_pos - buff); DBUG_ENTER("_ma_log_delete"); DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d", (ulong) page, changed_length, move_length)); DBUG_ASSERT(info->s->now_transactional && move_length); + DBUG_ASSERT(offset + changed_length <= _ma_get_page_used(info, buff)); /* Store address of new root page */ page/= info->s->block_size; @@ -1352,6 +1354,22 @@ static my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, uchar *buff, log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; } +#ifdef EXTRA_DEBUG_KEY_CHANGES + { + int page_length= _ma_get_page_used(info, buff); + ha_checksum crc; + crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE); + log_pos[0]= KEY_OP_CHECK; + int2store(log_pos+1, page_length); + int4store(log_pos+3, crc); + + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= log_pos; + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= 7; + changed_length+= 7; + translog_parts++; + } +#endif + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index c631594671f..0b3e84b76d6 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -1801,7 +1801,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, if (my_read(info->dfile.file, (uchar*)to, block_info.data_len, MYF(MY_NABP))) { - if (my_errno == -1) + if (my_errno == HA_ERR_FILE_TOO_SHORT) my_errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */ goto err; } diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c index b793ccd1295..841b83e01f3 100644 --- a/storage/maria/ma_ft_update.c +++ b/storage/maria/ma_ft_update.c @@ -330,7 +330,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key) /* creating pageful of keys */ bzero(info->buff, info->s->keypage_header); _ma_store_keynr(info, info->buff, keynr); - _ma_store_page_used(info, info->buff, length + info->s->keypage_header, 0); + _ma_store_page_used(info, info->buff, length + info->s->keypage_header); memcpy(info->buff + info->s->keypage_header, key_ptr, length); info->keyread_buff_used= info->page_changed=1; /* info->buff is used */ if ((root= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR || diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index ed9c785439b..beca5077ee5 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -206,8 +206,8 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, { uint translog_parts; LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7 + 7], *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 3]; DBUG_ENTER("_ma_log_prefix"); DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d", (ulong) page, changed_length, move_length)); @@ -223,7 +223,6 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, log_pos[0]= KEY_OP_DEL_PREFIX; int2store(log_pos+1, -move_length); log_pos+= 3; - translog_parts= 1; if (changed_length) { /* @@ -244,6 +243,8 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, int2store(log_pos+3, changed_length); log_pos+= 5; } + + translog_parts= 1; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); @@ -255,6 +256,22 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page, translog_parts= 2; } +#ifdef EXTRA_DEBUG_KEY_CHANGES + { + int page_length= _ma_get_page_used(info, buff); + ha_checksum crc; + crc= my_checksum(0, buff + LSN_STORE_SIZE, page_length - LSN_STORE_SIZE); + log_pos[0]= KEY_OP_CHECK; + int2store(log_pos+1, page_length); + int4store(log_pos+3, crc); + + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= log_pos; + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= 7; + changed_length+= 7; + translog_parts++; + } +#endif + DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, info->trn, info, log_array[TRANSLOG_INTERNAL_PARTS + @@ -273,8 +290,8 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, uchar *buff, uint org_length, uint new_length) { LSN lsn; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10], *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 3]; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10 + 7], *log_pos; int diff; uint translog_parts, extra_length; DBUG_ENTER("_ma_log_suffix"); @@ -305,10 +322,26 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, translog_parts= 2; extra_length= (uint) diff; } + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); +#ifdef EXTRA_DEBUG_KEY_CHANGES + { + ha_checksum crc; + crc= my_checksum(0, buff + LSN_STORE_SIZE, new_length - LSN_STORE_SIZE); + log_pos[0]= KEY_OP_CHECK; + int2store(log_pos+1, new_length); + int4store(log_pos+3, crc); + + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= log_pos; + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= 7; + extra_length+= 7; + translog_parts++; + } +#endif + DBUG_RETURN(translog_write_record(&lsn, LOGREC_REDO_INDEX, info->trn, info, log_array[TRANSLOG_INTERNAL_PARTS + @@ -321,6 +354,9 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page, /** @brief Log that a key was added to the page + @param buff Page buffer + @param buff_length Original length of buff (before key was added) + @note If handle_overflow is set, then we have to protect against logging changes that is outside of the page. @@ -334,12 +370,14 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, my_bool handle_overflow __attribute__ ((unused))) { LSN lsn; - uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3+ 3 + 3 + 3], *log_pos; - LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; + uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3 + 3 + 7]; + uchar *log_pos; + LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 3]; uint offset= (uint) (key_pos - buff); uint page_length= info->s->block_size - KEYPAGE_CHECKSUM_SIZE; + uint translog_parts; DBUG_ENTER("_ma_log_add"); - DBUG_PRINT("enter", ("page: %lu page_length: %u changed_length: %u " + DBUG_PRINT("enter", ("page: %lu org_page_length: %u changed_length: %u " "move_length: %d", (ulong) page, buff_length, changed_length, move_length)); @@ -394,6 +432,7 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, } int2store(log_pos+1, changed_length); log_pos+= 3; + translog_parts= 2; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - @@ -401,12 +440,31 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff, log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key_pos; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= changed_length; +#ifdef EXTRA_DEBUG_KEY_CHANGES + { + ha_checksum crc; + uint save_page_length= _ma_get_page_used(info, buff); + uint new_length= buff_length + move_length; + _ma_store_page_used(info, buff, new_length); + crc= my_checksum(0, buff + LSN_STORE_SIZE, new_length - LSN_STORE_SIZE); + log_pos[0]= KEY_OP_CHECK; + int2store(log_pos+1, new_length); + int4store(log_pos+3, crc); + + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].str= log_pos; + log_array[TRANSLOG_INTERNAL_PARTS + translog_parts].length= 7; + changed_length+= 7; + translog_parts++; + _ma_store_page_used(info, buff, save_page_length); + } +#endif + if (translog_write_record(&lsn, LOGREC_REDO_INDEX, info->trn, info, log_array[TRANSLOG_INTERNAL_PARTS + 0].length + changed_length, - TRANSLOG_INTERNAL_PARTS + 2, log_array, - log_data, NULL)) + TRANSLOG_INTERNAL_PARTS + translog_parts, + log_array, log_data, NULL)) DBUG_RETURN(-1); DBUG_RETURN(0); } @@ -627,11 +685,15 @@ err: KEY_OP_ADD_SUFFIX 2 length, data Add data to end of page KEY_OP_DEL_SUFFIX 2 length Reduce page length with this Sets position to start of page + KEY_OP_CHECK 6 page_length[2},CRC Used only when debugging + @return Operation status @retval 0 OK @retval 1 Error */ +long my_counter= 0; + uint _ma_apply_redo_index(MARIA_HA *info, LSN lsn, const uchar *header, uint head_length) { @@ -674,12 +736,12 @@ uint _ma_apply_redo_index(MARIA_HA *info, do { switch ((enum en_key_op) (*header++)) { - case KEY_OP_OFFSET: + case KEY_OP_OFFSET: /* 1 */ page_offset= uint2korr(header); header+= 2; DBUG_ASSERT(page_offset >= keypage_header && page_offset <= page_length); break; - case KEY_OP_SHIFT: + case KEY_OP_SHIFT: /* 2 */ { int length= sint2korr(header); header+= 2; @@ -695,7 +757,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, page_length+= length; break; } - case KEY_OP_CHANGE: + case KEY_OP_CHANGE: /* 3 */ { uint length= uint2korr(header); DBUG_ASSERT(page_offset != 0 && page_offset + length <= page_length); @@ -704,7 +766,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, header+= 2 + length; break; } - case KEY_OP_ADD_PREFIX: + case KEY_OP_ADD_PREFIX: /* 4 */ { uint insert_length= uint2korr(header); uint changed_length= uint2korr(header+2); @@ -718,7 +780,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, page_length+= insert_length; break; } - case KEY_OP_DEL_PREFIX: + case KEY_OP_DEL_PREFIX: /* 5 */ { uint length= uint2korr(header); header+= 2; @@ -731,7 +793,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, page_offset= keypage_header; /* Prepare for change */ break; } - case KEY_OP_ADD_SUFFIX: + case KEY_OP_ADD_SUFFIX: /* 6 */ { uint insert_length= uint2korr(header); DBUG_ASSERT(page_length + insert_length <= share->block_size); @@ -741,7 +803,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, header+= 2 + insert_length; break; } - case KEY_OP_DEL_SUFFIX: + case KEY_OP_DEL_SUFFIX: /* 7 */ { uint del_length= uint2korr(header); header+= 2; @@ -749,6 +811,21 @@ uint _ma_apply_redo_index(MARIA_HA *info, page_length-= del_length; break; } + case KEY_OP_CHECK: /* 8 */ +#ifdef EXTRA_DEBUG_KEY_CHANGES + { + uint check_page_length; + ha_checksum crc; + check_page_length= uint2korr(header); + crc= uint4korr(header+2); + _ma_store_page_used(info, buff, page_length); + DBUG_ASSERT(check_page_length == page_length); + DBUG_ASSERT(crc == (uint32) my_checksum(0, buff + LSN_STORE_SIZE, + page_length- LSN_STORE_SIZE)); +#endif + header+= 6; + break; + } case KEY_OP_NONE: default: DBUG_ASSERT(0); @@ -759,7 +836,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, DBUG_ASSERT(header == header_end); /* Write modified page */ - _ma_store_page_used(info, buff, page_length, nod_flag); + _ma_store_page_used(info, buff, page_length); /* Clean old stuff up. Gives us better compression of we archive things @@ -768,15 +845,6 @@ uint _ma_apply_redo_index(MARIA_HA *info, if (page_length < org_page_length) bzero(buff + page_length, org_page_length-page_length); - result= 0; - if (pagecache_write(share->pagecache, - &info->s->kfile, page, 0, - buff, PAGECACHE_PLAIN_PAGE, - PAGECACHE_LOCK_LEFT_WRITELOCKED, - PAGECACHE_PIN_LEFT_PINNED, - PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE)) - result= 1; - /* Mark page to be unlocked and written at _ma_unpin_all_pages() */ page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; page_link.changed= 1; diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index 0b24fe9594c..aee9d729d53 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -389,8 +389,8 @@ int _ma_readinfo(register MARIA_HA *info __attribute__ ((unused)), /* should not be done for transactional tables */ if (_ma_state_info_read_dsk(share->kfile.file, &share->state)) { - int error=my_errno ? my_errno : -1; - my_errno=error; + if (!my_errno) + my_errno= HA_ERR_FILE_TOO_SHORT; DBUG_RETURN(1); } } diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 2b1d6e4a48d..2866e922e6e 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -548,7 +548,7 @@ static LOG_DESC INIT_LOGREC_REDO_DELETE_ALL= "redo_delete_all", LOGREC_IS_GROUP_ITSELF, NULL, NULL}; static LOG_DESC INIT_LOGREC_REDO_REPAIR_TABLE= -{LOGRECTYPE_FIXEDLENGTH, FILEID_STORE_SIZE + 4, FILEID_STORE_SIZE + 4, +{LOGRECTYPE_FIXEDLENGTH, FILEID_STORE_SIZE + 4 + 8, FILEID_STORE_SIZE + 4 + 8, NULL, NULL, NULL, 0, "redo_repair_table", LOGREC_IS_GROUP_ITSELF, NULL, NULL}; diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 4aa98cb2f0a..f6652ea4494 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -155,6 +155,7 @@ enum en_key_op KEY_OP_DEL_PREFIX, /* Delete data at start of page */ KEY_OP_ADD_SUFFIX, /* Insert data at end of page */ KEY_OP_DEL_SUFFIX, /* Delete data at end of page */ + KEY_OP_CHECK /* For debugging; CRC of used part of page */ }; /* Size of log file; One log file is restricted to 4G */ diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 9fe2b5ec704..24293b79a1a 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -121,6 +121,10 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, &info.first_mbr_key, share->base.max_key_length, &info.maria_rtree_recursion_state, share->have_rtree ? 1024 : 0, + &info.key_write_undo_lsn, + (uint) (sizeof(LSN) * share->base.keys), + &info.key_delete_undo_lsn, + (uint) (sizeof(LSN) * share->base.keys), &changed_fields_bitmap, bitmap_buffer_size(share->base.fields), NullS)) diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index dff9d504f3c..68827e9fbbc 100755 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -44,7 +44,6 @@ #include "ma_pagecache.h" #include <my_bit.h> #include <errno.h> -#include <stdarg.h> /* Some compilation flags have been added specifically for this module @@ -95,7 +94,7 @@ #define PCBLOCK_INFO(B) \ DBUG_PRINT("info", \ - ("block: 0x%lx file: %lu page: %lu s: %0x hshL: 0x%lx req: %u/%u " \ + ("block: 0x%lx fd: %lu page: %lu s: %0x hshL: 0x%lx req: %u/%u " \ "wrlocks: %u pins: %u", \ (ulong)(B), \ (ulong)((B)->hash_link ? \ @@ -671,6 +670,8 @@ static inline uint next_power(uint value) division_limit division limit (may be zero) age_threshold age threshold (may be zero) block_size size of block (should be power of 2) + my_read_flags Flags used for all pread/pwrite calls + Usually MY_WME in case of recovery RETURN VALUE number of blocks in the key cache, if successful, @@ -688,7 +689,7 @@ static inline uint next_power(uint value) ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, - uint block_size) + uint block_size, myf my_readwrite_flags) { ulong blocks, hash_links, length; int error; @@ -721,8 +722,8 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, pagecache->mem_size= use_mem; pagecache->block_size= block_size; pagecache->shift= my_bit_log2(block_size); - DBUG_PRINT("info", ("block_size: %u", - block_size)); + pagecache->readwrite_flags= my_readwrite_flags | MY_NABP | MY_WAIT_IF_FULL; + DBUG_PRINT("info", ("block_size: %u", block_size)); DBUG_ASSERT(((uint)(1 << pagecache->shift)) == block_size); blocks= (ulong) (use_mem / (sizeof(PAGECACHE_BLOCK_LINK) + @@ -733,102 +734,99 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, We need to support page cache with just one block to be able to do scanning of rows-in-block files */ - if (blocks >= 1) + for ( ; ; ) { - for ( ; ; ) + if (blocks < 8) { - if (blocks < 8) - { - my_errno= ENOMEM; - goto err; - } - /* Set my_hash_entries to the next bigger 2 power */ - if ((pagecache->hash_entries= next_power(blocks)) < - (blocks) * 5/4) - pagecache->hash_entries<<= 1; - hash_links= 2 * blocks; + my_errno= ENOMEM; + goto err; + } + /* Set my_hash_entries to the next bigger 2 power */ + if ((pagecache->hash_entries= next_power(blocks)) < + (blocks) * 5/4) + pagecache->hash_entries<<= 1; + hash_links= 2 * blocks; #if defined(MAX_THREADS) - if (hash_links < MAX_THREADS + blocks - 1) - hash_links= MAX_THREADS + blocks - 1; + if (hash_links < MAX_THREADS + blocks - 1) + hash_links= MAX_THREADS + blocks - 1; #endif - while ((length= (ALIGN_SIZE(blocks * sizeof(PAGECACHE_BLOCK_LINK)) + - ALIGN_SIZE(hash_links * sizeof(PAGECACHE_HASH_LINK)) + - ALIGN_SIZE(sizeof(PAGECACHE_HASH_LINK*) * - pagecache->hash_entries))) + - (blocks << pagecache->shift) > use_mem) - blocks--; - /* Allocate memory for cache page buffers */ - if ((pagecache->block_mem= - my_large_malloc((ulong) blocks * pagecache->block_size, - MYF(MY_WME)))) - { - /* - Allocate memory for blocks, hash_links and hash entries; - For each block 2 hash links are allocated - */ - if ((pagecache->block_root= - (PAGECACHE_BLOCK_LINK*) my_malloc((size_t) length, MYF(0)))) - break; - my_large_free(pagecache->block_mem, MYF(0)); - pagecache->block_mem= 0; - } - blocks= blocks / 4*3; + while ((length= (ALIGN_SIZE(blocks * sizeof(PAGECACHE_BLOCK_LINK)) + + ALIGN_SIZE(hash_links * sizeof(PAGECACHE_HASH_LINK)) + + ALIGN_SIZE(sizeof(PAGECACHE_HASH_LINK*) * + pagecache->hash_entries))) + + (blocks << pagecache->shift) > use_mem) + blocks--; + /* Allocate memory for cache page buffers */ + if ((pagecache->block_mem= + my_large_malloc((ulong) blocks * pagecache->block_size, + MYF(MY_WME)))) + { + /* + Allocate memory for blocks, hash_links and hash entries; + For each block 2 hash links are allocated + */ + if ((pagecache->block_root= + (PAGECACHE_BLOCK_LINK*) my_malloc((size_t) length, MYF(0)))) + break; + my_large_free(pagecache->block_mem, MYF(0)); + pagecache->block_mem= 0; } - pagecache->blocks_unused= blocks; - pagecache->disk_blocks= (long) blocks; - pagecache->hash_links= hash_links; - pagecache->hash_root= - (PAGECACHE_HASH_LINK**) ((char*) pagecache->block_root + - ALIGN_SIZE(blocks*sizeof(PAGECACHE_BLOCK_LINK))); - pagecache->hash_link_root= - (PAGECACHE_HASH_LINK*) ((char*) pagecache->hash_root + - ALIGN_SIZE((sizeof(PAGECACHE_HASH_LINK*) * - pagecache->hash_entries))); - bzero((uchar*) pagecache->block_root, - pagecache->disk_blocks * sizeof(PAGECACHE_BLOCK_LINK)); - bzero((uchar*) pagecache->hash_root, - pagecache->hash_entries * sizeof(PAGECACHE_HASH_LINK*)); - bzero((uchar*) pagecache->hash_link_root, - pagecache->hash_links * sizeof(PAGECACHE_HASH_LINK)); - pagecache->hash_links_used= 0; - pagecache->free_hash_list= NULL; - pagecache->blocks_used= pagecache->blocks_changed= 0; - - pagecache->global_blocks_changed= 0; - pagecache->blocks_available=0; /* For debugging */ - - /* The LRU chain is empty after initialization */ - pagecache->used_last= NULL; - pagecache->used_ins= NULL; - pagecache->free_block_list= NULL; - pagecache->time= 0; - pagecache->warm_blocks= 0; - pagecache->min_warm_blocks= (division_limit ? - blocks * division_limit / 100 + 1 : - blocks); - pagecache->age_threshold= (age_threshold ? - blocks * age_threshold / 100 : + blocks= blocks / 4*3; + } + pagecache->blocks_unused= blocks; + pagecache->disk_blocks= (long) blocks; + pagecache->hash_links= hash_links; + pagecache->hash_root= + (PAGECACHE_HASH_LINK**) ((char*) pagecache->block_root + + ALIGN_SIZE(blocks*sizeof(PAGECACHE_BLOCK_LINK))); + pagecache->hash_link_root= + (PAGECACHE_HASH_LINK*) ((char*) pagecache->hash_root + + ALIGN_SIZE((sizeof(PAGECACHE_HASH_LINK*) * + pagecache->hash_entries))); + bzero((uchar*) pagecache->block_root, + pagecache->disk_blocks * sizeof(PAGECACHE_BLOCK_LINK)); + bzero((uchar*) pagecache->hash_root, + pagecache->hash_entries * sizeof(PAGECACHE_HASH_LINK*)); + bzero((uchar*) pagecache->hash_link_root, + pagecache->hash_links * sizeof(PAGECACHE_HASH_LINK)); + pagecache->hash_links_used= 0; + pagecache->free_hash_list= NULL; + pagecache->blocks_used= pagecache->blocks_changed= 0; + + pagecache->global_blocks_changed= 0; + pagecache->blocks_available=0; /* For debugging */ + + /* The LRU chain is empty after initialization */ + pagecache->used_last= NULL; + pagecache->used_ins= NULL; + pagecache->free_block_list= NULL; + pagecache->time= 0; + pagecache->warm_blocks= 0; + pagecache->min_warm_blocks= (division_limit ? + blocks * division_limit / 100 + 1 : blocks); + pagecache->age_threshold= (age_threshold ? + blocks * age_threshold / 100 : + blocks); - pagecache->cnt_for_resize_op= 0; - pagecache->resize_in_flush= 0; - pagecache->can_be_used= 1; + pagecache->cnt_for_resize_op= 0; + pagecache->resize_in_flush= 0; + pagecache->can_be_used= 1; - pagecache->waiting_for_hash_link.last_thread= NULL; - pagecache->waiting_for_block.last_thread= NULL; - DBUG_PRINT("exit", - ("disk_blocks: %ld block_root: 0x%lx hash_entries: %ld\ + pagecache->waiting_for_hash_link.last_thread= NULL; + pagecache->waiting_for_block.last_thread= NULL; + DBUG_PRINT("exit", + ("disk_blocks: %ld block_root: 0x%lx hash_entries: %ld\ hash_root: 0x%lx hash_links: %ld hash_link_root: 0x%lx", - pagecache->disk_blocks, (long) pagecache->block_root, - pagecache->hash_entries, (long) pagecache->hash_root, - pagecache->hash_links, (long) pagecache->hash_link_root)); - bzero((uchar*) pagecache->changed_blocks, - sizeof(pagecache->changed_blocks[0]) * - PAGECACHE_CHANGED_BLOCKS_HASH); - bzero((uchar*) pagecache->file_blocks, - sizeof(pagecache->file_blocks[0]) * - PAGECACHE_CHANGED_BLOCKS_HASH); - } + pagecache->disk_blocks, (long) pagecache->block_root, + pagecache->hash_entries, (long) pagecache->hash_root, + pagecache->hash_links, (long) pagecache->hash_link_root)); + bzero((uchar*) pagecache->changed_blocks, + sizeof(pagecache->changed_blocks[0]) * + PAGECACHE_CHANGED_BLOCKS_HASH); + bzero((uchar*) pagecache->file_blocks, + sizeof(pagecache->file_blocks[0]) * + PAGECACHE_CHANGED_BLOCKS_HASH); pagecache->blocks= pagecache->disk_blocks > 0 ? pagecache->disk_blocks : 0; DBUG_RETURN((ulong) pagecache->disk_blocks); @@ -981,7 +979,8 @@ ulong resize_pagecache(PAGECACHE *pagecache, end_pagecache(pagecache, 0); /* Don't free mutex */ /* The following will work even if use_mem is 0 */ blocks= init_pagecache(pagecache, pagecache->block_size, use_mem, - division_limit, age_threshold); + division_limit, age_threshold, + pagecache->readwrite_flags); finish: #ifdef THREAD @@ -2020,7 +2019,7 @@ restart: block->buffer, block->hash_link->pageno, block->type, - MYF(MY_NABP | MY_WAIT_IF_FULL)); + pagecache->readwrite_flags); pagecache_pthread_mutex_lock(&pagecache->cache_lock); pagecache->global_cache_write++; } @@ -2417,13 +2416,13 @@ static void read_block(PAGECACHE *pagecache, pagecache_disk_read_validator validator, uchar* validator_data) { - uint got_length; /* On entry cache_lock is locked */ DBUG_ENTER("read_block"); if (primary) { + size_t error; /* This code is executed only by threads that submitted primary requests @@ -2438,11 +2437,12 @@ static void read_block(PAGECACHE *pagecache, Here other threads may step in and register as secondary readers. They will register in block->wqueue[COND_FOR_REQUESTED]. */ - got_length= pagecache_fread(pagecache, &block->hash_link->file, - block->buffer, - block->hash_link->pageno, MYF(0)); + error= pagecache_fread(pagecache, &block->hash_link->file, + block->buffer, + block->hash_link->pageno, + pagecache->readwrite_flags); pagecache_pthread_mutex_lock(&pagecache->cache_lock); - if (got_length < pagecache->block_size) + if (error) block->status|= PCBLOCK_ERROR; else block->status= PCBLOCK_READ; @@ -2796,7 +2796,6 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, block->status&= ~PCBLOCK_DIRECT_W; DBUG_PRINT("info", ("Drop PCBLOCK_DIRECT_W for block: 0x%lx", (ulong) block)); - } if (make_lock_and_pin(pagecache, block, lock, pin, 0)) @@ -2996,10 +2995,6 @@ restart: DBUG_PRINT("info", ("read is done")); } - /* PCBLOCK_DIRECT_W should be unlocked in unlock */ - DBUG_ASSERT((block->status & PCBLOCK_DIRECT_W) == 0 || - lock == PAGECACHE_LOCK_LEFT_WRITELOCKED); - if (make_lock_and_pin(pagecache, block, lock, pin, file)) { /* @@ -3069,7 +3064,8 @@ no_key_cache: /* Key cache is not used */ /* We can't use mutex here as the key cache may not be initialized */ pagecache->global_cache_r_requests++; pagecache->global_cache_read++; - if (pagecache_fread(pagecache, file, (uchar*) buff, pageno, MYF(MY_NABP))) + if (pagecache_fread(pagecache, file, (uchar*) buff, pageno, + pagecache->readwrite_flags)) error= 1; DBUG_RETURN(error ? (uchar*) 0 : buff); } @@ -3169,7 +3165,7 @@ restart: block->buffer, block->hash_link->pageno, block->type, - MYF(MY_NABP | MY_WAIT_IF_FULL)); + pagecache->readwrite_flags); pagecache_pthread_mutex_lock(&pagecache->cache_lock); pagecache->global_cache_write++; @@ -3494,7 +3490,7 @@ no_key_cache: pagecache->global_cache_w_requests++; pagecache->global_cache_write++; if (pagecache_fwrite(pagecache, file, (uchar*) buff, pageno, type, - MYF(MY_NABP | MY_WAIT_IF_FULL))) + pagecache->readwrite_flags)) error=1; } @@ -3662,7 +3658,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, block->buffer, block->hash_link->pageno, block->type, - MYF(MY_NABP | MY_WAIT_IF_FULL)); + pagecache->readwrite_flags); pagecache_pthread_mutex_lock(&pagecache->cache_lock); make_lock_and_pin(pagecache, block, @@ -3744,7 +3740,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache, int rc= PCFLUSH_OK; DBUG_ENTER("flush_pagecache_blocks_int"); DBUG_PRINT("enter", - ("file: %d blocks_used: %lu blocks_changed: %lu type: %d", + ("fd: %d blocks_used: %lu blocks_changed: %lu type: %d", file->file, pagecache->blocks_used, pagecache->blocks_changed, type)); diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 99b6fe9f6ae..9ed743f9cdd 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -158,7 +158,8 @@ typedef struct st_pagecache ulonglong global_cache_r_requests;/* number of read requests (read hits) */ ulonglong global_cache_read; /* number of reads from files to cache */ - uint shift; /* block size = 2 ^ shift */ + uint shift; /* block size = 2 ^ shift */ + myf readwrite_flags; /* Flags to pread/pwrite() */ my_bool inited; my_bool resize_in_flush; /* true during flush of resize operation */ my_bool can_be_used; /* usage of cache for read/write is allowed */ @@ -183,7 +184,7 @@ extern PAGECACHE dflt_pagecache_var, *dflt_pagecache; extern ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold, - uint block_size); + uint block_size, myf my_read_flags); extern ulong resize_pagecache(PAGECACHE *pagecache, size_t use_mem, uint division_limit, uint age_threshold); diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index c6481412232..e47d686a09c 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -58,6 +58,7 @@ static FILE *tracef; /**< trace file for debugging */ static my_bool skip_DDLs; /**< if REDO phase should skip DDL records */ /** @brief to avoid writing a checkpoint if recovery did nothing. */ static my_bool checkpoint_useful; +static my_bool procent_printed; static ulonglong now; /**< for tracking execution time of phases */ uint warnings; /**< count of warnings */ @@ -156,10 +157,36 @@ void tprint(FILE *trace_file __attribute__ ((unused)), va_list args; va_start(args, format); if (trace_file != NULL) + { + if (procent_printed) + { + procent_printed= 0; + fputc('\n', trace_file ? trace_file : stderr); + } vfprintf(trace_file, format, args); + } va_end(args); } +void eprint(FILE *trace_file, const char *format, ...) + ATTRIBUTE_FORMAT(printf, 2, 3); + +void eprint(FILE *trace_file __attribute__ ((unused)), + const char *format __attribute__ ((unused)), ...) +{ + va_list args; + va_start(args, format); + if (procent_printed) + { + /* In silent mode, print on another line than the 0% 10% 20% line */ + procent_printed= 0; + fputc('\n', trace_file ? trace_file : stderr); + } + vfprintf(trace_file ? trace_file : stderr, format, args); + va_end(args); +} + + #define ALERT_USER() DBUG_ASSERT(0) static void print_preamble() @@ -312,6 +339,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, Detailed progress info goes to stderr, because ma_message_no_user() cannot put several messages on one line. */ + procent_printed= 1; fprintf(stderr, " (%.1f seconds); ", phase_took); } @@ -353,6 +381,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, if (recovery_message_printed == REC_MSG_UNDO) { float phase_took= (now - old_now)/10000000.0; + procent_printed= 1; fprintf(stderr, " (%.1f seconds); ", phase_took); } @@ -368,6 +397,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, if (recovery_message_printed == REC_MSG_FLUSH) { float phase_took= (now - old_now)/10000000.0; + procent_printed= 1; fprintf(stderr, " (%.1f seconds); ", phase_took); } @@ -381,7 +411,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, goto end; err: error= 1; - tprint(tracef, "Recovery of tables with transaction logs FAILED\n"); + tprint(tracef, "\nRecovery of tables with transaction logs FAILED\n"); end: hash_free(&all_dirty_pages); bzero(&all_dirty_pages, sizeof(all_dirty_pages)); @@ -404,6 +434,7 @@ end: else ma_message_no_user(ME_JUST_INFO, "recovery done"); } + procent_printed= 0; /* we don't cleanly close tables if we hit some error (may corrupt them) */ DBUG_RETURN(error); } @@ -418,7 +449,8 @@ static void display_record_position(const LOG_DESC *log_desc, if number==0, we're going over records which we had already seen and which form a group, so we indent below the group's end record */ - tprint(tracef, "%sRec#%u LSN (%lu,0x%lx) short_trid %u %s(num_type:%u) len %lu\n", + tprint(tracef, + "%sRec#%u LSN (%lu,0x%lx) short_trid %u %s(num_type:%u) len %lu\n", number ? "" : " ", number, LSN_IN_PARTS(rec->lsn), rec->short_trid, log_desc->name, rec->type, (ulong)rec->record_length); @@ -436,7 +468,7 @@ static int display_and_apply_record(const LOG_DESC *log_desc, return 1; } if ((error= (*log_desc->record_execute_in_redo_phase)(rec))) - tprint(tracef, "Got error when executing record\n"); + eprint(tracef, "Got error %d when executing record\n", my_errno); return error; } @@ -467,10 +499,10 @@ prototype_redo_exec_hook(LONG_TRANSACTION_ID) { char llbuf[22]; llstr(long_trid, llbuf); - tprint(tracef, "Found an old transaction long_trid %s short_trid %u" + eprint(tracef, "Found an old transaction long_trid %s short_trid %u" " with same short id as this new transaction, and has neither" - " committed nor rollback (undo_lsn: (%lu,0x%lx))\n", llbuf, - sid, LSN_IN_PARTS(ulsn)); + " committed nor rollback (undo_lsn: (%lu,0x%lx))\n", + llbuf, sid, LSN_IN_PARTS(ulsn)); goto err; } } @@ -570,11 +602,10 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } name= log_record_buffer.str; - tprint(tracef, "Table '%s'", name); /* TRUNCATE TABLE and REPAIR USE_FRM call maria_create(), so below we can find a REDO_CREATE_TABLE for a table which we have open, that's why we @@ -582,7 +613,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) */ if (close_one_table(name, rec->lsn)) { - tprint(tracef, " got error %d on close\n", my_errno); + eprint(tracef, "Table '%s' got error %d on close\n", name, my_errno); ALERT_USER(); goto end; } @@ -594,7 +625,8 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) /* check that we're not already using it */ if (share->reopen != 1) { - tprint(tracef, ", is already open (reopen=%u)\n", share->reopen); + eprint(tracef, "Table '%s is already open (reopen=%u)\n", + name, share->reopen); ALERT_USER(); goto end; } @@ -606,22 +638,23 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) one was renamed to its name, thus create_rename_lsn is 0 and should not be trusted. */ - tprint(tracef, ", is not transactional, ignoring creation\n"); + tprint(tracef, "Table '%s' is not transactional, ignoring creation\n", + name); ALERT_USER(); error= 0; goto end; } if (cmp_translog_addr(share->state.create_rename_lsn, rec->lsn) >= 0) { - tprint(tracef, ", has create_rename_lsn (%lu,0x%lx) more recent than" - " record, ignoring creation", - LSN_IN_PARTS(share->state.create_rename_lsn)); + tprint(tracef, "Table '%s' has create_rename_lsn (%lu,0x%lx) more " + "recent than record, ignoring creation", + name, LSN_IN_PARTS(share->state.create_rename_lsn)); error= 0; goto end; } if (maria_is_crashed(info)) { - tprint(tracef, ", is crashed, can't recreate it"); + eprint(tracef, "Table '%s' is crashed, can't recreate it\n", name); ALERT_USER(); goto end; } @@ -629,7 +662,8 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) info= NULL; } else /* one or two files absent, or header corrupted... */ - tprint(tracef, " can't be opened, probably does not exist"); + tprint(tracef, "Table '%s' can't be opened, probably does not exist\n", + name); /* if does not exist, or is older, overwrite it */ ptr= name + strlen(name) + 1; if ((flags= ptr[0] ? HA_DONT_TOUCH_DATA : 0)) @@ -653,7 +687,8 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) /** @todo handle symlinks */ if (data_file_name[0] || index_file_name[0]) { - tprint(tracef, ", DATA|INDEX DIRECTORY clauses are not handled\n"); + eprint(tracef, "Table '%s' DATA|INDEX DIRECTORY clauses are not handled\n", + name); goto end; } fn_format(filename, name, "", MARIA_NAME_IEXT, @@ -662,18 +697,18 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) MY_APPEND_EXT); linkname_ptr= NULL; create_flag= MY_DELETE_OLD; - tprint(tracef, ", creating as '%s'", filename); + tprint(tracef, "Table '%s' creating as '%s'", name, filename); if ((kfile= my_create_with_symlink(linkname_ptr, filename, 0, create_mode, MYF(MY_WME|create_flag))) < 0) { - tprint(tracef, " Failed to create index file\n"); + eprint(tracef, "Failed to create index file\n"); goto end; } if (my_pwrite(kfile, kfile_header, kfile_size_before_extension, 0, MYF(MY_NABP|MY_WME)) || my_chsize(kfile, keystart, 0, MYF(MY_WME))) { - tprint(tracef, " Failed to write to index file\n"); + eprint(tracef, "Failed to write to index file\n"); goto end; } if (!(flags & HA_DONT_TOUCH_DATA)) @@ -687,7 +722,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) MYF(MY_WME | create_flag))) < 0) || my_close(dfile, MYF(MY_WME))) { - tprint(tracef, " Failed to create data file\n"); + eprint(tracef, "Failed to create data file\n"); goto end; } /* @@ -699,7 +734,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) if (((info= maria_open(name, O_RDONLY, 0)) == NULL) || _ma_initialize_data_file(info->s, info->dfile.file)) { - tprint(tracef, " Failed to open new table or write to data file\n"); + eprint(tracef, "Failed to open new table or write to data file\n"); goto end; } } @@ -730,7 +765,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } old_name= log_record_buffer.str; @@ -867,13 +902,13 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) tprint(tracef, ", renaming '%s'", old_name); if (maria_rename(old_name, new_name)) { - tprint(tracef, "Failed to rename table\n"); + eprint(tracef, "Failed to rename table\n"); goto end; } info= maria_open(new_name, O_RDONLY, 0); if (info == NULL) { - tprint(tracef, "Failed to open renamed table\n"); + eprint(tracef, "Failed to open renamed table\n"); goto end; } if (_ma_update_create_rename_lsn(info->s, rec->lsn, TRUE)) @@ -887,7 +922,7 @@ drop: tprint(tracef, ", only dropping '%s'", old_name); if (maria_delete_table(old_name)) { - tprint(tracef, "Failed to drop table\n"); + eprint(tracef, "Failed to drop table\n"); goto end; } error= 0; @@ -907,6 +942,11 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE) { int error= 1; MARIA_HA *info; + HA_CHECK param; + char *name; + uint quick_repair; + DBUG_ENTER("exec_REDO_LOGREC_REDO_REPAIR_TABLE"); + if (skip_DDLs) { /* @@ -914,26 +954,46 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE) insertions into them. */ tprint(tracef, "we skip DDLs\n"); - return 0; + DBUG_RETURN(0); } if ((info= get_MARIA_HA_from_REDO_record(rec)) == NULL) - return 0; + DBUG_RETURN(0); + /* Otherwise, the mapping is newer than the table, and our record is newer than the mapping, so we can repair. */ tprint(tracef, " repairing...\n"); - HA_CHECK param; + maria_chk_init(¶m); - param.isam_file_name= info->s->open_file_name; - param.testflag= uint4korr(rec->header); - if (maria_repair(¶m, info, info->s->open_file_name, param.testflag)) + param.isam_file_name= name= info->s->open_file_name; + param.testflag= uint4korr(rec->header + FILEID_STORE_SIZE); + param.tmpdir= maria_tmpdir; + DBUG_ASSERT(maria_tmpdir); + + info->s->state.key_map= uint8korr(rec->header + FILEID_STORE_SIZE + 4); + quick_repair= param.testflag & T_QUICK; + + + if (param.testflag & T_REP_PARALLEL) + { + if (maria_repair_parallel(¶m, info, name, quick_repair)) + goto end; + } + else if (param.testflag & T_REP_BY_SORT) + { + if (maria_repair_by_sort(¶m, info, name, quick_repair)) + goto end; + } + else if (maria_repair(¶m, info, name, quick_repair)) goto end; + if (_ma_update_create_rename_lsn(info->s, rec->lsn, TRUE)) goto end; error= 0; + end: - return error; + DBUG_RETURN(error); } @@ -953,7 +1013,7 @@ prototype_redo_exec_hook(REDO_DROP_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } name= log_record_buffer.str; @@ -991,7 +1051,7 @@ prototype_redo_exec_hook(REDO_DROP_TABLE) tprint(tracef, ", dropping '%s'", name); if (maria_delete_table(name)) { - tprint(tracef, "Failed to drop table\n"); + eprint(tracef, "Failed to drop table\n"); goto end; } } @@ -1012,6 +1072,7 @@ prototype_redo_exec_hook(FILE_ID) int error= 1; const char *name; MARIA_HA *info; + DBUG_ENTER("exec_REDO_LOGREC_FILE_ID"); if (cmp_translog_addr(rec->lsn, checkpoint_start) < 0) { @@ -1022,7 +1083,7 @@ prototype_redo_exec_hook(FILE_ID) happened and so mapping is not needed. */ tprint(tracef, "ignoring because before checkpoint\n"); - return 0; + DBUG_RETURN(0); } enlarge_buffer(rec); @@ -1031,7 +1092,7 @@ prototype_redo_exec_hook(FILE_ID) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } sid= fileid_korr(log_record_buffer.str); @@ -1042,7 +1103,7 @@ prototype_redo_exec_hook(FILE_ID) prepare_table_for_close(info, rec->lsn); if (maria_close(info)) { - tprint(tracef, "Failed to close table\n"); + eprint(tracef, "Failed to close table\n"); goto end; } all_tables[sid].info= NULL; @@ -1052,7 +1113,7 @@ prototype_redo_exec_hook(FILE_ID) goto end; error= 0; end: - return error; + DBUG_RETURN(error); } @@ -1213,14 +1274,14 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD) enlarge_buffer(rec); if (log_record_buffer.str == NULL) { - tprint(tracef, "Failed to read allocate buffer for record\n"); + eprint(tracef, "Failed to read allocate buffer for record\n"); goto end; } if (translog_read_record(rec->lsn, 0, rec->record_length, log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } buff= log_record_buffer.str; @@ -1255,7 +1316,7 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } buff= log_record_buffer.str; @@ -1291,7 +1352,7 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_BLOBS) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } buff= log_record_buffer.str; @@ -1351,7 +1412,7 @@ prototype_redo_exec_hook(REDO_FREE_BLOCKS) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } @@ -1410,7 +1471,7 @@ prototype_redo_exec_hook(REDO_INDEX) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } @@ -1436,7 +1497,7 @@ prototype_redo_exec_hook(REDO_INDEX_NEW_PAGE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); goto end; } @@ -1493,7 +1554,7 @@ prototype_redo_exec_hook(UNDO_ROW_INSERT) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1532,7 +1593,7 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1564,7 +1625,7 @@ prototype_redo_exec_hook(UNDO_ROW_UPDATE) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1712,7 +1773,7 @@ prototype_redo_exec_hook(CLR_END) buff, NULL) != KEY_NR_STORE_SIZE + PAGE_STORE_SIZE) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); DBUG_RETURN(1); } key_nr= key_nr_korr(buff); @@ -1732,7 +1793,7 @@ prototype_redo_exec_hook(CLR_END) CLR_TYPE_STORE_SIZE, HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); DBUG_RETURN(1); } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1781,7 +1842,7 @@ prototype_undo_exec_hook(UNDO_ROW_INSERT) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } record_ptr= log_record_buffer.str; @@ -1818,7 +1879,7 @@ prototype_undo_exec_hook(UNDO_ROW_DELETE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } @@ -1860,7 +1921,7 @@ prototype_undo_exec_hook(UNDO_ROW_UPDATE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } @@ -1904,7 +1965,7 @@ prototype_undo_exec_hook(UNDO_KEY_INSERT) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } @@ -1949,7 +2010,7 @@ prototype_undo_exec_hook(UNDO_KEY_DELETE) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } @@ -1994,7 +2055,7 @@ prototype_undo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT) log_record_buffer.str, NULL) != rec->record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return 1; } @@ -2077,7 +2138,7 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) if (len == RECHEADER_READ_ERROR) { - tprint(tracef, "Failed to read header of the first record.\n"); + eprint(tracef, "Failed to read header of the first record.\n"); return 1; } if (translog_init_scanner(lsn, 1, &scanner, 1)) @@ -2211,7 +2272,10 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) translog_destroy_scanner(&scanner); translog_free_record_header(&rec); if (recovery_message_printed == REC_MSG_REDO) + { fprintf(stderr, " 100%%"); + procent_printed= 1; + } return 0; err: @@ -2343,7 +2407,7 @@ static int run_undo_phase(uint unfinished) display_record_position(log_desc, &rec, 0); if (log_desc->record_execute_in_undo_phase(&rec, trn)) { - tprint(tracef, "Got error when executing undo\n"); + tprint(tracef, "Got error %d when executing undo\n", my_errno); return 1; } } @@ -2542,7 +2606,7 @@ static LSN parse_checkpoint_record(LSN lsn) log_record_buffer.str, NULL) != rec.record_length) { - tprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record\n"); return LSN_ERROR; } @@ -2793,6 +2857,7 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) static ulonglong initial_remainder= -1; int cur_logno, cur_offset; ulonglong local_remainder; + int percentage_done; if (tracef == stdout) return; @@ -2800,6 +2865,7 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) { print_preamble(); fprintf(stderr, "recovered pages: 0%%"); + procent_printed= 1; recovery_message_printed= REC_MSG_REDO; } if (end_logno == FILENO_IMPOSSIBLE) @@ -2815,12 +2881,13 @@ static void print_redo_phase_progress(TRANSLOG_ADDRESS addr) max(end_logno - cur_logno - 1, 0) * TRANSLOG_FILE_SIZE + end_offset); if (initial_remainder == (ulonglong)(-1)) initial_remainder= local_remainder; - int percentage_done= - (initial_remainder - local_remainder) * ULL(100) / initial_remainder; + percentage_done= ((initial_remainder - local_remainder) * ULL(100) / + initial_remainder); if ((percentage_done - percentage_printed) >= 10) { percentage_printed= percentage_done; fprintf(stderr, " %d%%", percentage_done); + procent_printed= 1; } } diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c index eba2a519a3f..50d4e9e0fd2 100644 --- a/storage/maria/ma_rt_index.c +++ b/storage/maria/ma_rt_index.c @@ -662,7 +662,7 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, info->keyread_buff_used= 1; bzero(info->buff, info->s->keypage_header); _ma_store_keynr(info, info->buff, keynr); - _ma_store_page_used(info, info->buff, info->s->keypage_header, 0); + _ma_store_page_used(info, info->buff, info->s->keypage_header); res= maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL); @@ -698,9 +698,10 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key, } bzero(new_root_buf, info->s->keypage_header); + if (nod_flag) + _ma_store_keypage_flag(info, new_root_buf, KEYPAGE_FLAG_ISNOD); _ma_store_keynr(info, new_root_buf, keynr); - _ma_store_page_used(info, new_root_buf, info->s->keypage_header, - nod_flag); + _ma_store_page_used(info, new_root_buf, info->s->keypage_header); if ((new_root= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR) goto err1; diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c index 311137850f6..a976c252a93 100644 --- a/storage/maria/ma_rt_key.c +++ b/storage/maria/ma_rt_key.c @@ -59,7 +59,7 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key, info->s->base.rec_reflength); page_size+= key_length + info->s->base.rec_reflength; } - _ma_store_page_used(info, page_buf, page_size, nod_flag); + _ma_store_page_used(info, page_buf, page_size); DBUG_RETURN(0); } @@ -86,7 +86,7 @@ int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key, (key - page_buf)); page_size-= key_length + nod_flag; - _ma_store_page_used(info, page_buf, page_size, nod_flag); + _ma_store_page_used(info, page_buf, page_size); return 0; } diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c index 25cfb0be91a..b9583241366 100644 --- a/storage/maria/ma_rt_split.c +++ b/storage/maria/ma_rt_split.c @@ -340,11 +340,12 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } bzero(new_page, info->s->keypage_header); + if (nod_flag) + _ma_store_keypage_flag(info, new_page, KEYPAGE_FLAG_ISNOD); _ma_store_keynr(info, new_page, keyinfo->key_nr); - _ma_store_page_used(info, page, info->s->keypage_header + n1 * full_length, - nod_flag); + _ma_store_page_used(info, page, info->s->keypage_header + n1 * full_length) _ma_store_page_used(info, new_page, info->s->keypage_header + - n2 * full_length, nod_flag); + n2 * full_length); if ((*new_page_offs= _ma_new(info, DFLT_INIT_HITS, &page_link)) == HA_OFFSET_ERROR) diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index fe1335c39fe..20c5c999a8f 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -48,6 +48,7 @@ PAGECACHE *maria_pagecache= &maria_pagecache_var; PAGECACHE maria_log_pagecache_var; PAGECACHE *maria_log_pagecache= &maria_log_pagecache_var; +MY_TMPDIR *maria_tmpdir; /* Tempdir for redo */ /** @brief when transactionality does not matter we can use this transaction diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c index d46072e626a..5c362723fa8 100644 --- a/storage/maria/ma_test1.c +++ b/storage/maria/ma_test1.c @@ -76,11 +76,11 @@ int main(int argc,char *argv[]) /* Maria requires that we always have a page cache */ if (maria_init() || (init_pagecache(maria_pagecache, maria_block_size * 16, 0, 0, - maria_block_size) == 0) || + maria_block_size, MY_WME) == 0) || ma_control_file_create_or_open() || (init_pagecache(maria_log_pagecache, TRANSLOG_PAGECACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE) == 0) || + TRANSLOG_PAGE_SIZE, MY_WME) == 0) || translog_init(maria_data_root, TRANSLOG_FILE_SIZE, 0, 0, maria_log_pagecache, TRANSLOG_DEFAULT_FLAGS) || @@ -840,7 +840,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), printf("test1 Ver 1.2 \n"); exit(0); case '#': - DBUG_PUSH (argument); + DBUG_PUSH(argument); break; case '?': usage(); diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index 762d2d7ebb0..60c6a3be8b4 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -89,11 +89,11 @@ int main(int argc, char *argv[]) /* Maria requires that we always have a page cache */ if (maria_init() || (init_pagecache(maria_pagecache, pagecache_size, 0, 0, - maria_block_size) == 0) || + maria_block_size, MY_WME) == 0) || ma_control_file_create_or_open() || (init_pagecache(maria_log_pagecache, TRANSLOG_PAGECACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE) == 0) || + TRANSLOG_PAGE_SIZE, MY_WME) == 0) || translog_init(maria_data_root, TRANSLOG_FILE_SIZE, 0, 0, maria_log_pagecache, TRANSLOG_DEFAULT_FLAGS) || diff --git a/storage/maria/ma_test3.c b/storage/maria/ma_test3.c index 6d45e391e65..de8b4c83a51 100644 --- a/storage/maria/ma_test3.c +++ b/storage/maria/ma_test3.c @@ -178,7 +178,8 @@ void start_test(int id) exit(1); } if (pagecacheing && rnd(2) == 0) - init_pagecache(maria_pagecache, 65536L, 0, 0, MARIA_KEY_BLOCK_LENGTH); + init_pagecache(maria_pagecache, 65536L, 0, 0, MARIA_KEY_BLOCK_LENGTH, + MY_WME); printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); for (error=i=0 ; i < tests && !error; i++) diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 5348e4c6ac2..9116ca7cce4 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -380,9 +380,7 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int error; my_off_t new_root= *root; uchar key_buff[HA_MAX_KEY_BUFF]; -#ifdef NOT_YET DBUG_ENTER("_ma_ck_write_btree_with_log"); -#endif if (info->s->now_transactional) { @@ -399,6 +397,8 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, LEX_STRING log_array[TRANSLOG_INTERNAL_PARTS + 2]; struct st_msg_to_write_hook_for_undo_key msg; + /* Save if we need to write a clr record */ + info->key_write_undo_lsn[keyinfo->key_nr]= info->trn->undo_lsn; lsn_store(log_data, info->trn->undo_lsn); key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keyinfo->key_nr); @@ -426,15 +426,10 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo, } _ma_unpin_all_pages_and_finalize_row(info, lsn); -#ifdef NOT_YET DBUG_RETURN(error); -#else - return(error); -#endif } /* _ma_ck_write_btree_with_log */ - /** @brief Write a key to the b-tree @@ -485,7 +480,9 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, const uchar *key, bzero(info->buff, info->s->keypage_header); _ma_store_keynr(info, info->buff, keyinfo->key_nr); - _ma_store_page_used(info, info->buff, page_length, nod_flag); + _ma_store_page_used(info, info->buff, page_length); + if (nod_flag) + _ma_store_keypage_flag(info, info->buff, KEYPAGE_FLAG_ISNOD); (*keyinfo->store_key)(keyinfo, info->buff + info->s->keypage_header + nod_flag, &s_temp); @@ -727,7 +724,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, } (*keyinfo->store_key)(keyinfo,key_pos,&s_temp); a_length+=t_length; - _ma_store_page_used(info, anc_buff, a_length, nod_flag); + _ma_store_page_used(info, anc_buff, a_length); /* Check if the new key fits totally into the the page @@ -781,7 +778,7 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, /* fixing the page's length - it contains only one key now */ _ma_store_page_used(info, anc_buff, info->s->keypage_header + blen + - ft2len + 2, 0); + ft2len + 2); } /* the rest will be done when we're back from recursion */ } @@ -874,7 +871,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, split_length= (uint) (key_pos - split_buff); a_length= _ma_get_page_used(info, split_buff); - _ma_store_page_used(info, split_buff, split_length, nod_flag); + _ma_store_page_used(info, split_buff, split_length); key_pos=after_key; if (nod_flag) @@ -905,7 +902,9 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo, page_length= length + t_length + key_ref_length; bzero(new_buff, info->s->keypage_header); - _ma_store_page_used(info, new_buff, page_length, nod_flag); + if (nod_flag) + _ma_store_keypage_flag(info, new_buff, KEYPAGE_FLAG_ISNOD); + _ma_store_page_used(info, new_buff, page_length); /* Copy key number */ new_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]= @@ -1121,8 +1120,8 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, new_left_length= info->s->keypage_header+nod_flag+(keys/2)*curr_keylength; new_right_length=info->s->keypage_header+nod_flag+(((keys+1)/2)* curr_keylength); - _ma_store_page_used(info, curr_buff, new_left_length, nod_flag); - _ma_store_page_used(info, buff, new_right_length, nod_flag); + _ma_store_page_used(info, curr_buff, new_left_length); + _ma_store_page_used(info, buff, new_right_length); DBUG_PRINT("info", ("left_length: %u -> %u right_length: %u -> %u", left_length, new_left_length, @@ -1300,15 +1299,18 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo, left_length, right_length, new_left_length, new_right_length, extra_length)); - _ma_store_page_used(info, curr_buff,new_left_length,nod_flag); - _ma_store_page_used(info, buff,new_right_length,nod_flag); + _ma_store_page_used(info, curr_buff, new_left_length); + _ma_store_page_used(info, buff, new_right_length); bzero(extra_buff, info->s->keypage_header); + if (nod_flag) + _ma_store_keypage_flag(info, extra_buff, KEYPAGE_FLAG_ISNOD); + /* Copy key number */ extra_buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]= buff[info->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE]; - _ma_store_page_used(info, extra_buff, extra_buff_length, nod_flag); + _ma_store_page_used(info, extra_buff, extra_buff_length); /* move first largest keys to new page */ pos=buff+right_length-extra_length; @@ -1871,12 +1873,14 @@ static my_bool _ma_log_del_prefix(MARIA_HA *info, my_off_t page, uchar *buff, translog_parts= 1; extra_length= 0; - if (offset <= diff_length) + if (offset < diff_length + info->s->keypage_header) { /* Key is not anymore on page. Move data down, but take into account that the original page had grown with 'move_length bytes' */ + DBUG_ASSERT(offset + key_length <= diff_length + info->s->keypage_header); + log_pos[0]= KEY_OP_DEL_PREFIX; int2store(log_pos+1, diff_length - move_length); log_pos+= 3; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 0203dd2fb26..7bae30655be 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -296,7 +296,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "page_buffer_size", OPT_PAGE_BUFFER_SIZE, "", (uchar**) &check_param.use_buffers, (uchar**) &check_param.use_buffers, 0, - GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, + GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) USE_BUFFER_INIT, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, { "read_buffer_size", OPT_READ_BUFFER_SIZE, "", (uchar**) &check_param.read_buffer_length, @@ -998,7 +998,7 @@ static int maria_chk(HA_CHECK *param, char *filename) maria_lock_database(info, F_EXTRA_LCK); datafile= info->dfile.file; if (init_pagecache(maria_pagecache, param->use_buffers, 0, 0, - maria_block_size) == 0) + maria_block_size, MY_WME) == 0) { _ma_check_print_error(param, "Can't initialize page cache with %lu memory", (ulong) param->use_buffers); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 4e771a2c85a..bf02793b0ee 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -34,6 +34,9 @@ #endif /* Do extra sanity checking */ #define SANITY_CHECKS 1 +#ifdef EXTRA_DEBUG +#define EXTRA_DEBUG_KEY_CHANGES +#endif #define MAX_NONMAPPED_INSERTS 1000 #define MARIA_MAX_TREE_LEVELS 32 @@ -433,6 +436,8 @@ struct st_maria_handler DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ MEM_ROOT ft_memroot; /* used by the parser */ MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ + LSN *key_write_undo_lsn; /* Pointer to undo for each key */ + LSN *key_delete_undo_lsn; /* Pointer to undo for each key */ uchar *buff; /* page buffer */ uchar *keyread_buff; /* Buffer for last key read */ uchar *lastkey, *lastkey2; /* Last used search key */ @@ -543,29 +548,29 @@ struct st_maria_handler #define MAX_KEYPAGE_HEADER_SIZE (LSN_STORE_SIZE + KEYPAGE_USED_SIZE + \ KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + \ TRANSID_SIZE) +#define KEYPAGE_FLAG_ISNOD 1 #define _ma_get_page_used(info,x) \ - (((uint) mi_uint2korr(x + (info)->s->keypage_header - KEYPAGE_USED_SIZE)) & \ - 32767) -#define _ma_store_page_used(info,x,y,nod) \ -{ uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y); \ - mi_int2store(x + (info)->s->keypage_header - KEYPAGE_USED_SIZE, boh); } + ((uint) mi_uint2korr((x) + (info)->s->keypage_header - KEYPAGE_USED_SIZE)) +#define _ma_store_page_used(info,x,y) \ + mi_int2store((x) + (info)->s->keypage_header - KEYPAGE_USED_SIZE, (y)) #define _ma_test_if_nod(info,x) \ - (x[(info)->s->keypage_header-KEYPAGE_USED_SIZE] & 128 ? \ - (info)->s->base.key_reflength : 0) -#define _ma_get_used_and_nod(info,buff,length,nod) \ -{ \ - nod= 0; \ - length= mi_uint2korr((buff) + (info)->s->keypage_header - \ - KEYPAGE_USED_SIZE); \ - if (length & 32768) {length&= 32767; nod= (info)->s->base.key_reflength; } \ + ((_ma_get_keypage_flag(info,x) & KEYPAGE_FLAG_ISNOD) ? (info)->s->base.key_reflength : 0) + +#define _ma_get_used_and_nod(info,buff,length,nod) \ +{ \ + nod= _ma_test_if_nod((info),(buff)); \ + length= _ma_get_page_used((info),(buff)); \ } -#define _ma_store_keynr(info, x, nr) x[(info)->s->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]= nr +#define _ma_store_keynr(info, x, nr) x[(info)->s->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]= (nr) #define _ma_get_keynr(info, x) ((uchar) x[(info)->s->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]) #define _ma_store_transid(buff, transid) \ int6store((buff) + LSN_STORE_SIZE, (transid)) #define _ma_korr_transid(buff) \ uint6korr((buff) + LSN_STORE_SIZE) +#define _ma_get_keypage_flag(info,x) x[(info)->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE] +#define _ma_store_keypage_flag(info,x,flag) x[(info)->s->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]= (flag) + #define maria_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \ DBUG_PRINT("error", ("Marked table crashed")); \ diff --git a/storage/maria/maria_ftdump.c b/storage/maria/maria_ftdump.c index 9df86b50474..d691cbe0c3b 100644 --- a/storage/maria/maria_ftdump.c +++ b/storage/maria/maria_ftdump.c @@ -85,7 +85,7 @@ int main(int argc,char *argv[]) } init_pagecache(maria_pagecache, USE_BUFFER_INIT, 0, 0, - MARIA_KEY_BLOCK_LENGTH); + MARIA_KEY_BLOCK_LENGTH, MY_WME); if (!(info=maria_open(argv[0], O_RDONLY, HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER))) diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index b7b8a042435..dc0afdd4b64 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -516,7 +516,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) 2+4+16)); if (init_pagecache(maria_pagecache, MARIA_MIN_PAGE_CACHE_SIZE, 0, 0, - maria_block_size) == 0) + maria_block_size, MY_WME) == 0) { fprintf(stderr, "Can't initialize page cache\n"); goto err; @@ -2975,6 +2975,9 @@ static int save_state(MARIA_HA *isam_file,PACK_MRG_INFO *mrg, share->state.dellink= HA_OFFSET_ERROR; share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); + if (share->base.born_transactional) + share->state.create_rename_lsn= share->state.is_of_horizon= + LSN_REPAIRED_BY_MARIA_CHK; if (! maria_is_all_keys_active(share->state.key_map, share->base.keys)) { /* diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 22250a630ba..f27ae624674 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -29,9 +29,13 @@ const char *default_dbug_option= "d:t:i:O,\\maria_read_log.trace"; const char *default_dbug_option= "d:t:i:o,/tmp/maria_read_log.trace"; #endif #endif /* DBUG_OFF */ -static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent, - opt_check; +static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent; +static my_bool opt_check; +static const char *opt_tmpdir; static ulong opt_page_buffer_size; +static ulonglong opt_start_from_lsn; +static MY_TMPDIR maria_chk_tmpdir; + int main(int argc, char **argv) { @@ -66,7 +70,7 @@ int main(int argc, char **argv) /* same page cache for log and data; assumes same page size... */ DBUG_ASSERT(maria_block_size == TRANSLOG_PAGE_SIZE); if (init_pagecache(maria_pagecache, opt_page_buffer_size, 0, 0, - TRANSLOG_PAGE_SIZE) == 0) + TRANSLOG_PAGE_SIZE, MY_WME) == 0) { fprintf(stderr, "Got error in init_pagecache() (errno: %d)\n", errno); goto err; @@ -101,6 +105,19 @@ int main(int argc, char **argv) fprintf(stdout, "The transaction log starts from lsn (%lu,0x%lx)\n", LSN_IN_PARTS(lsn)); + if (opt_start_from_lsn) + { + if (opt_start_from_lsn < (ulonglong) lsn) + { + fprintf(stderr, "start_from_lsn is too small. Aborting\n"); + maria_end(); + goto err; + } + lsn= (LSN) opt_start_from_lsn; + fprintf(stdout, "Starting reading log from lsn (%lu,0x%lx)\n", + LSN_IN_PARTS(lsn)); + } + fprintf(stdout, "TRACE of the last maria_read_log\n"); if (maria_apply_log(lsn, opt_apply ? MARIA_LOG_APPLY : (opt_check ? MARIA_LOG_CHECK : @@ -113,17 +130,20 @@ int main(int argc, char **argv) fprintf(stdout, "%s: DOUBTFUL (%u warnings, check previous output)\n", my_progname_short, warnings_count); - goto end; -err: - /* don't touch anything more, in case we hit a bug */ - fprintf(stderr, "%s: FAILED\n", my_progname_short); - exit(1); end: maria_end(); + free_tmpdir(&maria_chk_tmpdir); free_defaults(default_argv); my_end(0); exit(0); return 0; /* No compiler warning */ + +err: + /* don't touch anything more, in case we hit a bug */ + fprintf(stderr, "%s: FAILED\n", my_progname_short); + free_tmpdir(&maria_chk_tmpdir); + free_defaults(default_argv); + exit(1); } @@ -147,17 +167,28 @@ static struct my_option my_long_options[] = #endif {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"display-only", 'o', "display brief info read from records' header", + {"display-only", 'd', "display brief info read from records' header", (uchar **) &opt_display_only, (uchar **) &opt_display_only, 0, GET_BOOL, NO_ARG,0, 0, 0, 0, 0, 0}, { "page_buffer_size", 'P', "", (uchar**) &opt_page_buffer_size, (uchar**) &opt_page_buffer_size, 0, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, - (long) MALLOC_OVERHEAD, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD, + (long) USE_BUFFER_INIT, (long) ~(ulong) 0, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0}, + { "start_from_lsn", 'o', "Start reading log from this lsn", + (uchar**) &opt_start_from_lsn, (uchar**) &opt_start_from_lsn, + 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, {"silent", 's', "Print less information during apply/undo phase", (uchar **) &opt_silent, (uchar **) &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"tmpdir", 't', "Path for temporary files. Multiple paths can be specified, " + "separated by " +#if defined( __WIN__) || defined(__NETWARE__) + "semicolon (;)" +#else + "colon (:)" +#endif + , (uchar**) &opt_tmpdir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"undo", 'u', "Apply UNDO records to tables. (disable with --disable-undo)", (uchar **) &opt_apply_undo, (uchar **) &opt_apply_undo, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -170,7 +201,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - VOID(printf("%s Ver 1.1 for %s on %s\n", + VOID(printf("%s Ver 1.2 for %s on %s\n", my_progname_short, SYSTEM_TYPE, MACHINE_TYPE)); NETWARE_SET_SCREEN_MODE(1); } @@ -230,4 +261,7 @@ static void get_options(int *argc,char ***argv) usage(); exit(1); } + if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir)) + exit(1); + maria_tmpdir= &maria_chk_tmpdir; } diff --git a/storage/maria/unittest/lockman2-t.c b/storage/maria/unittest/lockman2-t.c index 01af1a03d22..c00e2695a77 100644 --- a/storage/maria/unittest/lockman2-t.c +++ b/storage/maria/unittest/lockman2-t.c @@ -286,9 +286,10 @@ pthread_handler_t test_lockman(void *arg) return 0; } -int main() +int main(int argc __attribute__((unused)), char **argv) { int i; + MY_INIT(argv[0]); my_init(); pthread_mutex_init(&rt_mutex, 0); diff --git a/storage/maria/unittest/ma_pagecache_consist.c b/storage/maria/unittest/ma_pagecache_consist.c index fb0c4fac541..a2cf8c8f9d1 100644 --- a/storage/maria/unittest/ma_pagecache_consist.c +++ b/storage/maria/unittest/ma_pagecache_consist.c @@ -362,7 +362,7 @@ int main(int argc __attribute__((unused)), #endif if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PAGE_SIZE)) == 0) + PAGE_SIZE, 0)) == 0) { fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n", errno); diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c index 90938ae3921..8bf356afb97 100644 --- a/storage/maria/unittest/ma_pagecache_single.c +++ b/storage/maria/unittest/ma_pagecache_single.c @@ -16,6 +16,7 @@ static const char* default_dbug_option; #endif static char *file1_name= (char*)"page_cache_test_file_1"; +static char *file2_name= (char*)"page_cache_test_file_2"; static PAGECACHE_FILE file1; static pthread_cond_t COND_thread_count; static pthread_mutex_t LOCK_thread_count; @@ -69,21 +70,17 @@ static struct file_desc simple_delete_flush_test_file[]= file_name Path (and name) of file which should be reset */ -void reset_file(PAGECACHE_FILE file, char *file_name) +void reset_file(PAGECACHE_FILE *file, const char *file_name) { - flush_pagecache_blocks(&pagecache, &file1, FLUSH_RELEASE); - if (my_close(file1.file, MYF(0)) != 0) - { - diag("Got error during %s closing from close() (errno: %d)\n", - file_name, errno); + flush_pagecache_blocks(&pagecache, file, FLUSH_RELEASE); + if (my_close(file->file, MYF(MY_WME))) exit(1); - } - my_delete(file_name, MYF(0)); - if ((file.file= my_open(file_name, - O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1) + my_delete(file_name, MYF(MY_WME)); + if ((file->file= my_open(file_name, + O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1) { diag("Got error during %s creation from open() (errno: %d)\n", - file_name, errno); + file_name, my_errno); exit(1); } } @@ -116,7 +113,7 @@ int simple_read_write_test() simple_read_write_test_file))), "Simple write-read page file"); if (res) - reset_file(file1, file1_name); + reset_file(&file1, file1_name); free(buffw); free(buffr); DBUG_RETURN(res); @@ -131,8 +128,9 @@ int simple_read_change_write_read_test() { unsigned char *buffw= malloc(PAGE_SIZE); unsigned char *buffr= malloc(PAGE_SIZE); - int res; + int res, res2; DBUG_ENTER("simple_read_change_write_read_test"); + /* prepare the file */ bfill(buffw, PAGE_SIZE, '\1'); pagecache_write(&pagecache, &file1, 0, 3, (char*)buffw, @@ -161,15 +159,17 @@ int simple_read_change_write_read_test() 0); ok((res= test(memcmp(buffr, buffw, PAGE_SIZE) == 0)), "Simple read-change-write-read page "); + DBUG_ASSERT(pagecache.blocks_changed == 1); flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE); - ok((res&= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, + DBUG_ASSERT(pagecache.blocks_changed == 0); + ok((res2= test(test_file(file1, file1_name, PAGE_SIZE, PAGE_SIZE, simple_read_change_write_read_test_file))), "Simple read-change-write-read page file"); - if (res) - reset_file(file1, file1_name); + if (res && res2) + reset_file(&file1, file1_name); free(buffw); free(buffr); - DBUG_RETURN(res); + DBUG_RETURN(res && res2); } @@ -247,7 +247,7 @@ int simple_pin_test() simple_pin_test_file2))), "Simple pin page result file"); if (res) - reset_file(file1, file1_name); + reset_file(&file1, file1_name); err: free(buffw); free(buffr); @@ -289,7 +289,7 @@ int simple_delete_forget_test() simple_delete_forget_test_file))), "Simple delete-forget page file"); if (res) - reset_file(file1, file1_name); + reset_file(&file1, file1_name); free(buffw); free(buffr); DBUG_RETURN(res); @@ -331,7 +331,7 @@ int simple_delete_flush_test() simple_delete_flush_test_file))), "Simple delete-forget page file"); if (res) - reset_file(file1, file1_name); + reset_file(&file1, file1_name); free(buffw); free(buffr); DBUG_RETURN(res); @@ -344,13 +344,14 @@ int simple_delete_flush_test() int simple_big_test() { - unsigned char *buffw= (unsigned char *)malloc(PAGE_SIZE); - unsigned char *buffr= (unsigned char *)malloc(PAGE_SIZE); - struct file_desc *desc= - (struct file_desc *)malloc((PCACHE_SIZE/(PAGE_SIZE/2) + 1) * - sizeof(struct file_desc)); + unsigned char *buffw= (unsigned char *) my_malloc(PAGE_SIZE, MYF(MY_WME)); + unsigned char *buffr= (unsigned char *) my_malloc(PAGE_SIZE, MYF(MY_WME)); + struct file_desc *desc= ((struct file_desc *) + my_malloc((PCACHE_SIZE/(PAGE_SIZE/2) + 1) * + sizeof(struct file_desc), MYF(MY_WME))); int res, i; DBUG_ENTER("simple_big_test"); + /* prepare the file twice larger then cache */ for (i= 0; i < PCACHE_SIZE/(PAGE_SIZE/2); i++) { @@ -380,7 +381,8 @@ int simple_big_test() if (buffr[j] != (i & 0xff)) { diag("simple_big_test seq: page %u byte %u mismatch\n", i, j); - return 0; + res= 0; + goto err; } } } @@ -399,7 +401,8 @@ int simple_big_test() if (buffr[j] != (page & 0xff)) { diag("simple_big_test rnd: page %u byte %u mismatch\n", page, j); - return 0; + res= 0; + goto err; } } } @@ -410,11 +413,16 @@ int simple_big_test() desc))), "Simple big file"); if (res) - reset_file(file1, file1_name); - free(buffw); - free(buffr); + reset_file(&file1, file1_name); + +err: + my_free(buffw, 0); + my_free(buffr, 0); + my_free(desc, 0); DBUG_RETURN(res); } + + /* Thread function */ @@ -427,7 +435,6 @@ static void *test_thread(void *arg) my_thread_init(); DBUG_ENTER("test_thread"); - DBUG_PRINT("enter", ("param: %d", param)); if (!simple_read_write_test() || @@ -460,7 +467,7 @@ int main(int argc __attribute__((unused)), pthread_t tid; pthread_attr_t thr_attr; int *param, error, pagen; - + File tmp_file; MY_INIT(argv[0]); #ifndef DBUG_OFF @@ -475,10 +482,13 @@ int main(int argc __attribute__((unused)), DBUG_SET_INITIAL(default_dbug_option); } #endif - - DBUG_ENTER("main"); DBUG_PRINT("info", ("Main thread: %s\n", my_thread_name())); + + if ((tmp_file= my_open(file2_name, O_CREAT | O_TRUNC | O_RDWR, + MYF(MY_WME))) < 0) + exit(1); + if ((file1.file= my_open(file1_name, O_CREAT | O_TRUNC | O_RDWR, MYF(0))) == -1) { @@ -486,6 +496,9 @@ int main(int argc __attribute__((unused)), errno); exit(1); } + my_close(tmp_file, MYF(0)); + my_delete(file2_name, MYF(0)); + DBUG_PRINT("info", ("file1: %d", file1.file)); if (chmod(file1_name, S_IRWXU | S_IRWXG | S_IRWXO) != 0) { @@ -529,7 +542,7 @@ int main(int argc __attribute__((unused)), plan(12); if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PAGE_SIZE)) == 0) + PAGE_SIZE, MYF(MY_WME))) == 0) { fprintf(stderr,"Got error: init_pagecache() (errno: %d)\n", errno); @@ -571,12 +584,9 @@ int main(int argc __attribute__((unused)), end_pagecache(&pagecache, 1); DBUG_PRINT("info", ("Page cache ended")); - if (my_close(file1.file, MYF(0)) != 0) - { - fprintf(stderr, "Got error during file1 closing from close() (errno: %d)\n", - errno); + if (my_close(file1.file, MYF(MY_WME))) exit(1); - } + /*my_delete(file1_name, MYF(0));*/ my_end(0); diff --git a/storage/maria/unittest/ma_test_loghandler-t.c b/storage/maria/unittest/ma_test_loghandler-t.c index 48aae3e1b3e..452477f6975 100644 --- a/storage/maria/unittest/ma_test_loghandler-t.c +++ b/storage/maria/unittest/ma_test_loghandler-t.c @@ -170,7 +170,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE)) == 0) + TRANSLOG_PAGE_SIZE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c b/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c index 845e33b63a5..30c51c96ffb 100644 --- a/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c +++ b/storage/maria/unittest/ma_test_loghandler_first_lsn-t.c @@ -60,7 +60,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PCACHE_PAGE)) == 0) + PCACHE_PAGE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_max_lsn-t.c b/storage/maria/unittest/ma_test_loghandler_max_lsn-t.c index 68561443a02..5f9ed01cb4a 100644 --- a/storage/maria/unittest/ma_test_loghandler_max_lsn-t.c +++ b/storage/maria/unittest/ma_test_loghandler_max_lsn-t.c @@ -54,7 +54,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PCACHE_PAGE)) == 0) + PCACHE_PAGE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c index e5afa0b40db..c66ad6fdc8d 100644 --- a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c @@ -167,7 +167,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE)) == 0) + TRANSLOG_PAGE_SIZE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); @@ -332,7 +332,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE)) == 0) + TRANSLOG_PAGE_SIZE, 0)) == 0) { fprintf(stderr, "pass2: Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_multithread-t.c b/storage/maria/unittest/ma_test_loghandler_multithread-t.c index 0a81aeac55f..43e124f208c 100644 --- a/storage/maria/unittest/ma_test_loghandler_multithread-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multithread-t.c @@ -277,7 +277,7 @@ int main(int argc __attribute__((unused)), exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - TRANSLOG_PAGE_SIZE)) == 0) + TRANSLOG_PAGE_SIZE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_noflush-t.c b/storage/maria/unittest/ma_test_loghandler_noflush-t.c index a53e6257314..01e1bc71fbe 100644 --- a/storage/maria/unittest/ma_test_loghandler_noflush-t.c +++ b/storage/maria/unittest/ma_test_loghandler_noflush-t.c @@ -62,7 +62,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PCACHE_PAGE)) == 0) + PCACHE_PAGE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_pagecache-t.c b/storage/maria/unittest/ma_test_loghandler_pagecache-t.c index c93f57fad01..e384acad5e5 100644 --- a/storage/maria/unittest/ma_test_loghandler_pagecache-t.c +++ b/storage/maria/unittest/ma_test_loghandler_pagecache-t.c @@ -62,7 +62,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PCACHE_PAGE)) == 0) + PCACHE_PAGE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/ma_test_loghandler_purge-t.c b/storage/maria/unittest/ma_test_loghandler_purge-t.c index d9001b9d3ad..d59ac1a12dd 100644 --- a/storage/maria/unittest/ma_test_loghandler_purge-t.c +++ b/storage/maria/unittest/ma_test_loghandler_purge-t.c @@ -57,7 +57,7 @@ int main(int argc __attribute__((unused)), char *argv[]) exit(1); } if ((pagen= init_pagecache(&pagecache, PCACHE_SIZE, 0, 0, - PCACHE_PAGE)) == 0) + PCACHE_PAGE, 0)) == 0) { fprintf(stderr, "Got error: init_pagecache() (errno: %d)\n", errno); exit(1); diff --git a/storage/maria/unittest/test_file.c b/storage/maria/unittest/test_file.c index 758d0bfa81b..215fd54a819 100644 --- a/storage/maria/unittest/test_file.c +++ b/storage/maria/unittest/test_file.c @@ -24,32 +24,37 @@ int test_file(PAGECACHE_FILE file, char *file_name, off_t size, size_t buff_size, struct file_desc *desc) { MY_STAT stat_buff, *stat; - unsigned char *buffr= malloc(buff_size); + unsigned char *buffr= my_malloc(buff_size, MYF(0)); off_t pos= 0; size_t byte; int step= 0; + int res= 1; /* ok */ if ((stat= my_stat(file_name, &stat_buff, MYF(0))) == NULL) { diag("Can't stat() %s (errno: %d)\n", file_name, errno); - return 0; + res= 0; + goto err; } if (stat->st_size != size) { diag("file %s size is %lu (should be %lu)\n", file_name, (ulong) stat->st_size, (ulong) size); - return 0; + res= 0; /* failed */ + /* continue to get more information */ } + /* check content */ - my_seek(file.file, 0, SEEK_SET, MYF(0)); + my_seek(file.file, 0, SEEK_SET, MYF(MY_WME)); while (desc[step].length != 0) { if (my_read(file.file, (char*)buffr, desc[step].length, MYF(0)) != desc[step].length) { - diag("Can't read %u bytes from %s (errno: %d)\n", - (uint)desc[step].length, file_name, errno); - return 0; + diag("Can't read %u bytes from %s (file: %d errno: %d)\n", + (uint)desc[step].length, file_name, file.file, errno); + res= 0; + goto err; } for (byte= 0; byte < desc[step].length; byte++) { @@ -58,11 +63,15 @@ int test_file(PAGECACHE_FILE file, char *file_name, diag("content of %s mismatch 0x%x in position %lu instead of 0x%x\n", file_name, (uint) buffr[byte], (ulong) (pos + byte), desc[step].content); - return 0; + res= 0; + goto err; } } pos+= desc[step].length; step++; } - return 1; + +err: + my_free(buffr, 0); + return res; } diff --git a/storage/maria/unittest/trnman-t.c b/storage/maria/unittest/trnman-t.c index db137cf088c..103f76cf776 100644 --- a/storage/maria/unittest/trnman-t.c +++ b/storage/maria/unittest/trnman-t.c @@ -154,8 +154,9 @@ void test_trnman_read_from() } } -int main() +int main(int argc __attribute__((unused)), char **argv) { + MY_INIT(argv[0]); my_init(); plan(6); diff --git a/storage/myisam/mi_cache.c b/storage/myisam/mi_cache.c index d6dcc431a8d..1ccf038a570 100644 --- a/storage/myisam/mi_cache.c +++ b/storage/myisam/mi_cache.c @@ -97,8 +97,8 @@ int _mi_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length, DBUG_PRINT("error", ("Error %d reading next-multi-part block (Got %d bytes)", my_errno, (int) read_length)); - if (!my_errno || my_errno == -1) - my_errno=HA_ERR_WRONG_IN_RECORD; + if (!my_errno || my_errno == -1 || my_errno == HA_ERR_FILE_TOO_SHORT) + my_errno= HA_ERR_WRONG_IN_RECORD; DBUG_RETURN(1); } bzero(buff+read_length,MI_BLOCK_INFO_HEADER_LENGTH - in_buff_length - diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 38e518fd823..23f84819949 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -185,7 +185,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (flags & HA_CREATE_TMP_TABLE) { options|= HA_OPTION_TMP_TABLE; - create_mode|= O_EXCL | O_NOFOLLOW; + create_mode|= O_NOFOLLOW; } if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 2a12fd04641..0811de2b968 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -1764,7 +1764,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, uchar *buf, /* VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0))); */ if (my_read(info->dfile,(uchar*) to,block_info.data_len,MYF(MY_NABP))) { - if (my_errno == -1) + if (my_errno == HA_ERR_FILE_TOO_SHORT) my_errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */ goto err; } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 2d89fce2a81..ad23a42ab83 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -429,10 +429,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer) DBUG_RETURN(1); if (mi_state_info_read_dsk(share->kfile, &share->state, 1)) { - int error=my_errno ? my_errno : -1; + int error= my_errno ? my_errno : HA_ERR_FILE_TOO_SHORT; VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, MYF(MY_SEEK_NOT_DONE))); - my_errno=error; + my_errno= error; DBUG_RETURN(1); } } |