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)
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(&param, 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 */
......
......@@ -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);
}
......
......@@ -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));
......
......@@ -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,
......
......@@ -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);
}
......@@ -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()
......
......@@ -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)
......
......@@ -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;
......
......@@ -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;
}
......@@ -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);
......
......@@ -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 */
......
......@@ -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,
......
......@@ -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);
}
/*
......
......@@ -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
......
......@@ -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
......
......@@ -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))
......
......@@ -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);
......
......@@ -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;
......
......@@ -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 */
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -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;
......
......@@ -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 */
......@@ -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);
......
......@@ -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))
......
......@@ -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);
......@@ -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 */
......
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