List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:June 4 2008 1:58pm
Subject:bk commit into 5.1 tree (istruewing:1.2568) BUG#36708
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of istruewing.  When istruewing does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-06-04 15:57:58+02:00, istruewing@stripped +1 -0
  Bug#36708 - extreme fragmentation of a table with blob records
    
  Not to be pushed.
    
  Temporarily added DBUG statements to show how record parts are
  treated by each SQL statement.

  storage/myisam/mi_dynrec.c@stripped, 2008-06-04 15:57:56+02:00, istruewing@stripped +292 -2
    Bug#36708 - extreme fragmentation of a table with blob records
    Added DBUG statements.

diff -Nrup a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
--- a/storage/myisam/mi_dynrec.c	2008-03-31 09:40:37 +02:00
+++ b/storage/myisam/mi_dynrec.c	2008-06-04 15:57:56 +02:00
@@ -38,6 +38,7 @@ static int delete_dynamic_record(MI_INFO
 				 uint second_read);
 static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
 			  uint length);
+static void debug_print_frames(MI_INFO *info);
 
 #ifdef THREAD
 /* Play it safe; We have a small stack when using threads */
@@ -324,6 +325,7 @@ static int write_dynamic_record(MI_INFO 
   ulong length;
   my_off_t filepos;
   DBUG_ENTER("write_dynamic_record");
+  DBUG_PRINT("ingo", ("INSERT   record length: %lu", reclength));
 
   flag=0;
 
@@ -360,6 +362,7 @@ static int write_dynamic_record(MI_INFO 
       goto err;
   } while (reclength);
 
+  DBUG_EXECUTE_IF("ingo", debug_print_frames(info););
   DBUG_RETURN(0);
 err:
   DBUG_RETURN(1);
@@ -395,6 +398,8 @@ static int _mi_find_writepos(MI_INFO *in
     info->state->del--;
     info->state->empty-= block_info.block_len;
     *length= block_info.block_len;
+    DBUG_PRINT("ingo", ("Reusing   block %10ld from delete link",
+                        (long) *filepos));
   }
   else
   {
@@ -418,6 +423,8 @@ static int _mi_find_writepos(MI_INFO *in
     info->state->data_file_length+= tmp;
     info->s->state.split++;
     info->update|=HA_STATE_WRITE_AT_END;
+    DBUG_PRINT("ingo", ("Creating  block %10ld new at EOF",
+                        (long) *filepos));
   }
   DBUG_RETURN(0);
 } /* _mi_find_writepos */
@@ -531,6 +538,9 @@ static int delete_dynamic_record(MI_INFO
   int error;
   my_bool remove_next_block;
   DBUG_ENTER("delete_dynamic_record");
+  DBUG_EXECUTE("ingo", if (!second_read)
+                         DBUG_PRINT("ingo", ("DELETE   record %10ld",
+                                             (long) filepos)););
 
   /* First add a link from the last block to the new one */
   error= update_backward_delete_link(info, info->s->state.dellink, filepos);
@@ -539,6 +549,7 @@ static int delete_dynamic_record(MI_INFO
   do
   {
     /* Remove block at 'filepos' */
+    DBUG_PRINT("ingo", ("Deleting  block %10ld", (long) filepos));
     if ((b_type=_mi_get_block_info(&block_info,info->dfile,filepos))
 	& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
 	   BLOCK_FATAL_ERROR) ||
@@ -555,6 +566,8 @@ static int delete_dynamic_record(MI_INFO
 	BLOCK_DELETED && del_block.block_len+length < MI_DYN_MAX_BLOCK_LENGTH)
     {
       /* We can't remove this yet as this block may be the head block */
+      DBUG_PRINT("ingo", ("Combining block %10ld with deleted block %10ld",
+                          (long) filepos, (long) filepos + length));
       remove_next_block=1;
       length+=del_block.block_len;
     }
@@ -579,6 +592,8 @@ static int delete_dynamic_record(MI_INFO
       error=1;
   } while (!(b_type & BLOCK_LAST));
 
+  DBUG_EXECUTE_IF("ingo", if (!error && !second_read)
+                            debug_print_frames(info););
   DBUG_RETURN(error);
 }
 
@@ -705,6 +720,9 @@ int _mi_write_part_record(MI_INFO *info,
     /* Check first if we can join this block with the next one */
     MI_BLOCK_INFO del_block;
     my_off_t next_block=filepos+length+extra_length+res_length;
+    DBUG_PRINT("ingo", ("Splitting block %10ld from reused block %10ld",
+                        (long) filepos + length + extra_length,
+                        (long) filepos));
 
     del_block.second_read=0;
     if (next_block < info->state->data_file_length &&
@@ -714,6 +732,9 @@ int _mi_write_part_record(MI_INFO *info,
 	   & BLOCK_DELETED) &&
 	  res_length + del_block.block_len < MI_DYN_MAX_BLOCK_LENGTH)
       {
+        DBUG_PRINT("ingo",
+                   ("Combining block %10ld with deleted block %10ld",
+                    (long) filepos, (long) next_block));
 	if (unlink_deleted_block(info,&del_block))
 	  goto err;
 	res_length+=del_block.block_len;
@@ -783,6 +804,8 @@ static int update_dynamic_record(MI_INFO
   ulong length;
   MI_BLOCK_INFO block_info;
   DBUG_ENTER("update_dynamic_record");
+  DBUG_PRINT("ingo", ("UPDATE   record %10ld to length: %lu",
+                      (long) filepos, reclength));
 
   flag=block_info.second_read=0;
   /*
@@ -834,6 +857,8 @@ static int update_dynamic_record(MI_INFO
   {
     if (filepos != info->s->state.dellink)
     {
+      DBUG_PRINT("ingo", ("Reusing   block %10ld from old record",
+                          (long) filepos));
       block_info.next_filepos= HA_OFFSET_ERROR;
       if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
 	  & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
@@ -858,7 +883,9 @@ static int update_dynamic_record(MI_INFO
 	    info->s->base.max_data_file_length-tmp)
 	{
 	  /* extend file */
-	  DBUG_PRINT("info",("Extending file with %d bytes",tmp));
+          DBUG_EXECUTE("ingo", if (tmp) DBUG_PRINT("ingo",
+                                 ("Extending block %10ld at EOF with %d bytes",
+                                  (long) filepos, tmp)););
 	  if (info->nextpos == info->state->data_file_length)
 	    info->nextpos+= tmp;
 	  info->state->data_file_length+= tmp;
@@ -881,7 +908,10 @@ static int update_dynamic_record(MI_INFO
 	      BLOCK_DELETED)
 	  {
 	    /* Use; Unlink it and extend the current block */
-	    DBUG_PRINT("info",("Extending current block"));
+            DBUG_PRINT("ingo",
+                       ("Combining block %10ld with deleted block %10ld",
+                        (long) filepos, (long) block_info.filepos +
+                        block_info.block_len));
 	    if (unlink_deleted_block(info,&del_block))
 	      goto err;
 	    if ((length+=del_block.block_len) > MI_MAX_BLOCK_LENGTH)
@@ -894,6 +924,8 @@ static int update_dynamic_record(MI_INFO
 	      ulong rest_length= length-MI_MAX_BLOCK_LENGTH;
 	      set_if_bigger(rest_length, MI_MIN_BLOCK_LENGTH);
 	      next_pos= del_block.filepos+ del_block.block_len - rest_length;
+              DBUG_PRINT("ingo", ("Splitting block %10ld from combined block",
+                                  (long) next_pos));
 
 	      if (update_backward_delete_link(info, info->s->state.dellink,
 					      next_pos))
@@ -935,6 +967,7 @@ static int update_dynamic_record(MI_INFO
   if (block_info.next_filepos != HA_OFFSET_ERROR)
     if (delete_dynamic_record(info,block_info.next_filepos,1))
       goto err;
+  DBUG_EXECUTE_IF("ingo", debug_print_frames(info););
   DBUG_RETURN(0);
 err:
   DBUG_RETURN(1);
@@ -2004,3 +2037,260 @@ err:
   my_errno=HA_ERR_WRONG_IN_RECORD;	 /* Garbage */
   return BLOCK_ERROR;
 }
+
+
+#ifndef DBUG_OFF
+/**
+  Print block-frames of a dynamic record data file.
+
+  @parameter[in]        info            MyISAM table object
+*/
+
+static void debug_print_frames(MI_INFO *info)
+{
+  size_t        buffer_size;
+  long          filepos;
+  char          *buffer;
+  char          *file;
+  FILE          *fp= NULL;
+
+  DBUG_PRINT("ingo", ("----------"));
+
+  buffer_size= MI_MIN_BLOCK_LENGTH;
+  buffer= malloc(buffer_size);
+  if (!buffer)
+  {
+    DBUG_PRINT("ingo", ("Cannot allocate %lu bytes: %s",
+                        (ulong) buffer_size, strerror(errno)));
+    goto end;
+  }
+
+  fp= fopen(info->s->data_file_name, "rb");
+  if (!fp)
+  {
+    DBUG_PRINT("ingo", ("Cannot open '%s': %s", file, strerror(errno)));
+    goto end;
+  }
+
+  filepos= 0;
+  while (fread(buffer, 1, MI_MIN_BLOCK_LENGTH, fp) == MI_MIN_BLOCK_LENGTH)
+  {
+    char        *ptr;
+    const char  *type;
+    uint32      rec_len;
+    uint32      data_len;
+    uint32      block_len;
+    uint32      header_len;
+    uint32      total_len;
+    uint32      read_len;
+    ulonglong   next_filepos;
+    ulonglong   prev_filepos;
+
+    ptr= buffer;
+    switch (*ptr)
+    {
+    case 0:
+      type=         "Deleted block";
+      rec_len=      0;
+      data_len=     0;
+      block_len=    mi_uint3korr(ptr + 1) - MI_MIN_BLOCK_LENGTH;
+      next_filepos= mi_uint8korr(ptr + 4);
+      prev_filepos= mi_uint8korr(ptr + 12);
+      ptr+= 20;
+      break;
+
+    case 1:
+      type=         "Full  small record, full";
+      rec_len=      mi_uint2korr(ptr + 1);
+      data_len=     rec_len;
+      block_len=    data_len;
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 3;
+      break;
+
+    case 2:
+      type=         "Full   big  record, full";
+      rec_len=      mi_uint3korr(ptr + 1);
+      data_len=     rec_len;
+      block_len=    data_len;
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 4;
+      break;
+
+    case 3:
+      type=         "Full  small record, gap";
+      rec_len=      mi_uint2korr(ptr + 1);
+      data_len=     rec_len;
+      block_len=    data_len + (uchar) ptr[3];
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 4;
+      break;
+
+    case 4:
+      type=         "Full   big  record, gap";
+      rec_len=      mi_uint3korr(ptr + 1);
+      data_len=     rec_len;
+      block_len=    data_len + (uchar) ptr[4];
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 5;
+      break;
+
+    case 5:
+      type=         "Start small record";
+      rec_len=      mi_uint2korr(ptr + 1);
+      data_len=     mi_uint2korr(ptr + 3);
+      block_len=    data_len;
+      next_filepos= mi_uint8korr(ptr + 5);
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 13;
+      break;
+
+    case 6:
+      type=         "Start  big  record";
+      rec_len=      mi_uint3korr(ptr + 1);
+      data_len=     mi_uint3korr(ptr + 4);
+      block_len=    data_len;
+      next_filepos= mi_uint8korr(ptr + 7);
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 15;
+      break;
+
+    case 7:
+      type=         "End   small record, full";
+      rec_len=      0;
+      data_len=     mi_uint2korr(ptr + 1);
+      block_len=    data_len;
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 3;
+      break;
+
+    case 8:
+      type=         "End    big  record, full";
+      rec_len=      0;
+      data_len=     mi_uint3korr(ptr + 1);
+      block_len=    data_len;
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 4;
+      break;
+
+    case 9:
+      type=         "End   small record, gap";
+      rec_len=      0;
+      data_len=     mi_uint2korr(ptr + 1);
+      block_len=    data_len + (uchar) ptr[3];
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 4;
+      break;
+
+    case 10:
+      type=         "End    big  record, gap";
+      rec_len=      0;
+      data_len=     mi_uint3korr(ptr + 1);
+      block_len=    data_len + (uchar) ptr[4];
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 5;
+      break;
+
+    case 11:
+      type=         "Cont. small record";
+      rec_len=      0;
+      data_len=     mi_uint2korr(ptr + 1);
+      block_len=    data_len;
+      next_filepos= mi_uint8korr(ptr + 3);
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 11;
+      break;
+
+    case 12:
+      type=         "Cont.  big  record";
+      rec_len=      0;
+      data_len=     mi_uint3korr(ptr + 1);
+      block_len=    data_len;
+      next_filepos= mi_uint8korr(ptr + 4);
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 12;
+      break;
+
+    case 13:
+      type=         "Start giant record";
+      rec_len=      mi_uint4korr(ptr + 1);
+      data_len=     mi_uint3korr(ptr + 5);
+      block_len=    data_len;
+      next_filepos= mi_uint8korr(ptr + 8);
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= 16;
+      break;
+
+    default:
+      type=         "Invalid block type";
+      rec_len=      0;
+      data_len=     0;
+      block_len=    0;
+      next_filepos= HA_OFFSET_ERROR;
+      prev_filepos= HA_OFFSET_ERROR;
+      ptr+= MI_MIN_BLOCK_LENGTH;
+      break;
+
+    } /*end switch*/
+
+    header_len= ptr - buffer;
+    total_len= header_len + block_len;
+    read_len= total_len - MI_MIN_BLOCK_LENGTH;
+
+    if (*buffer)
+      DBUG_PRINT("ingo", ("%10ld %-24s block %-8u data %-8u "
+                          "next %10ld rec %-8u",
+                          (long) ftell(fp) - MI_MIN_BLOCK_LENGTH, type,
+                          total_len, data_len, (long) next_filepos, rec_len));
+    else
+      DBUG_PRINT("ingo", ("%10ld %-24s block %-8u data %-8u "
+                          "next %10ld prev %10ld",
+                          (long) ftell(fp) - MI_MIN_BLOCK_LENGTH, type,
+                          total_len, data_len, (long) next_filepos,
+                          (long) prev_filepos));
+
+    if (total_len > buffer_size)
+    {
+      buffer_size= total_len;
+      buffer= realloc(buffer, buffer_size);
+      if (!buffer)
+      {
+        DBUG_PRINT("ingo", ("Cannot allocate %u bytes: %s",
+                            buffer_size, strerror(errno)));
+        goto end;
+      }
+    }
+
+    if (fread(buffer + MI_MIN_BLOCK_LENGTH, 1, read_len, fp) != read_len)
+    {
+      DBUG_PRINT("ingo", ("Cannot read %u bytes from '%s': %s",
+                          read_len, file, strerror(errno)));
+      goto end;
+    }
+
+  } /*end while*/
+
+  if (!feof(fp) && !ferror(fp))
+    DBUG_PRINT("ingo", ("Ended abnormally"));
+
+end:
+
+  if (fp && fclose(fp))
+    DBUG_PRINT("ingo", ("Cannot close data file"));
+
+  if (buffer)
+    free(buffer);
+
+  DBUG_PRINT("ingo", ("=========="));
+  DBUG_PRINT("ingo", (""));
+}
+#endif /*!DBUG_OFF*/
+
Thread
bk commit into 5.1 tree (istruewing:1.2568) BUG#36708Ingo Struewing4 Jun