[Commits] Rev 3020: Aria issues: in lp:maria/5.1

Michael Widenius monty at askmonty.org
Mon Jan 24 15:19:42 EET 2011


At lp:maria/5.1

------------------------------------------------------------
revno: 3020
revision-id: monty at askmonty.org-20110124131940-6xh22if0cehedvbf
parent: monty at askmonty.org-20110120172600-qpblwhofksvat7v1
committer: Michael Widenius <monty at askmonty.org>
branch nick: maria-5.1
timestamp: Mon 2011-01-24 15:19:40 +0200
message:
  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)
-------------- next part --------------
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2011-01-11 23:48:34 +0000
+++ b/storage/maria/ha_maria.cc	2011-01-24 13:19:40 +0000
@@ -1065,8 +1065,7 @@ int ha_maria::check(THD * thd, HA_CHECK_
 
   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_
   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
     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 */

=== modified file 'storage/maria/ma_bitmap.c'
--- a/storage/maria/ma_bitmap.c	2011-01-04 22:09:05 +0000
+++ b/storage/maria/ma_bitmap.c	2011-01-24 13:19:40 +0000
@@ -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 *shar
   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
   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
       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
   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
 
 #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
   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
 #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_
         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, p
     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 *
     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);
 }
 
 

=== modified file 'storage/maria/ma_blockrec.c'
--- a/storage/maria/ma_blockrec.c	2011-01-06 20:49:17 +0000
+++ b/storage/maria/ma_blockrec.c	2011-01-24 13:19:40 +0000
@@ -4106,11 +4106,11 @@ static my_bool delete_head_or_tail(MARIA
 {
   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
     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
   }
   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
     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));

=== modified file 'storage/maria/ma_blockrec.h'
--- a/storage/maria/ma_blockrec.h	2011-01-04 22:09:05 +0000
+++ b/storage/maria/ma_blockrec.h	2011-01-24 13:19:40 +0000
@@ -78,6 +78,10 @@ enum en_page_type { UNALLOCATED_PAGE, HE
 #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_
                                   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(
 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,

=== modified file 'storage/maria/ma_check.c'
--- a/storage/maria/ma_check.c	2011-01-11 10:18:03 +0000
+++ b/storage/maria/ma_check.c	2011-01-24 13:19:40 +0000
@@ -1822,6 +1822,7 @@ static int check_block_record(HA_CHECK *
        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 *
     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 *
     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->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(MAR
                                      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);
 }

=== modified file 'storage/maria/ma_checkpoint.c'
--- a/storage/maria/ma_checkpoint.c	2010-08-12 17:55:00 +0000
+++ b/storage/maria/ma_checkpoint.c	2011-01-24 13:19:40 +0000
@@ -130,6 +130,9 @@ int ma_checkpoint_execute(CHECKPOINT_LEV
   /* 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 *st
         */
       }
     }
+#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()

=== modified file 'storage/maria/ma_create.c'
--- a/storage/maria/ma_create.c	2010-01-14 16:51:00 +0000
+++ b/storage/maria/ma_create.c	2011-01-24 13:19:40 +0000
@@ -1387,7 +1387,13 @@ int _ma_update_state_lsns_sub(MARIA_SHAR
   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)

=== modified file 'storage/maria/ma_delete.c'
--- a/storage/maria/ma_delete.c	2010-10-13 15:15:43 +0000
+++ b/storage/maria/ma_delete.c	2011-01-24 13:19:40 +0000
@@ -135,18 +135,13 @@ int maria_delete(MARIA_HA *info,const uc
     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 MARI
 
   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, MARI
       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, MARI
   {
     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;

=== modified file 'storage/maria/ma_extra.c'
--- a/storage/maria/ma_extra.c	2011-01-10 21:22:40 +0000
+++ b/storage/maria/ma_extra.c	2011-01-24 13:19:40 +0000
@@ -175,8 +175,8 @@ int maria_extra(MARIA_HA *info, enum ha_
     {
       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_
     }
     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_
     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_
         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
           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
       {
         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
   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;
 }

=== modified file 'storage/maria/ma_init.c'
--- a/storage/maria/ma_init.c	2010-06-13 22:13:32 +0000
+++ b/storage/maria/ma_init.c	2011-01-24 13:19:40 +0000
@@ -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);

=== modified file 'storage/maria/ma_key.c'
--- a/storage/maria/ma_key.c	2008-12-02 22:02:52 +0000
+++ b/storage/maria/ma_key.c	2011-01-24 13:19:40 +0000
@@ -636,8 +636,7 @@ int _ma_read_key_record(MARIA_HA *info,
     {                           /* 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 */

=== modified file 'storage/maria/ma_key_recover.c'
--- a/storage/maria/ma_key_recover.c	2010-10-13 15:15:43 +0000
+++ b/storage/maria/ma_key_recover.c	2011-01-24 13:19:40 +0000
@@ -66,7 +66,7 @@ void _ma_unpin_all_pages(MARIA_HA *info,
 #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,

=== modified file 'storage/maria/ma_keycache.c'
--- a/storage/maria/ma_keycache.c	2008-08-25 11:49:47 +0000
+++ b/storage/maria/ma_keycache.c	2011-01-24 13:19:40 +0000
@@ -79,8 +79,8 @@ int maria_assign_to_pagecache(MARIA_HA *
   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);
   }
 
   /*

=== modified file 'storage/maria/ma_locking.c'
--- a/storage/maria/ma_locking.c	2010-11-02 15:22:57 +0000
+++ b/storage/maria/ma_locking.c	2011-01-24 13:19:40 +0000
@@ -80,9 +80,8 @@ int maria_lock_database(MARIA_HA *info,
       {
         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,
           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 *
   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

=== modified file 'storage/maria/ma_open.c'
--- a/storage/maria/ma_open.c	2011-01-10 21:22:40 +0000
+++ b/storage/maria/ma_open.c	2011-01-24 13:19:40 +0000
@@ -41,10 +41,10 @@ static uchar *_ma_state_info_read(uchar
                                         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, i
     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, i
     }
     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, i
     /* 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, i
         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, i
               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, i
       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, i
                                            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

=== modified file 'storage/maria/ma_page.c'
--- a/storage/maria/ma_page.c	2010-09-07 20:57:00 +0000
+++ b/storage/maria/ma_page.c	2011-01-24 13:19:40 +0000
@@ -127,8 +127,7 @@ my_bool _ma_fetch_keypage(MARIA_PAGE *pa
   {
     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 *pa
                           _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 *
     {
       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))

=== modified file 'storage/maria/ma_pagecache.c'
--- a/storage/maria/ma_pagecache.c	2011-01-12 13:41:39 +0000
+++ b/storage/maria/ma_pagecache.c	2011-01-24 13:19:40 +0000
@@ -614,6 +614,26 @@ static my_bool pagecache_fwrite(PAGECACH
   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);

=== modified file 'storage/maria/ma_pagecache.h'
--- a/storage/maria/ma_pagecache.h	2008-10-14 15:18:14 +0000
+++ b/storage/maria/ma_pagecache.h	2011-01-24 13:19:40 +0000
@@ -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;
 

=== modified file 'storage/maria/ma_panic.c'
--- a/storage/maria/ma_panic.c	2007-12-31 11:52:45 +0000
+++ b/storage/maria/ma_panic.c	2011-01-24 13:19:40 +0000
@@ -67,8 +67,8 @@ int maria_panic(enum ha_panic_function f
       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 f
       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 */

=== modified file 'storage/maria/ma_recovery_util.c'
--- a/storage/maria/ma_recovery_util.c	2011-01-06 20:49:17 +0000
+++ b/storage/maria/ma_recovery_util.c	2011-01-24 13:19:40 +0000
@@ -59,9 +59,11 @@ void tprint(FILE *trace_file __attribute
   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);
   }

=== modified file 'storage/maria/ma_rkey.c'
--- a/storage/maria/ma_rkey.c	2011-01-10 21:22:40 +0000
+++ b/storage/maria/ma_rkey.c	2011-01-24 13:19:40 +0000
@@ -91,8 +91,7 @@ int maria_rkey(MARIA_HA *info, uchar *bu
   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;

=== modified file 'storage/maria/ma_search.c'
--- a/storage/maria/ma_search.c	2011-01-11 11:27:16 +0000
+++ b/storage/maria/ma_search.c	2011-01-24 13:19:40 +0000
@@ -379,8 +379,7 @@ int _ma_seq_search(const MARIA_KEY *key,
     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 *k
 
     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
       {
         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
                        ("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
         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 *
                  ("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 *
     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
     {
       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_KE
     {
       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,
       {
         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);
       }
     }

=== modified file 'storage/maria/ma_static.c'
--- a/storage/maria/ma_static.c	2010-08-18 07:52:57 +0000
+++ b/storage/maria/ma_static.c	2011-01-24 13:19:40 +0000
@@ -38,6 +38,8 @@ my_bool maria_delay_key_write= 0, maria_
 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;

=== modified file 'storage/maria/ma_update.c'
--- a/storage/maria/ma_update.c	2008-10-31 23:14:58 +0000
+++ b/storage/maria/ma_update.c	2011-01-24 13:19:40 +0000
@@ -216,7 +216,10 @@ int maria_update(register MARIA_HA *info
         {
           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 @@ int maria_update(register MARIA_HA *info
                                         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 @@ int maria_update(register MARIA_HA *info
   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 */

=== modified file 'storage/maria/ma_write.c'
--- a/storage/maria/ma_write.c	2010-12-10 15:15:18 +0000
+++ b/storage/maria/ma_write.c	2011-01-24 13:19:40 +0000
@@ -802,7 +802,7 @@ int _ma_insert(register MARIA_HA *info,
   {
     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,
   {
     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_KE
 
   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_KE
     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);

=== modified file 'storage/maria/maria_chk.c'
--- a/storage/maria/maria_chk.c	2010-12-05 12:25:01 +0000
+++ b/storage/maria/maria_chk.c	2011-01-24 13:19:40 +0000
@@ -1012,8 +1012,8 @@ static int maria_chk(HA_CHECK *param, ch
                             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, ch
         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, ch
     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, ch
     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))

=== modified file 'storage/maria/maria_def.h'
--- a/storage/maria/maria_def.h	2011-01-06 20:49:17 +0000
+++ b/storage/maria/maria_def.h	2011-01-24 13:19:40 +0000
@@ -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 */
 
@@ -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,
 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_
                                              pgcache_page_no_t page_no,
                                              uchar *data_ptr);
 extern PAGECACHE *maria_log_pagecache;
+extern uint _ma_file_callback_to_id(void *callback_data);

=== modified file 'storage/myisam/mi_panic.c'
--- a/storage/myisam/mi_panic.c	2006-12-31 00:32:21 +0000
+++ b/storage/myisam/mi_panic.c	2011-01-24 13:19:40 +0000
@@ -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 */



More information about the commits mailing list