diff options
34 files changed, 656 insertions, 414 deletions
diff --git a/dbug/dbug.c b/dbug/dbug.c index 9c92fcc9a7e..68e52388ae3 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -2263,6 +2263,16 @@ static void dbug_flush(CODE_STATE *cs) } /* dbug_flush */ +/* For debugging */ + +void _db_force_flush() +{ + CODE_STATE *cs; + get_code_state_or_return; + (void) fflush(cs->stack->out_file); +} + + void _db_lock_file_() { CODE_STATE *cs; diff --git a/extra/replace.c b/extra/replace.c index 9d1d8335014..9ba204f6b77 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -136,6 +136,7 @@ int main(int argc, char *argv[]) } } free_buffer(); + my_free(replace, MYF(0)); my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); exit(error ? 2 : 0); return 0; /* No compiler warning */ diff --git a/include/my_dbug.h b/include/my_dbug.h index 8c0df771ff2..5372a13f4af 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -47,6 +47,7 @@ extern void _db_end_(void); extern void _db_lock_file_(void); extern void _db_unlock_file_(void); extern FILE *_db_fp_(void); +extern void _db_force_flush(); #define DBUG_ENTER(a) const char *_db_func_, *_db_file_; uint _db_level_; \ char **_db_framep_; \ diff --git a/include/my_global.h b/include/my_global.h index 92326b2847c..4c78bf13e1c 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -410,6 +410,7 @@ C_MODE_END #ifndef stdin #include <stdio.h> #endif +#include <stdarg.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif diff --git a/include/my_sys.h b/include/my_sys.h index e04c0da3132..d6537fef32e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -653,6 +653,8 @@ extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, myf MyFlags, ...)) ATTRIBUTE_FORMAT(printf, 2, 4); +extern int my_printv_error(uint error, const char *format, myf MyFlags, + va_list ap); extern int my_error_register(const char **errmsgs, int first, int last); extern const char **my_error_unregister(int first, int last); extern int my_message(uint my_err, const char *str,myf MyFlags); @@ -866,7 +868,12 @@ extern int unpackfrm(uchar **, size_t *, const uchar *); extern ha_checksum my_checksum(ha_checksum crc, const uchar *mem, size_t count); +#ifndef DBUG_OFF extern void my_debug_put_break_here(void); +#else +#define my_debug_put_break_here() {} +#endif + 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 3b18a631221..10c91b95f7a 100644 --- a/include/myisamchk.h +++ b/include/myisamchk.h @@ -122,7 +122,7 @@ typedef struct st_handler_check_param my_off_t search_after_block; my_off_t new_file_pos, key_file_blocks; my_off_t keydata, totaldata, key_blocks, start_check_pos; - my_off_t used, empty, splits, del_length, link_used; + my_off_t used, empty, splits, del_length, link_used, lost; ha_rows total_records, total_deleted, records,del_blocks; ha_rows full_page_count, tail_count; ha_checksum record_checksum, glob_crc; diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index c3244fff402..8eb226d57ac 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -569,6 +569,7 @@ a a b 1 1 1 2 2 1 drop table t1,t2; +set autocommit=1; CREATE TABLE t1 (c1 varchar(250) NOT NULL) ROW_FORMAT=DYNAMIC; CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)) ROW_FORMAT=DYNAMIC; INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); @@ -2088,3 +2089,15 @@ drop table if exists t1; set global maria_log_file_size=4294967296; Warnings: Warning 1292 Truncated incorrect log_file_size value: '4294967296' +create table t1 (a int not null); +lock tables t1 write; +insert into t1 values (1),(2); +delete from t1; +unlock tables; +select * from t1; +a +insert into t1 values (1),(2); +delete from t1; +select * from t1; +a +drop table t1; diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test index d7f63193801..9654b5c76ec 100644 --- a/mysql-test/t/maria.test +++ b/mysql-test/t/maria.test @@ -546,6 +546,7 @@ disconnect root; connection default; select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; drop table t1,t2; +set autocommit=1; # # Full key. CREATE TABLE t1 (c1 varchar(250) NOT NULL) ROW_FORMAT=DYNAMIC; @@ -1336,6 +1337,21 @@ drop table if exists t1; --enable_warnings set global maria_log_file_size=4294967296; +# +# Test delete of all rows in autocommit and not autocommit +# + +create table t1 (a int not null); +lock tables t1 write; +insert into t1 values (1),(2); +delete from t1; +unlock tables; +select * from t1; +insert into t1 values (1),(2); +delete from t1; +select * from t1; +drop table t1; + # End of 5.2 tests --disable_result_log diff --git a/mysys/my_error.c b/mysys/my_error.c index d26c3d8cfde..81abbde96df 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -114,15 +114,39 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...) va_list args; char ebuff[ERRMSGSIZE+20]; DBUG_ENTER("my_printf_error"); - DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s", + DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", error, MyFlags, errno, format)); va_start(args,MyFlags); - (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args); + (void) my_vsnprintf(ebuff, sizeof(ebuff), format, args); va_end(args); DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags)); } + +/* + Error with va_list + + SYNOPSIS + my_printv_error() + error Errno + format Format string + MyFlags Flags + ... variable list +*/ + +int my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) +{ + char ebuff[ERRMSGSIZE+20]; + DBUG_ENTER("my_printv_error"); + DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", + error, MyFlags, errno, format)); + + (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap); + DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags)); +} + + /* Give message using error_handler_hook diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 3b179957932..aaf0553151f 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -94,7 +94,7 @@ parse_arguments() { # [mysql_install_db], and then merge with the command line arguments print_defaults=my_print_defaults -for dir in ./bin @bindir@ @bindir@ extra $print_defaults_bindir/../bin $print_defaults_bindir/../extra +for dir in ./extra ./bin @bindir@ @bindir@ $print_defaults_bindir/../bin $print_defaults_bindir/../extra do if test -x $dir/my_print_defaults then @@ -117,7 +117,7 @@ dirname=`dirname "$0"` if test -z "$bindir" then - for i in @bindir@ $basedir/bin "$dirname/../client" + for i in "$dirname/../client" $basedir/bin @bindir@ do if test -f $i/mysql then @@ -149,8 +149,8 @@ then fi # Find where first mysql_fix_privilege_tables.sql is located -for i in $basedir/support-files $basedir/share $basedir/share/mysql \ - $basedir/scripts $pkgdatadir . "$dirname" +for i in "$dirname" $basedir/support-files $basedir/share \ + $basedir/share/mysql $basedir/scripts $pkgdatadir . do if test -f $i/$file then diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9e653af2078..18f3b8cf55a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2314,10 +2314,6 @@ static void init_signals(void) struct sigaction sa; DBUG_ENTER("init_signals"); - if (test_flags & TEST_SIGINT) - { - my_sigset(thr_kill_signal, end_thread_signal); - } my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) @@ -2378,6 +2374,9 @@ static void init_signals(void) { // May be SIGINT sigdelset(&set, thr_kill_signal); + sigdelset(&set, SIGINT); + my_sigset(thr_kill_signal, end_thread_signal); + my_sigset(SIGINT, end_thread_signal); } sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9e66bfd4b47..b1f6dd0e564 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -394,12 +394,9 @@ Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg, const char *message_arg) { DBUG_ASSERT(! is_set()); -#ifdef DBUG_OFF - /* In production, refuse to overwrite an error with an OK packet. */ + /* Refuse to overwrite an error with an OK packet. */ if (is_error()) return; -#endif - /** Only allowed to report success if has not yet reported an error */ m_server_status= thd->server_status; m_total_warn_count= thd->total_warn_count; @@ -423,11 +420,9 @@ Diagnostics_area::set_eof_status(THD *thd) /** Only allowed to report eof if has not yet reported an error */ DBUG_ASSERT(! is_set()); -#ifdef DBUG_OFF - /* In production, refuse to overwrite an error with an EOF packet. */ + /* Refuse to overwrite an error with an EOF packet. */ if (is_error()) return; -#endif m_server_status= thd->server_status; /* diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 2cb818945af..d0870238244 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -159,8 +159,8 @@ static MYSQL_SYSVAR_ULONG(pagecache_age_threshold, static MYSQL_SYSVAR_ULONGLONG(pagecache_buffer_size, pagecache_buffer_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The size of the buffer used for index blocks for Maria tables. " - "Increase this to get better index handling (for all reads and multiple " - "writes) to as much as you can afford.", 0, 0, + "Increase this to get better index handling (for all reads and " + "multiple writes) to as much as you can afford.", 0, 0, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, IO_SIZE); static MYSQL_SYSVAR_ULONG(pagecache_division_limit, pagecache_division_limit, @@ -180,13 +180,13 @@ static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG, "Specifies how maria index statistics collection code should threat " - "NULLs. Possible values of name are \"nulls_unequal\", \"nulls_equal\", " + "NULLs. Possible values are \"nulls_unequal\", \"nulls_equal\", " "and \"nulls_ignored\".", 0, 0, 0, &maria_stats_method_typelib); static MYSQL_SYSVAR_ENUM(sync_log_dir, sync_log_dir, PLUGIN_VAR_RQCMDARG, "Controls syncing directory after log file growth and new file " - "creation. Possible values of are \"never\", \"newfile\" and " - "\"always\")", NULL, NULL, TRANSLOG_SYNC_DIR_NEWFILE, + "creation. Possible values are \"never\", \"newfile\" and " + "\"always\").", NULL, NULL, TRANSLOG_SYNC_DIR_NEWFILE, &maria_sync_log_dir_typelib); /***************************************************************************** @@ -1249,14 +1249,13 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) DBUG_RETURN(HA_ADMIN_FAILED); } - /** @todo BUG the if() below is always false for BLOCK_RECORD */ if (!do_optimize || - ((file->state->del || - ((file->s->data_file_type != BLOCK_RECORD) && - share->state.split != file->state->records)) && - (!(param.testflag & T_QUICK) || - (share->state.changed & (STATE_NOT_OPTIMIZED_KEYS | - STATE_NOT_OPTIMIZED_ROWS))))) + ((file->s->data_file_type == BLOCK_RECORD) ? + (share->state.changed & STATE_NOT_OPTIMIZED_ROWS) : + (file->state->del || share->state.split != file->state->records)) && + (!(param.testflag & T_QUICK) || + (share->state.changed & (STATE_NOT_OPTIMIZED_KEYS | + STATE_NOT_OPTIMIZED_ROWS)))) { ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ? maria_get_mask_all_keys_active(share->base.keys) : @@ -1294,13 +1293,7 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) { thd_proc_info(thd, "Repair with keycache"); param.testflag &= ~(T_REP_BY_SORT | T_REP_PARALLEL); - /* - Disable logging of index changes as the repair redo call will - make it for us - */ - _ma_tmp_disable_logging_for_table(file, 0); error= maria_repair(¶m, file, fixed_name, param.testflag & T_QUICK); - _ma_reenable_logging_for_table(file); /** @todo RECOVERY BUG we do things with the index file (maria_sort_index() after the above which already has logged the @@ -1362,6 +1355,9 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) _ma_check_print_warning(¶m, "Number of rows changed from %s to %s", llstr(rows, llbuff), llstr(file->state->records, llbuff2)); + /* Abort if warning was converted to error */ + if (current_thd->is_error()) + error= 1; } } else @@ -1594,7 +1590,7 @@ int ha_maria::enable_indexes(uint mode) maria_chk_init(¶m); param.op_name= "recreating_index"; param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK | - T_CREATE_MISSING_KEYS); + T_CREATE_MISSING_KEYS | T_SAFE_REPAIR); param.myf_rw &= ~MY_WAIT_IF_FULL; param.sort_buffer_length= THDVAR(thd,sort_buffer_size); param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); @@ -2039,6 +2035,16 @@ int ha_maria::extra_opt(enum ha_extra_function operation, ulong cache_size) int ha_maria::delete_all_rows() { + if (file->s->now_transactional && + ((table->in_use->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) || + table->in_use->locked_tables)) + { + /* + We are not in autocommit mode or user have done LOCK TABLES. + We must do the delete row by row to be able to rollback the command + */ + return HA_ERR_WRONG_COMMAND; + } return maria_delete_all_rows(file); } diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index a18ce90c043..e35658f55f1 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -46,16 +46,16 @@ Dynamic size records: - 3 bits are used to indicate + 3 bits are used to indicate Bytes free in 8K page - 0 Empty page - 1 0-30 % full (at least room for 3 records) - 2 30-60 % full (at least room for 2 records) - 3 60-90 % full (at least room for one record) - 4 100 % full (no more room for records) - 5 Tail page, 0-40 % full - 6 Tail page, 40-80 % full - 7 Full tail page or full blob page + 0 Empty page 8176 (head or tail) + 1 0-30 % full (at least room for 3 records) 5724 + 2 30-60 % full (at least room for 2 records) 3271 + 3 60-90 % full (at least room for one record) 818 + 4 100 % full (no more room for records) 0 + 5 Tail page, 0-40 % full 4906 + 6 Tail page, 40-80 % full 1636 + 7 Full tail page or full blob page 0 Assuming 8K pages, this will allow us to map: 8192 (bytes per page) * 8 bits/byte / 3 bits/page * 8192 (page size)= 170.7M @@ -222,7 +222,7 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file) /* Update size for bits */ /* TODO; Make this dependent of the row size */ - max_page_size= share->block_size - PAGE_OVERHEAD_SIZE; + max_page_size= share->block_size - PAGE_OVERHEAD_SIZE + DIR_ENTRY_SIZE; bitmap->sizes[0]= max_page_size; /* Empty page */ bitmap->sizes[1]= max_page_size - max_page_size * 30 / 100; bitmap->sizes[2]= max_page_size - max_page_size * 60 / 100; @@ -915,6 +915,7 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap, /* For each 6 bytes we have 6*8/3= 16 patterns */ page= (best_data - bitmap->map) / 6 * 16 + best_pos; + DBUG_ASSERT(page + 1 < bitmap->pages_covered); block->page= bitmap->page + 1 + page; block->page_count= TAIL_PAGE_COUNT_MARKER; block->empty_space= pattern_to_size(bitmap, best_bits); @@ -971,7 +972,7 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, LINT_INIT(best_pos); DBUG_ASSERT(size <= FULL_PAGE_SIZE(bitmap->block_size)); - for (; data < end; data += 6) + for (; data < end; data+= 6) { ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ uint i; @@ -991,14 +992,6 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, if (pattern <= min_bits) { /* There is enough space here */ - if (pattern == min_bits) - { - /* There is exactly enough space here, return this page */ - best_bits= min_bits; - best_data= data; - best_pos= i; - goto found; - } if ((int) pattern > (int) best_bits) { /* @@ -1009,16 +1002,19 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, best_bits= pattern; best_data= data; best_pos= i; + if (pattern == min_bits) + goto found; /* Best possible match */ } } } } if (!best_data) /* Found no place */ { - if (bitmap->used_size == bitmap->total_size) + if (data >= bitmap->map + bitmap->total_size) DBUG_RETURN(1); /* No space in bitmap */ /* Allocate data at end of bitmap */ bitmap->used_size+= 6; + set_if_smaller(bitmap->used_size, bitmap->total_size); best_data= data; best_pos= best_bits= 0; } @@ -1068,41 +1064,38 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size, the following patterns: 1-4 (head pages, not suitable for tail) or 7 (full tail page). See 'Dynamic size records' comment at start of file. - At the moment we only skip full tail pages (ie, all bits are + At the moment we only skip full head and tail pages (ie, all bits are set) as this is easy to detect with one simple test and is a quite common case if we have blobs. */ - if ((!bits && best_data) || bits == LL(0xffffffffffff)) + if ((!bits && best_data) || bits == LL(0xffffffffffff) || + bits == LL(04444444444444444)) continue; for (i= 0; i < 16; i++, bits >>= 3) { uint pattern= bits & 7; if (pattern <= min_bits && (!pattern || pattern >= 5)) { - if (pattern == min_bits) - { - best_bits= min_bits; - best_data= data; - best_pos= i; - goto found; - } if ((int) pattern > (int) best_bits) { best_bits= pattern; best_data= data; best_pos= i; + if (pattern == min_bits) + goto found; /* Can't be better */ } } } } if (!best_data) { - if (bitmap->used_size == bitmap->total_size) + if (data >= bitmap->map + bitmap->total_size) DBUG_RETURN(1); /* Allocate data at end of bitmap */ - best_data= end; + best_data= data; bitmap->used_size+= 6; + set_if_smaller(bitmap->used_size, bitmap->total_size); best_pos= best_bits= 0; } @@ -1253,6 +1246,7 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap, block->sub_blocks= 0; block->org_bitmap_value= 0; block->used= 0; + DBUG_ASSERT(page + best_area_size < bitmap->pages_covered); DBUG_PRINT("info", ("page: %lu page_count: %u", (ulong) block->page, block->page_count)); @@ -1290,7 +1284,10 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap, best_data++; } if (data_end < best_data) + { bitmap->used_size= (uint) (best_data - bitmap->map); + DBUG_ASSERT(bitmap->used_size <= bitmap->total_size); + } bitmap->changed= 1; DBUG_EXECUTE("bitmap", _ma_print_bitmap_changes(bitmap);); DBUG_RETURN(block->page_count); @@ -1326,7 +1323,11 @@ static my_bool find_head(MARIA_HA *info, uint length, uint position) */ block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); - while (allocate_head(bitmap, length, block)) + /* + We need to have DIRENTRY_SIZE here to take into account that we may + need an extra directory entry for the row + */ + while (allocate_head(bitmap, length + DIR_ENTRY_SIZE, block)) if (move_to_next_bitmap(info, bitmap)) return 1; return 0; @@ -1353,13 +1354,18 @@ static my_bool find_tail(MARIA_HA *info, uint length, uint position) MARIA_FILE_BITMAP *bitmap= &info->s->bitmap; MARIA_BITMAP_BLOCK *block; DBUG_ENTER("find_tail"); + DBUG_ASSERT(length <= info->s->block_size - PAGE_OVERHEAD_SIZE); /* Needed, as there is no error checking in dynamic_element */ if (allocate_dynamic(&info->bitmap_blocks, position)) DBUG_RETURN(1); block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); - while (allocate_tail(bitmap, length, block)) + /* + We have to add DIR_ENTRY_SIZE to ensure we have space for the tail and + it's directroy entry on the page + */ + while (allocate_tail(bitmap, length + DIR_ENTRY_SIZE, block)) if (move_to_next_bitmap(info, bitmap)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -1539,6 +1545,7 @@ static void use_head(MARIA_HA *info, ulonglong page, uint size, MARIA_BITMAP_BLOCK *block; uchar *data; uint offset, tmp, offset_page; + DBUG_ASSERT(page % bitmap->pages_covered); block= dynamic_element(&info->bitmap_blocks, block_position, MARIA_BITMAP_BLOCK*); @@ -1740,8 +1747,7 @@ my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row, extents_length= row->extents_count * ROW_EXTENT_SIZE; /* - The + 3 here is space to be able to store the number of segments - in the row header. + The + 3 is reserved for storing the number of segments in the row header. */ if ((head_length= (row->head_length + extents_length + 3)) <= max_page_size) @@ -2329,9 +2335,9 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) set_page_bits(info, bitmap, block->page, bits)) goto err; } - if (!(block->used & BLOCKUSED_USED) && - _ma_bitmap_reset_full_page_bits(info, bitmap, - block->page, page_count)) + else if (!(block->used & BLOCKUSED_USED) && + _ma_bitmap_reset_full_page_bits(info, bitmap, + block->page, page_count)) goto err; } @@ -2586,8 +2592,7 @@ flush_log_for_bitmap(uchar *page __attribute__((unused)), const MARIA_SHARE *share= (MARIA_SHARE*)data_ptr; #endif DBUG_ENTER("flush_log_for_bitmap"); - DBUG_ASSERT(share->page_type == PAGECACHE_LSN_PAGE && - share->now_transactional); + DBUG_ASSERT(share->now_transactional); /* WAL imposes that UNDOs reach disk before bitmap is flushed. We don't know the LSN of the last UNDO about this bitmap page, so we flush whole log. diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index ddf8e5069e1..4622f636867 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -1269,8 +1269,23 @@ static void calc_record_size(MARIA_HA *info, const uchar *record, } } row->field_lengths_length= (uint) (field_length_data - row->field_lengths); + /* + - row->base_length is base information we must have on a page in first + extent: + - flag byte (1) + is_nulls_extended (0 | 1) + null_bytes + pack_bytes + + table_checksum (0 | 1) + - row->min_length is minimum amount of data we must store on + a page. bitmap code will ensure we get at list this much + + total number of extents and one extent information + - fixed_not_null_fields_length is length of fixed length fields that can't + be compacted + - head_length is the amount of data for the head page + (ie, all fields except blobs) + */ row->min_length= (row->base_length + - size_to_store_key_length(row->field_lengths_length)); + (share->base.max_field_lengths ? + size_to_store_key_length(row->field_lengths_length) : + 0)); row->head_length= (row->min_length + share->base.fixed_not_null_fields_length + row->field_lengths_length + @@ -1534,11 +1549,11 @@ static my_bool get_head_or_tail_page(MARIA_HA *info, /* Read old page */ page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; res->buff= pagecache_read(share->pagecache, &info->dfile, - block->page, 0, buff, share->page_type, + block->page, 0, 0, share->page_type, lock, &page_link.link); - page_link.changed= res->buff == 0; + page_link.changed= res->buff != 0; push_dynamic(&info->pinned_pages, (void*) &page_link); - if (page_link.changed) + if (!page_link.changed) goto crashed; DBUG_ASSERT((res->buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == page_type); @@ -1620,10 +1635,10 @@ static my_bool get_rowpos_in_head_or_tail_page(MARIA_HA *info, else { page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; - res->buff= pagecache_read(share->pagecache, &info->dfile, - block->page, 0, buff, share->page_type, - lock, &page_link.link); - page_link.changed= res->buff != 0; + buff= pagecache_read(share->pagecache, &info->dfile, + block->page, 0, 0, share->page_type, + lock, &page_link.link); + page_link.changed= buff != 0; push_dynamic(&info->pinned_pages, (void*) &page_link); if (!page_link.changed) /* Read error */ goto err; @@ -1797,27 +1812,32 @@ static my_bool write_tail(MARIA_HA *info, info->state->data_file_length= position + block_size; } - DBUG_ASSERT(share->pagecache->block_size == block_size); - if (!(res= pagecache_write(share->pagecache, - &info->dfile, block->page, 0, - row_pos.buff,share->page_type, - block_is_read ? PAGECACHE_LOCK_WRITE_TO_READ : - PAGECACHE_LOCK_READ, - block_is_read ? PAGECACHE_PIN_LEFT_PINNED : - PAGECACHE_PIN, - PAGECACHE_WRITE_DELAY, &page_link.link, - LSN_IMPOSSIBLE))) + if (block_is_read) + { + /* Current page link is last element in pinned_pages */ + MARIA_PINNED_PAGE *page_link; + page_link= dynamic_element(&info->pinned_pages, + info->pinned_pages.elements-1, + MARIA_PINNED_PAGE*); + pagecache_unlock_by_link(share->pagecache, page_link->link, + PAGECACHE_LOCK_WRITE_TO_READ, + PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, + LSN_IMPOSSIBLE, 1); + DBUG_ASSERT(page_link->changed); + page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; + res= 0; + } + else if (!(res= pagecache_write(share->pagecache, + &info->dfile, block->page, 0, + row_pos.buff,share->page_type, + PAGECACHE_LOCK_READ, + PAGECACHE_PIN, + PAGECACHE_WRITE_DELAY, &page_link.link, + LSN_IMPOSSIBLE))) { page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK; page_link.changed= 1; - if (block_is_read) - { - /* Change the lock used when we read the page */ - set_dynamic(&info->pinned_pages, (void*) &page_link, - info->pinned_pages.elements-1); - } - else - push_dynamic(&info->pinned_pages, (void*) &page_link); + push_dynamic(&info->pinned_pages, (void*) &page_link); } DBUG_RETURN(res); } @@ -1909,7 +1929,6 @@ static my_bool write_full_pages(MARIA_HA *info, bzero(buff + block_size - PAGE_SUFFIX_SIZE - (data_size - copy_length), (data_size - copy_length) + PAGE_SUFFIX_SIZE); - DBUG_ASSERT(share->pagecache->block_size == block_size); if (pagecache_write(share->pagecache, &info->dfile, page, 0, buff, share->page_type, @@ -2333,6 +2352,7 @@ static my_bool write_block_record(MARIA_HA *info, my_bool row_extents_in_use, blob_full_pages_exists; LSN lsn; my_off_t position; + uint save_my_errno; DBUG_ENTER("write_block_record"); LINT_INIT(row_extents_first_part); @@ -2382,6 +2402,9 @@ static my_bool write_block_record(MARIA_HA *info, memcpy(data, row->empty_bits, share->base.pack_bytes); data+= share->base.pack_bytes; + DBUG_ASSERT(row_extents_in_use || undo_lsn != LSN_ERROR || + (uint) (data - row_pos->data) == row->min_length); + /* Allocate a buffer of rest of data (except blobs) @@ -2439,6 +2462,11 @@ static my_bool write_block_record(MARIA_HA *info, memcpy(tmp_data, field_length_data, row->field_lengths_length); tmp_data+= row->field_lengths_length; + DBUG_ASSERT(row_extents_in_use || undo_lsn != LSN_ERROR || + (uint) (tmp_data - row_pos->data) == row->min_length + + share->base.fixed_not_null_fields_length + + row->field_lengths_length); + /* Copy variable length fields and fields with null/zero */ for (end_column= share->columndef + share->base.fields - share->base.blobs; column < end_column ; @@ -2479,6 +2507,7 @@ static my_bool write_block_record(MARIA_HA *info, field_length_data+= 2; field_pos+= 2; } + DBUG_ASSERT(length <= column->length); break; default: /* Wrong data */ DBUG_ASSERT(0); @@ -2831,26 +2860,35 @@ static my_bool write_block_record(MARIA_HA *info, if (info->state->data_file_length <= position) info->state->data_file_length= position + block_size; - DBUG_ASSERT(share->pagecache->block_size == block_size); - if (pagecache_write(share->pagecache, - &info->dfile, head_block->page, 0, - page_buff, share->page_type, - head_block_is_read ? PAGECACHE_LOCK_WRITE_TO_READ : - PAGECACHE_LOCK_READ, - head_block_is_read ? PAGECACHE_PIN_LEFT_PINNED : - PAGECACHE_PIN, - PAGECACHE_WRITE_DELAY, &page_link.link, - LSN_IMPOSSIBLE)) - goto disk_err; - page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK; - page_link.changed= 1; if (head_block_is_read) { + MARIA_PINNED_PAGE *page_link; /* Head page is always the first pinned page */ - set_dynamic(&info->pinned_pages, (void*) &page_link, 0); + page_link= dynamic_element(&info->pinned_pages, 0, + MARIA_PINNED_PAGE*); + pagecache_unlock_by_link(share->pagecache, page_link->link, + PAGECACHE_LOCK_WRITE_TO_READ, + PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, + LSN_IMPOSSIBLE, 1); + page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; + page_link->changed= 1; } else + { + if (pagecache_write(share->pagecache, + &info->dfile, head_block->page, 0, + page_buff, share->page_type, + head_block_is_read ? PAGECACHE_LOCK_WRITE_TO_READ : + PAGECACHE_LOCK_READ, + head_block_is_read ? PAGECACHE_PIN_LEFT_PINNED : + PAGECACHE_PIN, + PAGECACHE_WRITE_DELAY, &page_link.link, + LSN_IMPOSSIBLE)) + goto disk_err; + page_link.unlock= PAGECACHE_LOCK_READ_UNLOCK; + page_link.changed= 1; push_dynamic(&info->pinned_pages, (void*) &page_link); + } if (share->now_transactional && (tmp_data_used || blob_full_pages_exists)) { @@ -2918,8 +2956,8 @@ static my_bool write_block_record(MARIA_HA *info, if (!*tmp_blob_lengths) /* Null or "" */ continue; - length= tmp_column->length - portable_sizeof_char_ptr; blob_length= *tmp_blob_lengths; + length= tmp_column->length - portable_sizeof_char_ptr; /* If last part of blog was on tail page, change blob_length to reflect this @@ -2929,7 +2967,7 @@ static my_bool write_block_record(MARIA_HA *info, if (blob_length) { memcpy_fixed((uchar*) &log_array_pos->str, - record + column->offset + length, + record + tmp_column->offset + length, sizeof(uchar*)); log_array_pos->length= blob_length; log_entry_length+= blob_length; @@ -3136,8 +3174,9 @@ disk_err: Unpin all pinned pages to not cause problems for disk cache. This is safe to call even if we already called _ma_unpin_all_pages() above. */ + save_my_errno= my_errno; _ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE); - + my_errno= save_my_errno; DBUG_RETURN(1); } @@ -3163,6 +3202,7 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, { struct st_row_pos_info row_pos; MARIA_BITMAP_BLOCKS *blocks= &row->insert_blocks; + int save_my_errno; DBUG_ENTER("allocate_and_write_block_record"); _ma_bitmap_flushable(info, 1); @@ -3201,10 +3241,13 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, /* Now let checkpoint happen but don't commit */ DBUG_EXECUTE_IF("maria_over_alloc_bitmap", sleep(1000);); DBUG_RETURN(0); + err: + save_my_errno= my_errno; if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE); + my_errno= save_my_errno; DBUG_RETURN(1); } @@ -3362,8 +3405,8 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, _ma_bitmap_flushable(info, 1); buff= pagecache_read(share->pagecache, - &info->dfile, (pgcache_page_no_t) page, 0, - info->buff, share->page_type, + &info->dfile, (pgcache_page_no_t) page, 0, 0, + share->page_type, PAGECACHE_LOCK_WRITE, &page_link.link); page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; page_link.changed= buff != 0; @@ -3512,8 +3555,8 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info, _ma_bitmap_flushable(info, 1); buff= pagecache_read(share->pagecache, - &info->dfile, (pgcache_page_no_t) page, 0, - info->buff, share->page_type, + &info->dfile, (pgcache_page_no_t) page, 0, 0, + share->page_type, PAGECACHE_LOCK_WRITE, &page_link.link); page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; page_link.changed= buff != 0; @@ -3746,10 +3789,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info, (ulong) ma_recordpos(page, record_number), (ulong) page, record_number)); - DBUG_ASSERT(share->pagecache->block_size == block_size); buff= pagecache_read(share->pagecache, - &info->dfile, page, 0, - 0, + &info->dfile, page, 0, 0, share->page_type, PAGECACHE_LOCK_WRITE, &page_link.link); page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK; @@ -3794,14 +3835,6 @@ static my_bool delete_head_or_tail(MARIA_HA *info, log_data, NULL)) DBUG_RETURN(1); } - if (pagecache_write(share->pagecache, - &info->dfile, page, 0, - buff, share->page_type, - lock_at_write, - PAGECACHE_PIN_LEFT_PINNED, - PAGECACHE_WRITE_DELAY, &page_link.link, - LSN_IMPOSSIBLE)) - DBUG_RETURN(1); } else /* page is now empty */ { @@ -3818,19 +3851,13 @@ static my_bool delete_head_or_tail(MARIA_HA *info, log_data, NULL)) DBUG_RETURN(1); } - /* Write the empty page (needed only for REPAIR to work) */ - if (pagecache_write(share->pagecache, - &info->dfile, page, 0, - buff, share->page_type, - lock_at_write, - PAGECACHE_PIN_LEFT_PINNED, - PAGECACHE_WRITE_DELAY, &page_link.link, - LSN_IMPOSSIBLE)) - DBUG_RETURN(1); - DBUG_ASSERT(empty_space >= share->bitmap.sizes[0]); } - /* The page is pinned with a read lock */ + + pagecache_unlock_by_link(share->pagecache, page_link.link, + lock_at_write, + PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, + LSN_IMPOSSIBLE, 1); page_link.unlock= lock_at_unpin; set_dynamic(&info->pinned_pages, (void*) &page_link, info->pinned_pages.elements-1); @@ -4105,7 +4132,6 @@ static uchar *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, if (extent->tail) lock= extent->lock_for_tail_pages; - DBUG_ASSERT(share->pagecache->block_size == share->block_size); buff= pagecache_read(share->pagecache, &info->dfile, extent->page, 0, info->buff, share->page_type, @@ -4439,6 +4465,10 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, field_pos+= 2; field_length_data+= 2; } +#ifdef SANITY_CHECKS + if (length > column->length) + goto err; +#endif if (read_long_data(info, field_pos, length, &extent, &data, &end_of_data)) DBUG_RETURN(my_errno); @@ -4673,7 +4703,6 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record, offset= ma_recordpos_to_dir_entry(record_pos); - DBUG_ASSERT(share->pagecache->block_size == block_size); if (!(buff= pagecache_read(share->pagecache, &info->dfile, ma_recordpos_to_page(record_pos), 0, info->buff, share->page_type, @@ -6762,13 +6791,15 @@ err: /** - @brief Pagecache callback to get the TRANSLOG_ADDRESS to flush up to, when a - data (non-bitmap) or index page needs to be flushed. Returns a real LSN. + @brief Get the TRANSLOG_ADDRESS to flush up to @param page Page's content @param page_no Page's number (<offset>/<page length>) @param data_ptr Callback data pointer (pointer to MARIA_SHARE) + @note + Usable for data (non-bitmap) and index pages + @retval LSN to flush up to */ diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index d8720efe939..e7bee662c1d 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -94,7 +94,8 @@ static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info, static void copy_data_file_state(MARIA_STATE_INFO *to, MARIA_STATE_INFO *from); static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info); -static void report_keypage_fault(HA_CHECK *param, my_off_t position); +static void report_keypage_fault(HA_CHECK *param, MARIA_HA *info, + my_off_t position); static my_bool create_new_data_handle(MARIA_SORT_PARAM *param, File new_file); @@ -496,7 +497,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info) PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, info->buff, 0, 0)) { - report_keypage_fault(param, share->state.key_root[key]); + report_keypage_fault(param, info, share->state.key_root[key]); if (!(param->testflag & T_INFO)) DBUG_RETURN(-1); result= -1; @@ -662,7 +663,7 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info, if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, buff, 0, 0)) { - report_keypage_fault(param, page); + report_keypage_fault(param, info, page); goto err; } param->key_file_blocks+=keyinfo->block_length; @@ -1578,6 +1579,7 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, uchar *dir_entry; uint row; char llbuff[22], llbuff2[22]; + ulonglong page= page_pos / share->block_size; DBUG_ENTER("check_head_page"); dir_entry= page_buff+ share->block_size - PAGE_SUFFIX_SIZE; @@ -1593,25 +1595,24 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, { _ma_check_print_error(param, "Page %9s: Row %3u is too short (%d bytes)", - llstr(page_pos, llbuff), row, length); + llstr(page, llbuff), row, length); DBUG_RETURN(1); } flag= (uint) (uchar) page_buff[pos]; if (flag & ~(ROW_FLAG_ALL)) _ma_check_print_error(param, "Page %9s: Row %3u has wrong flag: %d", - llstr(page_pos, llbuff), row, flag); + llstr(page, llbuff), row, flag); DBUG_PRINT("info", ("rowid: %s page: %lu row: %u", - llstr(ma_recordpos(page_pos/share->block_size, row), - llbuff), - (ulong) (page_pos / share->block_size), row)); + llstr(ma_recordpos(page, row), llbuff), + (ulong) page, row)); if (_ma_read_block_record2(info, record, page_buff+pos, page_buff+pos+length)) { _ma_check_print_error(param, "Page %9s: Row %3d is crashed", - llstr(page_pos, llbuff), row); + llstr(page, llbuff), row); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) DBUG_RETURN(1); continue; @@ -1621,7 +1622,7 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, ha_checksum checksum= (*share->calc_checksum)(info, record); if (info->cur_row.checksum != (checksum & 255)) _ma_check_print_error(param, "Page %9s: Row %3d has wrong checksum", - llstr(page_pos, llbuff), row); + llstr(page, llbuff), row); param->glob_crc+= checksum; } if (info->cur_row.extents_count) @@ -1631,8 +1632,8 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, /* Check that bitmap has the right marker for the found extents */ for (i= 0 ; i < info->cur_row.extents_count ; i++) { - uint page, page_count, page_type; - page= uint5korr(extents); + uint extent_page, page_count, page_type; + extent_page= uint5korr(extents); page_count= uint2korr(extents+5) & ~START_EXTENT_BIT; extents+= ROW_EXTENT_SIZE; page_type= BLOB_PAGE; @@ -1646,19 +1647,17 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, Check the whole extent with one test and only do the loop if something is wrong (for exact error reporting) */ - for ( ; page_count--; page++) + for ( ; page_count--; extent_page++) { uint bitmap_pattern; - if (_ma_check_if_right_bitmap_type(info, page_type, page, + if (_ma_check_if_right_bitmap_type(info, page_type, extent_page, &bitmap_pattern)) { _ma_check_print_error(param, "Page %9s: Row: %3d has an extent with wrong information in bitmap: Page %9s Page_type: %d Bitmap: %d", - llstr(page_pos, llbuff), row, - llstr(page * share->bitmap.block_size, - llbuff2), - page_type, - bitmap_pattern); + llstr(page, llbuff), row, + llstr(extent_page, llbuff2), + page_type, bitmap_pattern); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) DBUG_RETURN(1); } @@ -1668,8 +1667,7 @@ static my_bool check_head_page(HA_CHECK *param, MARIA_HA *info, uchar *record, param->full_page_count+= info->cur_row.full_page_count; param->tail_count+= info->cur_row.tail_count; if (check_keys_in_record(param, info, extend, - ma_recordpos(page_pos/share->block_size, row), - record)) + ma_recordpos(page, row), record)) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -1685,6 +1683,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, { MARIA_SHARE *share= info->s; my_off_t pos; + ulonglong page; uchar *page_buff, *bitmap_buff, *data; char llbuff[22], llbuff2[22]; uint block_size= share->block_size; @@ -1705,10 +1704,11 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, full_page_count= tail_count= 0; param->full_page_count= param->tail_count= 0; param->used= param->link_used= 0; + param->splits= info->state->data_file_length / block_size; - for (pos= 0; + for (pos= 0, page= 0; pos < info->state->data_file_length; - pos+= block_size) + pos+= block_size, page++) { uint row_count, real_row_count, empty_space, page_type, bitmap_pattern; LINT_INIT(row_count); @@ -1719,19 +1719,19 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, _ma_scan_end_block_record(info); return -1; } - if (((pos / block_size) % share->bitmap.pages_covered) == 0) + if ((page % share->bitmap.pages_covered) == 0) { /* Bitmap page */ if (pagecache_read(share->pagecache, &info->s->bitmap.file, - (pos / block_size), 1, + page, 1, bitmap_buff, PAGECACHE_PLAIN_PAGE, PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == 0) { _ma_check_print_error(param, "Page %9s: Got error: %d when reading datafile", - llstr(pos, llbuff), my_errno); + llstr(page, llbuff), my_errno); goto err; } param->used+= block_size; @@ -1739,11 +1739,10 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, continue; } /* Skip pages marked as empty in bitmap */ - offset_page= (((pos / block_size) % share->bitmap.pages_covered) -1) * 3; + offset_page= ((page % share->bitmap.pages_covered) -1) * 3; offset= offset_page & 7; data= bitmap_buff + offset_page / 8; bitmap_pattern= uint2korr(data); - param->splits++; if (!((bitmap_pattern >> offset) & 7)) { param->empty+= block_size; @@ -1753,22 +1752,22 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, if (pagecache_read(share->pagecache, &info->dfile, - (pos / block_size), 1, + page, 1, page_buff, share->page_type, PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == 0) { _ma_check_print_error(param, "Page %9s: Got error: %d when reading datafile", - llstr(pos, llbuff), my_errno); + llstr(page, llbuff), my_errno); goto err; } page_type= page_buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK; if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE) { _ma_check_print_error(param, - "Page %9s: Found wrong page type %d", - llstr(pos, llbuff), page_type); + "Page: %9s Found wrong page type %d", + llstr(page, llbuff), page_type); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; continue; @@ -1782,20 +1781,22 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, case HEAD_PAGE: row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET]; empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET); - param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + - row_count * DIR_ENTRY_SIZE); + param->used+= block_size - empty_space; param->link_used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + row_count * DIR_ENTRY_SIZE); + if (empty_space < share->bitmap.sizes[3]) + param->lost+= empty_space; full_dir= row_count == MAX_ROWS_PER_PAGE; break; case TAIL_PAGE: row_count= ((uchar*) page_buff)[DIR_COUNT_OFFSET]; empty_space= uint2korr(page_buff + EMPTY_SPACE_OFFSET); - param->used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + - row_count * DIR_ENTRY_SIZE); + param->used+= block_size - empty_space; param->link_used+= (PAGE_HEADER_SIZE + PAGE_SUFFIX_SIZE + row_count * DIR_ENTRY_SIZE); full_dir= row_count == MAX_ROWS_PER_PAGE; + if (empty_space < share->bitmap.sizes[6]) + param->lost+= empty_space; break; case BLOB_PAGE: full_page_count++; @@ -1805,19 +1806,19 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, param->used+= block_size; break; } - if (_ma_check_bitmap_data(info, page_type, pos / block_size, + if (_ma_check_bitmap_data(info, page_type, page, full_dir ? 0 : empty_space, &bitmap_pattern)) { if (bitmap_pattern == ~(uint) 0) _ma_check_print_error(param, - "Page: %9s: Wrong bitmap for data on page", - llstr(pos, llbuff)); + "Page %9s: Wrong bitmap for data on page", + llstr(page, llbuff)); else _ma_check_print_error(param, "Page %9s: Wrong data in bitmap. Page_type: %d empty_space: %u Bitmap-bits: %d", - llstr(pos, llbuff), page_type, empty_space, - bitmap_pattern); + llstr(page, llbuff), page_type, + empty_space, bitmap_pattern); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; } @@ -1839,11 +1840,11 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, /* Verify that rest of bitmap is zero */ - if ((pos / block_size) % share->bitmap.pages_covered) + if (page % share->bitmap.pages_covered) { /* Not at end of bitmap */ uint bitmap_pattern; - offset_page= (((pos / block_size) % share->bitmap.pages_covered) -1) * 3; + offset_page= ((page % share->bitmap.pages_covered) -1) * 3; offset= offset_page & 7; data= bitmap_buff + offset_page / 8; bitmap_pattern= uint2korr(data); @@ -1853,10 +1854,12 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, data - 2))) { ulonglong bitmap_page; - bitmap_page= pos / block_size / share->bitmap.pages_covered; + bitmap_page= page / share->bitmap.pages_covered; bitmap_page*= share->bitmap.pages_covered; - _ma_check_print_error(param, "Bitmap at %s has pages reserved outside of data file length", + _ma_check_print_error(param, + "Bitmap at page %s has pages reserved outside of " + "data file length", llstr(bitmap_page, llbuff)); DBUG_EXECUTE("bitmap", _ma_print_bitmap(&share->bitmap, bitmap_buff, bitmap_page);); @@ -1874,9 +1877,6 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, llstr(param->tail_count, llbuff), llstr(tail_count, llbuff2)); - /* Update splits to avoid warning */ - share->state.split= param->splits; - info->state->del= param->del_blocks; return param->error_printed != 0; err: @@ -1910,6 +1910,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) } param->records= param->del_blocks= 0; param->used= param->link_used= param->splits= param->del_length= 0; + param->lost= 0; param->tmp_record_checksum= param->glob_crc= 0; param->err_count= 0; @@ -1953,7 +1954,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) param->record_checksum != param->tmp_record_checksum) { _ma_check_print_error(param, - "Key pointers and record positions doesn't match"); + "Key pointers and record positions doesn't match"); error=1; } else if (param->glob_crc != info->state->checksum && @@ -1961,7 +1962,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))) { _ma_check_print_warning(param, - "Record checksum is not the same as checksum stored in the index file"); + "Record checksum is not the same as checksum stored in the index file"); error=1; } else if (!extend) @@ -1973,7 +1974,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) !(share->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL))) { _ma_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records", - key+1); + key+1); error=1; } } @@ -1982,37 +1983,41 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) if (param->del_length != info->state->empty) { _ma_check_print_warning(param, - "Found %s deleted space. Should be %s", - llstr(param->del_length,llbuff2), - llstr(info->state->empty,llbuff)); + "Found %s deleted space. Should be %s", + llstr(param->del_length,llbuff2), + llstr(info->state->empty,llbuff)); } - if (param->used + param->empty + param->del_length != - info->state->data_file_length) - { - _ma_check_print_warning(param, - "Found %s record data and %s unused data and %s deleted data", - llstr(param->used, llbuff), - llstr(param->empty,llbuff2), - llstr(param->del_length,llbuff3)); - _ma_check_print_warning(param, - "Total %s Should be: %s", - llstr((param->used+param->empty+param->del_length), - llbuff), - llstr(info->state->data_file_length,llbuff2)); - } - if (param->del_blocks != info->state->del) - { - _ma_check_print_warning(param, - "Found %10s deleted blocks Should be: %s", - llstr(param->del_blocks,llbuff), - llstr(info->state->del,llbuff2)); - } - if (param->splits != share->state.split) + /* Skip following checks for BLOCK RECORD as they don't make any sence */ + if (share->data_file_type != BLOCK_RECORD) { - _ma_check_print_warning(param, - "Found %10s parts Should be: %s parts", - llstr(param->splits, llbuff), - llstr(share->state.split,llbuff2)); + if (param->used + param->empty + param->del_length != + info->state->data_file_length) + { + _ma_check_print_warning(param, + "Found %s record data and %s unused data and %s deleted data", + llstr(param->used, llbuff), + llstr(param->empty,llbuff2), + llstr(param->del_length,llbuff3)); + _ma_check_print_warning(param, + "Total %s Should be: %s", + llstr((param->used+param->empty + + param->del_length), llbuff), + llstr(info->state->data_file_length,llbuff2)); + } + if (param->del_blocks != info->state->del) + { + _ma_check_print_warning(param, + "Found %10s deleted blocks Should be: %s", + llstr(param->del_blocks,llbuff), + llstr(info->state->del,llbuff2)); + } + if (param->splits != share->state.split) + { + _ma_check_print_warning(param, + "Found %10s parts Should be: %s parts", + llstr(param->splits, llbuff), + llstr(share->state.split,llbuff2)); + } } if (param->testflag & T_INFO) { @@ -2044,18 +2049,20 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) printf("Records:%18s\n", "0"); } printf("Record blocks:%12s Delete blocks:%10s\n", - llstr(param->splits - param->del_blocks, llbuff), + llstr(param->splits - param->del_blocks, llbuff), llstr(param->del_blocks, llbuff2)); printf("Record data: %12s Deleted data: %10s\n", - llstr(param->used - param->link_used,llbuff), + llstr(param->used - param->link_used,llbuff), llstr(param->del_length, llbuff2)); - printf("Lost space: %12s Linkdata: %10s\n", - llstr(param->empty, llbuff),llstr(param->link_used, llbuff2)); + printf("Empty space: %12s Linkdata: %10s\n", + llstr(param->empty, llbuff),llstr(param->link_used, llbuff2)); + if (param->lost) + printf("Lost space: %12s", llstr(param->lost, llbuff)); } my_free((uchar*) record,MYF(0)); DBUG_RETURN (error); - err: +err: my_free((uchar*) record,MYF(0)); param->testflag|=T_RETRY_WITHOUT_QUICK; DBUG_RETURN(1); @@ -2180,6 +2187,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, if (initialize_variables_for_repair(param, &sort_info, &sort_param, info, rep_quick)) goto err; + if (share->now_transactional) + _ma_tmp_disable_logging_for_table(info, 0); new_header_length= ((param->testflag & T_UNPACK) ? 0L : share->pack.header_length); @@ -2423,11 +2432,11 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, { if (start_records != info->state->records) printf("Data records: %s\n", llstr(info->state->records,llbuff)); - if (sort_info.dupp) - _ma_check_print_warning(param, - "%s records have been removed", - llstr(sort_info.dupp,llbuff)); } + if (sort_info.dupp) + _ma_check_print_warning(param, + "%s records have been removed", + llstr(sort_info.dupp,llbuff)); got_error= 0; /* If invoked by external program that uses thr_lock */ @@ -2469,6 +2478,8 @@ err: */ write_log_record_for_repair(param, info); } + _ma_reenable_logging_for_table(info); + my_free(sort_param.rec_buff, MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); @@ -2799,7 +2810,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, if (!_ma_fetch_keypage(info, keyinfo, pagepos,PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS, buff, 0, 0)) { - report_keypage_fault(param, pagepos); + report_keypage_fault(param, info, pagepos); goto err; } if ((nod_flag=_ma_test_if_nod(share, buff)) || keyinfo->flag & HA_FULLTEXT) @@ -2952,6 +2963,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info, my_off_t pos; ulonglong page; uint block_size= share->block_size; + MARIA_FILE_BITMAP *bitmap= &share->bitmap; DBUG_ENTER("maria_zerofill_data"); /* This works only with BLOCK_RECORD files */ @@ -2989,7 +3001,13 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info, bzero(buff, block_size); break; case BLOB_PAGE: - bzero(buff, LSN_SIZE); + if (_ma_bitmap_get_page_bits(info, bitmap, page) == 0) + { + /* Unallocated page */ + bzero(buff, block_size); + } + else + bzero(buff, LSN_SIZE); break; case HEAD_PAGE: case TAIL_PAGE: @@ -3364,6 +3382,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, (size_t) param->sort_buffer_length)) { param->retry_repair=1; + _ma_check_print_error(param, "Create index by sort failed"); goto err; } DBUG_EXECUTE_IF("maria_flush_whole_log", @@ -3404,7 +3423,10 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, param->read_cache.end_of_file=sort_param.filepos; if (maria_write_data_suffix(&sort_info,1) || end_io_cache(&sort_info.new_info->rec_cache)) + { + _ma_check_print_error(param, "Got error when flushing row cache"); goto err; + } sort_info.new_info->opt_flag&= ~WRITE_CACHE_USED; if (param->testflag & T_SAFE_REPAIR) @@ -3412,14 +3434,20 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, /* Don't repair if we loosed more than one row */ if (info->state->records+1 < start_records) { - info->state->records=start_records; + _ma_check_print_error(param, + "Rows lost; Aborting because safe repair was " + "requested"); + info->state->records=start_records; goto err; } } /** @todo RECOVERY BUG seems misplaced in some cases */ if (_ma_flush_table_files_after_repair(param, info)) + { + _ma_check_print_error(param, "Got error when flushing caches"); goto err; + } sort_info.new_info->state->data_file_length= sort_param.filepos; if (sort_info.new_info != sort_info.info) @@ -3433,6 +3461,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, copy_data_file_state(&share->state, &save_state); new_file= -1; sort_info.new_info= info; + info->rec_cache.file= info->dfile.file; } share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ @@ -3451,6 +3480,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, sync_dir) || _ma_open_datafile(info, share, -1)) { + _ma_check_print_error(param, "Couldn't change to new data file"); goto err; } if (param->testflag & T_UNPACK) @@ -3513,11 +3543,11 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, { if (start_records != info->state->records) printf("Data records: %s\n", llstr(info->state->records,llbuff)); - if (sort_info.dupp) - _ma_check_print_warning(param, - "%s records have been removed", - llstr(sort_info.dupp,llbuff)); } + if (sort_info.dupp) + _ma_check_print_warning(param, + "%s records have been removed", + llstr(sort_info.dupp,llbuff)); got_error=0; if (&share->state.state != info->state) @@ -3953,11 +3983,12 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, if (sort_param[0].fix_datafile) { /* - Append some nuls to the end of a memory mapped file. Destroy the + Append some nulls to the end of a memory mapped file. Destroy the write cache. The master thread did already detach from the share by remove_io_thread() in sort.c:thr_find_all_keys(). */ - if (maria_write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) + if (maria_write_data_suffix(&sort_info,1) || + end_io_cache(&info->rec_cache)) goto err; if (param->testflag & T_SAFE_REPAIR) { @@ -4013,17 +4044,18 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, if (my_chsize(share->kfile.file, info->state->key_file_length, 0, MYF(0))) _ma_check_print_warning(param, - "Can't change size of indexfile, error: %d", my_errno); + "Can't change size of indexfile, error: %d", + my_errno); if (!(param->testflag & T_SILENT)) { if (start_records != info->state->records) printf("Data records: %s\n", llstr(info->state->records,llbuff)); - if (sort_info.dupp) - _ma_check_print_warning(param, - "%s records have been removed", - llstr(sort_info.dupp,llbuff)); } + if (sort_info.dupp) + _ma_check_print_warning(param, + "%s records have been removed", + llstr(sort_info.dupp,llbuff)); got_error=0; if (&share->state.state != info->state) @@ -5121,7 +5153,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param, a_length+=t_length; _ma_store_page_used(share, anc_buff, a_length); key_block->end_pos+=t_length; - if (a_length <= keyinfo->block_length) + if (a_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)) { VOID(_ma_move_key(keyinfo, key_block->lastkey, key)); key_block->last_length=a_length-t_length; @@ -5196,37 +5228,40 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param) old_file= row_info->dfile.file; /* This only affects static and dynamic row formats */ row_info->dfile.file= row_info->rec_cache.file; - if (sort_info->current_key) - { - key= key_info->lastkey + key_info->s->base.max_key_length; - if ((error=(*row_info->s->read_record)(row_info, sort_param->record, - key_info->cur_row.lastpos)) && + if (flush_io_cache(&row_info->rec_cache)) + DBUG_RETURN(1); + + key= key_info->lastkey + key_info->s->base.max_key_length; + if ((error=(*row_info->s->read_record)(row_info, sort_param->record, + key_info->cur_row.lastpos)) && error != HA_ERR_RECORD_DELETED) + { + _ma_check_print_error(param,"Can't read record to be removed"); + row_info->dfile.file= old_file; + DBUG_RETURN(1); + } + row_info->cur_row.lastpos= key_info->cur_row.lastpos; + + for (i=0 ; i < sort_info->current_key ; i++) + { + uint key_length= _ma_make_key(key_info, i, key, sort_param->record, + key_info->cur_row.lastpos); + if (_ma_ck_delete(key_info, i, key, key_length)) { - _ma_check_print_error(param,"Can't read record to be removed"); + _ma_check_print_error(param, + "Can't delete key %d from record to be removed", + i+1); row_info->dfile.file= old_file; DBUG_RETURN(1); } - - for (i=0 ; i < sort_info->current_key ; i++) - { - uint key_length= _ma_make_key(key_info, i, key, sort_param->record, - key_info->cur_row.lastpos); - if (_ma_ck_delete(key_info, i, key, key_length)) - { - _ma_check_print_error(param, - "Can't delete key %d from record to be removed", - i+1); - row_info->dfile.file= old_file; - DBUG_RETURN(1); - } - } - if (sort_param->calc_checksum) - param->glob_crc-=(*key_info->s->calc_check_checksum)(key_info, - sort_param->record); } - error= (flush_io_cache(&row_info->rec_cache) || - (*row_info->s->delete_record)(row_info, sort_param->record)); + if (sort_param->calc_checksum) + param->glob_crc-=(*key_info->s->calc_check_checksum)(key_info, + sort_param->record); + error= (*row_info->s->delete_record)(row_info, sort_param->record); + if (error) + _ma_check_print_error(param,"Got error %d when deleting record", + my_errno); row_info->dfile.file= old_file; /* restore actual value */ row_info->state->records--; DBUG_RETURN(error); @@ -6024,7 +6059,7 @@ static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info, if (info->scan.dir < info->scan.dir_end) { _ma_check_print_info(sort_info->param, - "Wrong directory on page: %s", + "Wrong directory on page %s", llstr(page, llbuff)); goto read_next_page; } @@ -6075,8 +6110,8 @@ read_next_page: if (my_errno == HA_ERR_WRONG_CRC) { _ma_check_print_info(sort_info->param, - "Wrong CRC on page at %s", - llstr(page * share->block_size, llbuff)); + "Wrong CRC on datapage at %s", + llstr(page, llbuff)); continue; } DBUG_RETURN(my_errno); @@ -6089,15 +6124,14 @@ read_next_page: (uint) (uchar) info->scan.page_buff[DIR_COUNT_OFFSET]) != 0) break; _ma_check_print_info(sort_info->param, - "Wrong head page at %s", - llstr(page * share->block_size, llbuff)); + "Wrong head page at page %s", + llstr(page, llbuff)); } else if (page_type >= MAX_PAGE_TYPE) { _ma_check_print_info(sort_info->param, - "Found wrong page type: %d at %s", - page_type, llstr(page * share->block_size, - llbuff)); + "Found wrong page type: %d at page %s", + page_type, llstr(page, llbuff)); } } @@ -6199,17 +6233,19 @@ static int write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info) /* Give error message why reading of key page failed */ -static void report_keypage_fault(HA_CHECK *param, my_off_t position) +static void report_keypage_fault(HA_CHECK *param, MARIA_HA *info, + my_off_t position) { char buff[11]; + uint32 block_size= info->s->block_size; if (my_errno == HA_ERR_CRASHED) _ma_check_print_error(param, - "Wrong base information on indexpage at filepos: %s", - llstr(position, buff)); + "Wrong base information on indexpage at page: %s", + llstr(position / block_size, buff)); else _ma_check_print_error(param, - "Can't read indexpage from filepos: %s, " + "Can't read indexpage from page: %s, " "error: %d", - llstr(position,buff), my_errno); + llstr(position / block_size, buff), my_errno); } diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 83457847d5b..7d3376cc4ec 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -150,7 +150,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, if (datafile_type == BLOCK_RECORD) { if (type == FIELD_SKIP_PRESPACE) - type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */ + type= column->type= FIELD_NORMAL; /* SKIP_PRESPACE not supported */ if (type == FIELD_NORMAL && column->length > FULL_PAGE_SIZE(maria_block_size)) { @@ -297,15 +297,17 @@ int maria_create(const char *name, enum data_file_type datafile_type, share.base.max_field_lengths= max_field_lengths; share.base.field_offsets= 0; /* for future */ - if (pack_reclength != INT_MAX32) - pack_reclength+= max_field_lengths + long_varchar_count; - if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { options|= HA_OPTION_CHECKSUM; min_pack_length++; pack_reclength++; } + if (pack_reclength < INT_MAX32) + pack_reclength+= max_field_lengths + long_varchar_count; + else + pack_reclength= INT_MAX32; + if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) @@ -741,6 +743,13 @@ int maria_create(const char *name, enum data_file_type datafile_type, /* Add length of packed fields + length */ share.base.pack_reclength+= share.base.max_field_lengths+3; + /* Adjust max_pack_length, to be used if we have short rows */ + if (share.base.max_pack_length < maria_block_size) + { + share.base.max_pack_length+= FLAG_SIZE; + if (ci->transactional) + share.base.max_pack_length+= TRANSID_SIZE * 2; + } } /* max_data_file_length and max_key_file_length are recalculated on open */ @@ -1208,7 +1217,8 @@ uint maria_get_pointer_length(ulonglong file_length, uint def) Fixed size, not null columns Fixed length, null fields - Variable length fields (CHAR, VARCHAR) + Numbers (zero fill fields) + Variable length fields (CHAR, VARCHAR) according to length Blobs For same kind of fields, keep fields in original order @@ -1225,10 +1235,8 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr) MARIA_COLUMNDEF *a= *a_ptr, *b= *b_ptr; enum en_fieldtype a_type, b_type; - a_type= ((a->type == FIELD_NORMAL || a->type == FIELD_CHECK) ? - FIELD_NORMAL : a->type); - b_type= ((b->type == FIELD_NORMAL || b->type == FIELD_CHECK) ? - FIELD_NORMAL : b->type); + a_type= (a->type == FIELD_CHECK) ? FIELD_NORMAL : a->type; + b_type= (b->type == FIELD_CHECK) ? FIELD_NORMAL : b->type; if (a_type == FIELD_NORMAL && !a->null_bit) { @@ -1244,6 +1252,13 @@ static int compare_columns(MARIA_COLUMNDEF **a_ptr, MARIA_COLUMNDEF **b_ptr) return -1; if (b_type == FIELD_NORMAL) return 1; + if (a_type == FIELD_SKIP_ZERO) + return -1; + if (b_type == FIELD_SKIP_ZERO) + return 1; + if (a->type != FIELD_BLOB && b->type != FIELD_BLOB) + if (a->length != b->length) + return sign((long) a->length - (long) b->length); if (a_type == FIELD_BLOB) return 1; if (b_type == FIELD_BLOB) diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 945ab176e38..cdc0b7f0b5e 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -130,7 +130,11 @@ int maria_delete(MARIA_HA *info,const uchar *record) DBUG_RETURN(0); err: - save_errno=my_errno; + save_errno= my_errno; + DBUG_ASSERT(save_errno); + if (!save_errno) + save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */ + mi_sizestore(lastpos, info->cur_row.lastpos); if (save_errno != HA_ERR_RECORD_CHANGED) { @@ -140,14 +144,12 @@ err: VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); info->update|=HA_STATE_WRITTEN; /* Buffer changed */ allow_break(); /* Allow SIGHUP & SIGINT */ - my_errno=save_errno; if (save_errno == HA_ERR_KEY_NOT_FOUND) { maria_print_error(share, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; } - - DBUG_RETURN(my_errno); + DBUG_RETURN(my_errno= save_errno); } /* maria_delete */ diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index cb33160bdf6..3b4c8215eac 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -1301,7 +1301,8 @@ ulong _ma_calc_total_blob_length(MARIA_HA *info, const uchar *record) blob != end; blob++) { - blob->length= _ma_calc_blob_length(blob->pack_length,record + blob->offset); + blob->length= _ma_calc_blob_length(blob->pack_length, + record + blob->offset); length+=blob->length; } return length; diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index 2044772284d..17166de8f61 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -589,6 +589,7 @@ int _ma_decrement_open_count(MARIA_HA *info) if (share->state.open_count > 0) { share->state.open_count--; + share->changed= 1; /* We have to update state */ if (!(share->temporary | share->base.born_transactional)) { mi_int2store(buff,share->state.open_count); diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 39489a168c6..e4dcb4cd83a 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -287,7 +287,6 @@ enum enum_translog_status translog_status= TRANSLOG_UNINITED; #define TRANSLOG_CLSN_LEN_BITS 0xC0 /* Mask to get compressed LSN length */ - #include <my_atomic.h> /* an array that maps id of a MARIA_SHARE to this MARIA_SHARE */ static MARIA_SHARE **id_to_share= NULL; @@ -715,10 +714,14 @@ static void translog_check_cursor(struct st_buffer_cursor *cursor void translog_stop_writing() { + DBUG_ENTER("translog_stop_writing"); + DBUG_PRINT("error", ("errno: %d my_errno: %d", errno, my_errno)); translog_status= (translog_status == TRANSLOG_SHUTDOWN ? TRANSLOG_UNINITED : TRANSLOG_READONLY); log_descriptor.open_flags= O_BINARY | O_RDONLY; + DBUG_ASSERT(0); + DBUG_VOID_RETURN; } @@ -1165,7 +1168,6 @@ end: } - /* @brief remove file mark "in progress" (for multi-group records) @@ -2238,7 +2240,6 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer) (ulong) buffer->size)); translog_buffer_lock_assert_owner(buffer); - translog_wait_for_writers(buffer); if (buffer->overlay && buffer->overlay->file == buffer->file && @@ -2299,9 +2300,11 @@ static my_bool translog_buffer_flush(struct st_translog_buffer *buffer) PAGECACHE_PIN_LEFT_UNPINNED, 0, LSN_IMPOSSIBLE)) { - DBUG_PRINT("error", ("Can't write page (%lu,0x%lx) to pagecache", - (ulong) buffer->file, - (ulong) (LSN_OFFSET(buffer->offset)+ i))); + DBUG_PRINT("error", + ("Can't write page (%lu,0x%lx) to pagecache, error: %d", + (ulong) buffer->file, + (ulong) (LSN_OFFSET(buffer->offset)+ i), + my_errno)); translog_stop_writing(); DBUG_RETURN(1); } @@ -2489,7 +2492,6 @@ translog_check_sector_protection(uchar *page, TRANSLOG_FILE *file) @param page_no The page number (<offset>/<page length>) @param data_ptr Read callback data pointer (pointer to TRANSLOG_FILE) - @todo: add turning loghandler to read-only mode after merging with that patch. @@ -4021,7 +4023,6 @@ translog_buffer_increase_writers(struct st_translog_buffer *buffer) buffer target buffer */ - static void translog_buffer_decrease_writers(struct st_translog_buffer *buffer) { DBUG_ENTER("translog_buffer_decrease_writers"); @@ -4157,7 +4158,7 @@ translog_write_variable_record_chunk3_page(struct st_translog_parts *parts, 1 Error */ -static my_bool translog_advance_pointer(uint pages, uint16 last_page_data) +static my_bool translog_advance_pointer(int pages, uint16 last_page_data) { translog_size_t last_page_offset= (log_descriptor.page_overhead + last_page_data); @@ -4174,6 +4175,21 @@ static my_bool translog_advance_pointer(uint pages, uint16 last_page_data) (uint) last_page_data)); translog_lock_assert_owner(); + if (pages == -1) + { + /* + It is special case when we advance the pointer on the same page. + It can happened when we write last part of multi-group record. + */ + DBUG_ASSERT(last_page_data + log_descriptor.bc.current_page_fill <= + TRANSLOG_PAGE_SIZE); + offset= last_page_data; + last_page_offset= log_descriptor.bc.current_page_fill + last_page_data; + goto end; + } + DBUG_PRINT("info", ("last_page_offset %lu", (ulong) last_page_offset)); + DBUG_ASSERT(last_page_offset <= TRANSLOG_PAGE_SIZE); + /* The loop will be executed 1-3 times. Usually we advance the pointer to fill only the current buffer (if we have more then 1/2 of @@ -4258,14 +4274,15 @@ static my_bool translog_advance_pointer(uint pages, uint16 last_page_data) DBUG_RETURN(1); offset-= min_offset; } + DBUG_PRINT("info", ("drop write_counter")); + log_descriptor.bc.write_counter= 0; + log_descriptor.bc.previous_offset= 0; +end: log_descriptor.bc.ptr+= offset; log_descriptor.bc.buffer->size+= offset; translog_buffer_increase_writers(log_descriptor.bc.buffer); log_descriptor.horizon+= offset; /* offset increasing */ log_descriptor.bc.current_page_fill= last_page_offset; - DBUG_PRINT("info", ("drop write_counter")); - log_descriptor.bc.write_counter= 0; - log_descriptor.bc.previous_offset= 0; DBUG_PRINT("info", ("NewP buffer #%u: 0x%lx chaser: %d Size: %lu (%lu) " "offset: %u last page: %u", (uint) log_descriptor.bc.buffer->buffer_no, @@ -4285,7 +4302,6 @@ static my_bool translog_advance_pointer(uint pages, uint16 last_page_data) } - /* Get page rest @@ -4435,7 +4451,7 @@ translog_write_variable_record_1group(LSN *lsn, (log_descriptor.page_capacity_chunk_2 - 1), record_rest, parts->record_length)); /* record_rest + 3 is chunk type 3 overhead + record_rest */ - rc|= translog_advance_pointer(full_pages + additional_chunk3_page, + rc|= translog_advance_pointer((int)(full_pages + additional_chunk3_page), (record_rest ? record_rest + 3 : 0)); log_descriptor.bc.buffer->last_lsn= *lsn; @@ -4460,7 +4476,6 @@ translog_write_variable_record_1group(LSN *lsn, /* fill the pages */ translog_write_parts_on_page(&horizon, &cursor, first_page, parts); - DBUG_PRINT("info", ("absolute horizon: (%lu,0x%lx) local: (%lu,0x%lx)", LSN_IN_PARTS(log_descriptor.horizon), LSN_IN_PARTS(horizon))); @@ -4959,7 +4974,7 @@ translog_write_variable_record_mgroup(LSN *lsn, (ulong)(parts->record_length - (first_page - 1 + buffer_rest) - done))); - rc|= translog_advance_pointer(full_pages, 0); + rc|= translog_advance_pointer((int)full_pages, 0); rc|= translog_unlock(); @@ -5104,8 +5119,10 @@ translog_write_variable_record_mgroup(LSN *lsn, (ulong) full_pages * log_descriptor.page_capacity_chunk_2, chunk3_pages, (uint) chunk3_size, (uint) record_rest)); - rc= translog_advance_pointer(full_pages + chunk3_pages + - (chunk0_pages - 1), + rc= translog_advance_pointer((int)(full_pages + chunk3_pages + + (chunk0_pages - 1)) + + (full_pages + chunk3_pages + chunk0_pages + + chunk2_page == 1? -1 : 0), record_rest + header_fixed_part + (groups.elements - ((page_capacity - @@ -5573,7 +5590,6 @@ my_bool translog_write_record(LSN *lsn, DBUG_RETURN(1); } - if (tbl_info) { MARIA_SHARE *share= tbl_info->s; @@ -7526,7 +7542,7 @@ my_bool translog_purge_at_flush() if (unlikely(translog_status == TRANSLOG_READONLY)) { - DBUG_PRINT("info", ("The log is read onlyu => exit")); + DBUG_PRINT("info", ("The log is read only => exit")); DBUG_RETURN(0); } @@ -7639,4 +7655,3 @@ void translog_set_file_size(uint32 size) } DBUG_VOID_RETURN; } - diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 2d0513fd5a8..00aff46aafb 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -685,7 +685,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) disk_pos=_ma_columndef_read(disk_pos,&share->columndef[i]); share->columndef[i].pack_type=0; share->columndef[i].huff_tree=0; - if (share->columndef[i].type == (int) FIELD_BLOB) + if (share->columndef[i].type == FIELD_BLOB) { share->blobs[j].pack_length= share->columndef[i].length-portable_sizeof_char_ptr;; @@ -693,7 +693,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) j++; } } - share->columndef[i].type=(int) FIELD_LAST; /* End marker */ + share->columndef[i].type= FIELD_LAST; /* End marker */ disk_pos= _ma_column_nr_read(disk_pos, share->column_nr, share->base.fields); diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index cbd6ddcae76..86d4bd7dd35 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -145,7 +145,8 @@ int _ma_write_keypage(register MARIA_HA *info, lock, lock == PAGECACHE_LOCK_LEFT_WRITELOCKED ? PAGECACHE_PIN_LEFT_PINNED : - PAGECACHE_PIN, + (lock == PAGECACHE_LOCK_WRITE_UNLOCK ? + PAGECACHE_UNPIN : PAGECACHE_PIN), PAGECACHE_WRITE_DELAY, &page_link.link, LSN_IMPOSSIBLE); @@ -157,8 +158,7 @@ int _ma_write_keypage(register MARIA_HA *info, push_dynamic(&info->pinned_pages, (void*) &page_link); } DBUG_RETURN(res); - -} /* maria_write_keypage */ +} /* @@ -326,7 +326,11 @@ my_off_t _ma_new(register MARIA_HA *info, int level, (*page_link)->unlock= PAGECACHE_LOCK_WRITE_UNLOCK; (*page_link)->write_lock= PAGECACHE_LOCK_WRITE; - (*page_link)->changed= 0; + /* + We have to mark it changed as _ma_flush_pending_blocks() uses + 'changed' to know if we used the page cache or not + */ + (*page_link)->changed= 1; push_dynamic(&info->pinned_pages, (void*) *page_link); *page_link= dynamic_element(&info->pinned_pages, info->pinned_pages.elements-1, diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 98a11f2e677..4b0dada3a6b 100755 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2053,9 +2053,11 @@ restart: link_to_file_list(pagecache, block, file, (my_bool)(block->hash_link ? 1 : 0)); PCBLOCK_INFO(block); - block->status= error? PCBLOCK_ERROR : 0; + block->status= error ? PCBLOCK_ERROR : 0; #ifndef DBUG_OFF block->type= PAGECACHE_EMPTY_PAGE; + if (error) + my_debug_put_break_here(); #endif block->hash_link= hash_link; page_status= PAGE_TO_BE_READ; @@ -2239,8 +2241,8 @@ static my_bool get_wrlock(PAGECACHE *pagecache, file.file != block->hash_link->file.file || pageno != block->hash_link->pageno) { - DBUG_PRINT("info", ("the block 0x%lx changed => need retry" - "status %x files %d != %d or pages %d !=%d", + DBUG_PRINT("info", ("the block 0x%lx changed => need retry " + "status: %x files %d != %d or pages %d != %d", (ulong)block, block->status, file.file, block->hash_link->file.file, pageno, block->hash_link->pageno)); @@ -2446,7 +2448,10 @@ static void read_block(PAGECACHE *pagecache, pagecache->readwrite_flags); pagecache_pthread_mutex_lock(&pagecache->cache_lock); if (error) + { block->status|= PCBLOCK_ERROR; + my_debug_put_break_here(); + } else { block->status|= PCBLOCK_READ; @@ -2457,6 +2462,7 @@ static void read_block(PAGECACHE *pagecache, { DBUG_PRINT("error", ("read callback problem")); block->status|= PCBLOCK_ERROR; + my_debug_put_break_here(); } } DBUG_PRINT("read_block", @@ -2608,6 +2614,7 @@ void pagecache_unlock(PAGECACHE *pagecache, /* if we lock for write we must link the block to changed blocks */ DBUG_ASSERT((block->status & PCBLOCK_DIRECT_W) == 0 || (lock == PAGECACHE_LOCK_WRITE_UNLOCK || + lock == PAGECACHE_LOCK_WRITE_TO_READ || lock == PAGECACHE_LOCK_LEFT_WRITELOCKED)); /* if was_changed then status should be PCBLOCK_DIRECT_W or marked @@ -2616,7 +2623,8 @@ void pagecache_unlock(PAGECACHE *pagecache, DBUG_ASSERT(!was_changed || (block->status & PCBLOCK_DIRECT_W) || (block->status & PCBLOCK_CHANGED)); if ((block->status & PCBLOCK_DIRECT_W) && - (lock == PAGECACHE_LOCK_WRITE_UNLOCK)) + (lock == PAGECACHE_LOCK_WRITE_UNLOCK || + lock == PAGECACHE_LOCK_WRITE_TO_READ)) { if (!(block->status & PCBLOCK_CHANGED) && was_changed) link_to_changed_list(pagecache, block); @@ -2737,7 +2745,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, LSN lsn, my_bool was_changed) { DBUG_ENTER("pagecache_unlock_by_link"); - DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s", + DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s", (ulong) block, (uint) block->hash_link->file.file, (ulong) block->hash_link->pageno, was_changed, @@ -2790,6 +2798,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, /* if we lock for write we must link the block to changed blocks */ DBUG_ASSERT((block->status & PCBLOCK_DIRECT_W) == 0 || (lock == PAGECACHE_LOCK_WRITE_UNLOCK || + lock == PAGECACHE_LOCK_WRITE_TO_READ || lock == PAGECACHE_LOCK_LEFT_WRITELOCKED)); /* If was_changed then status should be PCBLOCK_DIRECT_W or marked @@ -2798,7 +2807,8 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, DBUG_ASSERT(!was_changed || (block->status & PCBLOCK_DIRECT_W) || (block->status & PCBLOCK_CHANGED)); if ((block->status & PCBLOCK_DIRECT_W) && - (lock == PAGECACHE_LOCK_WRITE_UNLOCK)) + (lock == PAGECACHE_LOCK_WRITE_UNLOCK || + lock == PAGECACHE_LOCK_WRITE_TO_READ)) { if (!(block->status & PCBLOCK_CHANGED) && was_changed) link_to_changed_list(pagecache, block); @@ -2844,7 +2854,7 @@ void pagecache_unpin_by_link(PAGECACHE *pagecache, LSN lsn) { DBUG_ENTER("pagecache_unpin_by_link"); - DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu", + DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu", (ulong) block, (uint) block->hash_link->file.file, (ulong) block->hash_link->pageno)); @@ -3177,6 +3187,7 @@ restart: if (error) { block->status|= PCBLOCK_ERROR; + my_debug_put_break_here(); goto err; } } @@ -3407,6 +3418,7 @@ restart: { if (block->status & PCBLOCK_ERROR) { + my_debug_put_break_here(); DBUG_PRINT("warning", ("Writing on page with error")); } else @@ -3431,6 +3443,7 @@ restart: { DBUG_PRINT("error", ("read callback problem")); block->status|= PCBLOCK_ERROR; + my_debug_put_break_here(); } KEYCACHE_DBUG_PRINT("key_cache_insert", ("Page injection")); @@ -3488,7 +3501,10 @@ restart: *page_link= block; if (block->status & PCBLOCK_ERROR) + { error= 1; + my_debug_put_break_here(); + } dec_counter_for_resize_op(pagecache); @@ -3692,6 +3708,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, if (error) { block->status|= PCBLOCK_ERROR; + my_debug_put_break_here(); if (!*first_errno) *first_errno= my_errno ? my_errno : -1; rc|= PCFLUSH_ERROR; @@ -3930,7 +3947,7 @@ restart: */ if ((rc|= flush_cached_blocks(pagecache, file, cache, end, type, &error)) & - PCFLUSH_ERROR) + (PCFLUSH_ERROR | PCFLUSH_PINNED)) last_errno=error; DBUG_PRINT("info", ("restarting...")); /* @@ -3965,7 +3982,8 @@ restart: if (pos != cache) { if ((rc|= flush_cached_blocks(pagecache, file, cache, pos, type, - &error)) & PCFLUSH_ERROR) + &error)) & + (PCFLUSH_ERROR | PCFLUSH_PINNED)) last_errno= error; } /* Wait until list of blocks in switch is empty */ diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c index cc73431dbf8..10cb82e46f7 100644 --- a/storage/maria/ma_pagecrc.c +++ b/storage/maria/ma_pagecrc.c @@ -13,7 +13,7 @@ @return crc of the page without special values */ -static uint32 maria_page_crc(ulong start, uchar *data, uint length) +static uint32 maria_page_crc(uint32 start, uchar *data, uint length) { uint32 crc= crc32(start, data, length); @@ -73,7 +73,7 @@ static my_bool maria_page_crc_check(uchar *page, } DBUG_RETURN(0); } - new_crc= maria_page_crc(page_no, page, data_length); + new_crc= maria_page_crc(page_no & UINT_MAX32, page, data_length); DBUG_ASSERT(new_crc != no_crc_val); res= test(new_crc != crc); if (res) @@ -103,7 +103,7 @@ my_bool maria_page_crc_set_normal(uchar *page, { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; int data_length= share->block_size - CRC_SIZE; - uint32 crc= maria_page_crc(page_no, page, data_length); + uint32 crc= maria_page_crc(page_no & UINT_MAX32, page, data_length); DBUG_ENTER("maria_page_crc_set"); DBUG_PRINT("info", ("Page %lu crc: %lu", (ulong) page_no, (ulong)crc)); @@ -129,9 +129,8 @@ my_bool maria_page_crc_set_index(uchar *page, { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; int data_length= _ma_get_page_used(share, page); - uint32 crc= maria_page_crc(page_no, page, data_length); + uint32 crc= maria_page_crc(page_no & UINT_MAX32, page, data_length); DBUG_ENTER("maria_page_crc_set"); - DBUG_PRINT("info", ("Page %lu crc: %lu", (ulong) page_no, (ulong) crc)); DBUG_ASSERT((uint)data_length <= share->block_size - CRC_SIZE); @@ -160,7 +159,7 @@ my_bool maria_page_crc_check_data(uchar *page, uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; - return (maria_page_crc_check(page, page_no, share, + return (maria_page_crc_check(page, page_no & UINT_MAX32, share, MARIA_NO_CRC_NORMAL_PAGE, share->block_size - CRC_SIZE)); } @@ -182,7 +181,7 @@ my_bool maria_page_crc_check_bitmap(uchar *page, uchar *data_ptr) { MARIA_SHARE *share= (MARIA_SHARE *)data_ptr; - return (maria_page_crc_check(page, page_no, share, + return (maria_page_crc_check(page, page_no & UINT_MAX32, share, MARIA_NO_CRC_BITMAP_PAGE, share->block_size - CRC_SIZE)); } @@ -210,7 +209,7 @@ my_bool maria_page_crc_check_index(uchar *page, DBUG_PRINT("error", ("Wrong page length: %u", length)); return (my_errno= HA_ERR_WRONG_CRC); } - return maria_page_crc_check(page, page_no, share, + return maria_page_crc_check(page, page_no & UINT_MAX32, share, MARIA_NO_CRC_NORMAL_PAGE, length); } diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 7e6255f0387..f2b257378cf 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -174,7 +174,7 @@ void tprint(FILE *trace_file __attribute__ ((unused)), if (procent_printed) { procent_printed= 0; - fputc('\n', trace_file ? trace_file : stderr); + fputc('\n', trace_file); } vfprintf(trace_file, format, args); } @@ -190,13 +190,22 @@ void eprint(FILE *trace_file __attribute__ ((unused)), va_list args; va_start(args, format); DBUG_PRINT("error", ("%s", format)); + if (!trace_file) + trace_file= stderr; + 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); + fputc('\n', trace_file); + } + vfprintf(trace_file , format, args); + fputc('\n', trace_file); + if (trace_file != stderr) + { + va_start(args, format); + my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args); } - vfprintf(trace_file ? trace_file : stderr, format, args); va_end(args); } @@ -411,7 +420,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, else if (uncommitted_trans > 0) { eprint(tracef, "***WARNING: %u uncommitted transactions; some tables may" - " be left inconsistent!***\n", uncommitted_trans); + " be left inconsistent!***", uncommitted_trans); recovery_warnings++; } @@ -517,7 +526,7 @@ static int display_and_apply_record(const LOG_DESC *log_desc, return 1; } if ((error= (*log_desc->record_execute_in_redo_phase)(rec))) - eprint(tracef, "Got error %d when executing record %s\n", + eprint(tracef, "Got error %d when executing record %s", my_errno, log_desc->name); return error; } @@ -548,7 +557,7 @@ prototype_redo_exec_hook(LONG_TRANSACTION_ID) llstr(long_trid, llbuf); 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", + " committed nor rollback (undo_lsn: (%lu,0x%lx))", llbuf, sid, LSN_IN_PARTS(ulsn)); goto err; } @@ -656,7 +665,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } name= (char *)log_record_buffer.str; @@ -667,7 +676,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) */ if (close_one_table(name, rec->lsn)) { - eprint(tracef, "Table '%s' got error %d on close\n", name, my_errno); + eprint(tracef, "Table '%s' got error %d on close", name, my_errno); ALERT_USER(); goto end; } @@ -679,7 +688,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) /* check that we're not already using it */ if (share->reopen != 1) { - eprint(tracef, "Table '%s is already open (reopen=%u)\n", + eprint(tracef, "Table '%s is already open (reopen=%u)", name, share->reopen); ALERT_USER(); goto end; @@ -708,7 +717,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) } if (maria_is_crashed(info)) { - eprint(tracef, "Table '%s' is crashed, can't recreate it\n", name); + eprint(tracef, "Table '%s' is crashed, can't recreate it", name); ALERT_USER(); goto end; } @@ -743,7 +752,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) /** @todo handle symlinks */ if (data_file_name[0] || index_file_name[0]) { - eprint(tracef, "Table '%s' DATA|INDEX DIRECTORY clauses are not handled\n", + eprint(tracef, "Table '%s' DATA|INDEX DIRECTORY clauses are not handled", name); goto end; } @@ -757,14 +766,14 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) if ((kfile= my_create_with_symlink(linkname_ptr, filename, 0, create_mode, MYF(MY_WME|create_flag))) < 0) { - eprint(tracef, "Failed to create index file\n"); + eprint(tracef, "Failed to create index file"); 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))) { - eprint(tracef, "Failed to write to index file\n"); + eprint(tracef, "Failed to write to index file"); goto end; } if (!(flags & HA_DONT_TOUCH_DATA)) @@ -778,7 +787,7 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) MYF(MY_WME | create_flag))) < 0) || my_close(dfile, MYF(MY_WME))) { - eprint(tracef, "Failed to create data file\n"); + eprint(tracef, "Failed to create data file"); goto end; } /* @@ -790,7 +799,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)) { - eprint(tracef, "Failed to open new table or write to data file\n"); + eprint(tracef, "Failed to open new table or write to data file"); goto end; } } @@ -820,7 +829,7 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } old_name= (char *)log_record_buffer.str; @@ -957,13 +966,13 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE) tprint(tracef, ", renaming '%s'", old_name); if (maria_rename(old_name, new_name)) { - eprint(tracef, "Failed to rename table\n"); + eprint(tracef, "Failed to rename table"); goto end; } info= maria_open(new_name, O_RDONLY, 0); if (info == NULL) { - eprint(tracef, "Failed to open renamed table\n"); + eprint(tracef, "Failed to open renamed table"); goto end; } if (_ma_update_create_rename_lsn(info->s, rec->lsn, TRUE)) @@ -977,7 +986,7 @@ drop: tprint(tracef, ", only dropping '%s'", old_name); if (maria_delete_table(old_name)) { - eprint(tracef, "Failed to drop table\n"); + eprint(tracef, "Failed to drop table"); goto end; } error= 0; @@ -1068,7 +1077,7 @@ prototype_redo_exec_hook(REDO_DROP_TABLE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } name= (char *)log_record_buffer.str; @@ -1106,7 +1115,7 @@ prototype_redo_exec_hook(REDO_DROP_TABLE) tprint(tracef, ", dropping '%s'", name); if (maria_delete_table(name)) { - eprint(tracef, "Failed to drop table\n"); + eprint(tracef, "Failed to drop table"); goto end; } } @@ -1147,7 +1156,7 @@ prototype_redo_exec_hook(FILE_ID) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } sid= fileid_korr(log_record_buffer.str); @@ -1158,7 +1167,7 @@ prototype_redo_exec_hook(FILE_ID) prepare_table_for_close(info, rec->lsn); if (maria_close(info)) { - eprint(tracef, "Failed to close table\n"); + eprint(tracef, "Failed to close table"); goto end; } all_tables[sid].info= NULL; @@ -1331,14 +1340,14 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD) enlarge_buffer(rec); if (log_record_buffer.str == NULL) { - eprint(tracef, "Failed to read allocate buffer for record\n"); + eprint(tracef, "Failed to read allocate buffer for record"); goto end; } if (translog_read_record(rec->lsn, 0, rec->record_length, log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } buff= log_record_buffer.str; @@ -1373,7 +1382,7 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } buff= log_record_buffer.str; @@ -1409,7 +1418,7 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_BLOBS) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } buff= log_record_buffer.str; @@ -1469,7 +1478,7 @@ prototype_redo_exec_hook(REDO_FREE_BLOCKS) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } @@ -1528,7 +1537,7 @@ prototype_redo_exec_hook(REDO_INDEX) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } @@ -1554,7 +1563,7 @@ prototype_redo_exec_hook(REDO_INDEX_NEW_PAGE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); goto end; } @@ -1618,7 +1627,7 @@ prototype_redo_exec_hook(UNDO_ROW_INSERT) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1655,7 +1664,7 @@ prototype_redo_exec_hook(UNDO_ROW_DELETE) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1689,7 +1698,7 @@ prototype_redo_exec_hook(UNDO_ROW_UPDATE) HA_CHECKSUM_STORE_SIZE, buff, NULL) != HA_CHECKSUM_STORE_SIZE) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } share->state.state.checksum+= ha_checksum_korr(buff); @@ -1729,7 +1738,7 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } to= log_record_buffer.str + LSN_STORE_SIZE + FILEID_STORE_SIZE + @@ -1851,7 +1860,7 @@ prototype_redo_exec_hook(CLR_END) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } logpos= (log_record_buffer.str + LSN_STORE_SIZE + FILEID_STORE_SIZE + @@ -1939,7 +1948,7 @@ prototype_undo_exec_hook(UNDO_ROW_INSERT) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } record_ptr= log_record_buffer.str; @@ -1977,7 +1986,7 @@ prototype_undo_exec_hook(UNDO_ROW_DELETE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } @@ -2013,7 +2022,7 @@ prototype_undo_exec_hook(UNDO_ROW_UPDATE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } @@ -2058,7 +2067,7 @@ prototype_undo_exec_hook(UNDO_KEY_INSERT) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } @@ -2104,7 +2113,7 @@ prototype_undo_exec_hook(UNDO_KEY_DELETE) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } @@ -2150,7 +2159,7 @@ prototype_undo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT) log_record_buffer.str, NULL) != rec->record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return 1; } @@ -2234,7 +2243,7 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) if (len == RECHEADER_READ_ERROR) { - eprint(tracef, "Failed to read header of the first record.\n"); + eprint(tracef, "Failed to read header of the first record."); return 1; } if (translog_scanner_init(lsn, 1, &scanner, 1)) @@ -2530,7 +2539,7 @@ static int run_undo_phase(uint uncommitted) display_record_position(log_desc, &rec, 0); if (log_desc->record_execute_in_undo_phase(&rec, trn)) { - eprint(tracef, "Got error %d when executing undo %s\n", my_errno, + eprint(tracef, "Got error %d when executing undo %s", my_errno, log_desc->name); DBUG_RETURN(1); } @@ -2741,7 +2750,7 @@ static LSN parse_checkpoint_record(LSN lsn) log_record_buffer.str, NULL) != rec.record_length) { - eprint(tracef, "Failed to read record\n"); + eprint(tracef, "Failed to read record"); return LSN_ERROR; } @@ -2999,6 +3008,7 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, TRANSLOG_INTERNAL_PARTS + 1, log_array, log_data, NULL); } + /* if we disabled before writing the record, record wouldn't reach log */ share->now_transactional= FALSE; /* @@ -3025,6 +3035,10 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, void _ma_reenable_logging_for_table(MARIA_HA *info) { MARIA_SHARE *share= info->s; + + if (share->now_transactional == share->base.born_transactional) + return; + if ((share->now_transactional= share->base.born_transactional)) { /* diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c index c3a0447d7d1..c117dc844dc 100644 --- a/storage/maria/ma_update.c +++ b/storage/maria/ma_update.c @@ -196,7 +196,11 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec) err: DBUG_PRINT("error",("key: %d errno: %d",i,my_errno)); - save_errno=my_errno; + save_errno= my_errno; + DBUG_ASSERT(save_errno); + if (!save_errno) + save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */ + if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM || my_errno == HA_ERR_RECORD_FILE_FULL) { diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 90c8f7246fa..6f8bd53e713 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -317,6 +317,8 @@ err: err2: save_errno=my_errno; DBUG_ASSERT(save_errno); + if (!save_errno) + save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */ DBUG_PRINT("error", ("got error: %d", save_errno)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index fc24dc0dba3..90c4238ad91 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -41,7 +41,7 @@ static const char *set_collation_name, *opt_tmpdir; static CHARSET_INFO *set_collation; static int stopwords_inited= 0; static MY_TMPDIR maria_chk_tmpdir; -static my_bool opt_transaction_logging; +static my_bool opt_transaction_logging, opt_debug; static const char *type_names[]= { @@ -179,7 +179,8 @@ enum options_mc { OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE, - OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG + OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD, OPT_TRANSACTION_LOG, + OPT_SKIP_SAFEMALLOC }; static struct my_option my_long_options[] = @@ -289,6 +290,13 @@ static struct my_option my_long_options[] = {"silent", 's', "Only print errors. One can use two -s to make maria_chk very silent.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifndef DBUG_OFF +#ifdef SAFEMALLOC + {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, + "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG, + 0, 0, 0, 0, 0, 0}, +#endif +#endif {"sort-index", 'S', "Sort index blocks. This speeds up 'read-next' in applications.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -713,6 +721,12 @@ get_one_option(int optid, break; case '#': DBUG_SET_INITIAL(argument ? argument : "d:t:o,/tmp/maria_chk.trace"); + opt_debug= 1; + break; + case OPT_SKIP_SAFEMALLOC: +#ifdef SAFEMALLOC + sf_malloc_quick=1; +#endif break; case 'V': print_version(); @@ -813,6 +827,10 @@ static void get_options(register int *argc,register char ***argv) exit(1); } + if (!opt_debug) + { + DEBUGGER_OFF; /* Speed up things a bit */ + } if (init_tmpdir(&maria_chk_tmpdir, opt_tmpdir)) exit(1); @@ -906,7 +924,7 @@ static int maria_chk(HA_CHECK *param, char *filename) if (param->testflag & T_SORT_RECORDS) { _ma_check_print_error(param, - "Record format used by '%s' is is not yet supported with repair/check", + "Record format used by '%s' is is not yet supported with sort-records", filename); param->error_printed= 0; error= 1; @@ -1443,7 +1461,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) else buff[0]=0; if (param->testflag & T_VERBOSE) - printf("%11.0g %12s %10d", + printf("%11.0f %12s %10d", share->state.rec_per_key_part[keyseg_nr++], buff,keyinfo->block_length); VOID(putchar('\n')); @@ -1464,7 +1482,7 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) printf(" %-6ld%-3d %-21s", (long) keyseg->start+1,keyseg->length,buff); if (param->testflag & T_VERBOSE) - printf("%11.0g", share->state.rec_per_key_part[keyseg_nr++]); + printf("%11.0f", share->state.rec_per_key_part[keyseg_nr++]); VOID(putchar('\n')); } keyseg++; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index aae2827e423..b26babd2f54 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -952,9 +952,9 @@ typedef struct st_maria_block_info #define UPDATE_AUTO_INC 8 #define UPDATE_OPEN_COUNT 16 -#define USE_BUFFER_INIT (((1024L*1024L*10-MALLOC_OVERHEAD)/8192)*8192) +#define USE_BUFFER_INIT (((1024L*1024L*128-MALLOC_OVERHEAD)/8192)*8192) #define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) +#define SORT_BUFFER_INIT (1024L*1024L*64-MALLOC_OVERHEAD) #define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) #define fast_ma_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _ma_writeinfo((INFO),0) diff --git a/storage/maria/unittest/Makefile.am b/storage/maria/unittest/Makefile.am index 41be27bd014..89b700dc792 100644 --- a/storage/maria/unittest/Makefile.am +++ b/storage/maria/unittest/Makefile.am @@ -100,3 +100,5 @@ ma_pagecache_consist_64kWR_t_big_CPPFLAGS = $(ma_pagecache_common_cppflags) -DPA CLEANFILES = maria_log_control page_cache_test_file_1 \ maria_log.???????? +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/storage/maria/unittest/ma_pagecache_consist.c b/storage/maria/unittest/ma_pagecache_consist.c index e591e53a02e..a2c9ac92939 100644 --- a/storage/maria/unittest/ma_pagecache_consist.c +++ b/storage/maria/unittest/ma_pagecache_consist.c @@ -462,7 +462,7 @@ int main(int argc __attribute__((unused)), errno); exit(1); } - /*my_delete(file1_name, MYF(0));*/ + my_delete(file1_name, MYF(0)); my_end(0); DBUG_PRINT("info", ("file1 (%d) closed", file1.file)); diff --git a/storage/maria/unittest/ma_pagecache_single.c b/storage/maria/unittest/ma_pagecache_single.c index 359751c3c2a..1135051d8f2 100644 --- a/storage/maria/unittest/ma_pagecache_single.c +++ b/storage/maria/unittest/ma_pagecache_single.c @@ -613,7 +613,7 @@ int main(int argc __attribute__((unused)), if (my_close(file1.file, MYF(MY_WME))) exit(1); - /*my_delete(file1_name, MYF(0));*/ + my_delete(file1_name, MYF(0)); my_end(0); DBUG_PRINT("info", ("file1 (%d) closed", file1.file)); diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t index 7a778aa998a..5b10fb8f948 100755 --- a/storage/maria/unittest/ma_test_all-t +++ b/storage/maria/unittest/ma_test_all-t @@ -121,7 +121,9 @@ sub run_check_tests ["--key_multiple -P -S","-sm"] ); my @ma_test2_opt= ( ["-L -K -W -P","-sm"], ["-L -K -W -P -A","-sm"], - ["-L -K -P -R3 -m50 -b1000000","-sm"], + ["-L -K -W -P -b32768", "-sm"], + ["-L -K -W -P -M -T -c -b32768 -t4 -m300", "-sm"], + ["-L -K -P -R3 -m50 -b1000000", "-sm"], ["-L -B","-sm"], ["-D -B -c","-sm"], ["-m10000 -e4096 -K","-sm"], @@ -200,8 +202,8 @@ sub run_repair_tests() "$maria_path/maria_chk$suffix -se test2", "$maria_path/maria_chk$suffix -sr test2", "$maria_path/maria_chk$suffix -se test2", - "$maria_path/ma_test2$suffix $silent -c -t4 $row_type", - "$maria_path/maria_chk$suffix -sz test1", + "$maria_path/ma_test2$suffix $silent -c -t4 -b32768 $row_type", + "$maria_path/maria_chk$suffix -s --zerofill test1", "$maria_path/maria_chk$suffix -se test1" ); @@ -294,7 +296,7 @@ sub run_tests_on_warnings_and_errors # ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135\n # In the following a failure is a success and success is a failure $com= "$maria_path/ma_test2$suffix $silent -L -K -R1 -m2000 "; - $com.= ">ma_test2_message.txt 2>&1 && false"; + $com.= ">ma_test2_message.txt 2>&1"; ok($com, $verbose, 0, 1); ok("cat ma_test2_message.txt", $verbose, 0); ok("grep \"Error: 135\" ma_test2_message.txt > /dev/null", $verbose, 0); @@ -421,18 +423,19 @@ sub ok print "Running: '$com'\n"; } $output= `$com 2>&1`; - $err= $? >> 8; + $err= $?; if ($verbose) { print "$output\n"; } - if ($err == $expected_error) + if ((!$err && !$expected_error) || + (($err >> 8) == $expected_error && $expected_error)) { print "ok\n"; return 1; } print "not ok\n"; - $msg= "\nFailed test '$com' "; + $msg= "\nFailed test '$com' with error $err "; if ($iteration) { $msg.= "(loop iteration $iteration.) "; @@ -445,6 +448,5 @@ sub ok $msg.= "Was expecting errcode: $expected_error\n"; } warn $msg; - return 0; } |