[Commits] 0fb84ce: Fixed compilation failure on MacOSX

Vicentiu Ciorbaru vicentiu at mariadb.org
Mon Dec 21 13:45:38 EET 2015


revision-id: 0fb84ce556ab6506ec2a1445e8586faddb76bc6f (mariadb-10.1.9-14-g0fb84ce)
parent(s): 0bbaadc1866384dacfd9ebb7b33865007a6e587d
author: Vicențiu Ciorbaru
committer: Vicențiu Ciorbaru
timestamp: 2015-12-21 13:43:54 +0200
message:

Fixed compilation failure on MacOSX

Due to a hack that has propagated to the maria storage engine, undefined
behaviour would result by bypassing the initialization code of variables
after my_thread_init().

By refactoring the nested logic into a separate function, this problem
is resolved.

---
 include/myisam.h          |   3 +-
 storage/maria/ma_sort.c   | 333 ++++++++++++++++++++++++----------------------
 storage/maria/maria_def.h |   3 +-
 storage/myisam/sort.c     | 324 +++++++++++++++++++++++---------------------
 4 files changed, 350 insertions(+), 313 deletions(-)

diff --git a/include/myisam.h b/include/myisam.h
index 88ce401..f7a3ae8 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -331,7 +331,8 @@ typedef struct st_sort_info
   my_off_t filelength, dupp, buff_length;
   ha_rows max_records;
   uint current_key, total_keys;
-  uint got_error, threads_running;
+  volatile uint got_error;
+  uint threads_running;
   myf myf_rw;
   enum data_file_type new_data_file_type;
 } MI_SORT_INFO;
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index a4ce4f8..1eae028 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -364,192 +364,211 @@ static ha_rows find_all_keys(MARIA_SORT_PARAM *info, ha_rows keys,
 } /* find_all_keys */
 
 
-/* Search after all keys and place them in a temp. file */
-
-pthread_handler_t _ma_thr_find_all_keys(void *arg)
+static my_bool _ma_thr_find_all_keys_exec(MARIA_SORT_PARAM* sort_param)
 {
-  MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg;
-  int error;
-  size_t memavl, old_memavl;
-  longlong sortbuff_size;
-  ha_keys UNINIT_VAR(keys), idx;
-  uint sort_length;
-  uint maxbuffer;
-  uchar **sort_keys=0;
+  DBUG_ENTER("_ma_thr_find_all_keys");
+  DBUG_PRINT("enter", ("master: %d", sort_param->master));
 
-  error=1;
+  my_bool error= FALSE;
+  if (sort_param->sort_info->got_error)
+    error= TRUE;
+  if (error)
+    DBUG_RETURN(error);
 
-  if (my_thread_init())
-    goto err;
+  set_sort_param_read_write(sort_param);
 
-  { /* Add extra block since DBUG_ENTER declare variables */
-    DBUG_ENTER("_ma_thr_find_all_keys");
-    DBUG_PRINT("enter", ("master: %d", sort_param->master));
-    if (sort_param->sort_info->got_error)
-      goto err;
+  ulonglong memavl, old_memavl, sortbuff_size;
+  ha_keys UNINIT_VAR(keys), idx;
+  uint sort_length;
+  uint maxbuffer;
+  uchar **sort_keys= NULL;
 
-    set_sort_param_read_write(sort_param);
+  my_b_clear(&sort_param->tempfile);
+  my_b_clear(&sort_param->tempfile_for_exceptions);
+  bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
+  bzero((char*) &sort_param->unique,  sizeof(sort_param->unique));
 
-    my_b_clear(&sort_param->tempfile);
-    my_b_clear(&sort_param->tempfile_for_exceptions);
-    bzero((char*) &sort_param->buffpek,sizeof(sort_param->buffpek));
-    bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
 
-    sortbuff_size= sort_param->sortbuff_size;
-    memavl=       MY_MAX(sortbuff_size, MIN_SORT_MEMORY);
-    idx=          (ha_keys) sort_param->sort_info->max_records;
-    sort_length=  sort_param->key_length;
-    maxbuffer=    1;
+  sortbuff_size= sort_param->sortbuff_size;
+  memavl=        MY_MAX(sortbuff_size, MIN_SORT_BUFFER);
+  idx=           (ha_keys) sort_param->sort_info->max_records;
+  sort_length=   sort_param->key_length;
+  maxbuffer=     1;
 
-    while (memavl >= MIN_SORT_MEMORY)
+  while (memavl >= MIN_SORT_BUFFER)
+  {
+    if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
+        (my_off_t) memavl)
+      keys= idx+1;
+    else if ((sort_param->sort_info->param->testflag &
+             (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) ==
+                T_FORCE_SORT_MEMORY)
     {
-      if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl)
-        keys= idx+1;
-      else if ((sort_param->sort_info->param->testflag &
-                (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) ==
-               T_FORCE_SORT_MEMORY)
-      {
-        /*
-          Use all of the given sort buffer for key data.
-          Allocate 1000 buffers at a start for new data. More buffers
-          will be allocated when needed.
-        */
-        keys= memavl / (sort_length+sizeof(char*));
-        maxbuffer= (uint) MY_MIN((ulonglong) 1000, (idx / keys)+1);
-      }
-      else
+      /*
+         Use all of the given sort buffer for key data.
+         Allocate 1000 buffers at a start for new data. More buffers
+         will be allocated when needed.
+      */
+      keys= memavl / (sort_length+sizeof(char*));
+      maxbuffer= (uint) MY_MIN((ulonglong) 1000, (idx / keys)+1);
+    }
+    else
+    {
+      uint maxbuffer_org;
+      do
       {
-        uint maxbuffer_org;
-        do
+        maxbuffer_org= maxbuffer;
+        if (memavl < sizeof(BUFFPEK)*maxbuffer ||
+            (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
+             (sort_length+sizeof(char*))) <= 1 ||
+            keys < (uint) maxbuffer)
         {
-          maxbuffer_org= maxbuffer;
-          if (memavl < sizeof(BUFFPEK)*maxbuffer ||
-              (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
-               (sort_length+sizeof(char*))) <= 1 ||
-              keys < maxbuffer)
-          {
-            _ma_check_print_error(sort_param->sort_info->param,
-                                  "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
-                                  sortbuff_size, (ulonglong) idx, sort_length);
-            goto err;
-          }
+          mysql_mutex_lock(&sort_param->sort_info->mutex);
+          _ma_check_print_error(sort_param->sort_info->param,
+                                "aria_sort_buffer_size is too small. Current "
+                                "aria_sort_buffer_size: %llu  rows: %llu  "
+                                "sort_length: %u",
+                                sortbuff_size, (ulonglong) idx, sort_length);
+          mysql_mutex_unlock(&sort_param->sort_info->mutex);
+          DBUG_RETURN(TRUE);
         }
-        while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org);
       }
-      if ((sort_keys= (uchar **)
-           my_malloc(keys*(sort_length+sizeof(char*))+
-                     ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
-                      HA_FT_MAXBYTELEN : 0), MYF(0))))
+      while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org);
+    }
+    if ((sort_keys= (uchar **)
+         my_malloc(keys*(sort_length+sizeof(char*))+
+                   ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
+                    HA_FT_MAXBYTELEN : 0), MYF(0))))
+    {
+      if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
+                                maxbuffer, MY_MIN(maxbuffer/2, 1000), MYF(0)))
       {
-        if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
-                                  maxbuffer, MY_MIN(maxbuffer/2, 1000), MYF(0)))
-        {
-          my_free(sort_keys);
-          sort_keys= (uchar **) NULL;            /* for err: label */
-        }
-        else
-          break;
+        my_free(sort_keys);
+        sort_keys= NULL;          /* Safety against double free on error. */
       }
-      old_memavl= memavl;
-      if ((memavl= memavl/4*3) < MIN_SORT_MEMORY &&
-          old_memavl > MIN_SORT_MEMORY)
-        memavl= MIN_SORT_MEMORY;
+      else
+        break;
     }
-    if (memavl < MIN_SORT_MEMORY)
-    {
-      /* purecov: begin inspected */
-      _ma_check_print_error(sort_param->sort_info->param,
-                            "aria_sort_buffer_size is too small. Current aria_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
-                            sortbuff_size, (ulonglong) idx, sort_length);
-      my_errno= ENOMEM;
-      goto err;
+    old_memavl= memavl;
+    if ((memavl= memavl/4*3) < MIN_SORT_MEMORY &&
+        old_memavl > MIN_SORT_MEMORY)
+      memavl= MIN_SORT_MEMORY;
+  }
+  if (memavl < MIN_SORT_MEMORY)
+  {
+    /* purecov: begin inspected */
+    mysql_mutex_lock(&sort_param->sort_info->mutex);
+    _ma_check_print_error(sort_param->sort_info->param,
+                          "aria_sort_buffer_size is too small. Current "
+                          "aria_sort_buffer_size: %llu  rows: %llu  "
+                          "sort_length: %u",
+                          sortbuff_size, (ulonglong) idx, sort_length);
+    my_errno= ENOMEM;
+    mysql_mutex_unlock(&sort_param->sort_info->mutex);
+    DBUG_RETURN(TRUE);
     /* purecov: end inspected */
-    }
-
-    if (sort_param->sort_info->param->testflag & T_VERBOSE)
-      my_fprintf(stdout,
-                 "Key %d - Allocating buffer for %llu keys\n",
-                 sort_param->key + 1, (ulonglong) keys);
-    sort_param->sort_keys= sort_keys;
+  }
+  if (sort_param->sort_info->param->testflag & T_VERBOSE)
+    my_fprintf(stdout,
+               "Key %d - Allocating buffer for %llu keys\n",
+               sort_param->key + 1, (ulonglong) keys);
+  sort_param->sort_keys= sort_keys;
 
-    idx= error= 0;
-    sort_keys[0]= (uchar*) (sort_keys+keys);
+  idx= error= 0;
+  sort_keys[0]= (uchar*) (sort_keys+keys);
 
-    DBUG_PRINT("info", ("reading keys"));
-    while (!(error= sort_param->sort_info->got_error) &&
-           !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
+  DBUG_PRINT("info", ("reading keys"));
+  while (!(error= sort_param->sort_info->got_error) &&
+         !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
+  {
+    if (sort_param->real_key_length > sort_param->key_length)
     {
-      if (sort_param->real_key_length > sort_param->key_length)
-      {
-        if (write_key(sort_param, sort_keys[idx],
-                      &sort_param->tempfile_for_exceptions))
-          goto err;
-        continue;
-      }
-
-      if (++idx == keys)
-      {
-        if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
-                                   (BUFFPEK *)alloc_dynamic(&sort_param->
-                                                            buffpek),
-                                   &sort_param->tempfile))
-          goto err;
-        sort_keys[0]= (uchar*) (sort_keys+keys);
-        memcpy(sort_keys[0], sort_keys[idx - 1],
-               (size_t) sort_param->key_length);
-        idx= 1;
-      }
-      sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
+      if (write_key(sort_param, sort_keys[idx],
+            &sort_param->tempfile_for_exceptions))
+        goto err;
+      continue;
     }
-    if (error > 0)
-      goto err;
-    if (sort_param->buffpek.elements)
+
+    if (++idx == keys)
     {
-      if (sort_param->write_keys(sort_param,sort_keys, idx,
-                                 (BUFFPEK *) alloc_dynamic(&sort_param->
-                                                           buffpek),
+      if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
+                                 (BUFFPEK *)alloc_dynamic(&sort_param->buffpek),
                                  &sort_param->tempfile))
         goto err;
-      sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
+      sort_keys[0]= (uchar*) (sort_keys+keys);
+      memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
+      idx= 1;
     }
-    else
-      sort_param->keys= idx;
+    sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
+  }
+  if (error > 0)
+    goto err;
+  if (sort_param->buffpek.elements)
+  {
+    if (sort_param->write_keys(sort_param,sort_keys, idx,
+                               (BUFFPEK *) alloc_dynamic(&sort_param->
+                                                         buffpek),
+                               &sort_param->tempfile))
+      goto err;
+    sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
+  }
+  else
+    sort_param->keys= idx;
 
-    goto ok;
+  DBUG_RETURN(FALSE);
 
 err:
-    DBUG_PRINT("error", ("got some error"));
-    sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
-    my_free(sort_keys);
-    sort_param->sort_keys= 0;
-    delete_dynamic(& sort_param->buffpek);
-    close_cached_file(&sort_param->tempfile);
-    close_cached_file(&sort_param->tempfile_for_exceptions);
-
-ok:
-    free_root(&sort_param->wordroot, MYF(0));
-    /*
-      Detach from the share if the writer is involved. Avoid others to
-      be blocked. This includes a flush of the write buffer. This will
-      also indicate EOF to the readers.
-      That means that a writer always gets here first and readers -
-      only when they see EOF. But if a reader finishes prematurely
-      because of an error it may reach this earlier - don't allow it
-      to detach the writer thread.
-    */
-    if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
-      remove_io_thread(&sort_param->sort_info->info->rec_cache);
-
-    /* Readers detach from the share if any. Avoid others to be blocked. */
-    if (sort_param->read_cache.share)
-      remove_io_thread(&sort_param->read_cache);
+  DBUG_PRINT("error", ("got some error"));
+  my_free(sort_keys);
+  sort_param->sort_keys= 0;
+  delete_dynamic(& sort_param->buffpek);
+  close_cached_file(&sort_param->tempfile);
+  close_cached_file(&sort_param->tempfile_for_exceptions);
+
+  DBUG_RETURN(TRUE);
+}
+
+/* Search after all keys and place them in a temp. file */
+
+pthread_handler_t _ma_thr_find_all_keys(void *arg)
+{
+  MARIA_SORT_PARAM *sort_param= (MARIA_SORT_PARAM*) arg;
+  my_bool error= FALSE;
+  /* If my_thread_init fails */
+  if (my_thread_init())
+    error= TRUE;
+
+  if (error || _ma_thr_find_all_keys_exec(sort_param))
+    error= TRUE;
+
+  /*
+     Thread must clean up after itself.
+  */
+  free_root(&sort_param->wordroot, MYF(0));
+  /*
+     Detach from the share if the writer is involved. Avoid others to
+     be blocked. This includes a flush of the write buffer. This will
+     also indicate EOF to the readers.
+     That means that a writer always gets here first and readers -
+     only when they see EOF. But if a reader finishes prematurely
+     because of an error it may reach this earlier - don't allow it
+     to detach the writer thread.
+     */
+  if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
+    remove_io_thread(&sort_param->sort_info->info->rec_cache);
+
+  /* Readers detach from the share if any. Avoid others to be blocked. */
+  if (sort_param->read_cache.share)
+    remove_io_thread(&sort_param->read_cache);
+
+  mysql_mutex_lock(&sort_param->sort_info->mutex);
+  if (error)
+    sort_param->sort_info->got_error= 1;
+
+  if (!--sort_param->sort_info->threads_running)
+    mysql_cond_signal(&sort_param->sort_info->cond);
+  mysql_mutex_unlock(&sort_param->sort_info->mutex);
 
-    mysql_mutex_lock(&sort_param->sort_info->mutex);
-    if (!--sort_param->sort_info->threads_running)
-      mysql_cond_signal(&sort_param->sort_info->cond);
-    mysql_mutex_unlock(&sort_param->sort_info->mutex);
-    DBUG_PRINT("exit", ("======== ending thread ========"));
-  }
   my_thread_end();
   return NULL;
 }
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index 676927b..fa7b954 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -67,7 +67,8 @@ typedef struct st_maria_sort_info
   pgcache_page_no_t page;
   ha_rows max_records;
   uint current_key, total_keys;
-  uint got_error, threads_running;
+  volatile uint got_error;
+  uint threads_running;
   myf myf_rw;
   enum data_file_type new_data_file_type, org_data_file_type;
 } MARIA_SORT_INFO;
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index f490e5f..f6e9bfe 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -344,192 +344,208 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, ha_rows keys,
   DBUG_RETURN((*maxbuffer)*(keys-1)+idx);
 } /* find_all_keys */
 
-/* Search after all keys and place them in a temp. file */
-
-pthread_handler_t thr_find_all_keys(void *arg)
+static my_bool thr_find_all_keys_exec(MI_SORT_PARAM *sort_param)
 {
-  MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
-  int error;
+  DBUG_ENTER("thr_find_all_keys");
+  DBUG_PRINT("enter", ("master: %d", sort_param->master));
+
+  my_bool error= FALSE;
+  if (sort_param->sort_info->got_error)
+    error= TRUE;
+  if (error)
+    DBUG_RETURN(error);
+
+  set_sort_param_read_write(sort_param);
+
   ulonglong memavl, old_memavl, sortbuff_size;
   ha_keys UNINIT_VAR(keys), idx;
   uint sort_length;
   uint maxbuffer;
-  uchar **sort_keys=0;
+  uchar **sort_keys= NULL;
 
-  error=1;
+  my_b_clear(&sort_param->tempfile);
+  my_b_clear(&sort_param->tempfile_for_exceptions);
+  bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
+  bzero((char*) &sort_param->unique,  sizeof(sort_param->unique));
 
-  if (my_thread_init())
-    goto err;
 
-  { /* Add extra block since DBUG_ENTER declare variables */
-    DBUG_ENTER("thr_find_all_keys");
-    DBUG_PRINT("enter", ("master: %d", sort_param->master));
-    if (sort_param->sort_info->got_error)
-      goto err;
+  sortbuff_size= sort_param->sortbuff_size;
+  memavl=        MY_MAX(sortbuff_size, MIN_SORT_BUFFER);
+  idx=           (ha_keys) sort_param->sort_info->max_records;
+  sort_length=   sort_param->key_length;
+  maxbuffer=     1;
 
-    set_sort_param_read_write(sort_param);
-
-    my_b_clear(&sort_param->tempfile);
-    my_b_clear(&sort_param->tempfile_for_exceptions);
-    bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
-    bzero((char*) &sort_param->unique,  sizeof(sort_param->unique));
-    sort_keys= (uchar **) NULL;
-
-    sortbuff_size= sort_param->sortbuff_size;
-    memavl=       MY_MAX(sortbuff_size, MIN_SORT_BUFFER);
-    idx=          (ha_keys) sort_param->sort_info->max_records;
-    sort_length=  sort_param->key_length;
-    maxbuffer=    1;
-
-    while (memavl >= MIN_SORT_BUFFER)
+  while (memavl >= MIN_SORT_BUFFER)
+  {
+    if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
+        (my_off_t) memavl)
+      keys= idx+1;
+    else if ((sort_param->sort_info->param->testflag &
+               (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) ==
+                 T_FORCE_SORT_MEMORY)
     {
-      if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
-          (my_off_t) memavl)
-        keys= idx+1;
-      else if ((sort_param->sort_info->param->testflag &
-                (T_FORCE_SORT_MEMORY | T_CREATE_MISSING_KEYS)) ==
-               T_FORCE_SORT_MEMORY)
-      {
-        /*
-          Use all of the given sort buffer for key data.
-          Allocate 1000 buffers at a start for new data. More buffers
-          will be allocated when needed.
-        */
-        keys= memavl / (sort_length+sizeof(char*));
-        maxbuffer= (uint) MY_MIN((ulonglong) 1000, (idx / keys)+1);
-      }
-      else
+      /*
+         Use all of the given sort buffer for key data.
+         Allocate 1000 buffers at a start for new data. More buffers
+         will be allocated when needed.
+      */
+      keys= memavl / (sort_length+sizeof(char*));
+      maxbuffer= (uint) MY_MIN((ulonglong) 1000, (idx / keys)+1);
+    }
+    else
+    {
+      uint maxbuffer_org;
+      do
       {
-        uint maxbuffer_org;
-        do
+        maxbuffer_org= maxbuffer;
+        if (memavl < sizeof(BUFFPEK)*maxbuffer ||
+            (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
+             (sort_length+sizeof(char*))) <= 1 ||
+            keys < (uint) maxbuffer)
         {
-          maxbuffer_org= maxbuffer;
-          if (memavl < sizeof(BUFFPEK)*maxbuffer ||
-              (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
-               (sort_length+sizeof(char*))) <= 1 ||
-              keys < (uint) maxbuffer)
-          {
-            mi_check_print_error(sort_param->sort_info->param,
-                                 "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
-                                 sortbuff_size, (ulonglong) idx, sort_length);
-            goto err;
-          }
+          mysql_mutex_lock(&sort_param->sort_info->mutex);
+          mi_check_print_error(sort_param->sort_info->param,
+              "myisam_sort_buffer_size is too small. Current "
+              "myisam_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
+              sortbuff_size, (ulonglong) idx, sort_length);
+          mysql_mutex_unlock(&sort_param->sort_info->mutex);
+          DBUG_RETURN(TRUE);
         }
-        while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org);
       }
-      if ((sort_keys= (uchar**)
-           my_malloc(keys*(sort_length+sizeof(char*))+
-                     ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
-                      HA_FT_MAXBYTELEN : 0), MYF(0))))
+      while ((maxbuffer= (uint) (idx/(keys-1)+1)) != maxbuffer_org);
+    }
+    if ((sort_keys= my_malloc(keys * (sort_length + sizeof(char *)) +
+                              ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
+                                 HA_FT_MAXBYTELEN : 0), MYF(0))))
+    {
+      if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
+                                maxbuffer, MY_MIN(maxbuffer/2, 1000), MYF(0)))
       {
-        if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
-                                  maxbuffer, MY_MIN(maxbuffer/2, 1000), MYF(0)))
-        {
-          my_free(sort_keys);
-          sort_keys= (uchar **) NULL; /* for err: label */
-        }
-        else
-          break;
+        my_free(sort_keys);
+        sort_keys= NULL;          /* Safety against double free on error. */
       }
-      old_memavl= memavl;
-      if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
-          old_memavl > MIN_SORT_BUFFER)
-        memavl= MIN_SORT_BUFFER;
+      else
+        break;
     }
-    if (memavl < MIN_SORT_BUFFER)
-    {
-      /* purecov: begin inspected */
-      mi_check_print_error(sort_param->sort_info->param,
-                           "myisam_sort_buffer_size is too small. Current myisam_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
-                           sortbuff_size, (ulonglong) idx, sort_length);
-      my_errno= ENOMEM;
-      goto err;
+    old_memavl= memavl;
+    if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
+        old_memavl > MIN_SORT_BUFFER)
+      memavl= MIN_SORT_BUFFER;
+  }
+  if (memavl < MIN_SORT_BUFFER)
+  {
+    /* purecov: begin inspected */
+    mysql_mutex_lock(&sort_param->sort_info->mutex);
+    mi_check_print_error(sort_param->sort_info->param,
+        "myisam_sort_buffer_size is too small. Current "
+        "myisam_sort_buffer_size: %llu  rows: %llu  sort_length: %u",
+        sortbuff_size, (ulonglong) idx, sort_length);
+    my_errno= ENOMEM;
+    mysql_mutex_unlock(&sort_param->sort_info->mutex);
+    DBUG_RETURN(TRUE);
     /* purecov: end inspected */
-    }
+  }
 
-    if (sort_param->sort_info->param->testflag & T_VERBOSE)
-      my_fprintf(stdout,
-                 "Key %d - Allocating buffer for %llu keys\n",
-                 sort_param->key + 1, (ulonglong) keys);
-    sort_param->sort_keys= sort_keys;
+  if (sort_param->sort_info->param->testflag & T_VERBOSE)
+    my_fprintf(stdout,
+        "Key %d - Allocating buffer for %llu keys\n",
+        sort_param->key + 1, (ulonglong) keys);
+  sort_param->sort_keys= sort_keys;
 
-    idx= error= 0;
-    sort_keys[0]= (uchar*) (sort_keys+keys);
+  idx= error= 0;
+  sort_keys[0]= (uchar*) (sort_keys+keys);
 
-    DBUG_PRINT("info", ("reading keys"));
-    while (!(error= sort_param->sort_info->got_error) &&
-           !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
+  DBUG_PRINT("info", ("reading keys"));
+  while (!(error= sort_param->sort_info->got_error) &&
+         !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
+  {
+    if (sort_param->real_key_length > sort_param->key_length)
     {
-      if (sort_param->real_key_length > sort_param->key_length)
-      {
-        if (write_key(sort_param, sort_keys[idx],
-                      &sort_param->tempfile_for_exceptions))
-          goto err;
-        continue;
-      }
-
-      if (++idx == keys)
-      {
-        if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
-                                   (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
-                                   &sort_param->tempfile))
-          goto err;
-        sort_keys[0]= (uchar*) (sort_keys+keys);
-        memcpy(sort_keys[0], sort_keys[idx - 1],
-               (size_t) sort_param->key_length);
-        idx= 1;
-      }
-      sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
+      if (write_key(sort_param, sort_keys[idx],
+                    &sort_param->tempfile_for_exceptions))
+        goto err;
+      continue;
     }
-    if (error > 0)
-      goto err;
-    if (sort_param->buffpek.elements)
+
+    if (++idx == keys)
     {
-      if (sort_param->write_keys(sort_param, sort_keys, idx,
+      if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
                                  (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
                                  &sort_param->tempfile))
         goto err;
-      sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
+      sort_keys[0]= (uchar*) (sort_keys+keys);
+      memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
+      idx= 1;
     }
-    else
-      sort_param->keys= idx;
+    sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
+  }
+  if (error > 0)
+    goto err;
+  if (sort_param->buffpek.elements)
+  {
+    if (sort_param->write_keys(sort_param, sort_keys, idx,
+                               (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
+                               &sort_param->tempfile))
+      goto err;
+    sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
+  }
+  else
+    sort_param->keys= idx;
 
-    goto ok;
+  DBUG_RETURN(FALSE);
 
 err:
-    DBUG_PRINT("error", ("got some error"));
-    sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
-    my_free(sort_keys);
-    sort_param->sort_keys= 0;
-    delete_dynamic(& sort_param->buffpek);
-    close_cached_file(&sort_param->tempfile);
-    close_cached_file(&sort_param->tempfile_for_exceptions);
-
-ok:
-    free_root(&sort_param->wordroot, MYF(0));
-    /*
-      Detach from the share if the writer is involved. Avoid others to
-      be blocked. This includes a flush of the write buffer. This will
-      also indicate EOF to the readers.
-      That means that a writer always gets here first and readers -
-      only when they see EOF. But if a reader finishes prematurely
-      because of an error it may reach this earlier - don't allow it
-      to detach the writer thread.
-    */
-    if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
-      remove_io_thread(&sort_param->sort_info->info->rec_cache);
-
-    /* Readers detach from the share if any. Avoid others to be blocked. */
-    if (sort_param->read_cache.share)
-      remove_io_thread(&sort_param->read_cache);
+  DBUG_PRINT("error", ("got some error"));
+  sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
+  my_free(sort_keys);
+  sort_param->sort_keys= 0;
+  delete_dynamic(& sort_param->buffpek);
+  close_cached_file(&sort_param->tempfile);
+  close_cached_file(&sort_param->tempfile_for_exceptions);
 
-    mysql_mutex_lock(&sort_param->sort_info->mutex);
-    if (!--sort_param->sort_info->threads_running)
-      mysql_cond_signal(&sort_param->sort_info->cond);
-    mysql_mutex_unlock(&sort_param->sort_info->mutex);
-    DBUG_PRINT("exit", ("======== ending thread ========"));
-    DBUG_LEAVE;
-  }
+  DBUG_RETURN(TRUE);
+}
+
+/* Search after all keys and place them in a temp. file */
+
+pthread_handler_t thr_find_all_keys(void *arg)
+{
+  MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
+  my_bool error= FALSE;
+  /* If my_thread_init fails */
+  if (my_thread_init())
+    error= TRUE;
+
+  if (error || thr_find_all_keys_exec(sort_param))
+    error= TRUE;
+
+  /*
+     Thread must clean up after itself.
+  */
+  free_root(&sort_param->wordroot, MYF(0));
+  /*
+     Detach from the share if the writer is involved. Avoid others to
+     be blocked. This includes a flush of the write buffer. This will
+     also indicate EOF to the readers.
+     That means that a writer always gets here first and readers -
+     only when they see EOF. But if a reader finishes prematurely
+     because of an error it may reach this earlier - don't allow it
+     to detach the writer thread.
+  */
+  if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
+    remove_io_thread(&sort_param->sort_info->info->rec_cache);
+
+  /* Readers detach from the share if any. Avoid others to be blocked. */
+  if (sort_param->read_cache.share)
+    remove_io_thread(&sort_param->read_cache);
+
+  mysql_mutex_lock(&sort_param->sort_info->mutex);
+  if (error)
+    sort_param->sort_info->got_error= 1;
+
+  if (!--sort_param->sort_info->threads_running)
+    mysql_cond_signal(&sort_param->sort_info->cond);
+  mysql_mutex_unlock(&sort_param->sort_info->mutex);
   my_thread_end();
   return NULL;
 }


More information about the commits mailing list