32 #undef DISK_BUFFER_SIZE
36 #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
37 #define DISK_BUFFER_SIZE (IO_SIZE*16)
44 extern void print_error(
const char *
fmt,...);
57 static int write_index(
MI_SORT_PARAM *info,uchar * *sort_keys,
61 BUFFPEK *buffpek,
int *maxbuffer,
67 uchar * *sort_keys,
BUFFPEK *lastbuff,
73 static int write_keys_varlen(
MI_SORT_PARAM *info,uchar **sort_keys,
79 uchar *key, uint sort_length, uint count);
82 uchar* key, uint sort_length,
101 int _create_index_by_sort(
MI_SORT_PARAM *info,my_bool no_messages,
102 ulonglong sortbuff_size)
104 int error,maxbuffer,skr;
105 uint sort_length, keys;
106 ulonglong memavl, old_memavl;
110 IO_CACHE tempfile, tempfile_for_exceptions;
111 DBUG_ENTER(
"_create_index_by_sort");
112 DBUG_PRINT(
"enter",(
"sort_length: %d", info->key_length));
114 if (info->keyinfo->flag & HA_VAR_LENGTH_KEY)
116 info->write_keys=write_keys_varlen;
117 info->read_to_buffer=read_to_buffer_varlen;
118 info->write_key= write_merge_key_varlen;
122 info->write_keys=write_keys;
124 info->write_key=write_merge_key;
127 my_b_clear(&tempfile);
128 my_b_clear(&tempfile_for_exceptions);
129 memset(&buffpek, 0,
sizeof(buffpek));
130 sort_keys= (uchar **) NULL; error= 1;
133 memavl= MY_MAX(sortbuff_size, MIN_SORT_BUFFER);
134 records= info->sort_info->max_records;
135 sort_length= info->key_length;
138 if ((memavl -
sizeof(
BUFFPEK)) / (sort_length +
sizeof(
char *)) > UINT_MAX32)
139 memavl=
sizeof(
BUFFPEK) + UINT_MAX32 * (sort_length +
sizeof(
char *));
141 while (memavl >= MIN_SORT_BUFFER)
143 if ((records < UINT_MAX32) &&
144 ((my_off_t) (records + 1) *
145 (sort_length +
sizeof(
char*)) <= (my_off_t) memavl))
146 keys= (uint)records+1;
151 if (memavl <
sizeof(
BUFFPEK)*(uint) maxbuffer ||
152 (keys=(memavl-
sizeof(
BUFFPEK)*(uint) maxbuffer)/
153 (sort_length+
sizeof(
char*))) <= 1 ||
154 keys < (uint) maxbuffer)
156 mi_check_print_error(info->sort_info->param,
157 "myisam_sort_buffer_size is too small");
161 while ((maxbuffer= (
int) (records/(keys-1)+1)) != skr);
163 if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+
sizeof(
char*))+
164 HA_FT_MAXBYTELEN, MYF(0))))
166 if (my_init_dynamic_array(&buffpek,
sizeof(
BUFFPEK), maxbuffer,
176 if ((memavl= memavl/4*3) < MIN_SORT_BUFFER && old_memavl > MIN_SORT_BUFFER)
177 memavl= MIN_SORT_BUFFER;
179 if (memavl < MIN_SORT_BUFFER)
181 mi_check_print_error(info->sort_info->param,
"MyISAM sort buffer too small");
184 (*info->lock_in_memory)(info->sort_info->param);
187 printf(
" - Searching for keys, allocating buffer for %d keys\n",keys);
189 if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
190 &tempfile,&tempfile_for_exceptions))
196 printf(
" - Dumping %lu keys\n", (ulong) records);
197 if (write_index(info,sort_keys, (uint) records))
202 keys=(keys*(sort_length+
sizeof(
char*)))/sort_length;
203 if (maxbuffer >= MERGEBUFF2)
206 printf(
" - Merging %lu keys\n", (ulong) records);
208 dynamic_element(&buffpek,0,
BUFFPEK *),&maxbuffer,&tempfile))
211 if (flush_io_cache(&tempfile) ||
212 reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
215 printf(
" - Last merge and dumping keys\n");
216 if (merge_index(info,keys,sort_keys,dynamic_element(&buffpek,0,
BUFFPEK *),
217 maxbuffer,&tempfile))
221 if (flush_ft_buf(info) || flush_pending_blocks(info))
224 if (my_b_inited(&tempfile_for_exceptions))
226 MI_INFO *idx=info->sort_info->info;
227 uint keyno=info->key;
228 uint key_length, ref_length=idx->s->rec_reflength;
231 printf(
" - Adding exceptions\n");
232 if (flush_io_cache(&tempfile_for_exceptions) ||
233 reinit_io_cache(&tempfile_for_exceptions,READ_CACHE,0L,0,0))
236 while (!my_b_read(&tempfile_for_exceptions,(uchar*)&key_length,
238 && !my_b_read(&tempfile_for_exceptions,(uchar*)sort_keys,
241 if (_mi_ck_write(idx,keyno,(uchar*) sort_keys,key_length-ref_length))
250 delete_dynamic(&buffpek);
251 close_cached_file(&tempfile);
252 close_cached_file(&tempfile_for_exceptions);
254 DBUG_RETURN(error ? -1 : 0);
267 DBUG_ENTER(
"find_all_keys");
270 sort_keys[0]=(uchar*) (sort_keys+keys);
272 while (!(error=(*info->key_read)(info,sort_keys[idx])))
274 if (info->real_key_length > info->key_length)
276 if (write_key(info,sort_keys[idx],tempfile_for_exceptions))
277 DBUG_RETURN(HA_POS_ERROR);
283 if (info->write_keys(info,sort_keys,idx-1,(
BUFFPEK *)alloc_dynamic(buffpek),
285 DBUG_RETURN(HA_POS_ERROR);
287 sort_keys[0]=(uchar*) (sort_keys+keys);
288 memcpy(sort_keys[0],sort_keys[idx-1],(
size_t) info->key_length);
291 sort_keys[idx]=sort_keys[idx-1]+info->key_length;
294 DBUG_RETURN(HA_POS_ERROR);
295 if (buffpek->elements)
297 if (info->write_keys(info,sort_keys,idx,(
BUFFPEK *)alloc_dynamic(buffpek),
299 DBUG_RETURN(HA_POS_ERROR);
300 *maxbuffer=buffpek->elements-1;
305 DBUG_RETURN((*maxbuffer)*(keys-1)+idx);
311 pthread_handler_t thr_find_all_keys(
void *arg)
315 ulonglong memavl, old_memavl;
316 uint keys, sort_length;
324 if (my_thread_init())
328 DBUG_ENTER(
"thr_find_all_keys");
329 DBUG_PRINT(
"enter", (
"master: %d", sort_param->master));
330 if (sort_param->sort_info->got_error)
333 if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
335 sort_param->write_keys= write_keys_varlen;
336 sort_param->read_to_buffer= read_to_buffer_varlen;
337 sort_param->write_key= write_merge_key_varlen;
341 sort_param->write_keys= write_keys;
343 sort_param->write_key= write_merge_key;
346 my_b_clear(&sort_param->tempfile);
347 my_b_clear(&sort_param->tempfile_for_exceptions);
348 memset(&sort_param->buffpek, 0,
sizeof(sort_param->buffpek));
349 memset(&sort_param->unique, 0,
sizeof(sort_param->unique));
350 sort_keys= (uchar **) NULL;
352 memavl= MY_MAX(sort_param->sortbuff_size, MIN_SORT_BUFFER);
353 idx= (uint)sort_param->sort_info->max_records;
354 sort_length= sort_param->key_length;
357 if ((memavl -
sizeof(
BUFFPEK)) / (sort_length +
358 sizeof(
char *)) > UINT_MAX32)
359 memavl=
sizeof(BUFFPEK) + UINT_MAX32 * (sort_length +
sizeof(
char *));
361 while (memavl >= MIN_SORT_BUFFER)
363 if ((my_off_t) (idx+1)*(sort_length+
sizeof(
char*)) <=
372 if (memavl <
sizeof(BUFFPEK)*maxbuffer ||
373 (keys=(memavl-
sizeof(BUFFPEK)*maxbuffer)/
374 (sort_length+
sizeof(
char*))) <= 1 ||
375 keys < (uint) maxbuffer)
377 mi_check_print_error(sort_param->sort_info->param,
378 "myisam_sort_buffer_size is too small");
382 while ((maxbuffer= (
int) (idx/(keys-1)+1)) != skr);
384 if ((sort_keys= (uchar**)
385 my_malloc(keys*(sort_length+
sizeof(
char*))+
386 ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
387 HA_FT_MAXBYTELEN : 0), MYF(0))))
389 if (my_init_dynamic_array(&sort_param->buffpek,
sizeof(BUFFPEK),
390 maxbuffer, maxbuffer/2))
393 sort_keys= (uchar **) NULL;
399 if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER &&
400 old_memavl > MIN_SORT_BUFFER)
401 memavl= MIN_SORT_BUFFER;
403 if (memavl < MIN_SORT_BUFFER)
405 mi_check_print_error(sort_param->sort_info->param,
406 "MyISAM sort buffer too small");
410 if (sort_param->sort_info->param->testflag & T_VERBOSE)
411 printf(
"Key %d - Allocating buffer for %d keys\n",
412 sort_param->key + 1, keys);
413 sort_param->sort_keys= sort_keys;
416 sort_keys[0]= (uchar*) (sort_keys+keys);
418 DBUG_PRINT(
"info", (
"reading keys"));
419 while (!(error= sort_param->sort_info->got_error) &&
420 !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
422 if (sort_param->real_key_length > sort_param->key_length)
424 if (write_key(sort_param, sort_keys[idx],
425 &sort_param->tempfile_for_exceptions))
432 if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
433 (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
434 &sort_param->tempfile))
436 sort_keys[0]= (uchar*) (sort_keys+keys);
437 memcpy(sort_keys[0], sort_keys[idx - 1], (
size_t) sort_param->key_length);
440 sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
444 if (sort_param->buffpek.elements)
446 if (sort_param->write_keys(sort_param, sort_keys, idx,
447 (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
448 &sort_param->tempfile))
450 sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
453 sort_param->keys= idx;
455 sort_param->sort_keys_length= keys;
459 DBUG_PRINT(
"error", (
"got some error"));
460 sort_param->sort_info->got_error= 1;
462 sort_param->sort_keys= 0;
463 delete_dynamic(& sort_param->buffpek);
464 close_cached_file(&sort_param->tempfile);
465 close_cached_file(&sort_param->tempfile_for_exceptions);
468 free_root(&sort_param->wordroot, MYF(0));
478 if (sort_param->master && sort_param->sort_info->info->rec_cache.share)
479 remove_io_thread(&sort_param->sort_info->info->rec_cache);
482 if (sort_param->read_cache.share)
483 remove_io_thread(&sort_param->read_cache);
486 if (!--sort_param->sort_info->threads_running)
489 DBUG_PRINT(
"exit", (
"======== ending thread ========"));
498 SORT_INFO *sort_info=sort_param->sort_info;
500 ulong UNINIT_VAR(length), keys;
501 ulong *rec_per_key_part=param->rec_per_key_part;
502 int got_error=sort_info->got_error;
508 DBUG_ENTER(
"thr_write_keys");
511 for (i= 0, sinfo= sort_param ;
512 i < sort_info->total_keys ;
515 if (!sinfo->sort_keys)
518 my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff));
523 mi_set_key_active(share->state.key_map, sinfo->key);
524 if (!sinfo->buffpek.elements)
526 if (param->testflag & T_VERBOSE)
528 printf(
"Key %d - Dumping %u keys\n",sinfo->key+1, sinfo->keys);
531 if (write_index(sinfo, sinfo->sort_keys, sinfo->keys) ||
532 flush_ft_buf(sinfo) || flush_pending_blocks(sinfo))
536 my_free(sinfo->sort_keys);
537 my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff));
541 for (i= 0, sinfo= sort_param ;
542 i < sort_info->total_keys ;
544 delete_dynamic(&sinfo->buffpek),
545 close_cached_file(&sinfo->tempfile),
546 close_cached_file(&sinfo->tempfile_for_exceptions),
547 rec_per_key_part+= sinfo->keyinfo->keysegs, sinfo++)
551 if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
553 sinfo->write_keys=write_keys_varlen;
554 sinfo->read_to_buffer=read_to_buffer_varlen;
555 sinfo->write_key=write_merge_key_varlen;
559 sinfo->write_keys=write_keys;
561 sinfo->write_key=write_merge_key;
563 if (sinfo->buffpek.elements)
565 uint maxbuffer=sinfo->buffpek.elements-1;
568 length=param->sort_buffer_length;
569 while (length >= MIN_SORT_BUFFER)
571 if ((mergebuf= my_malloc(length, MYF(0))))
581 keys=length/sinfo->key_length;
582 if (maxbuffer >= MERGEBUFF2)
584 if (param->testflag & T_VERBOSE)
585 printf(
"Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys);
587 dynamic_element(&sinfo->buffpek, 0, BUFFPEK *),
588 (
int*) &maxbuffer, &sinfo->tempfile))
594 if (flush_io_cache(&sinfo->tempfile) ||
595 reinit_io_cache(&sinfo->tempfile,READ_CACHE,0L,0,0))
600 if (param->testflag & T_VERBOSE)
601 printf(
"Key %d - Last merge and dumping keys\n", sinfo->key+1);
602 if (merge_index(sinfo, keys, (uchar **)mergebuf,
603 dynamic_element(&sinfo->buffpek,0,BUFFPEK *),
604 maxbuffer,&sinfo->tempfile) ||
605 flush_ft_buf(sinfo) ||
606 flush_pending_blocks(sinfo))
612 if (my_b_inited(&sinfo->tempfile_for_exceptions))
616 if (param->testflag & T_VERBOSE)
617 printf(
"Key %d - Dumping 'long' keys\n", sinfo->key+1);
619 if (flush_io_cache(&sinfo->tempfile_for_exceptions) ||
620 reinit_io_cache(&sinfo->tempfile_for_exceptions,READ_CACHE,0L,0,0))
627 !my_b_read(&sinfo->tempfile_for_exceptions,(uchar*)&key_length,
630 uchar ft_buf[HA_FT_MAXBYTELEN + HA_FT_WLEN + 10];
631 if (key_length >
sizeof(ft_buf) ||
632 my_b_read(&sinfo->tempfile_for_exceptions, (uchar*)ft_buf,
634 _mi_ck_write(info, sinfo->key, (uchar*)ft_buf,
635 key_length - info->s->rec_reflength))
639 if (!got_error && param->testflag & T_STATISTICS)
640 update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
641 param->stats_method == MI_STATS_METHOD_IGNORE_NULLS ?
642 sinfo->notnull : NULL,
643 (ulonglong) info->state->records);
646 DBUG_RETURN(got_error);
651 static int write_keys(
MI_SORT_PARAM *info,
register uchar **sort_keys,
652 uint count, BUFFPEK *buffpek,
IO_CACHE *tempfile)
655 uint sort_length=info->key_length;
656 DBUG_ENTER(
"write_keys");
658 my_qsort2((uchar*) sort_keys,count,
sizeof(uchar*),(qsort2_cmp) info->key_cmp,
660 if (!my_b_inited(tempfile) &&
661 open_cached_file(tempfile, my_tmpdir(info->tmpdir),
"ST",
662 DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
665 buffpek->file_pos=my_b_tell(tempfile);
666 buffpek->count=count;
668 for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
670 if (my_b_write(tempfile,(uchar*) *sort_keys,(uint) sort_length))
681 uint16 len = _mi_keylength(info->keyinfo, (uchar*) bufs);
684 if ((err= my_b_write(to_file, (uchar*)&len,
sizeof(len))))
686 if ((err= my_b_write(to_file,bufs, (uint) len)))
693 register uchar **sort_keys,
694 uint count, BUFFPEK *buffpek,
699 DBUG_ENTER(
"write_keys_varlen");
701 my_qsort2((uchar*) sort_keys,count,
sizeof(uchar*),(qsort2_cmp) info->key_cmp,
703 if (!my_b_inited(tempfile) &&
704 open_cached_file(tempfile, my_tmpdir(info->tmpdir),
"ST",
705 DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
708 buffpek->file_pos=my_b_tell(tempfile);
709 buffpek->count=count;
710 for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
712 if ((err= my_var_write(info,tempfile, (uchar*) *sort_keys)))
721 uint key_length=info->real_key_length;
722 DBUG_ENTER(
"write_key");
724 if (!my_b_inited(tempfile) &&
725 open_cached_file(tempfile, my_tmpdir(info->tmpdir),
"ST",
726 DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
729 if (my_b_write(tempfile,(uchar*)&key_length,
sizeof(key_length)) ||
730 my_b_write(tempfile,(uchar*)key,(uint) key_length))
738 static int write_index(
MI_SORT_PARAM *info,
register uchar **sort_keys,
741 DBUG_ENTER(
"write_index");
743 my_qsort2((uchar*) sort_keys,(
size_t) count,
sizeof(uchar*),
744 (qsort2_cmp) info->key_cmp,info);
747 if ((*info->key_write)(info,*sort_keys++))
757 uchar **sort_keys, BUFFPEK *buffpek,
763 DBUG_ENTER(
"merge_many_buff");
765 if (*maxbuffer < MERGEBUFF2)
767 if (flush_io_cache(t_file) ||
768 open_cached_file(&t_file2,my_tmpdir(info->tmpdir),
"ST",
769 DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
772 from_file= t_file ; to_file= &t_file2;
773 while (*maxbuffer >= MERGEBUFF2)
775 reinit_io_cache(from_file,READ_CACHE,0L,0,0);
776 reinit_io_cache(to_file,WRITE_CACHE,0L,0,0);
778 for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
780 if (
merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
781 buffpek+i,buffpek+i+MERGEBUFF-1))
784 if (
merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
785 buffpek+i,buffpek+ *maxbuffer))
787 if (flush_io_cache(to_file))
789 temp=from_file; from_file=to_file; to_file=
temp;
790 *maxbuffer= (int) (lastbuff-buffpek)-1;
793 close_cached_file(to_file);
794 if (to_file == t_file)
796 DBUG_ASSERT(t_file2.type == WRITE_CACHE);
798 t_file->current_pos= &t_file->write_pos;
799 t_file->current_end= &t_file->write_end;
802 DBUG_RETURN(*maxbuffer >= MERGEBUFF2);
825 if ((count=(uint) MY_MIN((ha_rows) buffpek->max_keys,buffpek->count)))
828 (length= sort_length*count),
829 buffpek->file_pos, MYF_RW))
831 buffpek->key=buffpek->base;
832 buffpek->file_pos+= length;
833 buffpek->count-= count;
834 buffpek->mem_count= count;
836 return (count*sort_length);
839 static uint read_to_buffer_varlen(
IO_CACHE *fromfile, BUFFPEK *buffpek,
843 uint16 length_of_key = 0;
847 if ((count=(uint) MY_MIN((ha_rows) buffpek->max_keys, buffpek->count)))
849 buffp = buffpek->base;
851 for (idx=1;idx<=count;idx++)
854 sizeof(length_of_key), buffpek->file_pos, MYF_RW))
856 buffpek->file_pos+=
sizeof(length_of_key);
858 length_of_key, buffpek->file_pos, MYF_RW))
860 buffpek->file_pos+=length_of_key;
861 buffp = buffp + sort_length;
863 buffpek->key=buffpek->base;
864 buffpek->count-= count;
865 buffpek->mem_count= count;
867 return (count*sort_length);
873 uint sort_length, uint count)
878 for (idx=1;idx<=count;idx++)
881 if ((err= my_var_write(info, to_file, bufs)))
883 bufs=bufs+sort_length;
889 static int write_merge_key(
MI_SORT_PARAM *info __attribute__((unused)),
891 uint sort_length, uint count)
893 return my_b_write(to_file, key, (
size_t) sort_length*count);
903 IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
904 BUFFPEK *Fb, BUFFPEK *Tb)
907 uint sort_length,maxcount;
909 my_off_t UNINIT_VAR(to_start_filepos);
911 BUFFPEK *buffpek,**refpek;
913 volatile int *killed= killed_ptr(info->sort_info->param);
914 DBUG_ENTER(
"merge_buffers");
917 maxcount=keys/((uint) (Tb-Fb) +1);
918 DBUG_ASSERT(maxcount > 0);
919 LINT_INIT(to_start_filepos);
921 to_start_filepos=my_b_tell(to_file);
922 strpos=(uchar*) sort_keys;
923 sort_length=info->key_length;
925 if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
926 (
int (*)(
void*, uchar *,uchar*)) info->key_cmp,
930 for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
932 count+= buffpek->count;
933 buffpek->base= strpos;
934 buffpek->max_keys=maxcount;
935 strpos+= (uint) (error=(
int) info->read_to_buffer(from_file,buffpek,
939 queue_insert(&queue,(uchar*) buffpek);
942 while (queue.elements > 1)
950 buffpek=(BUFFPEK*) queue_top(&queue);
953 if (info->write_key(info,to_file,(uchar*) buffpek->key,
954 (uint) sort_length,1))
961 if ((*info->key_write)(info,(
void*) buffpek->key))
966 buffpek->key+=sort_length;
967 if (! --buffpek->mem_count)
969 if (!(error=(
int) info->read_to_buffer(from_file,buffpek,sort_length)))
971 uchar *base=buffpek->base;
972 uint max_keys=buffpek->max_keys;
974 (void) queue_remove(&queue,0);
977 for (refpek= (BUFFPEK**) &queue_top(&queue);
978 refpek <= (BUFFPEK**) &queue_end(&queue);
982 if (buffpek->base+buffpek->max_keys*sort_length == base)
984 buffpek->max_keys+=max_keys;
987 else if (base+max_keys*sort_length == buffpek->base)
990 buffpek->max_keys+=max_keys;
997 else if (error == -1)
999 queue_replaced(&queue);
1002 buffpek=(BUFFPEK*) queue_top(&queue);
1003 buffpek->base=(uchar *) sort_keys;
1004 buffpek->max_keys=keys;
1009 if (info->write_key(info,to_file,(uchar*) buffpek->key,
1010 sort_length,buffpek->mem_count))
1017 register uchar *end;
1018 strpos= buffpek->key;
1019 for (end=strpos+buffpek->mem_count*sort_length;
1021 strpos+=sort_length)
1023 if ((*info->key_write)(info,(
void*) strpos))
1030 while ((error=(
int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
1033 lastbuff->count=count;
1035 lastbuff->file_pos=to_start_filepos;
1037 delete_queue(&queue);
1045 merge_index(
MI_SORT_PARAM *info, uint keys, uchar **sort_keys,
1046 BUFFPEK *buffpek,
int maxbuffer,
IO_CACHE *tempfile)
1048 DBUG_ENTER(
"merge_index");
1059 if (info->sort_info->ft_buf)
1061 err=sort_ft_buf_flush(info);
1062 my_free(info->sort_info->ft_buf);
1063 info->sort_info->ft_buf=0;