1
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
3
3
This program is free software; you can redistribute it and/or modify
4
4
it under the terms of the GNU General Public License as published by
5
5
the Free Software Foundation; either version 2 of the License, or
6
6
(at your option) any later version.
8
8
This program is distributed in the hope that it will be useful,
9
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
GNU General Public License for more details.
13
13
You should have received a copy of the GNU General Public License
14
14
along with this program; if not, write to the Free Software
15
15
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
50
50
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys,
52
BUFFPEK *buffpek,int *maxbuffer,
52
DYNAMIC_ARRAY *buffpek,int *maxbuffer,
54
IO_CACHE *tempfile_for_exceptions);
54
55
static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys,
55
56
uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
57
static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile);
56
58
static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys,
58
60
static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys,
67
69
BUFFPEK *Fb, BUFFPEK *Tb);
68
70
static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
70
static char **make_char_array(uint fields,uint length,myf my_flag);
72
73
/* Creates a index of sorted keys */
73
74
/* Returns 0 if everything went ok */
78
79
int error,maxbuffer,skr;
79
80
uint memavl,old_memavl,keys,sort_length;
81
DYNAMIC_ARRAY buffpek;
84
IO_CACHE tempfile, tempfile_for_exceptions;
84
85
DBUG_ENTER("_create_index_by_sort");
85
86
DBUG_PRINT("enter",("sort_length: %d", info->key_length));
87
88
my_b_clear(&tempfile);
88
buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
89
my_b_clear(&tempfile_for_exceptions);
90
bzero((char*) &buffpek,sizeof(buffpek));
91
sort_keys= (uchar **) NULL; error= 1;
91
94
memavl=max(sortbuff_size,MIN_SORT_MEMORY);
114
117
while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
116
if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0))))
119
if (sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+HA_FT_MAXLEN, MYF(0)))
118
if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)*
121
if (init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer, maxbuffer/2))
122
my_free((gptr) sort_keys,MYF(0));
123
my_free((gptr) sort_keys,MYF(0));
125
126
old_memavl=memavl;
126
127
if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
136
137
if (!no_messages)
137
138
printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
139
if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
140
if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
141
&tempfile,&tempfile_for_exceptions))
141
143
goto err; /* purecov: tested */
142
144
if (maxbuffer == 0)
154
156
if (!no_messages)
155
157
printf(" - Merging %lu keys\n",records); /* purecov: tested */
156
if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
158
if (merge_many_buff(info,keys,sort_keys,
159
dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile))
157
160
goto err; /* purecov: inspected */
159
162
if (flush_io_cache(&tempfile) ||
161
164
goto err; /* purecov: inspected */
162
165
if (!no_messages)
163
166
puts(" - Last merge and dumping keys"); /* purecov: tested */
164
if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile))
167
if (merge_index(info,keys,sort_keys,dynamic_element(&buffpek,0,BUFFPEK *),
168
maxbuffer,&tempfile))
165
169
goto err; /* purecov: inspected */
172
if (flush_pending_blocks(info->sort_info->param))
175
if (my_b_inited(&tempfile_for_exceptions))
177
MI_INFO *index=info->sort_info->info;
178
uint keyno=info->sort_info->key;
179
uint key_length, ref_length=index->s->rec_reflength;
181
if (flush_io_cache(&tempfile_for_exceptions) ||
182
reinit_io_cache(&tempfile_for_exceptions,READ_CACHE,0L,0,0))
185
while (!my_b_read(&tempfile_for_exceptions,(byte*)&key_length, sizeof(key_length))
186
&& !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys,(uint)key_length))
188
if (_mi_ck_write(index,keyno,(byte*)sort_keys,key_length-ref_length)) goto err;
171
196
my_free((gptr) sort_keys,MYF(0));
173
my_free((gptr) buffpek,MYF(0));
197
delete_dynamic(&buffpek);
174
198
close_cached_file(&tempfile);
199
close_cached_file(&tempfile_for_exceptions);
176
201
DBUG_RETURN(error ? -1 : 0);
177
202
} /* _create_index_by_sort */
180
205
/* Search after all keys and place them in a temp. file */
182
207
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
183
uchar **sort_keys, BUFFPEK *buffpek,
184
int *maxbuffer, IO_CACHE *tempfile)
208
uchar **sort_keys, DYNAMIC_ARRAY *buffpek,
209
int *maxbuffer, IO_CACHE *tempfile,
210
IO_CACHE *tempfile_for_exceptions)
188
214
DBUG_ENTER("find_all_keys");
190
idx=indexpos=error=0;
217
sort_keys[0]=(char*)(sort_keys+keys);
192
while (!(error=(*info->key_read)(info->sort_info,sort_keys[idx])))
219
while(!(error=(*info->key_read)(info->sort_info,sort_keys[idx])))
194
if ((uint) ++idx == keys)
196
if (indexpos >= (uint) *maxbuffer ||
197
write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile))
198
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
221
if (info->sort_info->real_key_length > info->key_length)
223
if (write_key(info,sort_keys[idx],tempfile_for_exceptions))
224
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
230
if (write_keys(info,sort_keys,idx-1,(BUFFPEK *)alloc_dynamic(buffpek),tempfile))
231
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
233
sort_keys[0]=(char*)(sort_keys+keys);
199
234
memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length);
237
sort_keys[idx]=sort_keys[idx-1]+info->key_length;
204
240
DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ /* purecov: inspected */
206
if (indexpos >= (uint) *maxbuffer ||
207
write_keys(info,sort_keys,idx,buffpek+indexpos,tempfile))
241
if (buffpek->elements)
243
if (write_keys(info,sort_keys,idx,(BUFFPEK *)alloc_dynamic(buffpek),tempfile))
208
244
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
209
*maxbuffer=(int) indexpos;
210
DBUG_RETURN(indexpos*(keys-1)+idx);
245
*maxbuffer=buffpek->elements-1;
250
DBUG_RETURN((*maxbuffer)*(keys-1)+idx);
211
251
} /* find_all_keys */
214
253
/* Write all keys in memory to file for later merge */
216
255
static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
222
261
DBUG_ENTER("write_keys");
224
263
qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
226
265
if (!my_b_inited(tempfile) &&
227
266
open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
229
268
DBUG_RETURN(1); /* purecov: inspected */
230
270
buffpek->file_pos=my_b_tell(tempfile);
231
271
buffpek->count=count;
237
277
} /* write_keys */
280
static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key, IO_CACHE *tempfile)
282
uint key_length=info->sort_info->real_key_length;
283
DBUG_ENTER("write_key");
285
if (!my_b_inited(tempfile) &&
286
open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE,
290
if (my_b_write(tempfile,(byte*)&key_length,sizeof(key_length)) ||
291
my_b_write(tempfile,(byte*)key,(uint) key_length))
240
296
/* Write index */
242
298
static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys,
326
382
/* If to_file == 0 then use info->key_write */
328
384
static int NEAR_F
329
merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
385
merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
330
386
IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
331
387
BUFFPEK *Fb, BUFFPEK *Tb)
473
529
} /* merge_index */
476
/* Make a pointer of arrays to keys */
478
static char **make_char_array(register uint fields, uint length, myf my_flag)
481
char **old_pos,*char_pos;
482
DBUG_ENTER("make_char_array");
484
if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag)))
486
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
488
*(pos++) = (char_pos+= length);
491
DBUG_RETURN(old_pos);
492
} /* make_char_array */