Commit 26565ae1 authored by Michael Widenius's avatar Michael Widenius

Aria issues:

- Fix for LP#700623 "Aria recovery: ma_blockrec.c:3930: _ma_update_at_original_place: Assertion `block->org_bitmap_value == _ma_bitmap_get_page_bits(info, &info->s->bitmap, page)' failed"
  - Issue was that when deleting a tail page where all index entries where full, the page was marked wrongly in the bitmap.
- If debug_assert_if_crashed_table is set, we now crash when we find Aria corrupted.
- Write more information if we find something wrong with the bitmap.
- Fixed that REPAIR also can fix wrong create_rename_lsn issues (a very unlikely event)
- Define STATE_CRASHED_FLAGS as set of all CRASHED flags (to simplify code)


storage/maria/ha_maria.cc:
  Mark the normal page cache (not the page cache for the logs) so that we can request extra debugging for it.
  Copy the value of debug_assert_if_crashed_table to maria_assert_if_crashed_table so that we can request a crash at exactly the point where we find Aria corrupted.
  Use STATE_CRASHED_FLAGS
storage/maria/ma_bitmap.c:
  Made bits_to_txt extern so that we can use this in maria_chk
  Added extra information to the log files to be able to easier find bitmap failures in recovery. (When compiling with -DEXTRA_DEBUG_BITMAP)
  Added _ma_get_bitmap_description() to request a clear text description of the bitmap.
  Simplify _ma_check_bitmap_data(), as we know the bitmap pattern in the caller.
storage/maria/ma_blockrec.c:
  In delete_head_or_tail(), fixed a bug where we sent wrong information to _ma_bitmap_set() if the directory was full for a page that should be freed.
  This fixed LP#700623 (failure in bitmap found during recovery)
storage/maria/ma_blockrec.h:
  Added definitions for _ma_get_bitmap_description() and bits_to_txt
storage/maria/ma_check.c:
  Simplify call to _ma_check_bitmap_data().
  Write more information if we find something wrong with the bitmap.
  Moved getting clear text information about the bitmap to ma_bitmap.c::_ma_get_bitmap_description()
storage/maria/ma_checkpoint.c:
  More asserts
storage/maria/ma_create.c:
  Fix wrong create_rename_lsn during repair.
  (Create_rename_lsn can be too big if someone restores an old maria_log_file after an Aria file was created)
storage/maria/ma_delete.c:
  Call _ma_set_fatal_error() in case of crashed file
  Remove not needed test of save_errno == HA_ERR_KEY_NOT_FOUND. (Handled by other code
storage/maria/ma_extra.c:
  Call _ma_set_fatal_error() in case of crashed file
  Reset share->bitmap.changed_not_flushed to not cause new ASSERTS to trigger.
  Added _ma_file_callback_to_id() for writing share->id to log file in case of DEBUG logging.
storage/maria/ma_init.c:
  Destroy also translog if it's readonly (as when called by maria_read_log -d)
storage/maria/ma_key.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_key_recover.c:
  STATE_CRASHED -> STATE_CRASHED_FLAGS
storage/maria/ma_keycache.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_locking.c:
  Call _ma_set_fatal_error() in case of crashed file.
  Added _ma_set_fatal_error()
storage/maria/ma_open.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_page.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_pagecache.c:
  Added extra information to log file to simply debugging of bitmap errors.
storage/maria/ma_pagecache.h:
  Added extra_debug flag to allow marking of row and index cache for extra logging (for debugging).
storage/maria/ma_panic.c:
  Flush both data and index blocks in case of HA_PANIC_CLOSE
  Fixed wrong position of 'break'. (Not critical for MariaDB as MariaDB never uses this code)
storage/maria/ma_recovery_util.c:
  Avoid writing extra not needed \n to DBUG log.
storage/maria/ma_rkey.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_search.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/ma_static.c:
  Define maria_assert_if_crashed_table
storage/maria/ma_update.c:
  Call _ma_set_fatal_error() in case of crashed file.
  The new code also avoids a problem where we before would print the error twice.
storage/maria/ma_write.c:
  Call _ma_set_fatal_error() in case of crashed file
storage/maria/maria_chk.c:
  STATE_CRASHED -> STATE_CRASHED_FLAGS
storage/maria/maria_def.h:
  Added STATE_CRASHED_PRINTED to avoid giving error message about crash twice.
  Added STATE_CRASHED_FLAGS to be able to easily detect and set all CRASHED related flags.
  Added prototypes for new functions.
storage/myisam/mi_panic.c:
  Fixed wrong position of 'break'. (Not critical for MariaDB as MariaDB never uses this code)
parent ab3e7f9f
...@@ -1065,8 +1065,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) ...@@ -1065,8 +1065,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!maria_is_crashed(file) && if (!maria_is_crashed(file) &&
(((param.testflag & T_CHECK_ONLY_CHANGED) && (((param.testflag & T_CHECK_ONLY_CHANGED) &&
!(share->state.changed & (STATE_CHANGED | STATE_CRASHED | !(share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR |
STATE_IN_REPAIR)) && STATE_IN_REPAIR)) &&
share->state.open_count == 0) || share->state.open_count == 0) ||
((param.testflag & T_FAST) && (share->state.open_count == ((param.testflag & T_FAST) && (share->state.open_count ==
...@@ -1104,15 +1103,15 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) ...@@ -1104,15 +1103,15 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!error) if (!error)
{ {
if ((share->state.changed & (STATE_CHANGED | if ((share->state.changed & (STATE_CHANGED |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR | STATE_CRASHED_FLAGS |
STATE_CRASHED | STATE_NOT_ANALYZED)) || STATE_IN_REPAIR | STATE_NOT_ANALYZED)) ||
(param.testflag & T_STATISTICS) || maria_is_crashed(file)) (param.testflag & T_STATISTICS) || maria_is_crashed(file))
{ {
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
pthread_mutex_lock(&share->intern_lock); pthread_mutex_lock(&share->intern_lock);
DBUG_PRINT("info", ("Reseting crashed state")); DBUG_PRINT("info", ("Reseting crashed state"));
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); STATE_IN_REPAIR);
if (!(table->db_stat & HA_READ_ONLY)) if (!(table->db_stat & HA_READ_ONLY))
error= maria_update_state_info(&param, file, error= maria_update_state_info(&param, file,
UPDATE_TIME | UPDATE_OPEN_COUNT | UPDATE_TIME | UPDATE_OPEN_COUNT |
...@@ -1544,8 +1543,8 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) ...@@ -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)) if ((share->state.changed & STATE_CHANGED) || maria_is_crashed(file))
{ {
DBUG_PRINT("info", ("Reseting crashed state")); DBUG_PRINT("info", ("Reseting crashed state"));
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); STATE_IN_REPAIR);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
} }
/* /*
...@@ -2025,8 +2024,7 @@ bool ha_maria::check_and_repair(THD *thd) ...@@ -2025,8 +2024,7 @@ bool ha_maria::check_and_repair(THD *thd)
check_opt.flags= T_MEDIUM | T_AUTO_REPAIR; check_opt.flags= T_MEDIUM | T_AUTO_REPAIR;
error= 1; error= 1;
if ((file->s->state.changed & if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) ==
(STATE_CRASHED | STATE_CRASHED_ON_REPAIR | STATE_MOVED)) ==
STATE_MOVED) STATE_MOVED)
{ {
sql_print_information("Zerofilling moved table: '%s'", sql_print_information("Zerofilling moved table: '%s'",
...@@ -2077,7 +2075,7 @@ bool ha_maria::check_and_repair(THD *thd) ...@@ -2077,7 +2075,7 @@ bool ha_maria::check_and_repair(THD *thd)
bool ha_maria::is_crashed() const 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)); (my_disable_locking && file->s->state.open_count));
} }
...@@ -3287,6 +3285,8 @@ static int ha_maria_init(void *p) ...@@ -3287,6 +3285,8 @@ static int ha_maria_init(void *p)
ma_checkpoint_init(checkpoint_interval); ma_checkpoint_init(checkpoint_interval);
maria_multi_threaded= maria_in_ha_maria= TRUE; maria_multi_threaded= maria_in_ha_maria= TRUE;
maria_create_trn_hook= maria_create_trn_for_mysql; 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) #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 */ /* We can only test for sub paths if my_symlink.c is using realpath */
......
...@@ -104,10 +104,11 @@ ...@@ -104,10 +104,11 @@
- On checkpoint - On checkpoint
(Ie: When we do a checkpoint, we have to ensure that all bitmaps are (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). 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) to simplify things)
The flow of writing a row is that: The flow of writing a row is that:
- Mark the bitmap not flushable (_ma_bitmap_flushable(X, 1))
- Lock the bitmap - Lock the bitmap
- Decide which data pages we will write to - Decide which data pages we will write to
- Mark them full in the bitmap page so that other threads do not try to - Mark them full in the bitmap page so that other threads do not try to
...@@ -119,6 +120,7 @@ ...@@ -119,6 +120,7 @@
pages (that is, we marked pages full but when we are done we realize pages (that is, we marked pages full but when we are done we realize
we didn't fill them) we didn't fill them)
- Unlock the bitmap. - Unlock the bitmap.
- Mark the bitmap flushable (_ma_bitmap_flushable(X, -1))
*/ */
#include "maria_def.h" #include "maria_def.h"
...@@ -127,6 +129,12 @@ ...@@ -127,6 +129,12 @@
#define FULL_HEAD_PAGE 4 #define FULL_HEAD_PAGE 4
#define FULL_TAIL_PAGE 7 #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*/ /*#define WRONG_BITMAP_FLUSH 1*/ /*define only for provoking bugs*/
#undef WRONG_BITMAP_FLUSH #undef WRONG_BITMAP_FLUSH
...@@ -273,6 +281,12 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share) ...@@ -273,6 +281,12 @@ my_bool _ma_bitmap_end(MARIA_SHARE *share)
delete_dynamic(&share->bitmap.pinned_pages); delete_dynamic(&share->bitmap.pinned_pages);
my_free(share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR)); my_free(share->bitmap.map, MYF(MY_ALLOW_ZERO_PTR));
share->bitmap.map= 0; 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; return res;
} }
...@@ -353,6 +367,24 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) ...@@ -353,6 +367,24 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
my_bool res= 0; my_bool res= 0;
MARIA_FILE_BITMAP *bitmap= &share->bitmap; MARIA_FILE_BITMAP *bitmap= &share->bitmap;
DBUG_ENTER("_ma_bitmap_flush_all"); 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); pthread_mutex_lock(&bitmap->bitmap_lock);
if (bitmap->changed || bitmap->changed_not_flushed) if (bitmap->changed || bitmap->changed_not_flushed)
{ {
...@@ -364,6 +396,15 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) ...@@ -364,6 +396,15 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock); pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock);
} }
#endif #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); DBUG_ASSERT(bitmap->flush_all_requested == 1);
/* /*
Bitmap is in a flushable state: its contents in memory are reflected by 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) ...@@ -680,7 +721,7 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
Print bitmap for debugging Print bitmap for debugging
SYNOPSIS SYNOPSIS
_ma_print_bitmap() _ma_print_bitmap_changes()
bitmap Bitmap to print bitmap Bitmap to print
IMPLEMENTATION IMPLEMENTATION
...@@ -691,12 +732,6 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern) ...@@ -691,12 +732,6 @@ static inline uint pattern_to_size(MARIA_FILE_BITMAP *bitmap, uint pattern)
#ifndef DBUG_OFF #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) static void _ma_print_bitmap_changes(MARIA_FILE_BITMAP *bitmap)
{ {
uchar *pos, *end, *org_pos; uchar *pos, *end, *org_pos;
...@@ -747,7 +782,6 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, ...@@ -747,7 +782,6 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
uchar *pos, *end; uchar *pos, *end;
char llbuff[22]; char llbuff[22];
end= bitmap->map + bitmap->used_size;
DBUG_LOCK_FILE; DBUG_LOCK_FILE;
fprintf(DBUG_FILE,"\nDump of bitmap page at %s\n", llstr(page, llbuff)); 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, ...@@ -781,6 +815,56 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
#endif /* DBUG_OFF */ #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 Reading & writing bitmap pages
***************************************************************************/ ***************************************************************************/
...@@ -2383,16 +2467,14 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) ...@@ -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 The page has all bits set; The following test is an optimization
to not set the bits to the same value as before. 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 (bits != current_bitmap_value)
{ {
if (set_page_bits(info, bitmap, block->page, bits)) if (set_page_bits(info, bitmap, block->page, bits))
goto err; goto err;
} }
else
{
DBUG_ASSERT(current_bitmap_value ==
_ma_bitmap_get_page_bits(info, bitmap, block->page));
}
} }
else if (!(block->used & BLOCKUSED_USED) && else if (!(block->used & BLOCKUSED_USED) &&
_ma_bitmap_reset_full_page_bits(info, bitmap, _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, ...@@ -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_type What kind of page this is
page Adress to page page Adress to page
empty_space Empty space on page empty_space Empty space on page
bitmap_pattern Store here the pattern that was in the bitmap for the bitmap_pattern Bitmap pattern for page (from bitmap)
page. This is always updated.
RETURN RETURN
0 ok 0 ok
1 error 1 error
*/ */
my_bool _ma_check_bitmap_data(MARIA_HA *info, my_bool _ma_check_bitmap_data(MARIA_HA *info, enum en_page_type page_type,
enum en_page_type page_type, pgcache_page_no_t page, uint empty_space, uint bitmap_pattern)
uint empty_space, uint *bitmap_pattern)
{ {
uint bits; uint bits;
switch (page_type) { switch (page_type) {
...@@ -2552,8 +2632,7 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info, ...@@ -2552,8 +2632,7 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info,
bits= 0; /* to satisfy compiler */ bits= 0; /* to satisfy compiler */
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return ((*bitmap_pattern= _ma_bitmap_get_page_bits(info, &info->s->bitmap, return (bitmap_pattern != bits);
page)) != bits);
} }
......
...@@ -4106,11 +4106,11 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ...@@ -4106,11 +4106,11 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
{ {
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
uint empty_space; uint empty_space;
uint block_size= share->block_size; int res;
my_bool page_is_empty;
uchar *buff; uchar *buff;
LSN lsn; LSN lsn;
MARIA_PINNED_PAGE page_link; MARIA_PINNED_PAGE page_link;
int res;
enum pagecache_page_lock lock_at_write, lock_at_unpin; enum pagecache_page_lock lock_at_write, lock_at_unpin;
DBUG_ENTER("delete_head_or_tail"); DBUG_ENTER("delete_head_or_tail");
DBUG_PRINT("enter", ("id: %lu (%lu:%u)", DBUG_PRINT("enter", ("id: %lu (%lu:%u)",
...@@ -4140,13 +4140,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ...@@ -4140,13 +4140,14 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
lock_at_unpin= PAGECACHE_LOCK_READ_UNLOCK; 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) if (res < 0)
DBUG_RETURN(1); DBUG_RETURN(1);
if (res == 0) /* after our deletion, page is still not empty */ if (res == 0) /* after our deletion, page is still not empty */
{ {
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE]; uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE];
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1]; LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
page_is_empty= 0;
if (share->now_transactional) if (share->now_transactional)
{ {
/* Log REDO data */ /* Log REDO data */
...@@ -4167,6 +4168,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ...@@ -4167,6 +4168,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
} }
else /* page is now empty */ else /* page is now empty */
{ {
page_is_empty= 1;
if (share->now_transactional) if (share->now_transactional)
{ {
uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE]; uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE];
...@@ -4198,8 +4200,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ...@@ -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 If there is not enough space for all possible tails, mark the
page full page full
*/ */
if (!head && !enough_free_entries(buff, share->block_size, if (!head && !page_is_empty && !enough_free_entries(buff, share->block_size,
1 + share->base.blobs)) 1 + share->base.blobs))
empty_space= 0; empty_space= 0;
DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space)); DBUG_RETURN(_ma_bitmap_set(info, page, head, empty_space));
......
...@@ -78,6 +78,10 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_ ...@@ -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_EXTENTS 128
#define ROW_FLAG_ALL (1+2+4+8+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 ********/ /******** Variables that affects how data pages are utilized ********/
/* Minium size of tail segment */ /* Minium size of tail segment */
...@@ -181,6 +185,8 @@ TRANSLOG_ADDRESS ...@@ -181,6 +185,8 @@ TRANSLOG_ADDRESS
maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr); maria_page_get_lsn(uchar *page, pgcache_page_no_t page_no, uchar* data_ptr);
/* ma_bitmap.c */ /* ma_bitmap.c */
extern const char *bits_to_txt[];
my_bool _ma_bitmap_init(MARIA_SHARE *share, File file); my_bool _ma_bitmap_init(MARIA_SHARE *share, File file);
my_bool _ma_bitmap_end(MARIA_SHARE *share); my_bool _ma_bitmap_end(MARIA_SHARE *share);
my_bool _ma_bitmap_flush(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, ...@@ -206,8 +212,7 @@ my_bool _ma_bitmap_find_new_place(MARIA_HA *info, MARIA_ROW *new_row,
MARIA_BITMAP_BLOCKS *result_blocks); MARIA_BITMAP_BLOCKS *result_blocks);
my_bool _ma_check_bitmap_data(MARIA_HA *info, my_bool _ma_check_bitmap_data(MARIA_HA *info,
enum en_page_type page_type, 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, my_bool _ma_check_if_right_bitmap_type(MARIA_HA *info,
enum en_page_type page_type, enum en_page_type page_type,
pgcache_page_no_t page, pgcache_page_no_t page,
...@@ -225,6 +230,10 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file, ...@@ -225,6 +230,10 @@ void _ma_bitmap_set_pagecache_callbacks(PAGECACHE_FILE *file,
void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
pgcache_page_no_t page); pgcache_page_no_t page);
#endif #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 _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
uint page_type, uint page_type,
......
...@@ -1822,6 +1822,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, ...@@ -1822,6 +1822,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
pos+= block_size, page++) pos+= block_size, page++)
{ {
uint row_count, real_row_count, empty_space, page_type, bitmap_pattern; uint row_count, real_row_count, empty_space, page_type, bitmap_pattern;
uint bitmap_for_page;
LINT_INIT(row_count); LINT_INIT(row_count);
LINT_INIT(empty_space); LINT_INIT(empty_space);
...@@ -1856,7 +1857,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, ...@@ -1856,7 +1857,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
offset= offset_page & 7; offset= offset_page & 7;
data= bitmap_buff + offset_page / 8; data= bitmap_buff + offset_page / 8;
bitmap_pattern= uint2korr(data); bitmap_pattern= uint2korr(data);
if (!((bitmap_pattern >> offset) & 7)) if (!(bitmap_for_page= ((bitmap_pattern >> offset) & 7)))
{ {
param->empty+= block_size; param->empty+= block_size;
param->del_blocks++; param->del_blocks++;
...@@ -1879,8 +1880,9 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, ...@@ -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) if (page_type == UNALLOCATED_PAGE || page_type >= MAX_PAGE_TYPE)
{ {
_ma_check_print_error(param, _ma_check_print_error(param,
"Page: %9s Found wrong page type %d", "Page: %9s Found wrong page type %d. Bitmap: %d '%s'",
llstr(page, llbuff), page_type); llstr(page, llbuff), page_type,
bitmap_for_page, bits_to_txt[bitmap_for_page]);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err; goto err;
continue; continue;
...@@ -1927,20 +1929,17 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, ...@@ -1927,20 +1929,17 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
param->used+= block_size; param->used+= block_size;
break; break;
} }
if (_ma_check_bitmap_data(info, page_type, page, if (_ma_check_bitmap_data(info, page_type,
full_dir ? 0 : empty_space, 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, _ma_check_print_error(param,
"Page %9s: Wrong data in bitmap. Page_type: " "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, 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)) if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
goto err; goto err;
} }
...@@ -6831,39 +6830,7 @@ static void print_bitmap_description(MARIA_SHARE *share, ...@@ -6831,39 +6830,7 @@ static void print_bitmap_description(MARIA_SHARE *share,
pgcache_page_no_t page, pgcache_page_no_t page,
uchar *bitmap_data) uchar *bitmap_data)
{ {
uchar *pos, *end; char tmp[MAX_BITMAP_INFO_LENGTH];
MARIA_FILE_BITMAP *bitmap= &share->bitmap; _ma_get_bitmap_description(&share->bitmap, bitmap_data, page, tmp);
uint count=0, dot_printed= 0; printf("Bitmap page %lu\n%s", (ulong) page, tmp);
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);
} }
...@@ -130,6 +130,9 @@ int ma_checkpoint_execute(CHECKPOINT_LEVEL level, my_bool no_wait) ...@@ -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 */ /* from then on, we are sure to be and stay the only checkpointer */
result= really_execute_checkpoint(); result= really_execute_checkpoint();
DBUG_EXECUTE_IF("maria_crash_after_checkpoint",
{ DBUG_PRINT("maria_crash", ("now")); DBUG_ABORT(); });
pthread_cond_broadcast(&COND_checkpoint); pthread_cond_broadcast(&COND_checkpoint);
end: end:
DBUG_RETURN(result); DBUG_RETURN(result);
...@@ -1065,6 +1068,14 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon) ...@@ -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 _ma_bitmap_flush_all() may wait, so don't keep intern_lock as
otherwise this would deadlock with allocate_and_write_block_record() otherwise this would deadlock with allocate_and_write_block_record()
......
...@@ -1387,7 +1387,13 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid, ...@@ -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.skip_redo_lsn= share->state.is_of_horizon= lsn;
share->state.create_trid= create_trid; share->state.create_trid= create_trid;
mi_int8store(trid_buff, 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; share->state.create_rename_lsn= lsn;
if (share->id != 0) if (share->id != 0)
......
...@@ -135,18 +135,13 @@ err: ...@@ -135,18 +135,13 @@ err:
save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */ save_errno= HA_ERR_INTERNAL_ERROR; /* Should never happen */
mi_sizestore(lastpos, info->cur_row.lastpos); 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)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */ info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */ 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); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED; save_errno= HA_ERR_CRASHED;
} }
DBUG_RETURN(my_errno= save_errno); DBUG_RETURN(my_errno= save_errno);
} /* maria_delete */ } /* maria_delete */
...@@ -213,7 +208,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key, ...@@ -213,7 +208,7 @@ my_bool _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
if ((old_root=*root) == HA_OFFSET_ERROR) if ((old_root=*root) == HA_OFFSET_ERROR)
{ {
my_errno=HA_ERR_CRASHED; _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ 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, ...@@ -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, if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag,
&kpos))) &kpos)))
{ {
my_errno= HA_ERR_CRASHED; _ma_set_fatal_error(share, HA_ERR_CRASHED);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
root= _ma_row_pos_from_key(&tmp_key); 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, ...@@ -410,8 +405,9 @@ static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
{ {
if (!nod_flag) if (!nod_flag)
{ {
/* This should newer happend */
DBUG_PRINT("error",("Didn't find key")); 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; goto err;
} }
save_flag=0; save_flag=0;
......
...@@ -175,8 +175,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, ...@@ -175,8 +175,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
{ {
if ((error= flush_io_cache(&info->rec_cache))) if ((error= flush_io_cache(&info->rec_cache)))
{ {
maria_print_error(info->s, HA_ERR_CRASHED); /* Fatal error found */
maria_mark_crashed(info); /* Fatal error found */ _ma_set_fatal_error(share, HA_ERR_CRASHED);
} }
} }
break; break;
...@@ -299,6 +299,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, ...@@ -299,6 +299,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
} }
pthread_mutex_lock(&THR_LOCK_maria); pthread_mutex_lock(&THR_LOCK_maria);
pthread_mutex_lock(&share->intern_lock); /* protect against Checkpoint */ 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 */ /* this makes the share not be re-used next time the table is opened */
share->last_version= 0L; /* Impossible version */ share->last_version= 0L; /* Impossible version */
pthread_mutex_unlock(&share->intern_lock); pthread_mutex_unlock(&share->intern_lock);
...@@ -382,8 +384,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, ...@@ -382,8 +384,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (share->data_file_type == BLOCK_RECORD && if (share->data_file_type == BLOCK_RECORD &&
share->bitmap.file.file >= 0) 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))) if (do_flush && my_sync(share->bitmap.file.file, MYF(0)))
error= my_errno; error= my_errno;
share->bitmap.changed_not_flushed= 0;
} }
/* For protection against Checkpoint, we set under intern_lock: */ /* For protection against Checkpoint, we set under intern_lock: */
share->last_version= 0L; /* Impossible version */ share->last_version= 0L; /* Impossible version */
...@@ -415,9 +420,9 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, ...@@ -415,9 +420,9 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
error= my_errno; error= my_errno;
if (error) if (error)
{ {
/* Fatal error found */
share->changed= 1; share->changed= 1;
maria_print_error(info->s, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
maria_mark_crashed(info); /* Fatal error found */
} }
} }
break; break;
...@@ -560,6 +565,12 @@ int _ma_sync_table_files(const MARIA_HA *info) ...@@ -560,6 +565,12 @@ int _ma_sync_table_files(const MARIA_HA *info)
my_sync(info->s->kfile.file, MYF(MY_WME))); 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 @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, ...@@ -608,6 +619,7 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
{ {
pthread_mutex_lock(&share->bitmap.bitmap_lock); pthread_mutex_lock(&share->bitmap.bitmap_lock);
share->bitmap.changed= 0; share->bitmap.changed= 0;
share->bitmap.changed_not_flushed= 0;
pthread_mutex_unlock(&share->bitmap.bitmap_lock); pthread_mutex_unlock(&share->bitmap.bitmap_lock);
} }
if (flush_pagecache_blocks(share->pagecache, &info->dfile, 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, ...@@ -622,7 +634,6 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
if (!error) if (!error)
return 0; return 0;
maria_print_error(info->s, HA_ERR_CRASHED); _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
maria_mark_crashed(info);
return 1; return 1;
} }
...@@ -99,7 +99,7 @@ void maria_end(void) ...@@ -99,7 +99,7 @@ void maria_end(void)
trid, recovery_failures); trid, recovery_failures);
} }
trnman_destroy(); trnman_destroy();
if (translog_status == TRANSLOG_OK) if (translog_status == TRANSLOG_OK || translog_status == TRANSLOG_READONLY)
translog_destroy(); translog_destroy();
end_pagecache(maria_log_pagecache, TRUE); end_pagecache(maria_log_pagecache, TRUE);
end_pagecache(maria_pagecache, TRUE); end_pagecache(maria_pagecache, TRUE);
......
...@@ -636,8 +636,7 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos) ...@@ -636,8 +636,7 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
{ /* Read only key */ { /* Read only key */
if (_ma_put_key_in_record(info,(uint) info->lastinx,buf)) if (_ma_put_key_in_record(info,(uint) info->lastinx,buf))
{ {
maria_print_error(info->s, HA_ERR_CRASHED); _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return -1; return -1;
} }
info->update|= HA_STATE_AKTIV; /* We should find a record */ info->update|= HA_STATE_AKTIV; /* We should find a record */
......
...@@ -66,7 +66,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) ...@@ -66,7 +66,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn)
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
DBUG_ASSERT((!pinned_page->changed || DBUG_ASSERT((!pinned_page->changed ||
undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional) || undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional) ||
(info->s->state.changed & STATE_CRASHED)); (info->s->state.changed & STATE_CRASHED_FLAGS));
#endif #endif
pagecache_unlock_by_link(info->s->pagecache, pinned_page->link, pagecache_unlock_by_link(info->s->pagecache, pinned_page->link,
pinned_page->unlock, PAGECACHE_UNPIN, pinned_page->unlock, PAGECACHE_UNPIN,
......
...@@ -79,8 +79,8 @@ int maria_assign_to_pagecache(MARIA_HA *info, ...@@ -79,8 +79,8 @@ int maria_assign_to_pagecache(MARIA_HA *info,
if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_RELEASE)) if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_RELEASE))
{ {
error= my_errno; error= my_errno;
maria_print_error(info->s, HA_ERR_CRASHED); /* Mark that table must be checked */
maria_mark_crashed(info); /* Mark that table must be checked */ _ma_set_fatal_error(share, error);
} }
/* /*
......
...@@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type) ...@@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
{ {
if (end_io_cache(&info->rec_cache)) if (end_io_cache(&info->rec_cache))
{ {
error=my_errno; error= my_errno;
maria_print_error(info->s, HA_ERR_CRASHED); _ma_set_fatal_error(share, error);
maria_mark_crashed(info);
} }
} }
if (!count) if (!count)
...@@ -129,10 +128,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type) ...@@ -129,10 +128,7 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
else else
share->not_flushed=1; share->not_flushed=1;
if (error) if (error)
{ _ma_set_fatal_error(share, error);
maria_print_error(info->s, HA_ERR_CRASHED);
maria_mark_crashed(info);
}
} }
} }
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
...@@ -528,6 +524,28 @@ void _ma_mark_file_crashed(MARIA_SHARE *share) ...@@ -528,6 +524,28 @@ void _ma_mark_file_crashed(MARIA_SHARE *share)
DBUG_VOID_RETURN; 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 @brief Set uuid of for a Maria file
......
...@@ -41,10 +41,10 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state); ...@@ -41,10 +41,10 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state);
pos+=size;} pos+=size;}
#define disk_pos_assert(pos, end_pos) \ #define disk_pos_assert(share, pos, end_pos) \
if (pos > end_pos) \ if (pos > end_pos) \
{ \ { \
my_errno=HA_ERR_CRASHED; \ _ma_set_fatal_error(share, HA_ERR_CRASHED); \
goto err; \ goto err; \
} }
...@@ -387,7 +387,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -387,7 +387,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
errpos= 3; errpos= 3;
if (my_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP))) 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; goto err;
} }
len=mi_uint2korr(share->state.header.state_info_length); 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) ...@@ -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); disk_pos= _ma_base_info_read(disk_cache + base_pos, &share->base);
share->state.state_length=base_pos; 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) && 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) && ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
(my_disable_locking && share->state.open_count)))) (my_disable_locking && share->state.open_count))))
{ {
...@@ -456,7 +458,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -456,7 +458,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
/* sanity check */ /* sanity check */
if (share->base.keystart > 65535 || share->base.rec_reflength > 8) 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; goto err;
} }
...@@ -567,7 +569,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -567,7 +569,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->keyinfo[i].share= share; share->keyinfo[i].share= share;
disk_pos=_ma_keydef_read(disk_pos, &share->keyinfo[i]); disk_pos=_ma_keydef_read(disk_pos, &share->keyinfo[i]);
share->keyinfo[i].key_nr= 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); end_pos);
if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE) if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
share->have_rtree= 1; share->have_rtree= 1;
...@@ -615,7 +618,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -615,7 +618,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
pos[0].language= pos[-1].language; pos[0].language= pos[-1].language;
if (!(pos[0].charset= pos[-1].charset)) if (!(pos[0].charset= pos[-1].charset))
{ {
my_errno=HA_ERR_CRASHED; _ma_set_fatal_error(share, HA_ERR_CRASHED);
goto err; goto err;
} }
pos++; pos++;
...@@ -647,7 +650,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) ...@@ -647,7 +650,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < uniques ; i++) for (i=0 ; i < uniques ; i++)
{ {
disk_pos=_ma_uniquedef_read(disk_pos, &share->uniqueinfo[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); HA_KEYSEG_SIZE, end_pos);
share->uniqueinfo[i].seg=pos; share->uniqueinfo[i].seg=pos;
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,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) ...@@ -751,7 +755,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->base.extra_rec_buff_size, share->base.extra_rec_buff_size,
share->base.max_key_length); 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); end_pos);
for (i= j= 0 ; i < share->base.fields ; i++) for (i= j= 0 ; i < share->base.fields ; i++)
{ {
...@@ -1875,7 +1880,7 @@ int maria_enable_indexes(MARIA_HA *info) ...@@ -1875,7 +1880,7 @@ int maria_enable_indexes(MARIA_HA *info)
DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu", DBUG_PRINT("error", ("data_file_length: %lu key_file_length: %lu",
(ulong) share->state.state.data_file_length, (ulong) share->state.state.data_file_length,
(ulong) share->state.state.key_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; error= HA_ERR_CRASHED;
} }
else else
......
...@@ -127,8 +127,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, ...@@ -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)); DBUG_PRINT("error",("Got errno: %d from pagecache_read",my_errno));
info->last_keypage=HA_OFFSET_ERROR; info->last_keypage=HA_OFFSET_ERROR;
maria_print_error(share, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
info->last_keypage= pos; info->last_keypage= pos;
...@@ -159,8 +158,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info, ...@@ -159,8 +158,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *page, MARIA_HA *info,
_ma_get_keynr(share, tmp))); _ma_get_keynr(share, tmp)));
DBUG_DUMP("page", tmp, page_size); DBUG_DUMP("page", tmp, page_size);
info->last_keypage = HA_OFFSET_ERROR; info->last_keypage = HA_OFFSET_ERROR;
maria_print_error(share, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
...@@ -552,8 +550,7 @@ my_bool _ma_compact_keypage(MARIA_PAGE *ma_page, TrID min_read_from) ...@@ -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", DBUG_PRINT("error",("Couldn't find last key: page_pos: 0x%lx",
(long) page)); (long) page));
maria_print_error(share, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (key_has_transid(page-1)) if (key_has_transid(page-1))
......
...@@ -614,6 +614,26 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache, ...@@ -614,6 +614,26 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache,
DBUG_ENTER("pagecache_fwrite"); DBUG_ENTER("pagecache_fwrite");
DBUG_ASSERT(type != PAGECACHE_READ_UNKNOWN_PAGE); 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 */ /* Todo: Integrate this with write_callback so we have only one callback */
if ((*filedesc->flush_log_callback)(buffer, pageno, filedesc->callback_data)) if ((*filedesc->flush_log_callback)(buffer, pageno, filedesc->callback_data))
DBUG_RETURN(1); DBUG_RETURN(1);
......
...@@ -173,6 +173,7 @@ typedef struct st_pagecache ...@@ -173,6 +173,7 @@ typedef struct st_pagecache
my_bool resize_in_flush; /* true during flush of resize operation */ 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 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 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() */ HASH files_in_flush; /**< files in flush_pagecache_blocks_int() */
} PAGECACHE; } PAGECACHE;
......
...@@ -67,8 +67,8 @@ int maria_panic(enum ha_panic_function flag) ...@@ -67,8 +67,8 @@ int maria_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA) if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break; break;
#endif #endif
if (flush_pagecache_blocks(info->s->pagecache, &info->s->kfile, if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_RELEASE)) FLUSH_RELEASE, FLUSH_RELEASE))
error=my_errno; error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED) if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache)) if (flush_io_cache(&info->rec_cache))
...@@ -92,8 +92,8 @@ int maria_panic(enum ha_panic_function flag) ...@@ -92,8 +92,8 @@ int maria_panic(enum ha_panic_function flag)
if (info->dfile.file >= 0 && my_close(info->dfile.file, MYF(0))) if (info->dfile.file >= 0 && my_close(info->dfile.file, MYF(0)))
error = my_errno; error = my_errno;
info->s->kfile.file= info->dfile.file= -1;/* Files aren't open anymore */ info->s->kfile.file= info->dfile.file= -1;/* Files aren't open anymore */
break;
#endif #endif
break;
case HA_PANIC_READ: /* Restore to before WRITE */ case HA_PANIC_READ: /* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE #ifdef CANT_OPEN_FILES_TWICE
{ /* Open closed files */ { /* Open closed files */
......
...@@ -59,9 +59,11 @@ void tprint(FILE *trace_file __attribute__ ((unused)), ...@@ -59,9 +59,11 @@ void tprint(FILE *trace_file __attribute__ ((unused)),
va_list args; va_list args;
#ifndef DBUG_OFF #ifndef DBUG_OFF
{ {
char buff[1024]; char buff[1024], *end;
va_start(args, format); va_start(args, format);
vsnprintf(buff, sizeof(buff)-1, format, args); vsnprintf(buff, sizeof(buff)-1, format, args);
if (*(end= strend(buff)) == '\n')
*end= 0; /* Don't print end \n */
DBUG_PRINT("info", ("%s", buff)); DBUG_PRINT("info", ("%s", buff));
va_end(args); va_end(args);
} }
......
...@@ -91,8 +91,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data, ...@@ -91,8 +91,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
case HA_KEY_ALG_RTREE: case HA_KEY_ALG_RTREE:
if (maria_rtree_find_first(info, &key, nextflag) < 0) if (maria_rtree_find_first(info, &key, nextflag) < 0)
{ {
maria_print_error(info->s, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
info->cur_row.lastpos= HA_OFFSET_ERROR; info->cur_row.lastpos= HA_OFFSET_ERROR;
} }
break; break;
......
...@@ -379,8 +379,7 @@ int _ma_seq_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, ...@@ -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); length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &page);
if (length == 0 || page > end) if (length == 0 || page > end)
{ {
maria_print_error(share, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error", DBUG_PRINT("error",
("Found wrong key: length: %u page: 0x%lx end: 0x%lx", ("Found wrong key: length: %u page: 0x%lx end: 0x%lx",
length, (long) page, (long) end)); length, (long) page, (long) end));
...@@ -562,8 +561,7 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page, ...@@ -562,8 +561,7 @@ int _ma_prefix_search(const MARIA_KEY *key, const MARIA_PAGE *ma_page,
if (page > end) if (page > end)
{ {
maria_print_error(share, HA_ERR_CRASHED); _ma_set_fatal_error(share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error", DBUG_PRINT("error",
("Found wrong key: length: %u page: 0x%lx end: %lx", ("Found wrong key: length: %u page: 0x%lx end: %lx",
length, (long) page, (long) end)); length, (long) page, (long) end));
...@@ -1043,8 +1041,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, ...@@ -1043,8 +1041,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
{ {
if (length > (uint) keyseg->length) if (length > (uint) keyseg->length)
{ {
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */ return 0; /* Error */
} }
if (length == 0) /* Same key */ if (length == 0) /* Same key */
...@@ -1059,8 +1056,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, ...@@ -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", ("Found too long null packed key: %u of %u at 0x%lx",
length, keyseg->length, (long) *page_pos)); length, keyseg->length, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16); DBUG_DUMP("key", *page_pos, 16);
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; return 0;
} }
continue; continue;
...@@ -1117,8 +1113,7 @@ uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag, ...@@ -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", DBUG_PRINT("error",("Found too long packed key: %u of %u at 0x%lx",
length, keyseg->length, (long) *page_pos)); length, keyseg->length, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16); DBUG_DUMP("key", *page_pos, 16);
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */ return 0; /* Error */
} }
store_key_length_inc(key,length); 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, ...@@ -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", ("Found too long binary packed key: %u of %u at 0x%lx",
length, keyinfo->maxlength, (long) *page_pos)); length, keyinfo->maxlength, (long) *page_pos));
DBUG_DUMP("key", *page_pos, 16); DBUG_DUMP("key", *page_pos, 16);
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Wrong key */ DBUG_RETURN(0); /* Wrong key */
} }
/* Key is packed against prev key, take prefix from prev 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, ...@@ -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) if (from_end != page_end)
{ {
DBUG_PRINT("error",("Error when unpacking key")); DBUG_PRINT("error",("Error when unpacking key"));
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Error */ DBUG_RETURN(0); /* Error */
} }
} }
...@@ -1456,8 +1449,7 @@ uchar *_ma_get_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *keypos) ...@@ -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)) if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{ {
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
} }
...@@ -1507,8 +1499,7 @@ static my_bool _ma_get_prev_key(MARIA_KEY *key, MARIA_PAGE *ma_page, ...@@ -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)) if (! (*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{ {
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }
...@@ -1561,8 +1552,7 @@ uchar *_ma_get_last_key(MARIA_KEY *key, MARIA_PAGE *ma_page, uchar *endpos) ...@@ -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", DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
(long) page)); (long) page));
maria_print_error(keyinfo->share, HA_ERR_CRASHED); _ma_set_fatal_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
} }
......
...@@ -38,6 +38,8 @@ my_bool maria_delay_key_write= 0, maria_page_checksums= 1; ...@@ -38,6 +38,8 @@ my_bool maria_delay_key_write= 0, maria_page_checksums= 1;
my_bool maria_inited= FALSE; my_bool maria_inited= FALSE;
my_bool maria_in_ha_maria= FALSE; /* If used from ha_maria or not */ 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_recovery_changed_data= 0, maria_recovery_verbose= 0;
my_bool maria_assert_if_crashed_table= 0;
pthread_mutex_t THR_LOCK_maria; pthread_mutex_t THR_LOCK_maria;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
ulong maria_concurrent_insert= 2; ulong maria_concurrent_insert= 2;
......
...@@ -216,7 +216,10 @@ err: ...@@ -216,7 +216,10 @@ err:
{ {
if ((flag++ && _ma_ft_del(info,i,new_key_buff,newrec,pos)) || if ((flag++ && _ma_ft_del(info,i,new_key_buff,newrec,pos)) ||
_ma_ft_add(info,i,old_key_buff,oldrec,pos)) _ma_ft_add(info,i,old_key_buff,oldrec,pos))
{
_ma_set_fatal_error(share, my_errno);
break; break;
}
} }
else else
{ {
...@@ -228,16 +231,17 @@ err: ...@@ -228,16 +231,17 @@ err:
oldrec, pos, info->cur_row.trid); oldrec, pos, info->cur_row.trid);
if ((flag++ && _ma_ck_delete(info, &new_key)) || if ((flag++ && _ma_ck_delete(info, &new_key)) ||
_ma_ck_write(info, &old_key)) _ma_ck_write(info, &old_key))
{
_ma_set_fatal_error(share, my_errno);
break; break;
}
} }
} }
} while (i-- != 0); } while (i-- != 0);
} }
else else
{ _ma_set_fatal_error(share, save_errno);
maria_print_error(share, HA_ERR_CRASHED);
maria_mark_crashed(info);
}
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED | info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
key_changed); key_changed);
...@@ -245,9 +249,6 @@ err: ...@@ -245,9 +249,6 @@ err:
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */ allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND) if (save_errno == HA_ERR_KEY_NOT_FOUND)
{ _ma_set_fatal_error(share, HA_ERR_CRASHED);
maria_print_error(share, HA_ERR_CRASHED);
save_errno=HA_ERR_CRASHED;
}
DBUG_RETURN(my_errno=save_errno); DBUG_RETURN(my_errno=save_errno);
} /* maria_update */ } /* maria_update */
...@@ -802,7 +802,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, ...@@ -802,7 +802,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
{ {
if (t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) 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); DBUG_RETURN(-1);
} }
bmove_upp(endpos+t_length, endpos, (uint) (endpos-key_pos)); bmove_upp(endpos+t_length, endpos, (uint) (endpos-key_pos));
...@@ -811,7 +811,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, ...@@ -811,7 +811,7 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
{ {
if (-t_length >= keyinfo->maxlength*2+MARIA_INDEX_OVERHEAD_SIZE) 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); DBUG_RETURN(-1);
} }
bmove(key_pos,key_pos-t_length,(uint) (endpos-key_pos)+t_length); 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, ...@@ -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))) 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); DBUG_RETURN(0);
} }
...@@ -1189,7 +1189,7 @@ static uchar *_ma_find_last_pos(MARIA_KEY *int_key, MARIA_PAGE *ma_page, ...@@ -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 */ memcpy(int_key->data, key_buff, length); /* previous key */
if (!(length=(*keyinfo->get_key)(&tmp_key, page_flag, 0, &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); DBUG_RETURN(0);
} }
} while (page < end); } while (page < end);
......
...@@ -1012,8 +1012,8 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1012,8 +1012,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
share->state.open_count != 0); share->state.open_count != 0);
if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) && if ((param->testflag & (T_REP_ANY | T_SORT_RECORDS)) &&
((share->state.changed & (STATE_CHANGED | STATE_CRASHED | ((share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR) || STATE_IN_REPAIR) ||
!(param->testflag & T_CHECK_ONLY_CHANGED)))) !(param->testflag & T_CHECK_ONLY_CHANGED))))
need_to_check=1; need_to_check=1;
...@@ -1030,8 +1030,8 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1030,8 +1030,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
need_to_check=1; need_to_check=1;
} }
if ((param->testflag & T_CHECK_ONLY_CHANGED) && if ((param->testflag & T_CHECK_ONLY_CHANGED) &&
(share->state.changed & (STATE_CHANGED | STATE_CRASHED | (share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR))) STATE_IN_REPAIR)))
need_to_check=1; need_to_check=1;
if (!need_to_check) if (!need_to_check)
{ {
...@@ -1250,8 +1250,8 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1250,8 +1250,8 @@ static int maria_chk(HA_CHECK *param, char *filename)
if (!error) if (!error)
{ {
DBUG_PRINT("info", ("Reseting crashed state")); DBUG_PRINT("info", ("Reseting crashed state"));
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); STATE_IN_REPAIR);
} }
else else
maria_mark_crashed(info); maria_mark_crashed(info);
...@@ -1304,14 +1304,13 @@ static int maria_chk(HA_CHECK *param, char *filename) ...@@ -1304,14 +1304,13 @@ static int maria_chk(HA_CHECK *param, char *filename)
if (!error) if (!error)
{ {
if (((share->state.changed & if (((share->state.changed &
(STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR | (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR)) ||
STATE_IN_REPAIR)) ||
share->state.open_count != 0) share->state.open_count != 0)
&& (param->testflag & T_UPDATE_STATE)) && (param->testflag & T_UPDATE_STATE))
info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; info->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
DBUG_PRINT("info", ("Reseting crashed state")); DBUG_PRINT("info", ("Reseting crashed state"));
share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS |
STATE_CRASHED_ON_REPAIR | STATE_IN_REPAIR); STATE_IN_REPAIR);
} }
else if (!maria_is_crashed(info) && else if (!maria_is_crashed(info) &&
(param->testflag & T_UPDATE_STATE)) (param->testflag & T_UPDATE_STATE))
......
...@@ -619,6 +619,9 @@ struct st_maria_handler ...@@ -619,6 +619,9 @@ struct st_maria_handler
#define STATE_NOT_MOVABLE 256 #define STATE_NOT_MOVABLE 256
#define STATE_MOVED 512 /* set if base->uuid != maria_uuid */ #define STATE_MOVED 512 /* set if base->uuid != maria_uuid */
#define STATE_IN_REPAIR 1024 /* We are running repair on table */ #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 */ /* options to maria_read_cache */
...@@ -701,7 +704,6 @@ struct st_maria_handler ...@@ -701,7 +704,6 @@ struct st_maria_handler
#endif #endif
#define DBUG_DUMP_KEY(name, key) DBUG_DUMP(name, (key)->data, (key)->data_length + (key)->ref_length) #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 */ /* Functions to store length of space packed keys, VARCHAR or BLOB keys */
#define store_key_length(key,length) \ #define store_key_length(key,length) \
...@@ -805,6 +807,7 @@ extern char *maria_data_root; ...@@ -805,6 +807,7 @@ extern char *maria_data_root;
extern uchar maria_zero_string[]; extern uchar maria_zero_string[];
extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data; extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data;
extern my_bool maria_recovery_verbose; extern my_bool maria_recovery_verbose;
extern my_bool maria_assert_if_crashed_table;
extern HASH maria_stored_state; extern HASH maria_stored_state;
extern int (*maria_create_trn_hook)(MARIA_HA *); extern int (*maria_create_trn_hook)(MARIA_HA *);
...@@ -918,6 +921,7 @@ extern int _ma_writeinfo(MARIA_HA *info, uint options); ...@@ -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_test_if_changed(MARIA_HA *info);
extern int _ma_mark_file_changed(MARIA_HA *info); extern int _ma_mark_file_changed(MARIA_HA *info);
extern void _ma_mark_file_crashed(MARIA_SHARE *share); 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_set_uuid(MARIA_HA *info, my_bool reset_uuid);
extern my_bool _ma_check_if_zero(uchar *pos, size_t size); extern my_bool _ma_check_if_zero(uchar *pos, size_t size);
extern int _ma_decrement_open_count(MARIA_HA *info); extern int _ma_decrement_open_count(MARIA_HA *info);
...@@ -1261,3 +1265,4 @@ extern my_bool maria_flush_log_for_page_none(uchar *page, ...@@ -1261,3 +1265,4 @@ extern my_bool maria_flush_log_for_page_none(uchar *page,
pgcache_page_no_t page_no, pgcache_page_no_t page_no,
uchar *data_ptr); uchar *data_ptr);
extern PAGECACHE *maria_log_pagecache; extern PAGECACHE *maria_log_pagecache;
extern uint _ma_file_callback_to_id(void *callback_data);
...@@ -71,8 +71,8 @@ int mi_panic(enum ha_panic_function flag) ...@@ -71,8 +71,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->dfile >= 0 && my_close(info->dfile,MYF(0))) if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
error = my_errno; error = my_errno;
info->s->kfile=info->dfile= -1; /* Files aren't open anymore */ info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
break;
#endif #endif
break;
case HA_PANIC_READ: /* Restore to before WRITE */ case HA_PANIC_READ: /* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE #ifdef CANT_OPEN_FILES_TWICE
{ /* Open closed files */ { /* Open closed files */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment