diff options
-rwxr-xr-x | mysql-test/lib/v1/mysql-test-run.pl | 2 | ||||
-rw-r--r-- | mysql-test/suite/maria/r/maria-recovery2.result | 2 | ||||
-rw-r--r-- | mysys/stacktrace.c | 2 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 27 | ||||
-rw-r--r-- | storage/maria/ha_maria.h | 1 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 44 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 5 | ||||
-rw-r--r-- | storage/maria/ma_open.c | 6 | ||||
-rw-r--r-- | storage/maria/ma_recovery.c | 24 | ||||
-rw-r--r-- | storage/maria/ma_recovery_util.c | 10 | ||||
-rw-r--r-- | storage/maria/maria_chk.c | 12 | ||||
-rw-r--r-- | storage/maria/maria_def.h | 11 | ||||
-rw-r--r-- | storage/maria/maria_read_log.c | 9 | ||||
-rw-r--r-- | storage/maria/trnman.c | 1 |
14 files changed, 120 insertions, 36 deletions
diff --git a/mysql-test/lib/v1/mysql-test-run.pl b/mysql-test/lib/v1/mysql-test-run.pl index 174de23c530..ddd6e6d936a 100755 --- a/mysql-test/lib/v1/mysql-test-run.pl +++ b/mysql-test/lib/v1/mysql-test-run.pl @@ -3970,7 +3970,7 @@ sub mysqld_arguments ($$$$) { } } - mtr_add_arg($args, "%s--character-set-server-set=latin1", $prefix); + mtr_add_arg($args, "%s--character-set-server=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); diff --git a/mysql-test/suite/maria/r/maria-recovery2.result b/mysql-test/suite/maria/r/maria-recovery2.result index 88db518254f..bca6d0d7c74 100644 --- a/mysql-test/suite/maria/r/maria-recovery2.result +++ b/mysql-test/suite/maria/r/maria-recovery2.result @@ -136,7 +136,7 @@ ERROR HY000: Lost connection to MySQL server during query * recovery happens check table t_corrupted1 extended; Table Op Msg_type Msg_text -mysqltest.t_corrupted1 check warning Table is marked as crashed and last repair failed +mysqltest.t_corrupted1 check warning Last repair was aborted before finishing mysqltest.t_corrupted1 check status OK * testing that checksum after recovery is as expected Checksum-check diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 75fda93b56e..80122a4e70f 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -86,7 +86,7 @@ void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)), #if BACKTRACE_DEMANGLE -char __attribute__ ((weak)) *my_demangle(const char *mangled_name, int *status) +char __attribute__ ((weak)) *my_demangle(const char *mangled_name __attribute__((unused)), int *status __attribute__((unused))) { return NULL; } diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 5140ad17d74..da23f76f143 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -749,6 +749,9 @@ static int maria_create_trn_for_mysql(MARIA_HA *info) (uchar*) thd->query(), thd->query_length()); } + else + DBUG_PRINT("info", ("lock_type: %d trnman_flags: %u", + info->lock_type, trnman_get_flags(trn))); /* QQ */ #endif DBUG_RETURN(0); } @@ -1055,7 +1058,8 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) if (!maria_is_crashed(file) && (((param.testflag & T_CHECK_ONLY_CHANGED) && !(share->state.changed & (STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR)) && + STATE_CRASHED_ON_REPAIR | + STATE_IN_REPAIR)) && share->state.open_count == 0) || ((param.testflag & T_FAST) && (share->state.open_count == (uint) (share->global_changed ? 1 : @@ -1092,14 +1096,15 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) if (!error) { if ((share->state.changed & (STATE_CHANGED | - STATE_CRASHED_ON_REPAIR | + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR | STATE_CRASHED | STATE_NOT_ANALYZED)) || (param.testflag & T_STATISTICS) || maria_is_crashed(file)) { file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; pthread_mutex_lock(&share->intern_lock); - share->state.changed &= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR); + DBUG_PRINT("info", ("Reseting crashed state")); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); if (!(table->db_stat & HA_READ_ONLY)) error= maria_update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT | @@ -1513,8 +1518,9 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) { if ((share->state.changed & STATE_CHANGED) || maria_is_crashed(file)) { - share->state.changed &= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR); + DBUG_PRINT("info", ("Reseting crashed state")); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; } /* @@ -2360,6 +2366,15 @@ int ha_maria::delete_table(const char *name) } +/* This is mainly for temporary tables, so no logging necessary */ + +void ha_maria::drop_table(const char *name) +{ + (void) close(); + (void) maria_delete_table(name); +} + + int ha_maria::external_lock(THD *thd, int lock_type) { DBUG_ENTER("ha_maria::external_lock"); diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index c0f2041fddb..6ca1f6ca797 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -135,6 +135,7 @@ public: ulonglong *nb_reserved_values); int rename_table(const char *from, const char *to); int delete_table(const char *name); + void drop_table(const char *name); int check(THD * thd, HA_CHECK_OPT * check_opt); int analyze(THD * thd, HA_CHECK_OPT * check_opt); int repair(THD * thd, HA_CHECK_OPT * check_opt); diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 89701913c9a..2c29fa27278 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -1377,7 +1377,8 @@ void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr, uint freed_size= 0; uchar *dir, *end; DBUG_ENTER("_ma_compact_block_page"); - DBUG_PRINT("enter", ("rownr: %u", rownr)); + DBUG_PRINT("enter", ("rownr: %u min_read_from: %lu", rownr, + (ulong) min_read_from)); DBUG_ASSERT(max_entry > 0 && max_entry < (block_size - PAGE_HEADER_SIZE - PAGE_SUFFIX_SIZE) / DIR_ENTRY_SIZE); @@ -3407,13 +3408,14 @@ static my_bool allocate_and_write_block_record(MARIA_HA *info, DBUG_ASSERT(row->checksum == (info->s->calc_checksum)(info, record)); } } + DBUG_PRINT("info", ("rowid: %lu (%lu:%u) length: %u", (ulong) row->lastpos, + (ulong) ma_recordpos_to_page(row->lastpos), + ma_recordpos_to_dir_entry(row->lastpos), + row_pos.length)); if (write_block_record(info, (uchar*) 0, record, row, blocks, blocks->block->org_bitmap_value != 0, &row_pos, undo_lsn, 0)) - goto err; /* Error reading bitmap */ - DBUG_PRINT("exit", ("rowid: %lu (%lu:%u)", (ulong) row->lastpos, - (ulong) ma_recordpos_to_page(row->lastpos), - ma_recordpos_to_dir_entry(row->lastpos))); + goto err; /* Now let checkpoint happen but don't commit */ DBUG_EXECUTE_IF("maria_over_alloc_bitmap", sleep(1000);); DBUG_RETURN(0); @@ -4404,13 +4406,15 @@ crashed: 1 error */ -static my_bool read_long_data(MARIA_HA *info, uchar *to, ulong length, +static my_bool read_long_data2(MARIA_HA *info, uchar *to, ulong length, MARIA_EXTENT_CURSOR *extent, uchar **data, uchar **end_of_data) { - DBUG_ENTER("read_long_data"); + uint left_length; + left_length= (uint) (*end_of_data - *data); + DBUG_ENTER("read_long_data2"); DBUG_PRINT("enter", ("length: %lu left_length: %u", - length, (uint) (*end_of_data - *data))); + length, left_length)); DBUG_ASSERT(*data <= *end_of_data); /* @@ -4422,14 +4426,15 @@ static my_bool read_long_data(MARIA_HA *info, uchar *to, ulong length, This may change in the future, which is why we have the loop written the way it's written. */ - if (extent->first_extent && length > (ulong) (*end_of_data - *data)) + if (extent->first_extent && length > left_length) + { *end_of_data= *data; + left_length= 0; + } for(;;) { - uint left_length; - left_length= (uint) (*end_of_data - *data); - if (likely(left_length >= length)) + if (unlikely(left_length >= length)) { memcpy(to, *data, length); (*data)+= length; @@ -4441,10 +4446,25 @@ static my_bool read_long_data(MARIA_HA *info, uchar *to, ulong length, length-= left_length; if (!(*data= read_next_extent(info, extent, end_of_data))) break; + left_length= (uint) (*end_of_data - *data); } DBUG_RETURN(1); } +static inline my_bool read_long_data(MARIA_HA *info, uchar *to, ulong length, + MARIA_EXTENT_CURSOR *extent, + uchar **data, uchar **end_of_data) +{ + uint left_length= (uint) (*end_of_data - *data); + if (likely(left_length >= length)) + { + memcpy(to, *data, length); + (*data)+= length; + return 0; + } + return read_long_data2(info, to, length, extent, data, end_of_data); +} + /* Read a record from page (helper function for _ma_read_block_record()) diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 69b1566a2bb..dd26046767f 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -154,6 +154,9 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) if (maria_is_crashed_on_repair(info)) _ma_check_print_warning(param, "Table is marked as crashed and last repair failed"); + else if (maria_in_repair(info)) + _ma_check_print_warning(param, + "Last repair was aborted before finishing"); else if (maria_is_crashed(info)) _ma_check_print_warning(param, "Table is marked as crashed"); @@ -2242,7 +2245,7 @@ static my_bool protect_against_repair_crash(MARIA_HA *info, if ((param->testflag & T_NO_CREATE_RENAME_LSN) == 0) { /* this can be true only for a transactional table */ - maria_mark_crashed_on_repair(info); + maria_mark_in_repair(info); if (_ma_state_info_write(share, MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET | MA_STATE_INFO_WRITE_LOCK)) diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 98ccb3e23cd..a43513cfaa0 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -209,6 +209,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, const char *name, DBUG_RETURN(m_info); err: + DBUG_PRINT("error", ("error: %d", my_errno)); save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE; if ((save_errno == HA_ERR_CRASHED) || (save_errno == HA_ERR_CRASHED_ON_USAGE) || @@ -918,10 +919,15 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if (!(m_info= maria_clone_internal(share, name, mode, data_file))) goto err; + if (maria_is_crashed(m_info)) + DBUG_PRINT("warning", ("table is crashed: changed: %u", + share->state.changed)); + pthread_mutex_unlock(&THR_LOCK_maria); DBUG_RETURN(m_info); err: + DBUG_PRINT("error", ("error: %d errpos: %d", my_errno, errpos)); save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE; if ((save_errno == HA_ERR_CRASHED) || (save_errno == HA_ERR_CRASHED_ON_USAGE) || diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index e74f52b2ef6..5fe4e55cb48 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -1,4 +1,5 @@ /* Copyright (C) 2006, 2007 MySQL AB + Copyright (C) 2010 Monty Program 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 @@ -56,6 +57,7 @@ static ulong skipped_undo_phase; static ulonglong now; /**< for tracking execution time of phases */ static int (*save_error_handler_hook)(uint, const char *,myf); static uint recovery_warnings; /**< count of warnings */ +static uint recovery_found_crashed_tables; #define prototype_redo_exec_hook(R) \ static int exec_REDO_LOGREC_ ## R(const TRANSLOG_HEADER_BUFFER *rec) @@ -219,7 +221,7 @@ int maria_recovery_from_log(void) TRUE, TRUE, TRUE, &warnings_count); if (!res) { - if (warnings_count == 0) + if (warnings_count == 0 && recovery_found_crashed_tables == 0) tprint(trace_file, "SUCCESS\n"); else tprint(trace_file, "DOUBTFUL (%u warnings, check previous output)\n", @@ -265,7 +267,7 @@ int maria_apply_log(LSN from_lsn, enum maria_apply_log_way apply, DBUG_ASSERT(apply == MARIA_LOG_APPLY || !should_run_undo_phase); DBUG_ASSERT(!maria_multi_threaded); - recovery_warnings= 0; + recovery_warnings= recovery_found_crashed_tables= 0; maria_recovery_changed_data= 0; /* checkpoints can happen only if TRNs have been built */ DBUG_ASSERT(should_run_undo_phase || !take_checkpoints); @@ -456,7 +458,7 @@ end: log_record_buffer.str= NULL; log_record_buffer.length= 0; ma_checkpoint_end(); - *warnings_count= recovery_warnings; + *warnings_count= recovery_warnings + recovery_found_crashed_tables; if (recovery_message_printed != REC_MSG_NONE) { if (procent_printed) @@ -726,9 +728,12 @@ prototype_redo_exec_hook(REDO_CREATE_TABLE) maria_close(info); info= NULL; } - else /* one or two files absent, or header corrupted... */ - tprint(tracef, "Table '%s' can't be opened, probably does not exist\n", - name); + else + { + /* one or two files absent, or header corrupted... */ + tprint(tracef, "Table '%s' can't be opened (Error: %d)\n", + name, my_errno); + } /* if does not exist, or is older, overwrite it */ ptr= name + strlen(name) + 1; if ((flags= ptr[0] ? HA_DONT_TOUCH_DATA : 0)) @@ -1206,6 +1211,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) */ tprint(tracef, ", record is corrupted"); info= NULL; + recovery_warnings++; goto end; } tprint(tracef, "Table '%s', id %u", name, sid); @@ -1215,6 +1221,8 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) tprint(tracef, ", is absent (must have been dropped later?)" " or its header is so corrupted that we cannot open it;" " we skip it"); + if (my_errno != ENOENT) + recovery_found_crashed_tables++; error= 0; goto end; } @@ -1238,6 +1246,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) */ tprint(tracef, ", is not transactional. Ignoring open request"); error= -1; + recovery_warnings++; goto end; } if (cmp_translog_addr(lsn_of_file_id, share->state.create_rename_lsn) <= 0) @@ -1246,6 +1255,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) " LOGREC_FILE_ID's LSN (%lu,0x%lx), ignoring open request", LSN_IN_PARTS(share->state.create_rename_lsn), LSN_IN_PARTS(lsn_of_file_id)); + recovery_warnings++; error= -1; goto end; /* @@ -1257,6 +1267,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) { eprint(tracef, "Table '%s' is crashed, skipping it. Please repair it with" " maria_chk -r", share->open_file_name.str); + recovery_found_crashed_tables++; error= -1; /* not fatal, try with other tables */ goto end; /* @@ -1275,6 +1286,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) (kfile_len == MY_FILEPOS_ERROR)) { tprint(tracef, ", length unknown\n"); + recovery_warnings++; goto end; } if (share->state.state.data_file_length != dfile_len) diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c index a45a990472e..19e61daf4ef 100644 --- a/storage/maria/ma_recovery_util.c +++ b/storage/maria/ma_recovery_util.c @@ -57,8 +57,16 @@ void tprint(FILE *trace_file __attribute__ ((unused)), const char *format __attribute__ ((unused)), ...) { va_list args; +#ifndef DBUG_OFF + { + char buff[1024]; + va_start(args, format); + vsnprintf(buff, sizeof(buff)-1, format, args); + DBUG_PRINT("info", ("%s", buff)); + va_end(args); + } +#endif va_start(args, format); - DBUG_PRINT("info", ("%s", format)); if (trace_file != NULL) { if (procent_printed) diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 0bf38ac5dc8..0fe230c108c 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -990,7 +990,7 @@ static int maria_chk(HA_CHECK *param, char *filename) if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) && ((share->state.changed & (STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR) || + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR) || !(param->testflag & T_CHECK_ONLY_CHANGED)))) need_to_check=1; @@ -1008,7 +1008,7 @@ static int maria_chk(HA_CHECK *param, char *filename) } if ((param->testflag & T_CHECK_ONLY_CHANGED) && (share->state.changed & (STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR))) + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR))) need_to_check=1; if (!need_to_check) { @@ -1225,8 +1225,11 @@ static int maria_chk(HA_CHECK *param, char *filename) if (!error && (param->testflag & T_ZEROFILL)) error= maria_zerofill(param, info, filename); if (!error) + { + DBUG_PRINT("info", ("Reseting crashed state")); share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR); + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); + } else maria_mark_crashed(info); } @@ -1278,8 +1281,9 @@ static int maria_chk(HA_CHECK *param, char *filename) if ((share->state.changed & STATE_CHANGED) && (param->testflag & T_UPDATE_STATE)) info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; + DBUG_PRINT("info", ("Reseting crashed state")); share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR); + STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); } else if (!maria_is_crashed(info) && (param->testflag & T_UPDATE_STATE)) diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 868885c961b..e9980cf9695 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -611,6 +611,7 @@ struct st_maria_handler #define STATE_NOT_ZEROFILLED 128 #define STATE_NOT_MOVABLE 256 #define STATE_MOVED 512 /* set if base->uuid != maria_uuid */ +#define STATE_IN_REPAIR 1024 /* We are running repair on table */ /* options to maria_read_cache */ @@ -666,11 +667,17 @@ struct st_maria_handler #define maria_mark_crashed_on_repair(x) do{(x)->s->state.changed|= \ STATE_CRASHED|STATE_CRASHED_ON_REPAIR; \ (x)->update|= HA_STATE_CHANGED; \ - DBUG_PRINT("error", \ - ("Marked table crashed")); \ + DBUG_PRINT("error", ("Marked table crashed on repair")); \ + }while(0) +#define maria_mark_in_repair(x) do{(x)->s->state.changed|= \ + STATE_CRASHED | STATE_IN_REPAIR; \ + (x)->update|= HA_STATE_CHANGED; \ + DBUG_PRINT("error", ("Marked table crashed for repair")); \ }while(0) #define maria_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED) #define maria_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR) +#define maria_in_repair(x) ((x)->s->state.changed & STATE_IN_REPAIR) + #ifdef EXTRA_DEBUG /** Brings additional information in certain debug builds and in standalone diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 2b2fa692f24..1e86decc1e0 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -1,4 +1,5 @@ /* Copyright (C) 2007 MySQL AB + Copyright (C) 2010 Monty Program 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 @@ -150,6 +151,9 @@ err: #include "ma_check_standalone.h" +enum options_mc { + OPT_CHARSETS_DIR=256 +}; static struct my_option my_long_options[] = { @@ -158,6 +162,9 @@ static struct my_option my_long_options[] = " Displays a lot of information if not run with --silent", (uchar **) &opt_apply, (uchar **) &opt_apply, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are.", + (uchar**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', "if --display-only, check if record is fully readable (for debugging)", (uchar **) &opt_check, (uchar **) &opt_check, 0, @@ -206,7 +213,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - VOID(printf("%s Ver 1.2 for %s on %s\n", + VOID(printf("%s Ver 1.3 for %s on %s\n", my_progname_short, SYSTEM_TYPE, MACHINE_TYPE)); NETWARE_SET_SCREEN_MODE(1); } diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c index ceb8ad2ae2d..2e03606ca7c 100644 --- a/storage/maria/trnman.c +++ b/storage/maria/trnman.c @@ -176,6 +176,7 @@ int trnman_init(TrID initial_trid) trnman_active_transactions= 0; trnman_committed_transactions= 0; trnman_allocated_transactions= 0; + dummy_transaction_object.min_read_from= ~(TrID) 0; /* for recovery */ pool= 0; global_trid_generator= initial_trid; |