diff options
28 files changed, 302 insertions, 183 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6a7d7cf50ea..580712b0d76 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1065,8 +1065,7 @@ 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 | + !(share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR)) && share->state.open_count == 0) || ((param.testflag & T_FAST) && (share->state.open_count == @@ -1104,15 +1103,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_IN_REPAIR | - STATE_CRASHED | STATE_NOT_ANALYZED)) || + STATE_CRASHED_FLAGS | + STATE_IN_REPAIR | 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); DBUG_PRINT("info", ("Reseting crashed state")); - share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | + STATE_IN_REPAIR); if (!(table->db_stat & HA_READ_ONLY)) error= maria_update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT | @@ -1544,8 +1543,8 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) if ((share->state.changed & STATE_CHANGED) || maria_is_crashed(file)) { DBUG_PRINT("info", ("Reseting crashed state")); - share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | + STATE_IN_REPAIR); file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; } /* @@ -2025,8 +2024,7 @@ bool ha_maria::check_and_repair(THD *thd) check_opt.flags= T_MEDIUM | T_AUTO_REPAIR; error= 1; - if ((file->s->state.changed & - (STATE_CRASHED | STATE_CRASHED_ON_REPAIR | STATE_MOVED)) == + if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) == STATE_MOVED) { sql_print_information("Zerofilling moved table: '%s'", @@ -2077,7 +2075,7 @@ bool ha_maria::check_and_repair(THD *thd) bool ha_maria::is_crashed() const { - return (file->s->state.changed & (STATE_CRASHED | STATE_MOVED) || + return (file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED) || (my_disable_locking && file->s->state.open_count)); } @@ -3287,6 +3285,8 @@ static int ha_maria_init(void *p) ma_checkpoint_init(checkpoint_interval); maria_multi_threaded= maria_in_ha_maria= TRUE; maria_create_trn_hook= maria_create_trn_for_mysql; + maria_pagecache->extra_debug= 1; + maria_assert_if_crashed_table= debug_assert_if_crashed_table; #if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH) /* We can only test for sub paths if my_symlink.c is using realpath */ diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index bc83f6ea0e9..2cbb66299a8 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -104,10 +104,11 @@ - On checkpoint (Ie: When we do a checkpoint, we have to ensure that all bitmaps are put on disk even if they are not in the page cache). - - When explicitely requested (for example on backup or after recvoery, + - When explicitely requested (for example on backup or after recovery, to simplify things) The flow of writing a row is that: + - Mark the bitmap not flushable (_ma_bitmap_flushable(X, 1)) - Lock the bitmap - Decide which data pages we will write to - Mark them full in the bitmap page so that other threads do not try to @@ -119,6 +120,7 @@ pages (that is, we marked pages full but when we are done we realize we didn't fill them) - Unlock the bitmap. + - Mark the bitmap flushable (_ma_bitmap_flushable(X, -1)) */ #include "maria_def.h" @@ -127,6 +129,12 @@ #define FULL_HEAD_PAGE 4 #define FULL_TAIL_PAGE 7 +const char *bits_to_txt[]= +{ + "empty", "00-30% full", "30-60% full", "60-90% full", "full", + "tail 00-40 % full", "tail 40-80 % full", "tail/blob full" +}; + /*#define WRONG_BITMAP_FLUSH 1*/ /*define only for provoking bugs*/ #undef WRONG_BITMAP_FLUSH @@ -273,6 +281,12 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share) delete_dynamic(&share->bitmap.pinned_pages); my_free(share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR)); share->bitmap.map= 0; + /* + This is to not get an assert in checkpoint. The bitmap will be flushed + at once by _ma_once_end_block_record() as part of the normal flush + of the kfile. + */ + share->bitmap.changed_not_flushed= 0; return res; } @@ -353,6 +367,24 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) my_bool res= 0; MARIA_FILE_BITMAP *bitmap= &share->bitmap; DBUG_ENTER("_ma_bitmap_flush_all"); + +#ifdef EXTRA_DEBUG_BITMAP + { + char buff[160]; + uint len= my_sprintf(buff, + (buff, "bitmap_flush: fd: %d id: %u " + "changed: %d changed_not_flushed: %d " + "flush_all_requsted: %d", + share->bitmap.file.file, + share->id, + bitmap->changed, + bitmap->changed_not_flushed, + bitmap->flush_all_requested)); + (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY, + (uchar*) buff, len); + } +#endif + pthread_mutex_lock(&bitmap->bitmap_lock); if (bitmap->changed || bitmap->changed_not_flushed) { @@ -364,6 +396,15 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock); } #endif +#ifdef EXTRA_DEBUG_BITMAP + { + char tmp[MAX_BITMAP_INFO_LENGTH]; + _ma_get_bitmap_description(bitmap, bitmap->map, bitmap->page, tmp); + (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY, + (uchar*) tmp, strlen(tmp)); + } +#endif + DBUG_ASSERT(bitmap->flush_all_requested == 1); /* Bitmap is in a flushable state: its contents in memory are reflected by @@ -680,7 +721,7 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern) Print bitmap for debugging SYNOPSIS - _ma_print_bitmap() + _ma_print_bitmap_changes() bitmap Bitmap to print IMPLEMENTATION @@ -691,12 +732,6 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern) #ifndef DBUG_OFF -const char *bits_to_txt[]= -{ - "empty", "00-30% full", "30-60% full", "60-90% full", "full", - "tail 00-40 % full", "tail 40-80 % full", "tail/blob full" -}; - static void _ma_print_bitmap_changes(MARIA_FILE_BITMAP *bitmap) { uchar *pos, *end, *org_pos; @@ -747,7 +782,6 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, uchar *pos, *end; char llbuff[22]; - end= bitmap->map + bitmap->used_size; DBUG_LOCK_FILE; fprintf(DBUG_FILE,"\nDump of bitmap page at %s\n", llstr(page, llbuff)); @@ -781,6 +815,56 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, #endif /* DBUG_OFF */ +/* + Return content of bitmap as a printable string +*/ + +void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, + uchar *bitmap_data, + pgcache_page_no_t page, + char *out) +{ + uchar *pos, *end; + uint count=0, dot_printed= 0, len; + char buff[80], last[80]; + + page++; + last[0]=0; + for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6) + { + ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */ + uint i; + + for (i= 0; i < 16 ; i++, bits>>= 3) + { + if (count > 60) + { + if (memcmp(buff, last, count)) + { + memcpy(last, buff, count); + len= my_sprintf(out, (out, "%8lu: ", (ulong) page - count)); + memcpy(out+len, buff, count); + out+= len + count + 1; + out[-1]= '\n'; + dot_printed= 0; + } + else if (!(dot_printed++)) + { + out= strmov(out, "...\n"); + } + count= 0; + } + buff[count++]= '0' + (uint) (bits & 7); + page++; + } + } + len= my_sprintf(out, (out, "%8lu: ", (ulong) page - count)); + memcpy(out+len, buff, count); + out[len + count]= '\n'; + out[len + count + 1]= 0; +} + + /*************************************************************************** Reading & writing bitmap pages ***************************************************************************/ @@ -2383,16 +2467,14 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) The page has all bits set; The following test is an optimization to not set the bits to the same value as before. */ + DBUG_ASSERT(current_bitmap_value == + _ma_bitmap_get_page_bits(info, bitmap, block->page)); + if (bits != current_bitmap_value) { if (set_page_bits(info, bitmap, block->page, bits)) goto err; } - else - { - DBUG_ASSERT(current_bitmap_value == - _ma_bitmap_get_page_bits(info, bitmap, block->page)); - } } else if (!(block->used & BLOCKUSED_USED) && _ma_bitmap_reset_full_page_bits(info, bitmap, @@ -2521,17 +2603,15 @@ my_bool _ma_bitmap_set(MARIA_HA *info, pgcache_page_no_t page, my_bool head, page_type What kind of page this is page Adress to page empty_space Empty space on page - bitmap_pattern Store here the pattern that was in the bitmap for the - page. This is always updated. + bitmap_pattern Bitmap pattern for page (from bitmap) RETURN 0 ok 1 error */ -my_bool _ma_check_bitmap_data(MARIA_HA *info, - enum en_page_type page_type, pgcache_page_no_t page, - uint empty_space, uint *bitmap_pattern) +my_bool _ma_check_bitmap_data(MARIA_HA *info, enum en_page_type page_type, + uint empty_space, uint bitmap_pattern) { uint bits; switch (page_type) { @@ -2552,8 +2632,7 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info, bits= 0; /* to satisfy compiler */ DBUG_ASSERT(0); } - return ((*bitmap_pattern= _ma_bitmap_get_page_bits(info, &info->s->bitmap, - page)) != bits); + return (bitmap_pattern != bits); } diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 7fe88bb1848..0db20d6ca12 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -4106,11 +4106,11 @@ static my_bool delete_head_or_tail(MARIA_HA *info, { MARIA_SHARE *share= info->s; uint empty_space; - uint block_size= share->block_size; + int res; + my_bool page_is_empty; uchar *buff; LSN lsn; MARIA_PINNED_PAGE page_link; - int res; enum pagecache_page_lock lock_at_write, lock_at_unpin; DBUG_ENTER("delete_head_or_tail"); DBUG_PRINT("enter", ("id: %lu (%lu:%u)", @@ -4140,13 +4140,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info, lock_at_unpin= PAGECACHE_LOCK_READ_UNLOCK; } - res= delete_dir_entry(buff, block_size, record_number, &empty_space); + res= delete_dir_entry(buff, share->block_size, record_number, &empty_space); if (res < 0) DBUG_RETURN(1); if (res == 0) /* after our deletion, page is still not empty */ { uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE]; LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1]; + page_is_empty= 0; if (share->now_transactional) { /* Log REDO data */ @@ -4167,6 +4168,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, } else /* page is now empty */ { + page_is_empty= 1; if (share->now_transactional) { uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE]; @@ -4198,8 +4200,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info, If there is not enough space for all possible tails, mark the page full */ - if (!head && !enough_free_entries(buff, share->block_size, - 1 + share->base.blobs)) + if (!head && !page_is_empty && !enough_free_entries(buff, share->block_size, + 1 + share->base.blobs)) empty_space= 0; DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space)); diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index e63af8eed5b..3201998e31c 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -78,6 +78,10 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_ #define ROW_FLAG_EXTENTS 128 #define ROW_FLAG_ALL (1+2+4+8+128) +/* Size for buffer to hold information about bitmap */ +#define MAX_BITMAP_INFO_LENGTH ((MARIA_MAX_KEY_BLOCK_LENGTH*8/3)*(61*11/60)+10) + + /******** Variables that affects how data pages are utilized ********/ /* Minium size of tail segment */ @@ -181,6 +185,8 @@ TRANSLOG_ADDRESS maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr); /* ma_bitmap.c */ +extern const char *bits_to_txt[]; + my_bool _ma_bitmap_init(MARIA_SHARE *share, File file); my_bool _ma_bitmap_end(MARIA_SHARE *share); my_bool _ma_bitmap_flush(MARIA_SHARE *share); @@ -206,8 +212,7 @@ my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *new_row, MARIA_BITMAP_BLOCKS *result_blocks); my_bool _ma_check_bitmap_data(MARIA_HA *info, enum en_page_type page_type, - pgcache_page_no_t page, - uint empty_space, uint *bitmap_pattern); + uint empty_space, uint bitmap_pattern); my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info, enum en_page_type page_type, pgcache_page_no_t page, @@ -225,6 +230,10 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file, void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, pgcache_page_no_t page); #endif +void _ma_get_bitmap_description(MARIA_FILE_BITMAP *bitmap, + uchar *bitmap_data, + pgcache_page_no_t page, + char *out); uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint page_type, diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 7ad3a4fc5eb..9a5cf755f5f 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -1822,6 +1822,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, pos+= block_size, page++) { uint row_count, real_row_count, empty_space, page_type, bitmap_pattern; + uint bitmap_for_page; LINT_INIT(row_count); LINT_INIT(empty_space); @@ -1856,7 +1857,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, offset= offset_page & 7; data= bitmap_buff + offset_page / 8; bitmap_pattern= uint2korr(data); - if (!((bitmap_pattern >> offset) & 7)) + if (!(bitmap_for_page= ((bitmap_pattern >> offset) & 7))) { param->empty+= block_size; param->del_blocks++; @@ -1879,8 +1880,9 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE) { _ma_check_print_error(param, - "Page: %9s Found wrong page type %d", - llstr(page, llbuff), page_type); + "Page: %9s Found wrong page type %d. Bitmap: %d '%s'", + llstr(page, llbuff), page_type, + bitmap_for_page, bits_to_txt[bitmap_for_page]); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; continue; @@ -1927,20 +1929,17 @@ 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, page, + if (_ma_check_bitmap_data(info, page_type, full_dir ? 0 : empty_space, - &bitmap_pattern)) + bitmap_for_page)) { - if (bitmap_pattern == ~(uint) 0) - _ma_check_print_error(param, - "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 full: %d empty_space: %u Bitmap-bits: %d", + "%d full: %d empty_space: %u Bitmap-bits: %d " + "'%s'", llstr(page, llbuff), page_type, full_dir, - empty_space, bitmap_pattern); + empty_space, bitmap_for_page, + bits_to_txt[bitmap_for_page]); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; } @@ -6831,39 +6830,7 @@ static void print_bitmap_description(MARIA_SHARE *share, pgcache_page_no_t page, uchar *bitmap_data) { - uchar *pos, *end; - MARIA_FILE_BITMAP *bitmap= &share->bitmap; - uint count=0, dot_printed= 0; - char buff[80], last[80]; - - printf("Bitmap page %lu\n", (ulong) page); - page++; - last[0]=0; - for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6) - { - ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */ - uint i; - - for (i= 0; i < 16 ; i++, bits>>= 3) - { - if (count > 60) - { - buff[count]= 0; - if (strcmp(buff, last)) - { - memcpy(last, buff, count+1); - printf("%8lu: %s\n", (ulong) page - count, buff); - dot_printed= 0; - } - else if (!(dot_printed++)) - printf("...\n"); - count= 0; - } - buff[count++]= '0' + (uint) (bits & 7); - page++; - } - } - buff[count]= 0; - printf("%8lu: %s\n", (ulong) page - count, buff); - fputs("\n", stdout); + char tmp[MAX_BITMAP_INFO_LENGTH]; + _ma_get_bitmap_description(&share->bitmap, bitmap_data, page, tmp); + printf("Bitmap page %lu\n%s", (ulong) page, tmp); } diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index 8a6e2b5d960..fdeec982f08 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -130,6 +130,9 @@ int ma_checkpoint_execute(CHECKPOINT_LEVEL level, my_bool no_wait) /* from then on, we are sure to be and stay the only checkpointer */ result= really_execute_checkpoint(); + DBUG_EXECUTE_IF("maria_crash_after_checkpoint", + { DBUG_PRINT("maria_crash", ("now")); DBUG_ABORT(); }); + pthread_cond_broadcast(&COND_checkpoint); end: DBUG_RETURN(result); @@ -1065,6 +1068,14 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon) */ } } +#ifdef EXTRA_DEBUG_BITMAP + else + { + DBUG_ASSERT(share->bitmap.changed == 0 && + share->bitmap.changed_not_flushed == 0); + } +#endif + /* _ma_bitmap_flush_all() may wait, so don't keep intern_lock as otherwise this would deadlock with allocate_and_write_block_record() diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 6886dc8f291..6967a47a023 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -1387,7 +1387,13 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid, share->state.skip_redo_lsn= share->state.is_of_horizon= lsn; share->state.create_trid= create_trid; mi_int8store(trid_buff, create_trid); - if (update_create_rename_lsn) + + /* + Update create_rename_lsn if update was requested or if the old one had an + impossible value. + */ + if (update_create_rename_lsn || + (share->state.create_rename_lsn > lsn && lsn != LSN_IMPOSSIBLE)) { share->state.create_rename_lsn= lsn; if (share->id != 0) diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index 5c04f358b14..087905c9440 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -135,18 +135,13 @@ err: save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */ mi_sizestore(lastpos, info->cur_row.lastpos); - if (save_errno != HA_ERR_RECORD_CHANGED) - { - maria_print_error(share, HA_ERR_CRASHED); - maria_mark_crashed(info); /* mark table crashed */ - } VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); info->update|=HA_STATE_WRITTEN; /* Buffer changed */ allow_break(); /* Allow SIGHUP & SIGINT */ - if (save_errno == HA_ERR_KEY_NOT_FOUND) + if (save_errno != HA_ERR_RECORD_CHANGED) { - maria_print_error(share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); + save_errno= HA_ERR_CRASHED; } DBUG_RETURN(my_errno= save_errno); } /* maria_delete */ @@ -213,7 +208,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, if ((old_root=*root) == HA_OFFSET_ERROR) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(info->s, HA_ERR_CRASHED); DBUG_RETURN(1); } if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ @@ -348,7 +343,7 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &kpos))) { - my_errno= HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(-1); } root= _ma_row_pos_from_key(&tmp_key); @@ -410,8 +405,9 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag, { if (!nod_flag) { + /* This should newer happend */ DBUG_PRINT("error",("Didn't find key")); - my_errno=HA_ERR_CRASHED; /* This should newer happend */ + _ma_set_fatal_error(share, HA_ERR_CRASHED); goto err; } save_flag=0; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index e436a51248a..cb946dffaf0 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -175,8 +175,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, { if ((error= flush_io_cache(&info->rec_cache))) { - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); /* Fatal error found */ + /* Fatal error found */ + _ma_set_fatal_error(share, HA_ERR_CRASHED); } } break; @@ -299,6 +299,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, } pthread_mutex_lock(&THR_LOCK_maria); pthread_mutex_lock(&share->intern_lock); /* protect against Checkpoint */ + /* Safety against assert in checkpoint */ + share->bitmap.changed_not_flushed= 0; /* this makes the share not be re-used next time the table is opened */ share->last_version= 0L; /* Impossible version */ pthread_mutex_unlock(&share->intern_lock); @@ -382,8 +384,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, if (share->data_file_type == BLOCK_RECORD && share->bitmap.file.file >= 0) { + DBUG_ASSERT(share->bitmap.non_flushable == 0 && + share->bitmap.changed == 0); if (do_flush && my_sync(share->bitmap.file.file, MYF(0))) error= my_errno; + share->bitmap.changed_not_flushed= 0; } /* For protection against Checkpoint, we set under intern_lock: */ share->last_version= 0L; /* Impossible version */ @@ -415,9 +420,9 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, error= my_errno; if (error) { + /* Fatal error found */ share->changed= 1; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); /* Fatal error found */ + _ma_set_fatal_error(share, HA_ERR_CRASHED); } } break; @@ -560,6 +565,12 @@ int _ma_sync_table_files(const MARIA_HA *info) my_sync(info->s->kfile.file, MYF(MY_WME))); } +uint _ma_file_callback_to_id(void *callback_data) +{ + MARIA_SHARE *share= (MARIA_SHARE*) callback_data; + return share ? share->id : 0; +} + /** @brief flushes the data and/or index file of a table @@ -608,6 +619,7 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index, { pthread_mutex_lock(&share->bitmap.bitmap_lock); share->bitmap.changed= 0; + share->bitmap.changed_not_flushed= 0; pthread_mutex_unlock(&share->bitmap.bitmap_lock); } if (flush_pagecache_blocks(share->pagecache, &info->dfile, @@ -622,7 +634,6 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index, if (!error) return 0; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); + _ma_set_fatal_error(info->s, HA_ERR_CRASHED); return 1; } diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c index 9cec978166f..9e5b600c972 100644 --- a/storage/maria/ma_init.c +++ b/storage/maria/ma_init.c @@ -99,7 +99,7 @@ void maria_end(void) trid, recovery_failures); } trnman_destroy(); - if (translog_status == TRANSLOG_OK) + if (translog_status == TRANSLOG_OK || translog_status == TRANSLOG_READONLY) translog_destroy(); end_pagecache(maria_log_pagecache, TRUE); end_pagecache(maria_pagecache, TRUE); diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c index 08702a9109e..207ae9a8bda 100644 --- a/storage/maria/ma_key.c +++ b/storage/maria/ma_key.c @@ -636,8 +636,7 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos) { /* Read only key */ if (_ma_put_key_in_record(info,(uint) info->lastinx,buf)) { - maria_print_error(info->s, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(info->s, HA_ERR_CRASHED); return -1; } info->update|= HA_STATE_AKTIV; /* We should find a record */ diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index 6de5253a2dd..aeaf9945599 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -66,7 +66,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) #ifdef EXTRA_DEBUG DBUG_ASSERT((!pinned_page->changed || undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional) || - (info->s->state.changed & STATE_CRASHED)); + (info->s->state.changed & STATE_CRASHED_FLAGS)); #endif pagecache_unlock_by_link(info->s->pagecache, pinned_page->link, pinned_page->unlock, PAGECACHE_UNPIN, diff --git a/storage/maria/ma_keycache.c b/storage/maria/ma_keycache.c index 39fc7d421ae..1eb40821a36 100644 --- a/storage/maria/ma_keycache.c +++ b/storage/maria/ma_keycache.c @@ -79,8 +79,8 @@ int maria_assign_to_pagecache(MARIA_HA *info, if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_RELEASE)) { error= my_errno; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); /* Mark that table must be checked */ + /* Mark that table must be checked */ + _ma_set_fatal_error(share, error); } /* diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index 6bb308e5959..dc1189619ed 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type) { if (end_io_cache(&info->rec_cache)) { - error=my_errno; - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); + error= my_errno; + _ma_set_fatal_error(share, error); } } if (!count) @@ -129,10 +128,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) else share->not_flushed=1; if (error) - { - maria_print_error(info->s, HA_ERR_CRASHED); - maria_mark_crashed(info); - } + _ma_set_fatal_error(share, error); } } info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); @@ -528,6 +524,28 @@ void _ma_mark_file_crashed(MARIA_SHARE *share) DBUG_VOID_RETURN; } +/* + Handle a fatal error + + - Mark the table as crashed + - Print an error message, if we had not issued an error message before + that the table had been crashed. + - set my_errno to error + - If 'maria_assert_if_crashed_table is set, then assert. +*/ + +void _ma_set_fatal_error(MARIA_SHARE *share, int error) +{ + maria_mark_crashed_share(share); + if (!(share->state.changed & STATE_CRASHED_PRINTED)) + { + share->state.changed|= STATE_CRASHED_PRINTED; + maria_print_error(share, error); + } + my_errno= error; + DBUG_ASSERT(!maria_assert_if_crashed_table); +} + /** @brief Set uuid of for a Maria file diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 0890ff7e000..f33340baf5c 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -41,10 +41,10 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); pos+=size;} -#define disk_pos_assert(pos, end_pos) \ +#define disk_pos_assert(share, pos, end_pos) \ if (pos > end_pos) \ { \ - my_errno=HA_ERR_CRASHED; \ + _ma_set_fatal_error(share, HA_ERR_CRASHED); \ goto err; \ } @@ -387,7 +387,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) errpos= 3; if (my_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP))) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); goto err; } len=mi_uint2korr(share->state.header.state_info_length); @@ -413,9 +413,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) } disk_pos= _ma_base_info_read(disk_cache + base_pos, &share->base); share->state.state_length=base_pos; + /* For newly opened tables we reset the error-has-been-printed flag */ + share->state.changed&= ~STATE_CRASHED_PRINTED; if (!(open_flags & HA_OPEN_FOR_REPAIR) && - ((share->state.changed & STATE_CRASHED) || + ((share->state.changed & STATE_CRASHED_FLAGS) || ((open_flags & HA_OPEN_ABORT_IF_CRASHED) && (my_disable_locking && share->state.open_count)))) { @@ -456,7 +458,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) /* sanity check */ if (share->base.keystart > 65535 || share->base.rec_reflength > 8) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); goto err; } @@ -567,7 +569,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->keyinfo[i].share= share; disk_pos=_ma_keydef_read(disk_pos, &share->keyinfo[i]); share->keyinfo[i].key_nr= i; - disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE, + disk_pos_assert(share, + disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE, end_pos); if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE) share->have_rtree= 1; @@ -615,7 +618,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) pos[0].language= pos[-1].language; if (!(pos[0].charset= pos[-1].charset)) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); goto err; } pos++; @@ -647,7 +650,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) for (i=0 ; i < uniques ; i++) { disk_pos=_ma_uniquedef_read(disk_pos, &share->uniqueinfo[i]); - disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs * + disk_pos_assert(share, + disk_pos + share->uniqueinfo[i].keysegs * HA_KEYSEG_SIZE, end_pos); share->uniqueinfo[i].seg=pos; for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++) @@ -751,7 +755,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->base.extra_rec_buff_size, share->base.max_key_length); - disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE, + disk_pos_assert(share, + disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE, end_pos); for (i= j= 0 ; i < share->base.fields ; i++) { @@ -1875,7 +1880,7 @@ int maria_enable_indexes(MARIA_HA *info) DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu", (ulong) share->state.state.data_file_length, (ulong) share->state.state.key_file_length)); - maria_print_error(info->s, HA_ERR_CRASHED); + _ma_set_fatal_error(share, HA_ERR_CRASHED); error= HA_ERR_CRASHED; } else diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index a4423133270..bcd50f028ec 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -127,8 +127,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, { DBUG_PRINT("error",("Got errno: %d from pagecache_read",my_errno)); info->last_keypage=HA_OFFSET_ERROR; - maria_print_error(share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(1); } info->last_keypage= pos; @@ -159,8 +158,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, _ma_get_keynr(share, tmp))); DBUG_DUMP("page", tmp, page_size); info->last_keypage = HA_OFFSET_ERROR; - maria_print_error(share, HA_ERR_CRASHED); - my_errno= HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(1); } } @@ -552,8 +550,7 @@ my_bool _ma_compact_keypage(MARIA_PAGE *ma_page, TrID min_read_from) { DBUG_PRINT("error",("Couldn't find last key: page_pos: 0x%lx", (long) page)); - maria_print_error(share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(1); } if (key_has_transid(page-1)) diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 1e79b04f7b6..97b9f70c902 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -614,6 +614,26 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache, DBUG_ENTER("pagecache_fwrite"); DBUG_ASSERT(type != PAGECACHE_READ_UNKNOWN_PAGE); +#ifdef EXTRA_DEBUG_BITMAP + /* + This code is very good when debugging changes in bitmaps or dirty lists + The above define should be defined for all Aria files if you want to + debug either of the above issues. + */ + + if (pagecache->extra_debug) + { + char buff[80]; + uint len= my_sprintf(buff, + (buff, "fwrite: fd: %d id: %u page: %lu", + filedesc->file, + _ma_file_callback_to_id(filedesc->callback_data), + (ulong) pageno)); + (void) translog_log_debug_info(0, LOGREC_DEBUG_INFO_QUERY, + (uchar*) buff, len); + } +#endif + /* Todo: Integrate this with write_callback so we have only one callback */ if ((*filedesc->flush_log_callback)(buffer, pageno, filedesc->callback_data)) DBUG_RETURN(1); diff --git a/storage/maria/ma_pagecache.h b/storage/maria/ma_pagecache.h index 821728ef374..5ed5719a8af 100644 --- a/storage/maria/ma_pagecache.h +++ b/storage/maria/ma_pagecache.h @@ -173,6 +173,7 @@ typedef struct st_pagecache my_bool resize_in_flush; /* true during flush of resize operation */ my_bool can_be_used; /* usage of cache for read/write is allowed */ my_bool in_init; /* Set to 1 in MySQL during init/resize */ + my_bool extra_debug; /* set to 1 if one wants extra logging */ HASH files_in_flush; /**< files in flush_pagecache_blocks_int() */ } PAGECACHE; diff --git a/storage/maria/ma_panic.c b/storage/maria/ma_panic.c index a86563f31fb..c723ab0b2b8 100644 --- a/storage/maria/ma_panic.c +++ b/storage/maria/ma_panic.c @@ -67,8 +67,8 @@ int maria_panic(enum ha_panic_function flag) if (info->s->options & HA_OPTION_READ_ONLY_DATA) break; #endif - if (flush_pagecache_blocks(info->s->pagecache, &info->s->kfile, - FLUSH_RELEASE)) + if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, + FLUSH_RELEASE, FLUSH_RELEASE)) error=my_errno; if (info->opt_flag & WRITE_CACHE_USED) if (flush_io_cache(&info->rec_cache)) @@ -92,8 +92,8 @@ int maria_panic(enum ha_panic_function flag) if (info->dfile.file >= 0 && my_close(info->dfile.file, MYF(0))) error = my_errno; info->s->kfile.file= info->dfile.file= -1;/* Files aren't open anymore */ - break; #endif + break; case HA_PANIC_READ: /* Restore to before WRITE */ #ifdef CANT_OPEN_FILES_TWICE { /* Open closed files */ diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c index ed9d8efc81b..2d65f59fd0a 100644 --- a/storage/maria/ma_recovery_util.c +++ b/storage/maria/ma_recovery_util.c @@ -59,9 +59,11 @@ void tprint(FILE *trace_file __attribute__ ((unused)), va_list args; #ifndef DBUG_OFF { - char buff[1024]; + char buff[1024], *end; va_start(args, format); vsnprintf(buff, sizeof(buff)-1, format, args); + if (*(end= strend(buff)) == '\n') + *end= 0; /* Don't print end \n */ DBUG_PRINT("info", ("%s", buff)); va_end(args); } diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c index 85b3b463f49..976e09ece99 100644 --- a/storage/maria/ma_rkey.c +++ b/storage/maria/ma_rkey.c @@ -91,8 +91,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data, case HA_KEY_ALG_RTREE: if (maria_rtree_find_first(info, &key, nextflag) < 0) { - maria_print_error(info->s, HA_ERR_CRASHED); - my_errno= HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); info->cur_row.lastpos= HA_OFFSET_ERROR; } break; diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index cf64612f30d..1d5800eb3de 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -379,8 +379,7 @@ int _ma_seq_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &page); if (length == 0 || page > end) { - maria_print_error(share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_PRINT("error", ("Found wrong key: length: %u page: 0x%lx end: 0x%lx", length, (long) page, (long) end)); @@ -562,8 +561,7 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, if (page > end) { - maria_print_error(share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_PRINT("error", ("Found wrong key: length: %u page: 0x%lx end: %lx", length, (long) page, (long) end)); @@ -1043,8 +1041,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, { if (length > (uint) keyseg->length) { - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); return 0; /* Error */ } if (length == 0) /* Same key */ @@ -1059,8 +1056,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, ("Found too long null packed key: %u of %u at 0x%lx", length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key", *page_pos, 16); - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); return 0; } continue; @@ -1117,8 +1113,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, DBUG_PRINT("error",("Found too long packed key: %u of %u at 0x%lx", length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key", *page_pos, 16); - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); return 0; /* Error */ } store_key_length_inc(key,length); @@ -1277,8 +1272,7 @@ uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag, ("Found too long binary packed key: %u of %u at 0x%lx", length, keyinfo->maxlength, (long) *page_pos)); DBUG_DUMP("key", *page_pos, 16); - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); DBUG_RETURN(0); /* Wrong key */ } /* Key is packed against prev key, take prefix from prev key. */ @@ -1369,8 +1363,7 @@ uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag, if (from_end != page_end) { DBUG_PRINT("error",("Error when unpacking key")); - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); DBUG_RETURN(0); /* Error */ } } @@ -1456,8 +1449,7 @@ uchar *_ma_get_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos) { if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page)) { - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); DBUG_RETURN(0); } } @@ -1507,8 +1499,7 @@ static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page, { if (! (*keyinfo->get_key)(key, page_flag, nod_flag, &page)) { - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); DBUG_RETURN(1); } } @@ -1561,8 +1552,7 @@ uchar *_ma_get_last_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *endpos) { DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx", (long) page)); - maria_print_error(keyinfo->share, HA_ERR_CRASHED); - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED); DBUG_RETURN(0); } } diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index 917385f9568..5c88ba6745b 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -38,6 +38,8 @@ my_bool maria_delay_key_write= 0, maria_page_checksums= 1; my_bool maria_inited= FALSE; my_bool maria_in_ha_maria= FALSE; /* If used from ha_maria or not */ my_bool maria_recovery_changed_data= 0, maria_recovery_verbose= 0; +my_bool maria_assert_if_crashed_table= 0; + pthread_mutex_t THR_LOCK_maria; #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) ulong maria_concurrent_insert= 2; diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c index 7b9e006ec43..531b7de8fec 100644 --- a/storage/maria/ma_update.c +++ b/storage/maria/ma_update.c @@ -216,7 +216,10 @@ err: { if ((flag++ && _ma_ft_del(info,i,new_key_buff,newrec,pos)) || _ma_ft_add(info,i,old_key_buff,oldrec,pos)) + { + _ma_set_fatal_error(share, my_errno); break; + } } else { @@ -228,16 +231,17 @@ err: oldrec, pos, info->cur_row.trid); if ((flag++ && _ma_ck_delete(info, &new_key)) || _ma_ck_write(info, &old_key)) + { + _ma_set_fatal_error(share, my_errno); break; + } } } } while (i-- != 0); } else - { - maria_print_error(share, HA_ERR_CRASHED); - maria_mark_crashed(info); - } + _ma_set_fatal_error(share, save_errno); + info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED | key_changed); @@ -245,9 +249,6 @@ err: VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ if (save_errno == HA_ERR_KEY_NOT_FOUND) - { - maria_print_error(share, HA_ERR_CRASHED); - save_errno=HA_ERR_CRASHED; - } + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(my_errno=save_errno); } /* maria_update */ diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 49f86fe291b..367676e4520 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -802,7 +802,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, { if (t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(-1); } bmove_upp(endpos+t_length, endpos, (uint) (endpos-key_pos)); @@ -811,7 +811,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, { if (-t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(-1); } bmove(key_pos,key_pos-t_length,(uint) (endpos-key_pos)+t_length); @@ -1176,7 +1176,7 @@ static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page, if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page))) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(0); } @@ -1189,7 +1189,7 @@ static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page, memcpy(int_key->data, key_buff, length); /* previous key */ if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &page))) { - my_errno=HA_ERR_CRASHED; + _ma_set_fatal_error(share, HA_ERR_CRASHED); DBUG_RETURN(0); } } while (page < end); diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index b9b0c681d0a..a2b4bdf5547 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -1012,8 +1012,8 @@ static int maria_chk(HA_CHECK *param, char *filename) share->state.open_count != 0); if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) && - ((share->state.changed & (STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR) || + ((share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS | + STATE_IN_REPAIR) || !(param->testflag & T_CHECK_ONLY_CHANGED)))) need_to_check=1; @@ -1030,8 +1030,8 @@ static int maria_chk(HA_CHECK *param, char *filename) need_to_check=1; } if ((param->testflag & T_CHECK_ONLY_CHANGED) && - (share->state.changed & (STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR))) + (share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS | + STATE_IN_REPAIR))) need_to_check=1; if (!need_to_check) { @@ -1250,8 +1250,8 @@ static int maria_chk(HA_CHECK *param, char *filename) if (!error) { DBUG_PRINT("info", ("Reseting crashed state")); - share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | - STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | + STATE_IN_REPAIR); } else maria_mark_crashed(info); @@ -1304,14 +1304,13 @@ static int maria_chk(HA_CHECK *param, char *filename) if (!error) { if (((share->state.changed & - (STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR | - STATE_IN_REPAIR)) || + (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR)) || share->state.open_count != 0) && (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_IN_REPAIR); + share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | + 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 2fbc84bae5f..cc6e3f239e0 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -619,6 +619,9 @@ struct st_maria_handler #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 */ +#define STATE_CRASHED_PRINTED 2048 + +#define STATE_CRASHED_FLAGS (STATE_CRASHED | STATE_CRASHED_ON_REPAIR | STATE_CRASHED_PRINTED) /* options to maria_read_cache */ @@ -701,7 +704,6 @@ struct st_maria_handler #endif #define DBUG_DUMP_KEY(name, key) DBUG_DUMP(name, (key)->data, (key)->data_length + (key)->ref_length) - /* Functions to store length of space packed keys, VARCHAR or BLOB keys */ #define store_key_length(key,length) \ @@ -805,6 +807,7 @@ extern char *maria_data_root; extern uchar maria_zero_string[]; extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data; extern my_bool maria_recovery_verbose; +extern my_bool maria_assert_if_crashed_table; extern HASH maria_stored_state; extern int (*maria_create_trn_hook)(MARIA_HA *); @@ -918,6 +921,7 @@ extern int _ma_writeinfo(MARIA_HA *info, uint options); extern int _ma_test_if_changed(MARIA_HA *info); extern int _ma_mark_file_changed(MARIA_HA *info); extern void _ma_mark_file_crashed(MARIA_SHARE *share); +void _ma_set_fatal_error(MARIA_SHARE *share, int error); extern my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid); extern my_bool _ma_check_if_zero(uchar *pos, size_t size); extern int _ma_decrement_open_count(MARIA_HA *info); @@ -1261,3 +1265,4 @@ extern my_bool maria_flush_log_for_page_none(uchar *page, pgcache_page_no_t page_no, uchar *data_ptr); extern PAGECACHE *maria_log_pagecache; +extern uint _ma_file_callback_to_id(void *callback_data); diff --git a/storage/myisam/mi_panic.c b/storage/myisam/mi_panic.c index 74c93761b61..b270712ba2d 100644 --- a/storage/myisam/mi_panic.c +++ b/storage/myisam/mi_panic.c @@ -71,8 +71,8 @@ int mi_panic(enum ha_panic_function flag) if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) error = my_errno; info->s->kfile=info->dfile= -1; /* Files aren't open anymore */ - break; #endif + break; case HA_PANIC_READ: /* Restore to before WRITE */ #ifdef CANT_OPEN_FILES_TWICE { /* Open closed files */ |