00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "myisam_priv.h"
00022 #include <stddef.h>
00023 #include <queue>
00024 #include <algorithm>
00025
00026
00027
00028 #undef MIN_SORT_MEMORY
00029 #undef MYF_RW
00030 #undef DISK_BUFFER_SIZE
00031
00032 #define MERGEBUFF 15
00033 #define MERGEBUFF2 31
00034 #define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
00035 #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
00036 #define DISK_BUFFER_SIZE (IO_SIZE*16)
00037
00038 using namespace std;
00039 using namespace drizzled;
00040
00041
00042
00043
00044
00045
00046 extern void print_error(const char *fmt,...);
00047
00048
00049
00050 static ha_rows find_all_keys(MI_SORT_PARAM *info,uint32_t keys,
00051 unsigned char **sort_keys,
00052 DYNAMIC_ARRAY *buffpek,
00053 size_t *maxbuffer,
00054 internal::io_cache_st *tempfile,
00055 internal::io_cache_st *tempfile_for_exceptions);
00056 static int write_keys(MI_SORT_PARAM *info,unsigned char **sort_keys,
00057 uint32_t count, BUFFPEK *buffpek,internal::io_cache_st *tempfile);
00058 static int write_key(MI_SORT_PARAM *info, unsigned char *key,
00059 internal::io_cache_st *tempfile);
00060 static int write_index(MI_SORT_PARAM *info,unsigned char * *sort_keys,
00061 uint32_t count);
00062 static int merge_many_buff(MI_SORT_PARAM *info,uint32_t keys,
00063 unsigned char * *sort_keys,
00064 BUFFPEK *buffpek,size_t *maxbuffer,
00065 internal::io_cache_st *t_file);
00066 static uint32_t read_to_buffer(internal::io_cache_st *fromfile,BUFFPEK *buffpek,
00067 uint32_t sort_length);
00068 static int merge_buffers(MI_SORT_PARAM *info,uint32_t keys,
00069 internal::io_cache_st *from_file, internal::io_cache_st *to_file,
00070 unsigned char * *sort_keys, BUFFPEK *lastbuff,
00071 BUFFPEK *Fb, BUFFPEK *Tb);
00072 static int merge_index(MI_SORT_PARAM *,uint,unsigned char **,BUFFPEK *, int,
00073 internal::io_cache_st *);
00074 static int write_keys_varlen(MI_SORT_PARAM *info,unsigned char **sort_keys,
00075 uint32_t count, BUFFPEK *buffpek,
00076 internal::io_cache_st *tempfile);
00077 static uint32_t read_to_buffer_varlen(internal::io_cache_st *fromfile,BUFFPEK *buffpek,
00078 uint32_t sort_length);
00079 static int write_merge_key(MI_SORT_PARAM *info, internal::io_cache_st *to_file,
00080 unsigned char *key, uint32_t sort_length, uint32_t count);
00081 static int write_merge_key_varlen(MI_SORT_PARAM *info,
00082 internal::io_cache_st *to_file,
00083 unsigned char* key, uint32_t sort_length,
00084 uint32_t count);
00085
00086 inline int
00087 my_var_write(MI_SORT_PARAM *info, internal::io_cache_st *to_file, unsigned char *bufs);
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 int _create_index_by_sort(MI_SORT_PARAM *info,bool no_messages,
00104 size_t sortbuff_size)
00105 {
00106 size_t skr;
00107 uint32_t memavl,keys;
00108 DYNAMIC_ARRAY buffpek;
00109 internal::io_cache_st tempfile, tempfile_for_exceptions;
00110
00111 if (info->keyinfo->flag & HA_VAR_LENGTH_KEY)
00112 {
00113 info->write_keys=write_keys_varlen;
00114 info->read_to_buffer=read_to_buffer_varlen;
00115 info->write_key= write_merge_key_varlen;
00116 }
00117 else
00118 {
00119 info->write_keys=write_keys;
00120 info->read_to_buffer=read_to_buffer;
00121 info->write_key=write_merge_key;
00122 }
00123
00124 tempfile.clear();
00125 tempfile_for_exceptions.clear();
00126 memset(&buffpek, 0, sizeof(buffpek));
00127 unsigned char** sort_keys= (unsigned char **) NULL;
00128 int error= 1;
00129 size_t maxbuffer=1;
00130
00131 memavl=max(sortbuff_size,(size_t)MIN_SORT_MEMORY);
00132 ha_rows records= info->sort_info->max_records;
00133 uint32_t sort_length= info->key_length;
00134
00135 while (memavl >= MIN_SORT_MEMORY)
00136 {
00137 if ((records < UINT32_MAX) &&
00138 ((internal::my_off_t) (records + 1) *
00139 (sort_length + sizeof(char*)) <= (internal::my_off_t) memavl))
00140 keys= (uint)records+1;
00141 else
00142 do
00143 {
00144 skr=maxbuffer;
00145 if (memavl < sizeof(BUFFPEK)* maxbuffer ||
00146 (keys=(memavl-sizeof(BUFFPEK)* maxbuffer) / (sort_length+sizeof(char*))) <= 1 ||
00147 keys < maxbuffer)
00148 {
00149 mi_check_print_error(info->sort_info->param,
00150 "myisam_sort_buffer_size is too small");
00151 goto err;
00152 }
00153 }
00154 while ((maxbuffer= (size_t)(records/(keys-1)+1)) != skr);
00155
00156 sort_keys=(unsigned char **)malloc(keys*(sort_length+sizeof(char*)));
00157 buffpek.init(sizeof(BUFFPEK), maxbuffer, maxbuffer/2);
00158 break;
00159 }
00160 if (memavl < MIN_SORT_MEMORY)
00161 {
00162 mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small");
00163 goto err;
00164 }
00165 (*info->lock_in_memory)(info->sort_info->param);
00166
00167 if (!no_messages)
00168 printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
00169
00170 if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
00171 &tempfile,&tempfile_for_exceptions))
00172 == HA_POS_ERROR)
00173 goto err;
00174 if (maxbuffer == 0)
00175 {
00176 if (!no_messages)
00177 printf(" - Dumping %u keys\n", (uint32_t) records);
00178 if (write_index(info,sort_keys, (uint) records))
00179 goto err;
00180 }
00181 else
00182 {
00183 keys=(keys*(sort_length+sizeof(char*)))/sort_length;
00184 if (maxbuffer >= MERGEBUFF2)
00185 {
00186 if (!no_messages)
00187 printf(" - Merging %u keys\n", (uint32_t) records);
00188 if (merge_many_buff(info,keys,sort_keys, (BUFFPEK*)buffpek.buffer, &maxbuffer, &tempfile))
00189 goto err;
00190 }
00191 if (tempfile.flush() ||
00192 tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00193 goto err;
00194 if (!no_messages)
00195 printf(" - Last merge and dumping keys\n");
00196 if (merge_index(info,keys,sort_keys, (BUFFPEK*)buffpek.buffer, maxbuffer, &tempfile))
00197 goto err;
00198 }
00199
00200 if (flush_pending_blocks(info))
00201 goto err;
00202
00203 if (tempfile_for_exceptions.inited())
00204 {
00205 MI_INFO *idx=info->sort_info->info;
00206 uint32_t keyno=info->key;
00207 uint32_t key_length, ref_length=idx->s->rec_reflength;
00208
00209 if (not no_messages)
00210 printf(" - Adding exceptions\n");
00211
00212 if (tempfile_for_exceptions.flush() || tempfile_for_exceptions.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00213 {
00214 goto err;
00215 }
00216
00217 while (not tempfile_for_exceptions.read(&key_length, sizeof(key_length))
00218 && not tempfile_for_exceptions.read(sort_keys, key_length))
00219 {
00220 if (_mi_ck_write(idx,keyno,(unsigned char*) sort_keys,key_length-ref_length))
00221 goto err;
00222 }
00223 }
00224
00225 error =0;
00226
00227 err:
00228 free(sort_keys);
00229 buffpek.free();
00230 tempfile.close_cached_file();
00231 tempfile_for_exceptions.close_cached_file();
00232
00233 return error ? -1 : 0;
00234 }
00235
00236
00237
00238
00239 static ha_rows find_all_keys(MI_SORT_PARAM *info, uint32_t keys,
00240 unsigned char **sort_keys,
00241 DYNAMIC_ARRAY *buffpek,
00242 size_t *maxbuffer, internal::io_cache_st *tempfile,
00243 internal::io_cache_st *tempfile_for_exceptions)
00244 {
00245 int error;
00246 uint32_t idx;
00247
00248 idx=error=0;
00249 sort_keys[0]=(unsigned char*) (sort_keys+keys);
00250
00251 while (!(error=(*info->key_read)(info,sort_keys[idx])))
00252 {
00253 if (info->real_key_length > info->key_length)
00254 {
00255 if (write_key(info,sort_keys[idx],tempfile_for_exceptions))
00256 return(HA_POS_ERROR);
00257 continue;
00258 }
00259
00260 if (++idx == keys)
00261 {
00262 if (info->write_keys(info,sort_keys,idx-1,(BUFFPEK *)buffpek->alloc(), tempfile))
00263 return HA_POS_ERROR;
00264
00265 sort_keys[0]=(unsigned char*) (sort_keys+keys);
00266 memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length);
00267 idx=1;
00268 }
00269 sort_keys[idx]=sort_keys[idx-1]+info->key_length;
00270 }
00271 if (error > 0)
00272 return(HA_POS_ERROR);
00273 if (buffpek->size())
00274 {
00275 if (info->write_keys(info,sort_keys,idx,(BUFFPEK *)buffpek->alloc(), tempfile))
00276 return HA_POS_ERROR;
00277 *maxbuffer=buffpek->size() - 1;
00278 }
00279 else
00280 *maxbuffer=0;
00281
00282 return((*maxbuffer)*(keys-1)+idx);
00283 }
00284
00285
00286 int thr_write_keys(MI_SORT_PARAM *sort_param)
00287 {
00288 SORT_INFO *sort_info= sort_param->sort_info;
00289 MI_CHECK *param= sort_info->param;
00290 uint32_t length= 0, keys;
00291 ulong *rec_per_key_part= param->rec_per_key_part;
00292 int got_error=sort_info->got_error;
00293 uint32_t i;
00294 MI_INFO *info=sort_info->info;
00295 MYISAM_SHARE *share=info->s;
00296 MI_SORT_PARAM *sinfo;
00297 unsigned char *mergebuf=0;
00298
00299 for (i= 0, sinfo= sort_param ;
00300 i < sort_info->total_keys ;
00301 i++, rec_per_key_part+=sinfo->keyinfo->keysegs, sinfo++)
00302 {
00303 if (!sinfo->sort_keys)
00304 {
00305 got_error=1;
00306 void * rec_buff_ptr= mi_get_rec_buff_ptr(info, sinfo->rec_buff);
00307 free(rec_buff_ptr);
00308 continue;
00309 }
00310 if (!got_error)
00311 {
00312 mi_set_key_active(share->state.key_map, sinfo->key);
00313 if (!sinfo->buffpek.size())
00314 {
00315 if (param->testflag & T_VERBOSE)
00316 {
00317 printf("Key %d - Dumping %u keys\n",sinfo->key+1, sinfo->keys);
00318 fflush(stdout);
00319 }
00320 if (write_index(sinfo, sinfo->sort_keys, sinfo->keys) || flush_pending_blocks(sinfo))
00321 got_error=1;
00322 }
00323 if (!got_error && param->testflag & T_STATISTICS)
00324 update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique,
00325 param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
00326 sinfo->notnull: NULL,
00327 (uint64_t) info->state->records);
00328 }
00329 free((unsigned char*) sinfo->sort_keys);
00330 void * rec_buff_ptr= mi_get_rec_buff_ptr(info, sinfo->rec_buff);
00331 free(rec_buff_ptr);
00332 sinfo->sort_keys=0;
00333 }
00334
00335 for (i= 0, sinfo= sort_param; i < sort_info->total_keys; i++,
00336 sinfo->buffpek.free(),
00337 sinfo->tempfile.close_cached_file(),
00338 sinfo->tempfile_for_exceptions.close_cached_file(),
00339 sinfo++)
00340 {
00341 if (got_error)
00342 continue;
00343 if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
00344 {
00345 sinfo->write_keys=write_keys_varlen;
00346 sinfo->read_to_buffer=read_to_buffer_varlen;
00347 sinfo->write_key=write_merge_key_varlen;
00348 }
00349 else
00350 {
00351 sinfo->write_keys=write_keys;
00352 sinfo->read_to_buffer=read_to_buffer;
00353 sinfo->write_key=write_merge_key;
00354 }
00355 if (sinfo->buffpek.size())
00356 {
00357 size_t maxbuffer=sinfo->buffpek.size() - 1;
00358 if (!mergebuf)
00359 {
00360 length=param->sort_buffer_length;
00361 while (length >= MIN_SORT_MEMORY)
00362 {
00363 if ((mergebuf= (unsigned char *)malloc(length)))
00364 break;
00365 length=length*3/4;
00366 }
00367 if (!mergebuf)
00368 {
00369 got_error=1;
00370 continue;
00371 }
00372 }
00373 keys=length/sinfo->key_length;
00374 if (maxbuffer >= MERGEBUFF2)
00375 {
00376 if (param->testflag & T_VERBOSE)
00377 printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys);
00378 if (merge_many_buff(sinfo, keys, (unsigned char **)mergebuf, (BUFFPEK*)sinfo->buffpek.buffer,
00379 &maxbuffer, &sinfo->tempfile))
00380 {
00381 got_error=1;
00382 continue;
00383 }
00384 }
00385 if (sinfo->tempfile.flush() || sinfo->tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00386 {
00387 got_error=1;
00388 continue;
00389 }
00390 if (param->testflag & T_VERBOSE)
00391 printf("Key %d - Last merge and dumping keys\n", sinfo->key+1);
00392 if (merge_index(sinfo, keys, (unsigned char **)mergebuf, (BUFFPEK*)sinfo->buffpek.buffer,
00393 maxbuffer,&sinfo->tempfile) ||
00394 flush_pending_blocks(sinfo))
00395 {
00396 got_error=1;
00397 continue;
00398 }
00399 }
00400 if (sinfo->tempfile_for_exceptions.inited())
00401 {
00402 uint32_t key_length;
00403
00404 if (param->testflag & T_VERBOSE)
00405 printf("Key %d - Dumping 'long' keys\n", sinfo->key+1);
00406
00407 if (sinfo->tempfile_for_exceptions.flush() || sinfo->tempfile_for_exceptions.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00408 {
00409 got_error=1;
00410 continue;
00411 }
00412
00413 while (!got_error && not sinfo->tempfile_for_exceptions.read(&key_length, sizeof(key_length)))
00414 {
00415 unsigned char ft_buf[10];
00416 if (key_length > sizeof(ft_buf) || sinfo->tempfile_for_exceptions.read(ft_buf, (uint)key_length)
00417 || _mi_ck_write(info, sinfo->key, (unsigned char*)ft_buf, key_length - info->s->rec_reflength))
00418 got_error= 1;
00419 }
00420 }
00421 }
00422 free((unsigned char*) mergebuf);
00423 return(got_error);
00424 }
00425
00426
00427
00428 static int write_keys(MI_SORT_PARAM *info, register unsigned char **sort_keys,
00429 uint32_t count, BUFFPEK *buffpek, internal::io_cache_st *tempfile)
00430 {
00431 unsigned char **end;
00432 uint32_t sort_length=info->key_length;
00433
00434 internal::my_qsort2((unsigned char*) sort_keys,count,sizeof(unsigned char*),(qsort2_cmp) info->key_cmp, info);
00435 if (not tempfile->inited() && tempfile->open_cached_file(P_tmpdir, "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
00436 return(1);
00437
00438 buffpek->file_pos= tempfile->tell();
00439 buffpek->count=count;
00440
00441 for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
00442 {
00443 if (tempfile->write(*sort_keys, sort_length))
00444 return(1);
00445 }
00446 return(0);
00447 }
00448
00449
00450 inline int
00451 my_var_write(MI_SORT_PARAM *info, internal::io_cache_st *to_file, unsigned char *bufs)
00452 {
00453 int err;
00454 uint16_t len = _mi_keylength(info->keyinfo, (unsigned char*) bufs);
00455
00456
00457 if ((err= to_file->write(&len, sizeof(len))))
00458 return (err);
00459 if ((err= to_file->write(bufs, len)))
00460 return (err);
00461 return (0);
00462 }
00463
00464
00465 static int write_keys_varlen(MI_SORT_PARAM *info,
00466 register unsigned char **sort_keys,
00467 uint32_t count, BUFFPEK *buffpek,
00468 internal::io_cache_st *tempfile)
00469 {
00470 unsigned char **end;
00471 int err;
00472
00473 internal::my_qsort2((unsigned char*) sort_keys,count,sizeof(unsigned char*),(qsort2_cmp) info->key_cmp, info);
00474 if (not tempfile->inited() && tempfile->open_cached_file(P_tmpdir, "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
00475 return(1);
00476
00477 buffpek->file_pos= tempfile->tell();
00478 buffpek->count=count;
00479 for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
00480 {
00481 if ((err= my_var_write(info,tempfile, (unsigned char*) *sort_keys)))
00482 return(err);
00483 }
00484 return(0);
00485 }
00486
00487
00488 static int write_key(MI_SORT_PARAM *info, unsigned char *key,
00489 internal::io_cache_st *tempfile)
00490 {
00491 uint32_t key_length=info->real_key_length;
00492
00493 if (not tempfile->inited() && tempfile->open_cached_file(P_tmpdir, "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
00494 return(1);
00495
00496 if (tempfile->write(&key_length, sizeof(key_length)) ||
00497 tempfile->write(key, key_length))
00498 return(1);
00499 return(0);
00500 }
00501
00502
00503
00504
00505 static int write_index(MI_SORT_PARAM *info, register unsigned char **sort_keys,
00506 register uint32_t count)
00507 {
00508 internal::my_qsort2((unsigned char*) sort_keys,(size_t) count,sizeof(unsigned char*),
00509 (qsort2_cmp) info->key_cmp,info);
00510 while (count--)
00511 {
00512 if ((*info->key_write)(info,*sort_keys++))
00513 return(-1);
00514 }
00515 return(0);
00516 }
00517
00518
00519
00520
00521 static int merge_many_buff(MI_SORT_PARAM *info, uint32_t keys,
00522 unsigned char **sort_keys, BUFFPEK *buffpek,
00523 size_t *maxbuffer, internal::io_cache_st *t_file)
00524 {
00525 uint32_t i;
00526 internal::io_cache_st t_file2, *from_file, *to_file, *temp;
00527 BUFFPEK *lastbuff;
00528
00529 if (*maxbuffer < MERGEBUFF2)
00530 return(0);
00531 if (t_file->flush() || t_file2.open_cached_file(P_tmpdir, "ST", DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
00532 return(1);
00533
00534 from_file= t_file ; to_file= &t_file2;
00535 while (*maxbuffer >= MERGEBUFF2)
00536 {
00537 from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0);
00538 to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0);
00539 lastbuff=buffpek;
00540 for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
00541 {
00542 if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
00543 buffpek+i,buffpek+i+MERGEBUFF-1))
00544 goto cleanup;
00545 }
00546 if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
00547 buffpek+i,buffpek+ *maxbuffer))
00548 break;
00549 if (to_file->flush())
00550 break;
00551 temp=from_file; from_file=to_file; to_file=temp;
00552 *maxbuffer= (int) (lastbuff-buffpek)-1;
00553 }
00554 cleanup:
00555 to_file->close_cached_file();
00556 if (to_file == t_file)
00557 *t_file=t_file2;
00558
00559 return(*maxbuffer >= MERGEBUFF2);
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 static uint32_t read_to_buffer(internal::io_cache_st *fromfile, BUFFPEK *buffpek,
00577 uint32_t sort_length)
00578 {
00579 register uint32_t count;
00580 uint32_t length;
00581
00582 if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
00583 {
00584 if (my_pread(fromfile->file,(unsigned char*) buffpek->base,
00585 (length= sort_length*count),buffpek->file_pos,MYF_RW))
00586 return((uint) -1);
00587 buffpek->key=buffpek->base;
00588 buffpek->file_pos+= length;
00589 buffpek->count-= count;
00590 buffpek->mem_count= count;
00591 }
00592 return (count*sort_length);
00593 }
00594
00595 static uint32_t read_to_buffer_varlen(internal::io_cache_st *fromfile, BUFFPEK *buffpek,
00596 uint32_t sort_length)
00597 {
00598 register uint32_t count;
00599 uint16_t length_of_key = 0;
00600 uint32_t idx;
00601 unsigned char *buffp;
00602
00603 if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
00604 {
00605 buffp = buffpek->base;
00606
00607 for (idx=1;idx<=count;idx++)
00608 {
00609 if (my_pread(fromfile->file,(unsigned char*)&length_of_key,sizeof(length_of_key),
00610 buffpek->file_pos,MYF_RW))
00611 return((uint) -1);
00612 buffpek->file_pos+=sizeof(length_of_key);
00613 if (my_pread(fromfile->file,(unsigned char*) buffp,length_of_key,
00614 buffpek->file_pos,MYF_RW))
00615 return((uint) -1);
00616 buffpek->file_pos+=length_of_key;
00617 buffp = buffp + sort_length;
00618 }
00619 buffpek->key=buffpek->base;
00620 buffpek->count-= count;
00621 buffpek->mem_count= count;
00622 }
00623 return (count*sort_length);
00624 }
00625
00626
00627 static int write_merge_key_varlen(MI_SORT_PARAM *info,
00628 internal::io_cache_st *to_file, unsigned char* key,
00629 uint32_t sort_length, uint32_t count)
00630 {
00631 uint32_t idx;
00632 unsigned char *bufs = key;
00633
00634 for (idx=1;idx<=count;idx++)
00635 {
00636 int err;
00637 if ((err= my_var_write(info, to_file, bufs)))
00638 return (err);
00639 bufs=bufs+sort_length;
00640 }
00641 return(0);
00642 }
00643
00644
00645 static int write_merge_key(MI_SORT_PARAM*,
00646 internal::io_cache_st *to_file, unsigned char *key,
00647 uint32_t sort_length, uint32_t count)
00648 {
00649 return to_file->write(key, sort_length*count);
00650 }
00651
00652
00653
00654
00655
00656 class compare_functor
00657 {
00658 qsort2_cmp key_compare;
00659 void *key_compare_arg;
00660 public:
00661 compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
00662 : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
00663 inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
00664 {
00665 int val= key_compare(key_compare_arg,
00666 &i->key, &j->key);
00667 return (val >= 0);
00668 }
00669 };
00670
00671
00672
00673
00674
00675
00676 static int
00677 merge_buffers(MI_SORT_PARAM *info, uint32_t keys, internal::io_cache_st *from_file,
00678 internal::io_cache_st *to_file, unsigned char **sort_keys, BUFFPEK *lastbuff,
00679 BUFFPEK *Fb, BUFFPEK *Tb)
00680 {
00681 int error;
00682 uint32_t sort_length,maxcount;
00683 ha_rows count;
00684 internal::my_off_t to_start_filepos= 0;
00685 unsigned char *strpos;
00686 BUFFPEK *buffpek;
00687 priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
00688 queue(compare_functor((qsort2_cmp) info->key_cmp, static_cast<void *>(info)));
00689 volatile int *killed= killed_ptr(info->sort_info->param);
00690
00691 count=error=0;
00692 maxcount=keys/((uint) (Tb-Fb) +1);
00693 assert(maxcount > 0);
00694 if (to_file)
00695 to_start_filepos= to_file->tell();
00696 strpos=(unsigned char*) sort_keys;
00697 sort_length=info->key_length;
00698
00699 for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
00700 {
00701 count+= buffpek->count;
00702 buffpek->base= strpos;
00703 buffpek->max_keys=maxcount;
00704 strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,
00705 sort_length));
00706 if (error == -1)
00707 goto err;
00708 queue.push(buffpek);
00709 }
00710
00711 while (queue.size() > 1)
00712 {
00713 for (;;)
00714 {
00715 if (*killed)
00716 {
00717 error=1; goto err;
00718 }
00719 buffpek= queue.top();
00720 if (to_file)
00721 {
00722 if (info->write_key(info,to_file,(unsigned char*) buffpek->key,
00723 (uint) sort_length,1))
00724 {
00725 error=1; goto err;
00726 }
00727 }
00728 else
00729 {
00730 if ((*info->key_write)(info,(void*) buffpek->key))
00731 {
00732 error=1; goto err;
00733 }
00734 }
00735 buffpek->key+=sort_length;
00736 if (! --buffpek->mem_count)
00737 {
00738 if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length)))
00739 {
00740 queue.pop();
00741 break;
00742 }
00743 }
00744 else if (error == -1)
00745 goto err;
00746
00747 queue.pop();
00748 queue.push(buffpek);
00749 }
00750 }
00751 buffpek= queue.top();
00752 buffpek->base=(unsigned char *) sort_keys;
00753 buffpek->max_keys=keys;
00754 do
00755 {
00756 if (to_file)
00757 {
00758 if (info->write_key(info,to_file,(unsigned char*) buffpek->key,
00759 sort_length,buffpek->mem_count))
00760 {
00761 error=1; goto err;
00762 }
00763 }
00764 else
00765 {
00766 register unsigned char *end;
00767 strpos= buffpek->key;
00768 for (end=strpos+buffpek->mem_count*sort_length;
00769 strpos != end ;
00770 strpos+=sort_length)
00771 {
00772 if ((*info->key_write)(info,(void*) strpos))
00773 {
00774 error=1; goto err;
00775 }
00776 }
00777 }
00778 }
00779 while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
00780 error != 0);
00781
00782 lastbuff->count=count;
00783 if (to_file)
00784 lastbuff->file_pos=to_start_filepos;
00785 err:
00786 return(error);
00787 }
00788
00789
00790
00791
00792 static int
00793 merge_index(MI_SORT_PARAM *info, uint32_t keys, unsigned char **sort_keys,
00794 BUFFPEK *buffpek, int maxbuffer, internal::io_cache_st *tempfile)
00795 {
00796 if (merge_buffers(info,keys,tempfile,(internal::io_cache_st*) 0,sort_keys,buffpek,buffpek,
00797 buffpek+maxbuffer))
00798 return(1);
00799 return(0);
00800 }
00801