From 7d259f649531885cfef6896a1762c356c6cc5754 Mon Sep 17 00:00:00 2001
From: Michael Widenius <monty@askmonty.org>
Date: Thu, 7 Oct 2010 12:51:34 +0300
Subject: [PATCH] Fixes some bug in Aria recovery: - _ma_apply_redo_index:
 Assertion `page_offset != 0 && page_offset + length <= page_length' failed
 Fixes one bug and one log assert when inserting rows: - _ma_log_split:
 Assertion `org_length <= info->s->max_index_block_size' failed -
 write_block_record:  Assertion '(data_length < MAX_TAIL_SIZE(block_size)'
 failed Mark in recovery log where _ma_log_add() calls was done (for better
 debugging).

storage/maria/ma_bitmap.c:
  Don't write a head part on a tail page. (Caused an assert in write_block_record())
storage/maria/ma_delete.c:
  Mark in recovery log where _ma_log_add() calls was done
storage/maria/ma_key_recover.c:
  Mark in recovery log where _ma_log_add() calls was done
  Fixed not handled logging case for overfull index pages.
storage/maria/ma_key_recover.h:
  Mark in recovery log where _ma_log_add() calls was done
storage/maria/ma_loghandler.h:
  Mark in recovery log where _ma_log_add() calls was done
storage/maria/ma_rt_key.c:
  Mark in recovery log where _ma_log_add() calls was done
storage/maria/ma_write.c:
  Mark in recovery log where _ma_log_add() calls was done.
  Fixed wrong call to _ma_split_page() for overfull pages
---
 storage/maria/ma_bitmap.c      |  4 ++--
 storage/maria/ma_delete.c      |  8 +++++---
 storage/maria/ma_key_recover.c | 29 ++++++++++++++++++++++++++---
 storage/maria/ma_key_recover.h |  3 ++-
 storage/maria/ma_loghandler.h  | 27 +++++++++++++++------------
 storage/maria/ma_rt_key.c      |  3 ++-
 storage/maria/ma_write.c       | 14 +++++++++++---
 7 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c
index 4f37d7b9a1f..d8b7a9b9a99 100644
--- a/storage/maria/ma_bitmap.c
+++ b/storage/maria/ma_bitmap.c
@@ -1016,7 +1016,7 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
   DBUG_PRINT("enter", ("size: %u", size));
 
   LINT_INIT(best_pos);
-  DBUG_ASSERT(size <= FULL_PAGE_SIZE(bitmap->block_size));
+  DBUG_ASSERT(size <= MAX_TAIL_SIZE(bitmap->block_size));
 
   for (; data < end; data += 6)
   {
@@ -1732,7 +1732,7 @@ my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row,
   row_length= find_where_to_split_row(share, row, extents_length,
                                       max_page_size);
 
-  full_page_size= FULL_PAGE_SIZE(share->block_size);
+  full_page_size= MAX_TAIL_SIZE(share->block_size);
   position= 0;
   if (head_length - row_length <= full_page_size)
     position= ELEMENTS_RESERVED_FOR_MAIN_PART -2;    /* Only head and tail */
diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
index 2420cac0e93..71ad60b545e 100644
--- a/storage/maria/ma_delete.c
+++ b/storage/maria/ma_delete.c
@@ -702,7 +702,8 @@ static int del(MARIA_HA *info, MARIA_KEY *key,
 
   if (share->now_transactional &&
       _ma_log_add(anc_page, a_length,
-                  key_start, s_temp.changed_length, s_temp.move_length, 1))
+                  key_start, s_temp.changed_length, s_temp.move_length, 1,
+                  KEY_OP_DEBUG_LOG_ADD_2))
     goto err;
 
   DBUG_RETURN(new_leaf_length <=
@@ -971,7 +972,8 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
                             anc_key_inserted.move_length,
                             key_deleted.changed_length),
                         anc_key_inserted.move_length -
-                        key_deleted.move_length, 1))
+                        key_deleted.move_length, 1,
+                        KEY_OP_DEBUG_LOG_ADD_3))
           goto err;
 
         /*
@@ -1211,7 +1213,7 @@ static int underflow(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
                           anc_key_inserted.move_length,
                           key_deleted.changed_length),
                       anc_key_inserted.move_length -
-                      key_deleted.move_length, 1))
+                      key_deleted.move_length, 1,KEY_OP_DEBUG_LOG_ADD_4))
         goto err;
 
       /*
diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
index 1a61731e817..d20875fec3a 100644
--- a/storage/maria/ma_key_recover.c
+++ b/storage/maria/ma_key_recover.c
@@ -488,7 +488,8 @@ my_bool _ma_log_suffix(MARIA_PAGE *ma_page, uint org_length, uint new_length)
 my_bool _ma_log_add(MARIA_PAGE *ma_page,
                     uint org_page_length __attribute__ ((unused)),
                     uchar *key_pos, uint changed_length, int move_length,
-                    my_bool handle_overflow __attribute__ ((unused)))
+                    my_bool handle_overflow __attribute__ ((unused)),
+                    enum en_key_debug debug_marker __attribute__((unused)))
 {
   LSN lsn;
   uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 2 + 3 + 3 + 3 + 3 + 7 +
@@ -511,7 +512,7 @@ my_bool _ma_log_add(MARIA_PAGE *ma_page,
   DBUG_ASSERT(move_length <= (int) changed_length);
   DBUG_ASSERT(ma_page->org_size == min(org_page_length, max_page_size));
   DBUG_ASSERT(ma_page->size == org_page_length + move_length);
-  DBUG_ASSERT(offset < max_page_size);
+  DBUG_ASSERT(offset <= ma_page->org_size);
 
   /*
     Write REDO entry that contains the logical operations we need
@@ -525,7 +526,7 @@ my_bool _ma_log_add(MARIA_PAGE *ma_page,
 
 #ifdef EXTRA_DEBUG_KEY_CHANGES
   *log_pos++= KEY_OP_DEBUG;
-  *log_pos++= KEY_OP_DEBUG_LOG_ADD;
+  *log_pos++= debug_marker;
 #endif
 
   /* Store keypage_flag */
@@ -575,11 +576,33 @@ my_bool _ma_log_add(MARIA_PAGE *ma_page,
     log_pos+= 3;
     if (move_length)
     {
+      if (move_length < 0)
+      {
+        DBUG_ASSERT(offset - move_length <= org_page_length);
+        if (offset - move_length > current_size)
+        {
+          /*
+            Truncate to end of page. We will add data to it from
+            the page buffer below
+          */
+          move_length= (int) offset - (int) current_size;
+        }
+      }
       log_pos[0]= KEY_OP_SHIFT;
       int2store(log_pos+1, move_length);
       log_pos+= 3;
       current_size+= move_length;
     }
+    /*
+      Handle case where page was shortend but 'changed_length' goes over
+      'current_size'. This can only happen when there was a page overflow
+      and we will below add back the overflow part
+    */
+    if (offset + changed_length > current_size)
+    {
+      DBUG_ASSERT(offset + changed_length <= ma_page->size);
+      changed_length= current_size - offset;
+    }
     log_pos[0]= KEY_OP_CHANGE;
   }
   int2store(log_pos+1, changed_length);
diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h
index 3fdb045ee40..d6b69010d5d 100644
--- a/storage/maria/ma_key_recover.h
+++ b/storage/maria/ma_key_recover.h
@@ -70,7 +70,8 @@ my_bool _ma_log_suffix(MARIA_PAGE *page, uint org_length,
                        uint new_length);
 my_bool _ma_log_add(MARIA_PAGE *page, uint buff_length, uchar *key_pos,
                     uint changed_length, int move_length,
-                    my_bool handle_overflow);
+                    my_bool handle_overflow,
+                    enum en_key_debug debug_marker);
 my_bool _ma_log_delete(MARIA_PAGE *page, const uchar *key_pos,
                        uint changed_length, uint move_length,
                        uint append_length, enum en_key_debug debug_marker);
diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h
index 8e04164a81a..8a0b2a1310c 100644
--- a/storage/maria/ma_loghandler.h
+++ b/storage/maria/ma_loghandler.h
@@ -178,18 +178,21 @@ enum en_key_debug
   KEY_OP_DEBUG_FATHER_CHANGED_1,	/* 3 */
   KEY_OP_DEBUG_FATHER_CHANGED_2,	/* 4 */
   KEY_OP_DEBUG_LOG_SPLIT,		/* 5 */
-  KEY_OP_DEBUG_LOG_ADD,			/* 6 */
-  KEY_OP_DEBUG_LOG_PREFIX_1,		/* 7 */
-  KEY_OP_DEBUG_LOG_PREFIX_2,		/* 8 */
-  KEY_OP_DEBUG_LOG_PREFIX_3,		/* 9 */
-  KEY_OP_DEBUG_LOG_PREFIX_4,		/* 10 */
-  KEY_OP_DEBUG_LOG_PREFIX_5,		/* 11 */
-  KEY_OP_DEBUG_LOG_DEL_CHANGE_1,	/* 12 */
-  KEY_OP_DEBUG_LOG_DEL_CHANGE_2,	/* 13 */
-  KEY_OP_DEBUG_LOG_DEL_CHANGE_3,	/* 14 */
-  KEY_OP_DEBUG_LOG_DEL_CHANGE_RT,	/* 15 */
-  KEY_OP_DEBUG_LOG_DEL_PREFIX,		/* 16 */
-  KEY_OP_DEBUG_LOG_MIDDLE		/* 17 */
+  KEY_OP_DEBUG_LOG_ADD_1,		/* 6 */
+  KEY_OP_DEBUG_LOG_ADD_2,		/* 7 */
+  KEY_OP_DEBUG_LOG_ADD_3,		/* 8 */
+  KEY_OP_DEBUG_LOG_ADD_4,		/* 9 */
+  KEY_OP_DEBUG_LOG_PREFIX_1,		/* 10 */
+  KEY_OP_DEBUG_LOG_PREFIX_2,		/* 11 */
+  KEY_OP_DEBUG_LOG_PREFIX_3,		/* 12 */
+  KEY_OP_DEBUG_LOG_PREFIX_4,		/* 13 */
+  KEY_OP_DEBUG_LOG_PREFIX_5,		/* 14 */
+  KEY_OP_DEBUG_LOG_DEL_CHANGE_1,	/* 15 */
+  KEY_OP_DEBUG_LOG_DEL_CHANGE_2,	/* 16 */
+  KEY_OP_DEBUG_LOG_DEL_CHANGE_3,	/* 17 */
+  KEY_OP_DEBUG_LOG_DEL_CHANGE_RT,	/* 18 */
+  KEY_OP_DEBUG_LOG_DEL_PREFIX,		/* 19 */
+  KEY_OP_DEBUG_LOG_MIDDLE		/* 20 */
 };
 
 
diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c
index 2e204990a3b..fa173605cd3 100644
--- a/storage/maria/ma_rt_key.c
+++ b/storage/maria/ma_rt_key.c
@@ -59,7 +59,8 @@ int maria_rtree_add_key(const MARIA_KEY *key, MARIA_PAGE *page,
     page_store_size(share, page);
     if (share->now_transactional &&
         _ma_log_add(page, key_pos - page->buff,
-                    key_pos, tot_key_length, tot_key_length, 0))
+                    key_pos, tot_key_length, tot_key_length, 0,
+                    KEY_OP_DEBUG_LOG_ADD_1))
       DBUG_RETURN(-1);
     DBUG_RETURN(0);
   }
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index c6718299d17..a69799dda4b 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -768,6 +768,10 @@ int _ma_insert(register MARIA_HA *info, MARIA_KEY *key,
   DBUG_PRINT("enter",("key_pos: 0x%lx", (ulong) key_pos));
   DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
 
+  /*
+    Note that anc_page->size can be bigger then block_size in case of
+    delete key that caused increase of page length
+  */
   org_anc_length= a_length= anc_page->size;
   nod_flag= anc_page->node;
 
@@ -887,7 +891,8 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
     {
       if (share->now_transactional && 
           _ma_log_add(anc_page, org_anc_length,
-                      key_pos, s_temp.changed_length, t_length, 1))
+                      key_pos, s_temp.changed_length, t_length, 1,
+                      KEY_OP_DEBUG_LOG_ADD_1))
         DBUG_RETURN(-1);
     }
     DBUG_RETURN(0);				/* There is room on page */
@@ -911,7 +916,9 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
                                  father_page, father_key_pos,
                                  &s_temp));
   }
-  DBUG_RETURN(_ma_split_page(info, key, anc_page, org_anc_length,
+  DBUG_RETURN(_ma_split_page(info, key, anc_page,
+                             min(org_anc_length,
+                                 info->s->max_index_block_size),
                              key_pos, s_temp.changed_length, t_length,
                              key_buff, insert_last));
 } /* _ma_insert */
@@ -1971,7 +1978,8 @@ my_bool _ma_log_change(MARIA_PAGE *ma_page, const uchar *key_pos, uint length,
    @fn     _ma_log_split()
    @param
      ma_page		Page that is changed
-     org_length	        Original length of page
+     org_length	        Original length of page. Can be bigger than block_size
+                        for block that overflowed
      new_length		New length of page
      key_pos		Where key is inserted on page (may be 0 if no key)
      key_length		Number of bytes changed at key_pos
-- 
2.30.9