47 #include <my_getopt.h>
48 #ifdef HAVE_SYS_VADVISE_H
49 #include <sys/vadvise.h>
51 #ifdef HAVE_SYS_MMAN_H
60 my_off_t
page, uchar *buff, ha_rows *keys,
61 ha_checksum *key_checksum, uint
level);
63 static ha_checksum calc_checksum(ha_rows count);
66 my_off_t pagepos, File new_file);
67 static int sort_key_read(
MI_SORT_PARAM *sort_param,
void *key);
68 static int sort_ft_key_read(
MI_SORT_PARAM *sort_param,
void *key);
70 static int sort_key_cmp(
MI_SORT_PARAM *sort_param,
const void *a,
const void *b);
71 static int sort_ft_key_write(
MI_SORT_PARAM *sort_param,
const void *a);
72 static int sort_key_write(
MI_SORT_PARAM *sort_param,
const void *a);
77 uchar *key, my_off_t prev_block);
82 static ha_checksum mi_byte_checksum(
const uchar *
buf, uint length);
88 memset(param, 0,
sizeof(*param));
89 param->opt_follow_links=1;
90 param->keys_in_use= ~(ulonglong) 0;
91 param->search_after_block=HA_OFFSET_ERROR;
92 param->auto_increment_value= 0;
93 param->use_buffers=USE_BUFFER_INIT;
94 param->read_buffer_length=READ_BUFFER_INIT;
95 param->write_buffer_length=READ_BUFFER_INIT;
96 param->sort_buffer_length=SORT_BUFFER_INIT;
97 param->sort_key_blocks=BUFFERS_WHEN_SORTING;
98 param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
99 param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
100 param->start_check_pos=0;
101 param->max_record_length= LONGLONG_MAX;
102 param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
103 param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
104 param->need_print_msg_lock= 0;
113 if (mi_is_crashed_on_repair(info))
114 mi_check_print_warning(param,
115 "Table is marked as crashed and last repair failed");
116 else if (mi_is_crashed(info))
117 mi_check_print_warning(param,
118 "Table is marked as crashed");
119 if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
122 uint save=param->warning_printed;
123 mi_check_print_warning(param,
124 share->state.open_count==1 ?
125 "%d client is using or hasn't closed the table properly" :
126 "%d clients are using or haven't closed the table properly",
127 share->state.open_count);
129 if (param->testflag & T_UPDATE_STATE)
130 param->warning_printed=save;
140 uint delete_link_length;
141 my_off_t empty,next_link,UNINIT_VAR(old_link);
142 char buff[22],buff2[22];
143 DBUG_ENTER(
"chk_del");
145 param->record_checksum=0;
146 delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
147 info->s->rec_reflength+1);
149 if (!(test_flag & T_SILENT))
150 puts(
"- check record delete-chain");
152 next_link=info->s->state.dellink;
153 if (info->state->del == 0)
155 if (test_flag & T_VERBOSE)
157 puts(
"No recordlinks");
162 if (test_flag & T_VERBOSE)
163 printf(
"Recordlinks: ");
165 for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
167 if (*killed_ptr(param))
169 if (test_flag & T_VERBOSE)
170 printf(
" %9s",llstr(next_link,buff));
171 if (next_link >= info->state->data_file_length)
174 next_link, MYF(MY_NABP)))
176 if (test_flag & T_VERBOSE) puts(
"");
177 mi_check_print_error(param,
"Can't read delete-link at filepos: %s",
178 llstr(next_link,buff));
183 if (test_flag & T_VERBOSE) puts(
"");
184 mi_check_print_error(param,
"Record at pos: %s is not remove-marked",
185 llstr(next_link,buff));
188 if (info->s->options & HA_OPTION_PACK_RECORD)
190 my_off_t prev_link=mi_sizekorr(buff+12);
191 if (empty && prev_link != old_link)
193 if (test_flag & T_VERBOSE) puts(
"");
194 mi_check_print_error(param,
"Deleted block at %s doesn't point back at previous delete link",llstr(next_link,buff2));
198 next_link=mi_sizekorr(buff+4);
199 empty+=mi_uint3korr(buff+1);
203 param->record_checksum+=(ha_checksum) next_link;
204 next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
205 empty+=info->s->base.pack_reclength;
208 if (test_flag & T_VERBOSE)
210 if (empty != info->state->empty)
212 mi_check_print_warning(param,
213 "Found %s deleted space in delete link chain. Should be %s",
215 llstr(info->state->empty,buff));
217 if (next_link != HA_OFFSET_ERROR)
219 mi_check_print_error(param,
220 "Found more than the expected %s deleted rows in delete link chain",
221 llstr(info->state->del, buff));
226 mi_check_print_error(param,
227 "Found %s deleted rows in delete link chain. Should be %s",
228 llstr(info->state->del - i, buff2),
229 llstr(info->state->del, buff));
236 param->testflag|=T_RETRY_WITHOUT_QUICK;
237 if (test_flag & T_VERBOSE) puts(
"");
238 mi_check_print_error(param,
"record delete-link-chain corrupted");
245 static int check_k_link(
MI_CHECK *param,
register MI_INFO *info, uint nr)
248 uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
250 char llbuff[21], llbuff2[21];
252 DBUG_ENTER(
"check_k_link");
253 DBUG_PRINT(
"enter", (
"block_size: %u", block_size));
255 if (param->testflag & T_VERBOSE)
256 printf(
"block_size %4u:", block_size);
258 next_link=info->s->state.key_del[nr];
259 records= (ha_rows) (info->state->key_file_length / block_size);
260 while (next_link != HA_OFFSET_ERROR && records > 0)
262 if (*killed_ptr(param))
264 if (param->testflag & T_VERBOSE)
265 printf(
"%16s",llstr(next_link,llbuff));
268 if (next_link + block_size > info->state->key_file_length)
271 mi_check_print_error(param,
"Invalid key block position: %s "
272 "key block size: %u file_length: %s",
273 llstr(next_link, llbuff), block_size,
274 llstr(info->state->key_file_length, llbuff2));
280 if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
283 mi_check_print_error(param,
"Mis-aligned key block: %s "
284 "minimum key block length: %u",
285 llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
295 if (!(buff=key_cache_read(info->s->key_cache,
296 info->s->kfile, next_link, DFLT_INIT_HITS,
297 (uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
298 MI_MIN_KEY_BLOCK_LENGTH, 1)))
301 mi_check_print_error(param,
"key cache read error for block: %s",
302 llstr(next_link,llbuff));
306 next_link=mi_sizekorr(buff);
308 param->key_file_blocks+=block_size;
310 if (param->testflag & T_VERBOSE)
312 if (next_link != HA_OFFSET_ERROR)
313 printf(
"%16s\n",llstr(next_link,llbuff));
317 DBUG_RETURN (next_link != HA_OFFSET_ERROR);
326 register my_off_t skr,
size;
327 char buff[22],buff2[22];
328 DBUG_ENTER(
"chk_size");
330 if (!(param->testflag & T_SILENT)) puts(
"- check file-size");
333 flush_key_blocks(info->s->key_cache,
334 info->s->kfile, FLUSH_FORCE_WRITE);
336 size=
mysql_file_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
337 if ((skr=(my_off_t) info->state->key_file_length) != size)
340 if (skr > size && mi_is_any_key_active(info->s->state.key_map))
343 mi_check_print_error(param,
344 "Size of indexfile is: %-8s Should be: %s",
345 llstr(size,buff), llstr(skr,buff2));
348 mi_check_print_warning(param,
349 "Size of indexfile is: %-8s Should be: %s",
350 llstr(size,buff), llstr(skr,buff2));
352 if (!(param->testflag & T_VERY_SILENT) &&
353 ! (info->s->options & HA_OPTION_COMPRESS_RECORD) &&
354 ulonglong2double(info->state->key_file_length) >
355 ulonglong2double(info->s->base.margin_key_file_length)*0.9)
356 mi_check_print_warning(param,
"Keyfile is almost full, %10s of %10s used",
357 llstr(info->state->key_file_length,buff),
358 llstr(info->s->base.max_key_file_length-1,buff));
361 skr=(my_off_t) info->state->data_file_length;
362 if (info->s->options & HA_OPTION_COMPRESS_RECORD)
363 skr+= MEMMAP_EXTRA_MARGIN;
365 if (info->data_file_type == STATIC_RECORD &&
366 skr < (my_off_t) info->s->base.reloc*info->s->base.min_pack_length)
367 skr=(my_off_t) info->s->base.reloc*info->s->base.min_pack_length;
371 info->state->data_file_length=
size;
372 if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
375 mi_check_print_error(param,
"Size of datafile is: %-9s Should be: %s",
376 llstr(size,buff), llstr(skr,buff2));
377 param->testflag|=T_RETRY_WITHOUT_QUICK;
381 mi_check_print_warning(param,
382 "Size of datafile is: %-9s Should be: %s",
383 llstr(size,buff), llstr(skr,buff2));
386 if (!(param->testflag & T_VERY_SILENT) &&
387 !(info->s->options & HA_OPTION_COMPRESS_RECORD) &&
388 ulonglong2double(info->state->data_file_length) >
389 (ulonglong2double(info->s->base.max_data_file_length)*0.9))
390 mi_check_print_warning(param,
"Datafile is almost full, %10s of %10s used",
391 llstr(info->state->data_file_length,buff),
392 llstr(info->s->base.max_data_file_length-1,buff2));
401 uint key,found_keys=0,full_text_keys=0,result=0;
403 ha_checksum old_record_checksum,init_checksum;
404 my_off_t all_keydata,all_totaldata,key_totlength,length;
405 ulong *rec_per_key_part;
408 char buff[22],buff2[22];
409 DBUG_ENTER(
"chk_key");
411 if (!(param->testflag & T_SILENT))
412 puts(
"- check key delete-chain");
414 param->key_file_blocks=info->s->base.keystart;
415 for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
416 if (check_k_link(param,info,key))
418 if (param->testflag & T_VERBOSE) puts(
"");
419 mi_check_print_error(param,
"key delete-link-chain corrupted");
423 if (!(param->testflag & T_SILENT)) puts(
"- check index reference");
425 all_keydata=all_totaldata=key_totlength=0;
426 old_record_checksum=0;
427 init_checksum=param->record_checksum;
428 if (!(share->options &
429 (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
430 old_record_checksum=calc_checksum(info->state->records+info->state->del-1)*
431 share->base.pack_reclength;
432 rec_per_key_part= param->rec_per_key_part;
433 for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
434 rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++)
436 param->key_crc[key]=0;
437 if (! mi_is_key_active(share->state.key_map, key))
440 memcpy((
char*) rec_per_key_part,
441 (
char*) (share->state.rec_per_key_part +
442 (uint) (rec_per_key_part - param->rec_per_key_part)),
443 keyinfo->keysegs*
sizeof(*rec_per_key_part));
448 param->record_checksum=init_checksum;
450 memset(¶m->unique_count, 0,
sizeof(param->unique_count));
451 memset(¶m->notnull_count, 0,
sizeof(param->notnull_count));
453 if ((!(param->testflag & T_SILENT)))
454 printf (
"- check data record references index: %d\n",key+1);
455 if (keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL))
457 if (share->state.key_root[key] == HA_OFFSET_ERROR &&
458 (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
460 if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
461 DFLT_INIT_HITS,info->buff,0))
463 mi_check_print_error(param,
"Can't read indexpage from filepos: %s",
464 llstr(share->state.key_root[key],buff));
465 if (!(param->testflag & T_INFO))
470 param->key_file_blocks+=keyinfo->block_length;
472 param->keydata=param->totaldata=0;
475 if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
476 &keys, param->key_crc+key,1))
478 if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
480 if (keys != info->state->records)
482 mi_check_print_error(param,
"Found %s keys of %s",llstr(keys,buff),
483 llstr(info->state->records,buff2));
484 if (!(param->testflag & T_INFO))
489 if (found_keys - full_text_keys == 1 &&
491 (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ||
492 (param->testflag & T_DONT_CHECK_CHECKSUM)))
493 old_record_checksum=param->record_checksum;
494 else if (old_record_checksum != param->record_checksum)
497 mi_check_print_error(param,
"Key %u doesn't point at same records that key 1",
500 mi_check_print_error(param,
"Key 1 doesn't point at all records");
501 if (!(param->testflag & T_INFO))
507 if ((uint) share->base.auto_key -1 == key)
510 ulonglong auto_increment;
512 _mi_read_key_record(info, 0L, info->rec_buff);
513 auto_increment= retrieve_auto_increment(info, info->rec_buff);
514 if (auto_increment > info->s->state.auto_increment)
516 mi_check_print_warning(param,
"Auto-increment value: %s is smaller "
517 "than max used value: %s",
518 llstr(info->s->state.auto_increment,buff2),
519 llstr(auto_increment, buff));
521 if (param->testflag & T_AUTO_INC)
523 set_if_bigger(info->s->state.auto_increment,
525 set_if_bigger(info->s->state.auto_increment,
526 param->auto_increment_value);
530 mi_extra(info,HA_EXTRA_KEYREAD,0);
531 memset(info->lastkey, 0, keyinfo->seg->length);
532 if (!mi_rkey(info, info->rec_buff, key, (
const uchar*) info->lastkey,
533 (key_part_map)1, HA_READ_KEY_EXACT))
536 uint save=param->warning_printed;
537 mi_check_print_warning(param,
"Found row where the auto_increment "
538 "column has the value 0");
539 param->warning_printed=save;
541 mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
544 length=(my_off_t) isam_key_length(info,keyinfo)*keys + param->key_blocks*2;
545 if (param->testflag & T_INFO && param->totaldata != 0L && keys != 0L)
546 printf(
"Key: %2d: Keyblocks used: %3d%% Packed: %4d%% Max levels: %2d\n",
548 (
int) (my_off_t2double(param->keydata)*100.0/my_off_t2double(param->totaldata)),
549 (
int) ((my_off_t2double(length) - my_off_t2double(param->keydata))*100.0/
550 my_off_t2double(length)),
552 all_keydata+=param->keydata; all_totaldata+=param->totaldata; key_totlength+=length;
555 if (param->testflag & T_STATISTICS)
556 update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
557 param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
558 param->notnull_count: NULL,
559 (ulonglong)info->state->records);
561 if (param->testflag & T_INFO)
563 if (all_totaldata != 0L && found_keys > 0)
564 printf(
"Total: Keyblocks used: %3d%% Packed: %4d%%\n\n",
565 (
int) (my_off_t2double(all_keydata)*100.0/
566 my_off_t2double(all_totaldata)),
567 (
int) ((my_off_t2double(key_totlength) -
568 my_off_t2double(all_keydata))*100.0/
569 my_off_t2double(key_totlength)));
570 else if (all_totaldata != 0L && mi_is_any_key_active(share->state.key_map))
573 if (param->key_file_blocks != info->state->key_file_length &&
574 param->keys_in_use != ~(ulonglong) 0)
575 mi_check_print_warning(param,
"Some data are unreferenced in keyfile");
576 if (found_keys != full_text_keys)
577 param->record_checksum=old_record_checksum-init_checksum;
579 param->record_checksum=0;
585 my_off_t
page, uchar *buff, ha_rows *keys,
586 ha_checksum *key_checksum, uint
level)
588 char llbuff[22],llbuff2[22];
589 DBUG_ENTER(
"chk_index_down");
592 if (page + keyinfo->block_length > info->state->key_file_length)
598 mi_check_print_error(param,
"Invalid key block position: %s "
599 "key block size: %u file_length: %s",
600 llstr(page, llbuff), keyinfo->block_length,
601 llstr(info->state->key_file_length, llbuff2));
602 if (page + keyinfo->block_length > max_length)
605 info->state->key_file_length= (max_length &
606 ~ (my_off_t) (keyinfo->block_length - 1));
611 if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
614 mi_check_print_error(param,
"Mis-aligned key block: %s "
615 "minimum key block length: %u",
616 llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
621 if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
623 mi_check_print_error(param,
"Can't read key from filepos: %s",
627 param->key_file_blocks+=keyinfo->block_length;
628 if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
656 void mi_collect_stats_nonulls_first(
HA_KEYSEG *keyseg, ulonglong *notnull,
660 first_null= (uint) (ha_find_null(keyseg, key) - keyseg);
665 for (kp= 0; kp < first_null; kp++)
696 int mi_collect_stats_nonulls_next(
HA_KEYSEG *keyseg, ulonglong *notnull,
697 uchar *prev_key, uchar *last_key)
700 uint first_null_seg, kp;
711 ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY,
712 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diffs);
713 seg= keyseg + diffs[0] - 1;
716 first_null_seg= (uint) (ha_find_null(seg, last_key + diffs[1]) - keyseg);
717 for (kp= 0; kp < first_null_seg; kp++)
732 my_off_t page, uchar *buff, ha_rows *keys,
733 ha_checksum *key_checksum, uint level)
736 uint used_length,comp_flag,nod_flag,key_length=0;
737 uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
738 my_off_t next_page,
record;
741 DBUG_ENTER(
"chk_index");
742 DBUG_DUMP(
"buff",(uchar*) buff,mi_getint(buff));
745 if (keyinfo->flag & HA_SPATIAL)
748 if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
750 mi_check_print_error(param,
"Not enough memory for keyblock");
754 if (keyinfo->flag & HA_NOSAME)
755 comp_flag=SEARCH_FIND | SEARCH_UPDATE;
757 comp_flag=SEARCH_SAME;
758 nod_flag=mi_test_if_nod(buff);
759 used_length=mi_getint(buff);
760 keypos=buff+2+nod_flag;
761 endpos=buff+used_length;
763 param->keydata+=used_length; param->totaldata+=keyinfo->block_length;
765 if (level > param->max_level)
766 param->max_level=
level;
768 if (used_length > keyinfo->block_length)
770 mi_check_print_error(param,
"Wrong pageinfo at page: %s",
776 if (*killed_ptr(param))
778 memcpy((
char*) info->lastkey,(
char*) key,key_length);
779 info->lastkey_length=key_length;
782 next_page=_mi_kpos(nod_flag,keypos);
783 if (chk_index_down(param,info,keyinfo,next_page,
784 temp_buff,keys,key_checksum,level+1))
788 if (keypos >= endpos ||
789 (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
793 mi_check_print_error(param,
"Wrong key block length at page: %s",llstr(page,llbuff));
797 (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
798 comp_flag, diff_pos)) >=0)
800 DBUG_DUMP(
"old",(uchar*) info->lastkey, info->lastkey_length);
801 DBUG_DUMP(
"new",(uchar*) key, key_length);
802 DBUG_DUMP(
"new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
804 if (comp_flag & SEARCH_FIND && flag == 0)
805 mi_check_print_error(param,
"Found duplicated key at page %s",llstr(page,llbuff));
807 mi_check_print_error(param,
"Key in wrong position at page %s",llstr(page,llbuff));
810 if (param->testflag & T_STATISTICS)
814 if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
815 ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
816 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
818 else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
820 diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
821 param->notnull_count,
824 param->unique_count[diff_pos[0]-1]++;
828 if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
829 mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
833 (*key_checksum)+= mi_byte_checksum((uchar*) key,
834 key_length- info->s->rec_reflength);
835 record= _mi_dpos(info,0,key+key_length);
836 if (keyinfo->flag & HA_FULLTEXT)
840 get_key_full_length_rdonly(off, key);
841 subkeys=ft_sintXkorr(key+off);
845 if (chk_index_down(param,info,&info->s->ft2_keyinfo,record,
846 temp_buff,&tmp_keys,key_checksum,1))
848 if (tmp_keys + subkeys)
850 mi_check_print_error(param,
851 "Number of words in the 2nd level tree "
852 "does not match the number in the header. "
853 "Parent word in on the page %s, offset %u",
854 llstr(page,llbuff), (uint) (old_keypos-buff));
862 if (record >= info->state->data_file_length)
865 char llbuff2[22], llbuff3[22];
867 mi_check_print_error(param,
"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
868 DBUG_PRINT(
"test",(
"page: %s record: %s filelength: %s",
869 llstr(page,llbuff),llstr(record,llbuff2),
870 llstr(info->state->data_file_length,llbuff3)));
871 DBUG_DUMP(
"key",(uchar*) key,key_length);
872 DBUG_DUMP(
"new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
875 param->record_checksum+=(ha_checksum) record;
877 if (keypos != endpos)
879 mi_check_print_error(param,
"Keyblock size at page %s is not correct. Block length: %d key length: %d",
880 llstr(page,llbuff), used_length, (keypos - buff));
883 my_afree((uchar*) temp_buff);
886 my_afree((uchar*) temp_buff);
893 static ha_checksum calc_checksum(ha_rows count)
896 DBUG_ENTER(
"calc_checksum");
910 DBUG_PRINT(
"exit",(
"sum: %lx",(ulong) sum));
911 DBUG_RETURN((ha_checksum) sum);
921 DBUG_ENTER(
"isam_key_length");
923 length= info->s->rec_reflength;
924 for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++)
925 length+= keyseg->length;
927 DBUG_PRINT(
"exit",(
"length: %d",length));
936 int error,got_error,flag;
937 uint key,UNINIT_VAR(left_length),b_type,field;
938 ha_rows records,del_blocks;
939 my_off_t used,empty,pos,splits,UNINIT_VAR(start_recpos),
940 del_length,link_used,start_block;
941 uchar *record= 0, *UNINIT_VAR(
to);
942 char llbuff[22],llbuff2[22],llbuff3[22];
943 ha_checksum intern_record_checksum;
944 ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
945 my_bool static_row_size;
948 DBUG_ENTER(
"chk_data_link");
950 if (!(param->testflag & T_SILENT))
953 puts(
"- check records and index references");
955 puts(
"- check record links");
958 if (!mi_alloc_rec_buff(info, -1, &record))
960 mi_check_print_error(param,
"Not enough memory for record");
963 records=del_blocks=0;
964 used=link_used=splits=del_length=0;
965 intern_record_checksum=param->glob_crc=0;
967 empty=info->s->pack.header_length;
971 if (info->s->data_file_type == COMPRESSED_RECORD)
973 for (field=0 ; field < info->s->base.fields ; field++)
975 if (info->s->rec[field].base_type == FIELD_BLOB ||
976 info->s->rec[field].base_type == FIELD_VARCHAR)
984 pos=my_b_tell(¶m->read_cache);
985 memset(key_checksum, 0, info->s->base.keys *
sizeof(key_checksum[0]));
986 while (pos < info->state->data_file_length)
988 if (*killed_ptr(param))
990 switch (info->s->data_file_type) {
992 if (my_b_read(¶m->read_cache,(uchar*) record,
993 info->s->base.pack_reclength))
996 pos+=info->s->base.pack_reclength;
1001 del_length+=info->s->base.pack_reclength;
1004 param->glob_crc+= mi_static_checksum(info,record);
1005 used+=info->s->base.pack_reclength;
1007 case DYNAMIC_RECORD:
1008 flag=block_info.second_read=0;
1009 block_info.next_filepos=pos;
1012 if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
1013 (start_block=block_info.next_filepos),
1014 sizeof(block_info.header),
1015 (flag ? 0 : READING_NEXT) | READING_HEADER))
1017 if (start_block & (MI_DYN_ALIGN_SIZE-1))
1019 mi_check_print_error(param,
"Wrong aligned block at %s",
1020 llstr(start_block,llbuff));
1023 b_type=_mi_get_block_info(&block_info,-1,start_block);
1024 if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
1027 if (b_type & BLOCK_SYNC_ERROR)
1031 mi_check_print_error(param,
"Unexpected byte: %d at link: %s",
1032 (
int) block_info.header[0],
1033 llstr(start_block,llbuff));
1036 pos=block_info.filepos+block_info.block_len;
1039 if (b_type & BLOCK_DELETED)
1041 if (block_info.block_len < info->s->base.min_block_length)
1043 mi_check_print_error(param,
1044 "Deleted block with impossible length %lu at %s",
1045 block_info.block_len,llstr(pos,llbuff));
1048 if ((block_info.next_filepos != HA_OFFSET_ERROR &&
1049 block_info.next_filepos >= info->state->data_file_length) ||
1050 (block_info.prev_filepos != HA_OFFSET_ERROR &&
1051 block_info.prev_filepos >= info->state->data_file_length))
1053 mi_check_print_error(param,
"Delete link points outside datafile at %s",
1058 del_length+=block_info.block_len;
1059 pos=block_info.filepos+block_info.block_len;
1063 mi_check_print_error(param,
"Wrong bytesec: %d-%d-%d at linkstart: %s",
1064 block_info.header[0],block_info.header[1],
1065 block_info.header[2],
1066 llstr(start_block,llbuff));
1069 if (info->state->data_file_length < block_info.filepos+
1070 block_info.block_len)
1072 mi_check_print_error(param,
1073 "Recordlink that points outside datafile at %s",
1082 pos=block_info.filepos+block_info.block_len;
1083 if (block_info.rec_len > (uint) info->s->base.max_pack_length)
1085 mi_check_print_error(param,
"Found too long record (%lu) at %s",
1086 (ulong) block_info.rec_len,
1087 llstr(start_recpos,llbuff));
1091 if (info->s->base.blobs)
1093 if (!(
to= mi_alloc_rec_buff(info, block_info.rec_len,
1096 mi_check_print_error(param,
1097 "Not enough memory (%lu) for blob at %s",
1098 (ulong) block_info.rec_len,
1099 llstr(start_recpos,llbuff));
1106 left_length=block_info.rec_len;
1108 if (left_length < block_info.data_len)
1110 mi_check_print_error(param,
"Found too long record (%lu) at %s",
1111 (ulong) block_info.data_len,
1112 llstr(start_recpos,llbuff));
1116 if (_mi_read_cache(¶m->read_cache,(uchar*)
to,block_info.filepos,
1117 (uint) block_info.data_len,
1118 flag == 1 ? READING_NEXT : 0))
1120 to+=block_info.data_len;
1121 link_used+= block_info.filepos-start_block;
1122 used+= block_info.filepos - start_block + block_info.data_len;
1123 empty+=block_info.block_len-block_info.data_len;
1124 left_length-=block_info.data_len;
1127 if (b_type & BLOCK_LAST)
1129 mi_check_print_error(param,
1130 "Wrong record length %s of %s at %s",
1131 llstr(block_info.rec_len-left_length,llbuff),
1132 llstr(block_info.rec_len, llbuff2),
1133 llstr(start_recpos,llbuff3));
1137 if (info->state->data_file_length < block_info.next_filepos)
1139 mi_check_print_error(param,
1140 "Found next-recordlink that points outside datafile at %s",
1141 llstr(block_info.filepos,llbuff));
1146 }
while (left_length);
1149 if (_mi_rec_unpack(info,record,info->rec_buff,block_info.rec_len) ==
1152 mi_check_print_error(param,
"Found wrong record at %s",
1153 llstr(start_recpos,llbuff));
1158 info->checksum=mi_checksum(info,record);
1159 if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE))
1161 if (_mi_rec_check(info,record, info->rec_buff,block_info.rec_len,
1162 test(info->s->calc_checksum)))
1164 mi_check_print_error(param,
"Found wrong packed record at %s",
1165 llstr(start_recpos,llbuff));
1170 param->glob_crc+= info->checksum;
1174 pos=block_info.filepos+block_info.block_len;
1176 case COMPRESSED_RECORD:
1177 if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header, pos,
1178 info->s->pack.ref_length, READING_NEXT))
1182 (void) _mi_pack_get_block_info(info, &info->bit_buff, &block_info,
1183 &info->rec_buff, -1, start_recpos);
1184 pos=block_info.filepos+block_info.rec_len;
1185 if (block_info.rec_len < (uint) info->s->min_pack_length ||
1186 block_info.rec_len > (uint) info->s->max_pack_length)
1188 mi_check_print_error(param,
1189 "Found block with wrong recordlength: %d at %s",
1190 block_info.rec_len, llstr(start_recpos,llbuff));
1194 if (_mi_read_cache(¶m->read_cache,(uchar*) info->rec_buff,
1195 block_info.filepos, block_info.rec_len, READING_NEXT))
1197 if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
1198 info->rec_buff, block_info.rec_len))
1200 mi_check_print_error(param,
"Found wrong record at %s",
1201 llstr(start_recpos,llbuff));
1204 if (static_row_size)
1205 param->glob_crc+= mi_static_checksum(info,record);
1207 param->glob_crc+= mi_checksum(info,record);
1208 link_used+= (block_info.filepos - start_recpos);
1209 used+= (pos-start_recpos);
1216 intern_record_checksum+=(ha_checksum) start_recpos;
1218 if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1220 printf(
"%s\r", llstr(records,llbuff)); (void) fflush(stdout);
1225 for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys;
1228 if (mi_is_key_active(info->s->state.key_map, key))
1230 if(!(keyinfo->flag & HA_FULLTEXT))
1232 uint key_length=_mi_make_key(info,key,info->lastkey,record,
1240 #ifdef HAVE_RTREE_KEYS
1241 (keyinfo->flag & HA_SPATIAL) ?
1242 rtree_find_first(info, key, info->lastkey, key_length,
1243 MBR_EQUAL | MBR_DATA) :
1245 _mi_search(info,keyinfo,info->lastkey,key_length,
1246 SEARCH_SAME, info->s->state.key_root[key]);
1249 mi_check_print_error(param,
"Record at: %10s "
1250 "Can't find key for index: %2d",
1251 llstr(start_recpos,llbuff),key+1);
1252 if (error++ > MAXERR || !(param->testflag & T_VERBOSE))
1257 key_checksum[key]+=mi_byte_checksum((uchar*) info->lastkey,
1266 if (error++ > MAXERR || !(param->testflag & T_VERBOSE))
1271 if (param->testflag & T_WRITE_LOOP)
1273 (void) fputs(
" \r",stdout); (void) fflush(stdout);
1275 if (records != info->state->records)
1277 mi_check_print_error(param,
"Record-count is not ok; is %-10s Should be: %s",
1278 llstr(records,llbuff), llstr(info->state->records,llbuff2));
1281 else if (param->record_checksum &&
1282 param->record_checksum != intern_record_checksum)
1284 mi_check_print_error(param,
1285 "Keypointers and record positions doesn't match");
1288 else if (param->glob_crc != info->state->checksum &&
1290 (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
1292 mi_check_print_warning(param,
1293 "Record checksum is not the same as checksum stored in the index file\n");
1298 for (key=0 ; key < info->s->base.keys; key++)
1300 if (key_checksum[key] != param->key_crc[key] &&
1301 !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1303 mi_check_print_error(param,
"Checksum for key: %2d doesn't match checksum for records",
1310 if (del_length != info->state->empty)
1312 mi_check_print_warning(param,
1313 "Found %s deleted space. Should be %s",
1314 llstr(del_length,llbuff2),
1315 llstr(info->state->empty,llbuff));
1317 if (used+empty+del_length != info->state->data_file_length)
1319 mi_check_print_warning(param,
1320 "Found %s record-data and %s unused data and %s deleted-data",
1321 llstr(used,llbuff),llstr(empty,llbuff2),
1322 llstr(del_length,llbuff3));
1323 mi_check_print_warning(param,
1324 "Total %s, Should be: %s",
1325 llstr((used+empty+del_length),llbuff),
1326 llstr(info->state->data_file_length,llbuff2));
1328 if (del_blocks != info->state->del)
1330 mi_check_print_warning(param,
1331 "Found %10s deleted blocks Should be: %s",
1332 llstr(del_blocks,llbuff),
1333 llstr(info->state->del,llbuff2));
1335 if (splits != info->s->state.split)
1337 mi_check_print_warning(param,
1338 "Found %10s key parts. Should be: %s",
1339 llstr(splits,llbuff),
1340 llstr(info->s->state.split,llbuff2));
1342 if (param->testflag & T_INFO)
1344 if (param->warning_printed || param->error_printed)
1346 if (used != 0 && ! param->error_printed)
1348 printf(
"Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n",
1349 llstr(records,llbuff), (
long)((used-link_used)/records),
1350 (info->s->base.blobs ? 0.0 :
1351 (ulonglong2double((ulonglong) info->s->base.reclength*records)-
1352 my_off_t2double(used))/
1353 ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1354 printf(
"Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n",
1355 (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0),
1356 (!records ? 100 : (
int) (ulonglong2double(del_length+empty)/
1357 my_off_t2double(used)*100.0)),
1358 ulonglong2double(splits - del_blocks) / records);
1360 printf(
"Record blocks:%12s Delete blocks:%10s\n",
1361 llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1362 printf(
"Record data: %12s Deleted data: %10s\n",
1363 llstr(used-link_used,llbuff),llstr(del_length,llbuff2));
1364 printf(
"Lost space: %12s Linkdata: %10s\n",
1365 llstr(empty,llbuff),llstr(link_used,llbuff2));
1367 my_free(mi_get_rec_buff_ptr(info, record));
1368 DBUG_RETURN (error);
1370 mi_check_print_error(param,
"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1372 my_free(mi_get_rec_buff_ptr(info, record));
1373 param->testflag|=T_RETRY_WITHOUT_QUICK;
1431 static int mi_drop_all_indexes(
MI_CHECK *param,
MI_INFO *info, my_bool force)
1437 DBUG_ENTER(
"mi_drop_all_indexes");
1446 if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
1448 DBUG_PRINT(
"repair", (
"creating missing indexes"));
1449 for (i= 0; i < share->base.keys; i++)
1451 DBUG_PRINT(
"repair", (
"index #: %u key_root: 0x%lx active: %d",
1452 i, (
long) state->key_root[i],
1453 mi_is_key_active(state->key_map, i)));
1454 if ((state->key_root[i] != HA_OFFSET_ERROR) &&
1455 !mi_is_key_active(state->key_map, i))
1462 DBUG_PRINT(
"repair", (
"nonempty and disabled: recreate all"));
1466 if (i >= share->base.keys)
1473 DBUG_PRINT(
"repair", (
"all disabled are empty: create missing"));
1474 error= flush_key_blocks(share->key_cache, share->kfile,
1483 mi_clear_all_keys_active(state->key_map);
1484 DBUG_PRINT(
"repair", (
"declared all indexes disabled"));
1488 if ((error= flush_key_blocks(share->key_cache, share->kfile,
1489 FLUSH_IGNORE_CHANGED)))
1493 for (i= 0; i < share->base.keys; i++)
1494 state->key_root[i]= HA_OFFSET_ERROR;
1497 for (i= 0; i < state->header.max_block_size_index; i++)
1498 state->key_del[i]= HA_OFFSET_ERROR;
1501 info->state->key_file_length= share->base.keystart;
1503 DBUG_PRINT(
"repair", (
"dropped all indexes"));
1515 char *
name,
int rep_quick)
1517 int error,got_error;
1518 ha_rows start_records,new_header_length;
1522 char llbuff[22],llbuff2[22];
1525 DBUG_ENTER(
"mi_repair");
1527 memset(&sort_info, 0,
sizeof(sort_info));
1528 memset(&sort_param, 0,
sizeof(sort_param));
1529 start_records=info->state->records;
1530 new_header_length=(param->testflag & T_UNPACK) ? 0L :
1531 share->pack.header_length;
1534 sort_param.sort_info=&sort_info;
1536 if (!(param->testflag & T_SILENT))
1538 printf(
"- recovering (with keycache) MyISAM-table '%s'\n",name);
1539 printf(
"Data records: %s\n", llstr(info->state->records,llbuff));
1541 param->testflag|=T_REP;
1543 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1544 param->testflag|=T_CALC_CHECKSUM;
1546 DBUG_ASSERT(param->use_buffers < SIZE_T_MAX);
1548 if (!param->using_global_keycache)
1549 (void) init_key_cache(dflt_key_cache, param->key_cache_block_size,
1550 param->use_buffers, 0, 0);
1552 if (init_io_cache(¶m->read_cache,info->dfile,
1553 (uint) param->read_buffer_length,
1554 READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1556 memset(&info->rec_cache, 0,
sizeof(info->rec_cache));
1560 if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
1561 WRITE_CACHE, new_header_length, 1,
1562 MYF(MY_WME | MY_WAIT_IF_FULL)))
1564 info->opt_flag|=WRITE_CACHE_USED;
1565 if (!mi_alloc_rec_buff(info, -1, &sort_param.record) ||
1566 !mi_alloc_rec_buff(info, -1, &sort_param.rec_buff))
1568 mi_check_print_error(param,
"Not enough memory for extra record");
1576 fn_format(param->temp_filename,
1577 share->data_file_name,
"",
1579 0, param->tmpfile_createflag,
1582 mi_check_print_error(param,
"Can't create new tempfile: '%s'",
1583 param->temp_filename);
1586 if (new_header_length &&
1587 filecopy(param,new_file,info->dfile,0L,new_header_length,
1590 info->s->state.dellink= HA_OFFSET_ERROR;
1591 info->rec_cache.file=new_file;
1592 if (param->testflag & T_UNPACK)
1594 share->options&= ~HA_OPTION_COMPRESS_RECORD;
1595 mi_int2store(share->state.header.options,share->options);
1598 sort_info.info=info;
1599 sort_info.param = param;
1600 sort_param.read_cache=param->read_cache;
1601 sort_param.pos=sort_param.max_pos=share->pack.header_length;
1602 sort_param.filepos=new_header_length;
1603 param->read_cache.end_of_file=sort_info.filelength=
1606 sort_param.fix_datafile= (my_bool) (! rep_quick);
1607 sort_param.master=1;
1608 sort_info.max_records= ~(ha_rows) 0;
1610 set_data_file_type(&sort_info, share);
1611 del=info->state->del;
1612 info->state->records=info->state->del=share->state.split=0;
1613 info->state->empty=0;
1615 if (param->testflag & T_CALC_CHECKSUM)
1616 sort_param.calc_checksum= 1;
1618 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
1621 if (param->testflag & T_CREATE_MISSING_KEYS)
1622 mi_set_all_keys_active(share->state.key_map, share->base.keys);
1623 mi_drop_all_indexes(param, info, TRUE);
1628 while (!(error=sort_get_next_record(&sort_param)))
1630 if (writekeys(&sort_param))
1632 if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1634 DBUG_DUMP(
"record",(uchar*) sort_param.record,share->base.pack_reclength);
1635 mi_check_print_info(param,
"Duplicate key %2d for record at %10s against new record at %10s",
1637 llstr(sort_param.start_recpos,llbuff),
1638 llstr(info->dupp_key_pos,llbuff2));
1639 if (param->testflag & T_VERBOSE)
1641 (void) _mi_make_key(info,(uint) info->errkey,info->lastkey,
1642 sort_param.record,0L);
1643 _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
1647 if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1649 param->testflag|=T_RETRY_WITHOUT_QUICK;
1650 param->error_printed=1;
1655 if (sort_write_record(&sort_param))
1658 if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1659 flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1662 if (param->testflag & T_WRITE_LOOP)
1664 (void) fputs(
" \r",stdout); (void) fflush(stdout);
1668 mi_check_print_warning(param,
1669 "Can't change size of indexfile, error: %d",
1674 if (rep_quick && del+sort_info.dupp != info->state->del)
1676 mi_check_print_error(param,
"Couldn't fix table with quick recovery: Found wrong number of deleted records");
1677 mi_check_print_error(param,
"Run recovery again without -q");
1679 param->retry_repair=1;
1680 param->testflag|=T_RETRY_WITHOUT_QUICK;
1683 if (param->testflag & T_SAFE_REPAIR)
1686 if (info->state->records+1 < start_records)
1688 info->state->records=start_records;
1697 info->dfile=new_file;
1698 info->state->data_file_length=sort_param.filepos;
1699 share->state.version=(ulong) time((time_t*) 0);
1703 info->state->data_file_length=sort_param.max_pos;
1705 if (param->testflag & T_CALC_CHECKSUM)
1706 info->state->checksum=param->glob_crc;
1708 if (!(param->testflag & T_SILENT))
1710 if (start_records != info->state->records)
1711 printf(
"Data records: %s\n", llstr(info->state->records,llbuff));
1713 mi_check_print_warning(param,
1714 "%s records have been removed",
1715 llstr(sort_info.dupp,llbuff));
1720 if (&share->state.state != info->state)
1721 memcpy( &share->state.state, info->state,
sizeof(*info->state));
1730 info->dfile=new_file= -1;
1740 if (info->s->file_map)
1742 (void) my_munmap((
char*) info->s->file_map,
1743 (size_t) info->s->mmaped_length);
1744 info->s->file_map= NULL;
1746 if (change_to_newfile(share->data_file_name, MI_NAME_DEXT, DATA_TMP_EXT,
1747 (param->testflag & T_BACKUP_DATA ?
1748 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
1749 mi_open_datafile(info,share,name,-1))
1752 param->retry_repair= 0;
1757 if (! param->error_printed)
1758 mi_check_print_error(param,
"%d for record at pos %s",my_errno,
1759 llstr(sort_param.start_recpos,llbuff));
1764 param->temp_filename, MYF(MY_WME));
1765 info->rec_cache.file=-1;
1767 mi_mark_crashed_on_repair(info);
1769 my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff));
1770 my_free(mi_get_rec_buff_ptr(info, sort_param.record));
1771 my_free(sort_info.buff);
1772 (void) end_io_cache(¶m->read_cache);
1773 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1774 (void) end_io_cache(&info->rec_cache);
1775 got_error|=flush_blocks(param, share->key_cache, share->kfile);
1776 if (!got_error && param->testflag & T_UNPACK)
1778 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1779 share->pack.header_length=0;
1780 share->data_file_type=sort_info.new_data_file_type;
1782 share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1783 STATE_NOT_ANALYZED);
1784 DBUG_RETURN(got_error);
1794 MI_INFO *info= sort_param->sort_info->info;
1795 uchar *buff= sort_param->record;
1796 my_off_t filepos= sort_param->filepos;
1797 DBUG_ENTER(
"writekeys");
1799 key=info->lastkey+info->s->base.max_key_length;
1800 for (i=0 ; i < info->s->base.keys ; i++)
1802 if (mi_is_key_active(info->s->state.key_map, i))
1804 if (info->s->keyinfo[i].flag & HA_FULLTEXT )
1806 if (_mi_ft_add(info, i, key, buff, filepos))
1810 else if (info->s->keyinfo[i].flag & HA_SPATIAL)
1812 uint key_length=_mi_make_key(info,i,key,buff,filepos);
1813 if (rtree_insert(info, i, key, key_length))
1819 uint key_length=_mi_make_key(info,i,key,buff,filepos);
1820 if (_mi_ck_write(info,i,key,key_length))
1828 if (my_errno == HA_ERR_FOUND_DUPP_KEY)
1830 info->errkey=(int) i;
1833 if (mi_is_key_active(info->s->state.key_map, i))
1835 if (info->s->keyinfo[i].flag & HA_FULLTEXT)
1837 if (_mi_ft_del(info,i, key,buff,filepos))
1842 uint key_length=_mi_make_key(info,i,key,buff,filepos);
1843 if (_mi_ck_delete(info,i,key,key_length))
1850 if (sort_param->calc_checksum)
1851 sort_param->sort_info->param->glob_crc-= info->checksum;
1852 DBUG_PRINT(
"error",(
"errno: %d",my_errno));
1859 int movepoint(
register MI_INFO *info, uchar *record, my_off_t oldpos,
1860 my_off_t newpos, uint prot_key)
1865 DBUG_ENTER(
"movepoint");
1867 key=info->lastkey+info->s->base.max_key_length;
1868 for (i=0 ; i < info->s->base.keys; i++)
1870 if (i != prot_key && mi_is_key_active(info->s->state.key_map, i))
1872 key_length=_mi_make_key(info,i,key,record,oldpos);
1873 if (info->s->keyinfo[i].flag & HA_NOSAME)
1877 keyinfo=info->s->keyinfo+
i;
1878 if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1879 (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1880 info->s->state.key_root[i]))
1882 nod_flag=mi_test_if_nod(info->buff);
1883 _mi_dpointer(info,info->int_keypos-nod_flag-
1884 info->s->rec_reflength,newpos);
1885 if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1886 DFLT_INIT_HITS,info->buff))
1891 if (_mi_ck_delete(info,i,key,key_length))
1893 key_length=_mi_make_key(info,i,key,record,newpos);
1894 if (_mi_ck_write(info,i,key,key_length))
1905 void lock_memory(
MI_CHECK *param __attribute__((unused)))
1908 if (param->opt_lock_memory)
1910 int success = mlockall(MCL_CURRENT);
1911 if (geteuid() == 0 && success != 0)
1912 mi_check_print_warning(param,
1913 "Failed to lock memory. errno %d",my_errno);
1923 if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
1925 mi_check_print_error(param,
"%d when trying to write bufferts",my_errno);
1928 if (!param->using_global_keycache)
1929 end_key_cache(key_cache,1);
1936 int mi_sort_index(
MI_CHECK *param,
register MI_INFO *info,
char * name)
1941 my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1942 uint r_locks,w_locks;
1946 DBUG_ENTER(
"mi_sort_index");
1949 for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1951 if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
1954 if (!(param->testflag & T_SILENT))
1955 printf(
"- Sorting index for MyISAM-table '%s'\n",name);
1958 fn_format(param->temp_filename,name,
"", MI_NAME_IEXT,2+4+32);
1960 fn_format(param->temp_filename,
1961 param->temp_filename,
1962 "", INDEX_TMP_EXT, 2+4),
1963 0, param->tmpfile_createflag, MYF(0))) <= 0)
1965 mi_check_print_error(param,
"Can't create new tempfile: '%s'",
1966 param->temp_filename);
1969 if (filecopy(param, new_file,share->kfile,0L,
1970 (ulong) share->base.keystart,
"headerblock"))
1973 param->new_file_pos=share->base.keystart;
1974 for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1977 if (! mi_is_key_active(info->s->state.key_map, key))
1982 index_pos[key]= HA_OFFSET_ERROR;
1986 if (share->state.key_root[key] != HA_OFFSET_ERROR)
1988 index_pos[key]=param->new_file_pos;
1989 if (sort_one_index(param,info,keyinfo,share->state.key_root[key],
1994 index_pos[key]= HA_OFFSET_ERROR;
1998 flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
2000 share->state.version=(ulong) time((time_t*) 0);
2001 old_state= share->state;
2002 r_locks= share->r_locks;
2003 w_locks= share->w_locks;
2004 old_lock= info->lock_type;
2007 share->r_locks= share->w_locks= share->tot_locks= 0;
2008 (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
2012 if (change_to_newfile(share->index_file_name, MI_NAME_IEXT, INDEX_TMP_EXT,
2014 mi_open_keyfile(share))
2016 info->lock_type= F_UNLCK;
2017 _mi_readinfo(info,F_WRLCK,0);
2018 info->lock_type= old_lock;
2019 share->r_locks= r_locks;
2020 share->w_locks= w_locks;
2021 share->tot_locks= r_locks+w_locks;
2022 share->state= old_state;
2024 info->state->key_file_length=param->new_file_pos;
2025 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2026 for (key=0 ; key < info->s->base.keys ; key++)
2027 info->s->state.key_root[key]=index_pos[key];
2028 for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
2029 info->s->state.key_del[key]= HA_OFFSET_ERROR;
2031 info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
2038 param->temp_filename, MYF(MY_WME));
2046 my_off_t pagepos, File new_file)
2048 uint length,nod_flag,used_length, key_length;
2049 uchar *buff,*keypos,*endpos;
2050 uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
2051 my_off_t new_page_pos,next_page;
2053 DBUG_ENTER(
"sort_one_index");
2056 DBUG_ASSERT(keyinfo->key_alg != HA_KEY_ALG_RTREE);
2057 new_page_pos=param->new_file_pos;
2058 param->new_file_pos+=keyinfo->block_length;
2060 if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
2062 mi_check_print_error(param,
"Not enough memory for key block");
2065 if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
2067 mi_check_print_error(param,
"Can't read key block from filepos: %s",
2068 llstr(pagepos,llbuff));
2071 if ((nod_flag=mi_test_if_nod(buff)) || keyinfo->flag & HA_FULLTEXT)
2073 used_length=mi_getint(buff);
2074 keypos=buff+2+nod_flag;
2075 endpos=buff+used_length;
2080 next_page=_mi_kpos(nod_flag,keypos);
2081 _mi_kpointer(info,keypos-nod_flag,param->new_file_pos);
2082 if (sort_one_index(param,info,keyinfo,next_page,new_file))
2085 (
"From page: %ld, keyoffset: %lu used_length: %d",
2086 (ulong) pagepos, (ulong) (keypos - buff),
2087 (
int) used_length));
2088 DBUG_DUMP(
"buff",(uchar*) buff,used_length);
2092 if (keypos >= endpos ||
2093 (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
2095 DBUG_ASSERT(keypos <= endpos);
2096 if (keyinfo->flag & HA_FULLTEXT)
2100 get_key_full_length_rdonly(off, key);
2101 subkeys=ft_sintXkorr(key+off);
2104 next_page= _mi_dpos(info,0,key+key_length);
2105 _mi_dpointer(info,keypos-nod_flag-info->s->rec_reflength,
2106 param->new_file_pos);
2107 if (sort_one_index(param,info,&info->s->ft2_keyinfo,
2108 next_page,new_file))
2116 length=mi_getint(buff);
2117 memset(buff+length, 0, keyinfo->block_length-length);
2119 new_page_pos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
2121 mi_check_print_error(param,
"Can't write indexblock, error: %d",my_errno);
2124 my_afree((uchar*) buff);
2127 my_afree((uchar*) buff);
2141 int change_to_newfile(
const char * filename,
const char * old_ext,
2142 const char * new_ext, myf MyFlags)
2144 char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
2146 (void) fn_format(old_filename,filename,
"",old_ext,2+4+32);
2147 return my_redel(old_filename,
2148 fn_format(new_filename,old_filename,
"",new_ext,2+4),
2149 MYF(MY_WME | MY_LINK_WARNING | MyFlags));
2156 int lock_file(
MI_CHECK *param, File file, my_off_t start,
int lock_type,
2157 const char *filetype,
const char *filename)
2159 if (my_lock(file,lock_type,start,F_TO_EOF,
2160 param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
2161 MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT)))
2163 mi_check_print_error(param,
" %d when locking %s '%s'",my_errno,filetype,filename);
2164 param->error_printed=2;
2173 int filecopy(
MI_CHECK *param, File
to,File from,my_off_t start,
2174 my_off_t length,
const char *
type)
2176 char tmp_buff[IO_SIZE],*buff;
2178 DBUG_ENTER(
"filecopy");
2180 buff_length=(ulong) MY_MIN(param->write_buffer_length,length);
2181 if (!(buff=my_malloc(buff_length,MYF(0))))
2183 buff=tmp_buff; buff_length=IO_SIZE;
2187 while (length > buff_length)
2189 if (
mysql_file_read(from, (uchar*) buff, buff_length, MYF(MY_NABP)) ||
2192 length-= buff_length;
2194 if (
mysql_file_read(from, (uchar*) buff, (uint) length, MYF(MY_NABP)) ||
2197 if (buff != tmp_buff)
2201 if (buff != tmp_buff)
2203 mi_check_print_error(param,
"Can't copy %s to tempfile, error %d",
2225 const char * name,
int rep_quick)
2230 ha_rows start_records;
2231 my_off_t new_header_length,del;
2236 ulong *rec_per_key_part;
2239 ulonglong UNINIT_VAR(
key_map);
2240 DBUG_ENTER(
"mi_repair_by_sort");
2242 start_records=info->state->records;
2245 new_header_length=(param->testflag & T_UNPACK) ? 0 :
2246 share->pack.header_length;
2247 if (!(param->testflag & T_SILENT))
2249 printf(
"- recovering (with sort) MyISAM-table '%s'\n",name);
2250 printf(
"Data records: %s\n", llstr(start_records,llbuff));
2252 param->testflag|=T_REP;
2254 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2255 param->testflag|=T_CALC_CHECKSUM;
2257 memset(&sort_info, 0,
sizeof(sort_info));
2258 memset(&sort_param, 0,
sizeof(sort_param));
2259 if (!(sort_info.key_block=
2260 alloc_key_blocks(param,
2261 (uint) param->sort_key_blocks,
2262 share->base.max_key_block_length))
2263 || init_io_cache(¶m->read_cache,info->dfile,
2264 (uint) param->read_buffer_length,
2265 READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) ||
2267 init_io_cache(&info->rec_cache,info->dfile,
2268 (uint) param->write_buffer_length,
2269 WRITE_CACHE,new_header_length,1,
2270 MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw)))
2272 sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks;
2273 info->opt_flag|=WRITE_CACHE_USED;
2274 info->rec_cache.file=info->dfile;
2276 if (!mi_alloc_rec_buff(info, -1, &sort_param.record) ||
2277 !mi_alloc_rec_buff(info, -1, &sort_param.rec_buff))
2279 mi_check_print_error(param,
"Not enough memory for extra record");
2286 fn_format(param->temp_filename,
2287 share->data_file_name,
"",
2289 0, param->tmpfile_createflag,
2292 mi_check_print_error(param,
"Can't create new tempfile: '%s'",
2293 param->temp_filename);
2296 if (new_header_length &&
2297 filecopy(param, new_file,info->dfile,0L,new_header_length,
2300 if (param->testflag & T_UNPACK)
2302 share->options&= ~HA_OPTION_COMPRESS_RECORD;
2303 mi_int2store(share->state.header.options,share->options);
2305 share->state.dellink= HA_OFFSET_ERROR;
2306 info->rec_cache.file=new_file;
2309 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2312 mi_drop_all_indexes(param, info, FALSE);
2313 key_map= share->state.key_map;
2314 if (param->testflag & T_CREATE_MISSING_KEYS)
2320 sort_info.info=info;
2321 sort_info.param = param;
2323 set_data_file_type(&sort_info, share);
2324 sort_param.filepos=new_header_length;
2327 param->read_cache.end_of_file=sort_info.filelength=
2330 sort_param.wordlist=NULL;
2331 init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
2333 if (share->data_file_type == DYNAMIC_RECORD)
2334 length= MY_MAX(share->base.min_pack_length + 1, share->base.min_block_length);
2335 else if (share->data_file_type == COMPRESSED_RECORD)
2336 length=share->base.min_block_length;
2338 length=share->base.pack_reclength;
2339 sort_info.max_records=
2340 ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records :
2341 (ha_rows) (sort_info.filelength/length+1));
2342 sort_param.key_cmp=sort_key_cmp;
2343 sort_param.lock_in_memory=lock_memory;
2344 sort_param.tmpdir=param->tmpdir;
2345 sort_param.sort_info=&sort_info;
2346 sort_param.fix_datafile= (my_bool) (! rep_quick);
2347 sort_param.master =1;
2349 del=info->state->del;
2351 if (param->testflag & T_CALC_CHECKSUM)
2352 sort_param.calc_checksum= 1;
2354 rec_per_key_part= param->rec_per_key_part;
2355 for (sort_param.key=0 ; sort_param.key < share->base.keys ;
2356 rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
2358 sort_param.read_cache=param->read_cache;
2359 sort_param.keyinfo=share->keyinfo+sort_param.key;
2360 sort_param.seg=sort_param.keyinfo->seg;
2365 if (! mi_is_key_active(
key_map, sort_param.key))
2368 memcpy((
char*) rec_per_key_part,
2369 (
char*) (share->state.rec_per_key_part +
2370 (uint) (rec_per_key_part - param->rec_per_key_part)),
2371 sort_param.keyinfo->keysegs*
sizeof(*rec_per_key_part));
2372 DBUG_PRINT(
"repair", (
"skipping seemingly disabled index #: %u",
2377 if ((!(param->testflag & T_SILENT)))
2378 printf (
"- Fixing index %d\n",sort_param.key+1);
2379 sort_param.max_pos=sort_param.pos=share->pack.header_length;
2380 keyseg=sort_param.seg;
2381 memset(sort_param.unique, 0,
sizeof(sort_param.unique));
2382 sort_param.key_length=share->rec_reflength;
2383 for (i=0 ; keyseg[
i].type != HA_KEYTYPE_END; i++)
2385 sort_param.key_length+=keyseg[
i].length;
2386 if (keyseg[i].flag & HA_SPACE_PACK)
2387 sort_param.key_length+=get_pack_length(keyseg[i].length);
2388 if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
2389 sort_param.key_length+=2 +
test(keyseg[i].length >= 127);
2390 if (keyseg[i].flag & HA_NULL_PART)
2391 sort_param.key_length++;
2393 info->state->records=info->state->del=share->state.split=0;
2394 info->state->empty=0;
2396 if (sort_param.keyinfo->flag & HA_FULLTEXT)
2398 uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
2399 sort_param.keyinfo->seg->charset->mbmaxlen;
2400 sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
2405 if (sort_param.keyinfo->parser == &ft_default_parser)
2412 sort_info.max_records=
2413 (ha_rows) (sort_info.filelength/ft_min_word_len+1);
2422 sort_info.max_records= 10 *
2423 MY_MAX(param->sort_buffer_length, MIN_SORT_BUFFER) /
2424 sort_param.key_length;
2427 sort_param.key_read=sort_ft_key_read;
2428 sort_param.key_write=sort_ft_key_write;
2432 sort_param.key_read=sort_key_read;
2433 sort_param.key_write=sort_key_write;
2436 if (_create_index_by_sort(&sort_param,
2437 (my_bool) (!(param->testflag & T_VERBOSE)),
2438 param->sort_buffer_length))
2440 param->retry_repair=1;
2444 sort_param.calc_checksum= 0;
2445 free_root(&sort_param.wordroot, MYF(0));
2448 sort_info.max_records= (ha_rows) info->state->records;
2450 if (param->testflag & T_STATISTICS)
2451 update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
2452 param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
2453 sort_param.notnull: NULL,
2454 (ulonglong) info->state->records);
2456 mi_set_key_active(share->state.key_map, sort_param.key);
2457 DBUG_PRINT(
"repair", (
"set enabled index #: %u", sort_param.key));
2459 if (sort_param.fix_datafile)
2461 param->read_cache.end_of_file=sort_param.filepos;
2462 if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache))
2464 if (param->testflag & T_SAFE_REPAIR)
2467 if (info->state->records+1 < start_records)
2469 info->state->records=start_records;
2473 share->state.state.data_file_length = info->state->data_file_length=
2476 share->state.version=(ulong) time((time_t*) 0);
2478 info->dfile=new_file;
2479 share->data_file_type=sort_info.new_data_file_type;
2480 share->pack.header_length=(ulong) new_header_length;
2481 sort_param.fix_datafile=0;
2484 info->state->data_file_length=sort_param.max_pos;
2486 param->read_cache.file=info->dfile;
2487 reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length,
2491 if (param->testflag & T_WRITE_LOOP)
2493 (void) fputs(
" \r",stdout); (void) fflush(stdout);
2496 if (rep_quick && del+sort_info.dupp != info->state->del)
2498 mi_check_print_error(param,
"Couldn't fix table with quick recovery: Found wrong number of deleted records");
2499 mi_check_print_error(param,
"Run recovery again without -q");
2501 param->retry_repair=1;
2502 param->testflag|=T_RETRY_WITHOUT_QUICK;
2506 if (rep_quick & T_FORCE_UNIQUENESS)
2508 my_off_t skr=info->state->data_file_length+
2509 (share->options & HA_OPTION_COMPRESS_RECORD ?
2510 MEMMAP_EXTRA_MARGIN : 0);
2512 if (share->data_file_type == STATIC_RECORD &&
2513 skr < share->base.reloc*share->base.min_pack_length)
2514 skr=share->base.reloc*share->base.min_pack_length;
2516 if (skr != sort_info.filelength)
2518 mi_check_print_warning(param,
2519 "Can't change size of datafile, error: %d",
2522 if (param->testflag & T_CALC_CHECKSUM)
2523 info->state->checksum=param->glob_crc;
2526 mi_check_print_warning(param,
2527 "Can't change size of indexfile, error: %d",
2530 if (!(param->testflag & T_SILENT))
2532 if (start_records != info->state->records)
2533 printf(
"Data records: %s\n", llstr(info->state->records,llbuff));
2535 mi_check_print_warning(param,
2536 "%s records have been removed",
2537 llstr(sort_info.dupp,llbuff));
2541 if (&share->state.state != info->state)
2542 memcpy( &share->state.state, info->state,
sizeof(*info->state));
2545 got_error|= flush_blocks(param, share->key_cache, share->kfile);
2546 (void) end_io_cache(&info->rec_cache);
2553 info->dfile=new_file= -1;
2554 if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, DATA_TMP_EXT,
2555 (param->testflag & T_BACKUP_DATA ?
2556 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
2557 mi_open_datafile(info,share,name,-1))
2563 if (! param->error_printed)
2564 mi_check_print_error(param,
"%d when fixing table",my_errno);
2569 param->temp_filename, MYF(MY_WME));
2570 if (info->dfile == new_file)
2571 if (unlikely(mi_open_datafile(info, share, name, -1)))
2572 param->retry_repair= 0;
2574 mi_mark_crashed_on_repair(info);
2576 else if (
key_map == share->state.key_map)
2577 share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2578 share->state.changed|=STATE_NOT_SORTED_PAGES;
2580 my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff));
2581 my_free(mi_get_rec_buff_ptr(info, sort_param.record));
2582 my_free(sort_info.key_block);
2583 my_free(sort_info.ft_buf);
2584 my_free(sort_info.buff);
2585 (void) end_io_cache(¶m->read_cache);
2586 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2587 if (!got_error && (param->testflag & T_UNPACK))
2589 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2590 share->pack.header_length=0;
2592 DBUG_RETURN(got_error);
2638 const char * name,
int rep_quick)
2641 uint
i,key, total_key_length, istep;
2643 ha_rows start_records;
2644 my_off_t new_header_length,del;
2648 ulong *rec_per_key_part;
2654 ulonglong UNINIT_VAR(
key_map);
2655 pthread_attr_t thr_attr;
2656 ulong max_pack_reclength;
2658 DBUG_ENTER(
"mi_repair_parallel");
2660 start_records=info->state->records;
2663 new_header_length=(param->testflag & T_UNPACK) ? 0 :
2664 share->pack.header_length;
2665 if (!(param->testflag & T_SILENT))
2667 printf(
"- parallel recovering (with sort) MyISAM-table '%s'\n",name);
2668 printf(
"Data records: %s\n", llstr(start_records,llbuff));
2670 param->testflag|=T_REP;
2672 if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2673 param->testflag|=T_CALC_CHECKSUM;
2703 DBUG_PRINT(
"info", (
"is quick repair: %d", rep_quick));
2704 memset(&sort_info, 0,
sizeof(sort_info));
2707 &sort_info.mutex, MY_MUTEX_INIT_FAST);
2710 ¶m->print_msg_mutex, MY_MUTEX_INIT_FAST);
2711 param->need_print_msg_lock= 1;
2713 if (!(sort_info.key_block=
2714 alloc_key_blocks(param, (uint) param->sort_key_blocks,
2715 share->base.max_key_block_length)) ||
2716 init_io_cache(¶m->read_cache, info->dfile,
2717 (uint) param->read_buffer_length,
2718 READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)) ||
2720 (init_io_cache(&info->rec_cache, info->dfile,
2721 (uint) param->write_buffer_length,
2722 WRITE_CACHE, new_header_length, 1,
2723 MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw) ||
2724 init_io_cache(&new_data_cache, -1,
2725 (uint) param->write_buffer_length,
2726 READ_CACHE, new_header_length, 1,
2727 MYF(MY_WME | MY_DONT_CHECK_FILESIZE)))))
2729 sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks;
2730 info->opt_flag|=WRITE_CACHE_USED;
2731 info->rec_cache.file=info->dfile;
2737 fn_format(param->temp_filename,
2738 share->data_file_name,
"",
2740 0, param->tmpfile_createflag,
2743 mi_check_print_error(param,
"Can't create new tempfile: '%s'",
2744 param->temp_filename);
2747 if (new_header_length &&
2748 filecopy(param, new_file,info->dfile,0L,new_header_length,
2751 if (param->testflag & T_UNPACK)
2753 share->options&= ~HA_OPTION_COMPRESS_RECORD;
2754 mi_int2store(share->state.header.options,share->options);
2756 share->state.dellink= HA_OFFSET_ERROR;
2757 info->rec_cache.file=new_file;
2760 info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2763 mi_drop_all_indexes(param, info, FALSE);
2764 key_map= share->state.key_map;
2765 if (param->testflag & T_CREATE_MISSING_KEYS)
2771 sort_info.info=info;
2772 sort_info.param = param;
2774 set_data_file_type(&sort_info, share);
2777 param->read_cache.end_of_file=sort_info.filelength=
2780 if (share->data_file_type == DYNAMIC_RECORD)
2781 rec_length= MY_MAX(share->base.min_pack_length + 1, share->base.min_block_length);
2782 else if (share->data_file_type == COMPRESSED_RECORD)
2783 rec_length=share->base.min_block_length;
2785 rec_length=share->base.pack_reclength;
2798 sort_info.max_records=
2799 ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records + 1:
2800 (ha_rows) (sort_info.filelength/rec_length+1));
2802 del=info->state->del;
2805 max_pack_reclength= share->base.pack_reclength;
2806 if (share->options & HA_OPTION_COMPRESS_RECORD)
2807 set_if_bigger(max_pack_reclength, share->max_pack_length);
2809 my_malloc((uint) share->base.keys *
2813 mi_check_print_error(param,
"Not enough memory for key!");
2817 rec_per_key_part= param->rec_per_key_part;
2818 info->state->records=info->state->del=share->state.split=0;
2819 info->state->empty=0;
2821 for (i=key=0, istep=1 ; key < share->base.keys ;
2822 rec_per_key_part+=sort_param[
i].keyinfo->keysegs, i+=istep, key++)
2824 sort_param[
i].key=key;
2825 sort_param[
i].keyinfo=share->keyinfo+key;
2826 sort_param[
i].seg=sort_param[
i].keyinfo->seg;
2831 if (! mi_is_key_active(
key_map, key))
2834 memcpy((
char*) rec_per_key_part,
2835 (
char*) (share->state.rec_per_key_part+
2836 (uint) (rec_per_key_part - param->rec_per_key_part)),
2837 sort_param[i].keyinfo->keysegs*
sizeof(*rec_per_key_part));
2842 if ((!(param->testflag & T_SILENT)))
2843 printf (
"- Fixing index %d\n",key+1);
2844 if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
2846 sort_param[
i].key_read=sort_ft_key_read;
2847 sort_param[
i].key_write=sort_ft_key_write;
2851 sort_param[
i].key_read=sort_key_read;
2852 sort_param[
i].key_write=sort_key_write;
2854 sort_param[
i].key_cmp=sort_key_cmp;
2855 sort_param[
i].lock_in_memory=lock_memory;
2856 sort_param[
i].tmpdir=param->tmpdir;
2857 sort_param[
i].sort_info=&sort_info;
2858 sort_param[
i].master=0;
2859 sort_param[
i].fix_datafile=0;
2860 sort_param[
i].calc_checksum= 0;
2862 sort_param[
i].filepos=new_header_length;
2863 sort_param[
i].max_pos=sort_param[
i].pos=share->pack.header_length;
2865 sort_param[
i].record= (((uchar *)(sort_param+share->base.keys))+
2866 (max_pack_reclength * i));
2867 if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2869 mi_check_print_error(param,
"Not enough memory!");
2873 sort_param[
i].key_length=share->rec_reflength;
2874 for (keyseg=sort_param[i].seg; keyseg->type != HA_KEYTYPE_END;
2877 sort_param[
i].key_length+=keyseg->length;
2878 if (keyseg->flag & HA_SPACE_PACK)
2879 sort_param[
i].key_length+=get_pack_length(keyseg->length);
2880 if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
2881 sort_param[
i].key_length+=2 +
test(keyseg->length >= 127);
2882 if (keyseg->flag & HA_NULL_PART)
2883 sort_param[
i].key_length++;
2885 total_key_length+=sort_param[
i].key_length;
2887 if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
2889 uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
2890 sort_param[
i].keyinfo->seg->charset->mbmaxlen;
2891 sort_param[
i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
2892 init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
2895 sort_info.total_keys=
i;
2896 sort_param[0].master= 1;
2897 sort_param[0].fix_datafile= (my_bool)(! rep_quick);
2898 sort_param[0].calc_checksum=
test(param->testflag & T_CALC_CHECKSUM);
2900 if (!ftparser_alloc_param(info))
2903 sort_info.got_error=0;
2915 init_io_cache_share(¶m->read_cache, &io_share, NULL, i);
2917 init_io_cache_share(&new_data_cache, &io_share, &info->rec_cache, i);
2920 io_share.total_threads= 0;
2922 (void) pthread_attr_init(&thr_attr);
2923 (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
2925 for (i=0 ; i < sort_info.total_keys ; i++)
2935 sort_param[
i].read_cache= ((rep_quick || !
i) ? param->read_cache :
2937 DBUG_PRINT(
"io_cache_share", (
"thread: %u read_cache: 0x%lx",
2938 i, (
long) &sort_param[i].read_cache));
2946 sort_param[
i].sortbuff_size=
2947 #ifndef USING_SECOND_APPROACH
2948 param->sort_buffer_length/sort_info.total_keys;
2950 param->sort_buffer_length*sort_param[
i].key_length/total_key_length;
2953 &sort_param[i].
thr, &thr_attr,
2955 (
void *) (sort_param+i))))
2957 mi_check_print_error(param,
"Cannot start a repair thread (errno= %d)",
2960 if (io_share.total_threads)
2961 remove_io_thread(&sort_param[i].read_cache);
2962 DBUG_PRINT(
"error", (
"Cannot start a repair thread"));
2963 sort_info.got_error=1;
2966 sort_info.threads_running++;
2968 (void) pthread_attr_destroy(&thr_attr);
2971 while (sort_info.threads_running)
2975 if ((got_error= thr_write_keys(sort_param)))
2977 param->retry_repair=1;
2982 if (sort_param[0].fix_datafile)
2989 if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache))
2991 if (param->testflag & T_SAFE_REPAIR)
2994 if (info->state->records+1 < start_records)
2996 info->state->records=start_records;
3000 share->state.state.data_file_length= info->state->data_file_length=
3001 sort_param->filepos;
3003 share->state.version=(ulong) time((time_t*) 0);
3010 info->dfile=new_file;
3012 share->data_file_type=sort_info.new_data_file_type;
3013 share->pack.header_length=(ulong) new_header_length;
3016 info->state->data_file_length=sort_param->max_pos;
3018 if (rep_quick && del+sort_info.dupp != info->state->del)
3020 mi_check_print_error(param,
"Couldn't fix table with quick recovery: Found wrong number of deleted records");
3021 mi_check_print_error(param,
"Run recovery again without -q");
3022 param->retry_repair=1;
3023 param->testflag|=T_RETRY_WITHOUT_QUICK;
3027 if (rep_quick & T_FORCE_UNIQUENESS)
3029 my_off_t skr=info->state->data_file_length+
3030 (share->options & HA_OPTION_COMPRESS_RECORD ?
3031 MEMMAP_EXTRA_MARGIN : 0);
3033 if (share->data_file_type == STATIC_RECORD &&
3034 skr < share->base.reloc*share->base.min_pack_length)
3035 skr=share->base.reloc*share->base.min_pack_length;
3037 if (skr != sort_info.filelength)
3039 mi_check_print_warning(param,
3040 "Can't change size of datafile, error: %d",
3043 if (param->testflag & T_CALC_CHECKSUM)
3044 info->state->checksum=param->glob_crc;
3047 mi_check_print_warning(param,
3048 "Can't change size of indexfile, error: %d", my_errno);
3050 if (!(param->testflag & T_SILENT))
3052 if (start_records != info->state->records)
3053 printf(
"Data records: %s\n", llstr(info->state->records,llbuff));
3055 mi_check_print_warning(param,
3056 "%s records have been removed",
3057 llstr(sort_info.dupp,llbuff));
3061 if (&share->state.state != info->state)
3062 memcpy(&share->state.state, info->state,
sizeof(*info->state));
3065 got_error|= flush_blocks(param, share->key_cache, share->kfile);
3071 (void) end_io_cache(&info->rec_cache);
3079 (void) end_io_cache(&new_data_cache);
3086 info->dfile=new_file= -1;
3087 if (change_to_newfile(share->data_file_name, MI_NAME_DEXT, DATA_TMP_EXT,
3088 (param->testflag & T_BACKUP_DATA ?
3089 MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
3090 mi_open_datafile(info,share,name,-1))
3096 if (! param->error_printed)
3097 mi_check_print_error(param,
"%d when fixing table",my_errno);
3102 param->temp_filename, MYF(MY_WME));
3103 if (info->dfile == new_file)
3104 if (unlikely(mi_open_datafile(info, share, name, -1)))
3105 param->retry_repair= 0;
3107 mi_mark_crashed_on_repair(info);
3109 else if (
key_map == share->state.key_map)
3110 share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
3111 share->state.changed|=STATE_NOT_SORTED_PAGES;
3116 param->need_print_msg_lock= 0;
3118 my_free(sort_info.ft_buf);
3119 my_free(sort_info.key_block);
3120 my_free(sort_param);
3121 my_free(sort_info.buff);
3122 (void) end_io_cache(¶m->read_cache);
3123 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
3124 if (!got_error && (param->testflag & T_UNPACK))
3126 share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
3127 share->pack.header_length=0;
3129 DBUG_RETURN(got_error);
3134 static int sort_key_read(
MI_SORT_PARAM *sort_param,
void *key)
3137 SORT_INFO *sort_info=sort_param->sort_info;
3138 MI_INFO *info=sort_info->info;
3139 DBUG_ENTER(
"sort_key_read");
3141 if ((error=sort_get_next_record(sort_param)))
3143 if (info->state->records == sort_info->max_records)
3145 mi_check_print_error(sort_info->param,
3146 "Key %d - Found too many records; Can't continue",
3150 sort_param->real_key_length=
3151 (info->s->rec_reflength+
3152 _mi_make_key(info, sort_param->key, (uchar*) key,
3153 sort_param->record, sort_param->filepos));
3155 memset(key+sort_param->real_key_length, 0,
3156 (sort_param->key_length-sort_param->real_key_length));
3158 DBUG_RETURN(sort_write_record(sort_param));
3161 static int sort_ft_key_read(
MI_SORT_PARAM *sort_param,
void *key)
3164 SORT_INFO *sort_info=sort_param->sort_info;
3165 MI_INFO *info=sort_info->info;
3167 DBUG_ENTER(
"sort_ft_key_read");
3169 if (!sort_param->wordlist)
3173 free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
3174 if ((error=sort_get_next_record(sort_param)))
3176 if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record,
3177 &sort_param->wordroot)))
3181 error=sort_write_record(sort_param);
3183 sort_param->wordptr=sort_param->wordlist=wptr;
3188 wptr=(
FT_WORD*)(sort_param->wordptr);
3191 sort_param->real_key_length=(info->s->rec_reflength+
3192 _ft_make_key(info, sort_param->key,
3193 key, wptr++, sort_param->filepos));
3195 if (sort_param->key_length > sort_param->real_key_length)
3196 memset(key+sort_param->real_key_length, 0,
3197 (sort_param->key_length-sort_param->real_key_length));
3201 free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
3202 sort_param->wordlist=0;
3203 error=sort_write_record(sort_param);
3206 sort_param->wordptr=(
void*)wptr;
3247 uint found_record,b_type,left_length;
3249 uchar *UNINIT_VAR(to);
3251 SORT_INFO *sort_info=sort_param->sort_info;
3253 MI_INFO *info=sort_info->info;
3255 char llbuff[22],llbuff2[22];
3256 DBUG_ENTER(
"sort_get_next_record");
3258 if (*killed_ptr(param))
3261 switch (share->data_file_type) {
3265 if (my_b_read(&sort_param->read_cache,sort_param->record,
3266 share->base.pack_reclength))
3268 if (sort_param->read_cache.error)
3269 param->out_flag |= O_DATA_LOST;
3270 param->retry_repair=1;
3271 param->testflag|=T_RETRY_WITHOUT_QUICK;
3274 sort_param->start_recpos=sort_param->pos;
3275 if (!sort_param->fix_datafile)
3277 sort_param->filepos=sort_param->pos;
3278 if (sort_param->master)
3279 share->state.split++;
3281 sort_param->max_pos=(sort_param->pos+=share->base.pack_reclength);
3282 if (*sort_param->record)
3284 if (sort_param->calc_checksum)
3285 param->glob_crc+= (info->checksum=
3286 mi_static_checksum(info,sort_param->record));
3289 if (!sort_param->fix_datafile && sort_param->master)
3292 info->state->empty+=share->base.pack_reclength;
3295 case DYNAMIC_RECORD:
3297 pos=sort_param->pos;
3298 searching=(sort_param->fix_datafile && (param->testflag & T_EXTEND));
3299 parallel_flag= (sort_param->read_cache.file < 0) ? READING_NEXT : 0;
3302 found_record=block_info.second_read= 0;
3306 pos=MY_ALIGN(pos,MI_DYN_ALIGN_SIZE);
3307 param->testflag|=T_RETRY_WITHOUT_QUICK;
3308 sort_param->start_recpos=pos;
3312 if (pos > sort_param->max_pos)
3313 sort_param->max_pos=pos;
3314 if (pos & (MI_DYN_ALIGN_SIZE-1))
3316 if ((param->testflag & T_VERBOSE) || searching == 0)
3317 mi_check_print_info(param,
"Wrong aligned block at %s",
3322 if (found_record && pos == param->search_after_block)
3323 mi_check_print_info(param,
"Block: %s used by record at %s",
3324 llstr(param->search_after_block,llbuff),
3325 llstr(sort_param->start_recpos,llbuff2));
3326 if (_mi_read_cache(&sort_param->read_cache,
3327 (uchar*) block_info.header,pos,
3328 MI_BLOCK_INFO_HEADER_LENGTH,
3329 (! found_record ? READING_NEXT : 0) |
3330 parallel_flag | READING_HEADER))
3334 mi_check_print_info(param,
3335 "Can't read whole record at %s (errno: %d)",
3336 llstr(sort_param->start_recpos,llbuff),errno);
3341 if (searching && ! sort_param->fix_datafile)
3343 param->error_printed=1;
3344 param->retry_repair=1;
3345 param->testflag|=T_RETRY_WITHOUT_QUICK;
3348 b_type=_mi_get_block_info(&block_info,-1,pos);
3349 if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3350 ((b_type & BLOCK_FIRST) &&
3351 (block_info.rec_len < (uint) share->base.min_pack_length ||
3352 block_info.rec_len > (uint) share->base.max_pack_length)))
3355 if (param->testflag & T_VERBOSE || searching == 0)
3356 mi_check_print_info(param,
3357 "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3358 block_info.header[0],block_info.header[1],
3359 block_info.header[2],llstr(pos,llbuff));
3362 block_info.second_read=0;
3365 for (i=MI_DYN_ALIGN_SIZE ;
3366 i < MI_BLOCK_INFO_HEADER_LENGTH ;
3367 i+= MI_DYN_ALIGN_SIZE)
3368 if (block_info.header[i] >= 1 &&
3369 block_info.header[i] <= MI_MAX_DYN_HEADER_BYTE)
3372 sort_param->start_recpos=pos;
3375 if (b_type & BLOCK_DELETED)
3378 if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3379 share->base.min_block_length)
3382 mi_check_print_info(param,
3383 "Deleted block with impossible length %u at %s",
3384 block_info.block_len,llstr(pos,llbuff));
3389 if ((block_info.next_filepos != HA_OFFSET_ERROR &&
3390 block_info.next_filepos >=
3391 info->state->data_file_length) ||
3392 (block_info.prev_filepos != HA_OFFSET_ERROR &&
3393 block_info.prev_filepos >= info->state->data_file_length))
3396 mi_check_print_info(param,
3397 "Delete link points outside datafile at %s",
3407 pos+= MI_DYN_ALIGN_SIZE;
3408 sort_param->start_recpos=pos;
3409 block_info.second_read=0;
3415 if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3416 share->base.min_block_length ||
3417 block_info.block_len > (uint) share->base.max_pack_length+
3421 mi_check_print_info(param,
3422 "Found block with impossible length %u at %s; Skipped",
3423 block_info.block_len+ (uint) (block_info.filepos-pos),
3428 pos+= MI_DYN_ALIGN_SIZE;
3429 sort_param->start_recpos=pos;
3430 block_info.second_read=0;
3434 if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
3436 if (!sort_param->fix_datafile && sort_param->master &&
3437 (b_type & BLOCK_DELETED))
3439 info->state->empty+=block_info.block_len;
3441 share->state.split++;
3447 pos+=MI_DYN_ALIGN_SIZE;
3448 sort_param->start_recpos=pos;
3451 pos=block_info.filepos+block_info.block_len;
3452 block_info.second_read=0;
3456 if (!sort_param->fix_datafile && sort_param->master)
3457 share->state.split++;
3458 if (! found_record++)
3460 sort_param->find_length=left_length=block_info.rec_len;
3461 sort_param->start_recpos=pos;
3462 if (!sort_param->fix_datafile)
3463 sort_param->filepos=sort_param->start_recpos;
3464 if (sort_param->fix_datafile && (param->testflag & T_EXTEND))
3465 sort_param->pos=block_info.filepos+1;
3467 sort_param->pos=block_info.filepos+block_info.block_len;
3468 if (share->base.blobs)
3470 if (!(to=mi_alloc_rec_buff(info,block_info.rec_len,
3471 &(sort_param->rec_buff))))
3473 if (param->max_record_length >= block_info.rec_len)
3475 mi_check_print_error(param,
"Not enough memory for blob at %s (need %lu)",
3476 llstr(sort_param->start_recpos,llbuff),
3477 (ulong) block_info.rec_len);
3482 mi_check_print_info(param,
"Not enough memory for blob at %s (need %lu); Row skipped",
3483 llstr(sort_param->start_recpos,llbuff),
3484 (ulong) block_info.rec_len);
3490 to= sort_param->rec_buff;
3492 if (left_length < block_info.data_len || ! block_info.data_len)
3494 mi_check_print_info(param,
3495 "Found block with too small length at %s; Skipped",
3496 llstr(sort_param->start_recpos,llbuff));
3499 if (block_info.filepos + block_info.data_len >
3500 sort_param->read_cache.end_of_file)
3502 mi_check_print_info(param,
3503 "Found block that points outside data file at %s",
3504 llstr(sort_param->start_recpos,llbuff));
3513 uint header_len= (uint) (block_info.filepos - pos);
3514 uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3516 if (prefetch_len > block_info.data_len)
3517 prefetch_len= block_info.data_len;
3520 memcpy(to, block_info.header + header_len, prefetch_len);
3521 block_info.filepos+= prefetch_len;
3522 block_info.data_len-= prefetch_len;
3523 left_length-= prefetch_len;
3527 if (block_info.data_len &&
3528 _mi_read_cache(&sort_param->read_cache,to,block_info.filepos,
3529 block_info.data_len,
3530 (found_record == 1 ? READING_NEXT : 0) |
3533 mi_check_print_info(param,
3534 "Read error for block at: %s (error: %d); Skipped",
3535 llstr(block_info.filepos,llbuff),my_errno);
3538 left_length-=block_info.data_len;
3539 to+=block_info.data_len;
3540 pos=block_info.next_filepos;
3541 if (pos == HA_OFFSET_ERROR && left_length)
3543 mi_check_print_info(param,
"Wrong block with wrong total length starting at %s",
3544 llstr(sort_param->start_recpos,llbuff));
3547 if (pos + MI_BLOCK_INFO_HEADER_LENGTH > sort_param->read_cache.end_of_file)
3549 mi_check_print_info(param,
"Found link that points at %s (outside data file) at %s",
3551 llstr(sort_param->start_recpos,llbuff));
3554 }
while (left_length);
3556 if (_mi_rec_unpack(info,sort_param->record,sort_param->rec_buff,
3557 sort_param->find_length) != MY_FILE_ERROR)
3559 if (sort_param->read_cache.error < 0)
3561 if (sort_param->calc_checksum)
3562 info->checksum= mi_checksum(info, sort_param->record);
3563 if ((param->testflag & (T_EXTEND | T_REP)) || searching)
3565 if (_mi_rec_check(info, sort_param->record, sort_param->rec_buff,
3566 sort_param->find_length,
3567 (param->testflag & T_QUICK) &&
3568 sort_param->calc_checksum &&
3569 test(info->s->calc_checksum)))
3571 mi_check_print_info(param,
"Found wrong packed record at %s",
3572 llstr(sort_param->start_recpos,llbuff));
3576 if (sort_param->calc_checksum)
3577 param->glob_crc+= info->checksum;
3581 mi_check_print_info(param,
"Key %d - Found wrong stored record at %s",
3583 llstr(sort_param->start_recpos,llbuff));
3585 pos=(sort_param->start_recpos+=MI_DYN_ALIGN_SIZE);
3588 case COMPRESSED_RECORD:
3589 for (searching=0 ;; searching=1, sort_param->pos++)
3591 if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
3593 share->pack.ref_length,READING_NEXT))
3595 if (searching && ! sort_param->fix_datafile)
3597 param->error_printed=1;
3598 param->retry_repair=1;
3599 param->testflag|=T_RETRY_WITHOUT_QUICK;
3602 sort_param->start_recpos=sort_param->pos;
3603 if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
3604 &sort_param->rec_buff, -1, sort_param->pos))
3606 if (!block_info.rec_len &&
3607 sort_param->pos + MEMMAP_EXTRA_MARGIN ==
3608 sort_param->read_cache.end_of_file)
3610 if (block_info.rec_len < (uint) share->min_pack_length ||
3611 block_info.rec_len > (uint) share->max_pack_length)
3614 mi_check_print_info(param,
"Found block with wrong recordlength: %d at %s\n",
3616 llstr(sort_param->pos,llbuff));
3619 if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
3620 block_info.filepos, block_info.rec_len,
3624 mi_check_print_info(param,
"Couldn't read whole record from %s",
3625 llstr(sort_param->pos,llbuff));
3628 if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
3629 sort_param->rec_buff, block_info.rec_len))
3632 mi_check_print_info(param,
"Found wrong record at %s",
3633 llstr(sort_param->pos,llbuff));
3636 if (!sort_param->fix_datafile)
3638 sort_param->filepos=sort_param->pos;
3639 if (sort_param->master)
3640 share->state.split++;
3642 sort_param->max_pos=(sort_param->pos=block_info.filepos+
3643 block_info.rec_len);
3644 info->packed_length=block_info.rec_len;
3645 if (sort_param->calc_checksum)
3646 param->glob_crc+= (info->checksum=
3647 mi_checksum(info, sort_param->record));
3676 ulong block_length,reclength;
3678 uchar block_buff[8];
3679 SORT_INFO *sort_info=sort_param->sort_info;
3681 MI_INFO *info=sort_info->info;
3683 DBUG_ENTER(
"sort_write_record");
3685 if (sort_param->fix_datafile)
3687 switch (sort_info->new_data_file_type) {
3689 if (my_b_write(&info->rec_cache,sort_param->record,
3690 share->base.pack_reclength))
3692 mi_check_print_error(param,
"%d when writing to datafile",my_errno);
3695 sort_param->filepos+=share->base.pack_reclength;
3696 info->s->state.split++;
3699 case DYNAMIC_RECORD:
3701 from=sort_param->rec_buff;
3705 reclength=info->s->base.pack_reclength+
3706 _my_calc_total_blob_length(info,sort_param->record)+
3707 ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
3708 MI_DYN_DELETE_BLOCK_HEADER;
3709 if (sort_info->buff_length < reclength)
3711 if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3712 MYF(MY_FREE_ON_ERROR |
3713 MY_ALLOW_ZERO_PTR))))
3715 sort_info->buff_length=reclength;
3717 from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3720 info->checksum=mi_checksum(info,sort_param->record);
3721 reclength=_mi_rec_pack(info,from,sort_param->record);
3727 block_length=reclength+ 3 +
test(reclength >= (65520-3));
3728 if (block_length < share->base.min_block_length)
3729 block_length=share->base.min_block_length;
3730 info->update|=HA_STATE_WRITE_AT_END;
3731 block_length=MY_ALIGN(block_length,MI_DYN_ALIGN_SIZE);
3732 if (block_length > MI_MAX_BLOCK_LENGTH)
3733 block_length=MI_MAX_BLOCK_LENGTH;
3734 if (_mi_write_part_record(info,0L,block_length,
3735 sort_param->filepos+block_length,
3736 &from,&reclength,&flag))
3738 mi_check_print_error(param,
"%d when writing to datafile",my_errno);
3741 sort_param->filepos+=block_length;
3742 info->s->state.split++;
3743 }
while (reclength);
3746 case COMPRESSED_RECORD:
3747 reclength=info->packed_length;
3748 length= save_pack_length((uint) share->pack.version, block_buff,
3750 if (info->s->base.blobs)
3751 length+= save_pack_length((uint) share->pack.version,
3752 block_buff + length, info->blob_length);
3753 if (my_b_write(&info->rec_cache,block_buff,length) ||
3754 my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
3756 mi_check_print_error(param,
"%d when writing to datafile",my_errno);
3760 sort_param->filepos+=reclength+length;
3761 info->s->state.split++;
3767 if (sort_param->master)
3769 info->state->records++;
3770 if ((param->testflag & T_WRITE_LOOP) &&
3771 (info->state->records % WRITE_COUNT) == 0)
3774 printf(
"%s\r", llstr(info->state->records,llbuff));
3775 (void) fflush(stdout);
3784 static int sort_key_cmp(
MI_SORT_PARAM *sort_param,
const void *a,
3788 return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3789 USE_WHOLE_KEY, SEARCH_SAME, not_used));
3793 static int sort_key_write(
MI_SORT_PARAM *sort_param,
const void *a)
3796 char llbuff[22],llbuff2[22];
3797 SORT_INFO *sort_info=sort_param->sort_info;
3801 if (sort_info->key_block->inited)
3803 cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3804 (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3806 if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3807 ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3808 (uchar*) a, USE_WHOLE_KEY,
3809 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3810 else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3812 diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3813 sort_param->notnull,
3814 sort_info->key_block->lastkey,
3817 sort_param->unique[diff_pos[0]-1]++;
3822 if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3823 mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3826 if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3829 sort_info->info->lastpos=get_record_for_key(sort_info->info,
3830 sort_param->keyinfo,
3832 mi_check_print_warning(param,
3833 "Duplicate key for record at %10s against record at %10s",
3834 llstr(sort_info->info->lastpos,llbuff),
3835 llstr(get_record_for_key(sort_info->info,
3836 sort_param->keyinfo,
3837 sort_info->key_block->
3840 param->testflag|=T_RETRY_WITHOUT_QUICK;
3841 if (sort_info->param->testflag & T_VERBOSE)
3842 _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3843 return (sort_delete_record(sort_param));
3848 mi_check_print_error(param,
3849 "Internal error: Keys are not in order from sort");
3853 return (sort_insert_key(sort_param,sort_info->key_block,
3854 (uchar*) a, HA_OFFSET_ERROR));
3859 SORT_INFO *sort_info=sort_param->sort_info;
3862 uint val_off, val_len;
3867 val_len=share->ft2_keyinfo.keylength;
3868 get_key_full_length_rdonly(val_off, ft_buf->lastkey);
3869 to=ft_buf->lastkey+val_off;
3874 error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
3876 for (from=to+val_len;
3877 !error && from < ft_buf->buf;
3880 memcpy(to, from, val_len);
3881 error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
3887 error=flush_pending_blocks(sort_param);
3889 ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count);
3890 _mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN,
3891 share->state.key_root[sort_param->key]);
3893 sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
3894 sort_param->keyinfo=share->keyinfo+sort_param->key;
3895 share->state.key_root[sort_param->key]=HA_OFFSET_ERROR;
3897 return error ? error :
3898 sort_insert_key(sort_param,sort_info->key_block,
3899 ft_buf->lastkey,HA_OFFSET_ERROR);
3902 static int sort_ft_key_write(
MI_SORT_PARAM *sort_param,
const void *a)
3904 uint a_len, val_off, val_len, error;
3906 SORT_INFO *sort_info=sort_param->sort_info;
3910 val_len= HA_FT_WLEN + sort_info->info->s->rec_reflength;
3911 get_key_full_length_rdonly(a_len, (uchar *)a);
3919 if ((sort_info->info->s->base.key_reflength <=
3920 sort_info->info->s->rec_reflength) &&
3921 (sort_info->info->s->options &
3922 (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
3923 ft_buf=(
SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
3928 sort_param->key_write=sort_key_write;
3929 return sort_key_write(sort_param, a);
3931 sort_info->ft_buf=ft_buf;
3932 goto word_init_ft_buf;
3934 get_key_full_length_rdonly(val_off, ft_buf->lastkey);
3936 if (ha_compare_text(sort_param->seg->charset,
3937 ((uchar *)a)+1,a_len-1,
3938 ft_buf->lastkey+1,val_off-1, 0, 0)==0)
3943 return sort_insert_key(sort_param,key_block,
3944 ((uchar *)a)+a_len, HA_OFFSET_ERROR);
3948 memcpy (ft_buf->buf, (
char *)a+a_len, val_len);
3949 ft_buf->buf+=val_len;
3950 if (ft_buf->buf < ft_buf->end)
3954 p=ft_buf->lastkey+val_off;
3956 while (key_block->inited)
3958 sort_info->key_block=key_block;
3959 sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo;
3960 ft_buf->count=(uint) (ft_buf->buf - p)/val_len;
3963 for (error=0; !error && p < ft_buf->buf; p+= val_len)
3964 error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR);
3970 if ((error=sort_ft_buf_flush(sort_param)))
3975 memcpy(ft_buf->lastkey, a, a_len);
3976 ft_buf->buf=ft_buf->lastkey+a_len;
3985 ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
3995 return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
4003 my_off_t prev_block)
4005 uint a_length,t_length,nod_flag;
4006 my_off_t filepos,key_file_length;
4007 uchar *anc_buff,*lastkey;
4011 SORT_INFO *sort_info= sort_param->sort_info;
4013 DBUG_ENTER(
"sort_insert_key");
4015 anc_buff=key_block->buff;
4016 info=sort_info->info;
4017 lastkey=key_block->lastkey;
4018 nod_flag= (key_block == sort_info->key_block ? 0 :
4019 info->s->base.key_reflength);
4021 if (!key_block->inited)
4023 key_block->inited=1;
4024 if (key_block == sort_info->key_block_end)
4026 mi_check_print_error(param,
"To many key-block-levels; Try increasing sort_key_blocks");
4029 a_length=2+nod_flag;
4030 key_block->end_pos=anc_buff+2;
4034 a_length=mi_getint(anc_buff);
4038 _mi_kpointer(info,key_block->end_pos,prev_block);
4040 t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
4041 (uchar*) 0,lastkey,lastkey,key,
4043 (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
4045 mi_putint(anc_buff,a_length,nod_flag);
4046 key_block->end_pos+=t_length;
4047 if (a_length <= keyinfo->block_length)
4049 (void) _mi_move_key(keyinfo,key_block->lastkey,key);
4050 key_block->last_length=a_length-t_length;
4055 mi_putint(anc_buff,key_block->last_length,nod_flag);
4056 memset(anc_buff+key_block->last_length, 0,
4057 keyinfo->block_length - key_block->last_length);
4058 key_file_length=info->state->key_file_length;
4059 if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
4063 if (key_file_length == info->state->key_file_length)
4065 if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
4069 (uint) keyinfo->block_length, filepos,
4072 DBUG_DUMP(
"buff",(uchar*) anc_buff,mi_getint(anc_buff));
4075 if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
4079 key_block->inited=0;
4080 DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
4091 SORT_INFO *sort_info=sort_param->sort_info;
4093 MI_INFO *info=sort_info->info;
4094 DBUG_ENTER(
"sort_delete_record");
4096 if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
4098 mi_check_print_error(param,
4099 "Quick-recover aborted; Run recovery without switch -q or with switch -qq");
4102 if (info->s->options & HA_OPTION_COMPRESS_RECORD)
4104 mi_check_print_error(param,
4105 "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'myisamchk --safe-recover' to fix it\n",stderr);;
4109 old_file=info->dfile;
4110 info->dfile=info->rec_cache.file;
4111 if (sort_info->current_key)
4113 key=info->lastkey+info->s->base.max_key_length;
4114 if ((error=(*info->s->read_rnd)(info,sort_param->record,info->lastpos,0)) &&
4115 error != HA_ERR_RECORD_DELETED)
4117 mi_check_print_error(param,
"Can't read record to be removed");
4118 info->dfile=old_file;
4122 for (i=0 ; i < sort_info->current_key ; i++)
4124 uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
4125 if (_mi_ck_delete(info,i,key,key_length))
4127 mi_check_print_error(param,
"Can't delete key %d from record to be removed",i+1);
4128 info->dfile=old_file;
4132 if (sort_param->calc_checksum)
4133 param->glob_crc-=(*info->s->calc_checksum)(info, sort_param->record);
4135 error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
4136 info->dfile=old_file;
4137 info->state->records--;
4145 uint nod_flag,length;
4146 my_off_t filepos,key_file_length;
4148 SORT_INFO *sort_info= sort_param->sort_info;
4149 myf myf_rw=sort_info->param->myf_rw;
4150 MI_INFO *info=sort_info->info;
4152 DBUG_ENTER(
"flush_pending_blocks");
4154 filepos= HA_OFFSET_ERROR;
4156 for (key_block=sort_info->key_block ; key_block->inited ; key_block++)
4158 key_block->inited=0;
4159 length=mi_getint(key_block->buff);
4161 _mi_kpointer(info,key_block->end_pos,filepos);
4162 key_file_length=info->state->key_file_length;
4163 memset(key_block->buff+length, 0, keyinfo->block_length-length);
4164 if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
4168 if (key_file_length == info->state->key_file_length)
4170 if (_mi_write_keypage(info, keyinfo, filepos,
4171 DFLT_INIT_HITS, key_block->buff))
4175 (uint) keyinfo->block_length, filepos, myf_rw))
4177 DBUG_DUMP(
"buff",(uchar*) key_block->buff,length);
4180 info->s->state.key_root[sort_param->key]=filepos;
4191 DBUG_ENTER(
"alloc_key_blocks");
4194 buffer_length+IO_SIZE)*blocks,
4197 mi_check_print_error(param,
"Not enough memory for sort-key-blocks");
4200 for (i=0 ; i < blocks ; i++)
4203 block[
i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
4211 int test_if_almost_full(
MI_INFO *info)
4213 if (info->s->options & HA_OPTION_COMPRESS_RECORD)
4216 MYF(MY_THREADSAFE)) / 10 * 9 >
4217 (my_off_t) info->s->base.max_key_file_length ||
4220 (my_off_t) info->s->base.max_data_file_length;
4225 int recreate_table(
MI_CHECK *param,
MI_INFO **org_info,
char *filename)
4235 uint unpack,key_parts;
4236 ha_rows max_records;
4237 ulonglong file_length,tmp_length;
4239 DBUG_ENTER(
"recreate_table");
4243 status_info= (*org_info)->state[0];
4244 info.state= &status_info;
4245 share= *(*org_info)->s;
4246 unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
4247 (param->testflag & T_UNPACK);
4250 memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
4251 (
size_t) (
sizeof(
MI_KEYDEF)*share.base.keys));
4253 key_parts= share.base.all_key_parts;
4255 (key_parts+share.base.keys))))
4257 my_afree((uchar*) keyinfo);
4261 my_alloca(
sizeof(
MI_COLUMNDEF)*(share.base.fields+1))))
4263 my_afree((uchar*) keyinfo);
4264 my_afree((uchar*) keysegs);
4268 my_alloca(
sizeof(
MI_UNIQUEDEF)*(share.state.header.uniques+1))))
4270 my_afree((uchar*) recdef);
4271 my_afree((uchar*) keyinfo);
4272 my_afree((uchar*) keysegs);
4277 memcpy((uchar*) recdef,(uchar*) share.rec,
4278 (
size_t) (
sizeof(
MI_COLUMNDEF)*(share.base.fields+1)));
4279 for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
4281 if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
4282 rec->type != FIELD_BLOB &&
4283 rec->type != FIELD_VARCHAR &&
4284 rec->type != FIELD_CHECK)
4285 rec->type=(int) FIELD_NORMAL;
4289 memcpy((uchar*) keysegs,(uchar*) share.keyparts,
4290 (
size_t) (
sizeof(
HA_KEYSEG)*(key_parts+share.base.keys+
4291 share.state.header.uniques)));
4293 for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
4296 for (; keyseg->type ; keyseg++)
4298 if (param->language)
4299 keyseg->language=param->language;
4306 memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
4307 (
size_t) (
sizeof(
MI_UNIQUEDEF)*(share.state.header.uniques)));
4308 for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
4309 u_ptr != u_end ; u_ptr++)
4312 keyseg+=u_ptr->keysegs+1;
4314 unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
4315 (param->testflag & T_UNPACK);
4316 share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
4318 file_length=(ulonglong)
mysql_file_seek(info.dfile, 0L, MY_SEEK_END, MYF(0));
4319 tmp_length= file_length+file_length/10;
4320 set_if_bigger(file_length,param->max_data_file_length);
4321 set_if_bigger(file_length,tmp_length);
4322 set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
4324 if (share.options & HA_OPTION_COMPRESS_RECORD)
4325 share.base.records= max_records= info.state->records;
4326 else if (!(share.options & HA_OPTION_PACK_RECORD))
4327 max_records= (ha_rows) (file_length / share.base.pack_reclength);
4331 (void) mi_close(*org_info);
4332 memset(&create_info, 0,
sizeof(create_info));
4333 create_info.max_rows= max_records;
4334 create_info.reloc_rows=share.base.reloc;
4335 create_info.old_options=(share.options |
4336 (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
4338 create_info.data_file_length=file_length;
4339 create_info.auto_increment=share.state.auto_increment;
4340 create_info.language = (param->language ? param->language :
4341 share.state.header.language);
4342 create_info.key_file_length= status_info.key_file_length;
4347 create_info.with_auto_increment= TRUE;
4350 if (mi_create(filename,
4351 share.base.keys - share.state.header.uniques,
4352 keyinfo, share.base.fields, recdef,
4353 share.state.header.uniques, uniquedef,
4355 HA_DONT_TOUCH_DATA))
4357 mi_check_print_error(param,
"Got error %d when trying to recreate indexfile",my_errno);
4360 *org_info=mi_open(filename,O_RDWR,
4361 (param->testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
4362 (param->testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
4363 HA_OPEN_ABORT_IF_LOCKED);
4366 mi_check_print_error(param,
"Got error %d when trying to open re-created indexfile",
4371 (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
4372 (void) _mi_readinfo(*org_info,F_WRLCK,0);
4373 (*org_info)->state->records=info.state->records;
4374 if (share.state.create_time)
4375 (*org_info)->s->state.create_time=share.state.create_time;
4376 (*org_info)->s->state.unique=(*org_info)->this_unique=
4378 (*org_info)->state->checksum=info.state->checksum;
4379 (*org_info)->state->del=info.state->del;
4380 (*org_info)->s->state.dellink=share.state.dellink;
4381 (*org_info)->state->empty=info.state->empty;
4382 (*org_info)->state->data_file_length=info.state->data_file_length;
4383 if (update_state_info(param,*org_info,UPDATE_TIME | UPDATE_STAT |
4388 my_afree((uchar*) uniquedef);
4389 my_afree((uchar*) keyinfo);
4390 my_afree((uchar*) recdef);
4391 my_afree((uchar*) keysegs);
4398 int write_data_suffix(
SORT_INFO *sort_info, my_bool fix_datafile)
4400 MI_INFO *info=sort_info->info;
4402 if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
4404 uchar buff[MEMMAP_EXTRA_MARGIN];
4405 memset(buff, 0,
sizeof(buff));
4406 if (my_b_write(&info->rec_cache,buff,
sizeof(buff)))
4408 mi_check_print_error(sort_info->param,
4409 "%d when writing to datafile",my_errno);
4412 sort_info->param->read_cache.end_of_file+=
sizeof(buff);
4423 if (update & UPDATE_OPEN_COUNT)
4425 share->state.open_count=0;
4426 share->global_changed=0;
4428 if (update & UPDATE_STAT)
4430 uint
i, key_parts= mi_uint2korr(share->state.header.key_parts);
4431 share->state.rec_per_key_rows=info->state->records;
4432 share->state.changed&= ~STATE_NOT_ANALYZED;
4433 if (info->state->records)
4435 for (i=0; i<key_parts; i++)
4437 if (!(share->state.rec_per_key_part[i]=param->rec_per_key_part[i]))
4438 share->state.changed|= STATE_NOT_ANALYZED;
4442 if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME | UPDATE_AUTO_INC))
4444 if (update & UPDATE_TIME)
4446 share->state.check_time= (long) time((time_t*) 0);
4447 if (!share->state.create_time)
4448 share->state.create_time=share->state.check_time;
4456 if (info->lock_type == F_WRLCK)
4457 share->state.state= *info->state;
4458 if (mi_state_info_write(share->kfile,&share->state,1+2))
4464 uint r_locks=share->r_locks,w_locks=share->w_locks;
4465 share->r_locks= share->w_locks= share->tot_locks= 0;
4466 error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
4467 share->r_locks=r_locks;
4468 share->w_locks=w_locks;
4469 share->tot_locks=r_locks+w_locks;
4474 mi_check_print_error(param,
"%d when updating keyfile",my_errno);
4492 my_bool repair_only)
4495 DBUG_ENTER(
"update_auto_increment_key");
4497 if (!info->s->base.auto_key ||
4498 ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
4500 if (!(param->testflag & T_VERY_SILENT))
4501 mi_check_print_info(param,
4502 "Table: %s doesn't have an auto increment key\n",
4503 param->isam_file_name);
4506 if (!(param->testflag & T_SILENT) &&
4507 !(param->testflag & T_REP))
4508 printf(
"Updating MyISAM file: %s\n", param->isam_file_name);
4513 if (!mi_alloc_rec_buff(info, -1, &record))
4515 mi_check_print_error(param,
"Not enough memory for extra record");
4519 mi_extra(info,HA_EXTRA_KEYREAD,0);
4520 if (mi_rlast(info, record, info->s->base.auto_key-1))
4522 if (my_errno != HA_ERR_END_OF_FILE)
4524 mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
4525 my_free(mi_get_rec_buff_ptr(info, record));
4526 mi_check_print_error(param,
"%d when reading last record",my_errno);
4530 info->s->state.auto_increment=param->auto_increment_value;
4534 ulonglong auto_increment= retrieve_auto_increment(info, record);
4535 set_if_bigger(info->s->state.auto_increment,auto_increment);
4537 set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
4539 mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
4540 my_free(mi_get_rec_buff_ptr(info, record));
4541 update_state_info(param, info, UPDATE_AUTO_INC);
4597 void update_key_parts(
MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4598 ulonglong *unique, ulonglong *notnull,
4601 ulonglong count=0,tmp, unique_tuples;
4602 ulonglong tuples= records;
4604 for (parts=0 ; parts < keyinfo->keysegs ; parts++)
4606 count+=unique[parts];
4607 unique_tuples= count + 1;
4610 tuples= notnull[parts];
4616 unique_tuples -= (records - notnull[parts]);
4619 if (unique_tuples == 0)
4621 else if (count == 0)
4624 tmp= (tuples + unique_tuples/2) / unique_tuples;
4630 set_if_bigger(tmp,1);
4631 if (tmp >= (ulonglong) ~(ulong) 0)
4632 tmp=(ulonglong) ~(ulong) 0;
4634 *rec_per_key_part=(ulong) tmp;
4640 static ha_checksum mi_byte_checksum(
const uchar *
buf, uint length)
4643 const uchar *end=buf+length;
4644 for (crc=0; buf != end; buf++)
4645 crc=((crc << 1) + *((uchar*) buf)) +
4646 test(crc & (((ha_checksum) 1) << (8*
sizeof(ha_checksum)-1)));
4650 static my_bool mi_too_big_key_for_sort(
MI_KEYDEF *key, ha_rows rows)
4652 uint key_maxlength=key->maxlength;
4653 if (key->flag & HA_FULLTEXT)
4655 uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
4656 key->seg->charset->mbmaxlen;
4657 key_maxlength+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
4659 return (key->flag & HA_SPATIAL) ||
4660 (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
4661 ((ulonglong) rows * key_maxlength > myisam_max_temp_length));
4673 void mi_disable_non_unique_index(
MI_INFO *info, ha_rows rows)
4679 DBUG_ASSERT(info->state->records == 0 &&
4680 (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4681 for (i=0 ; i < share->base.keys ; i++,key++)
4683 if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4684 ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4686 mi_clear_key_active(share->state.key_map, i);
4687 info->update|= HA_STATE_CHANGED;
4699 my_bool mi_test_if_sort_rep(
MI_INFO *info, ha_rows rows,
4700 ulonglong
key_map, my_bool force)
4710 if (! mi_is_any_key_active(key_map))
4712 for (i=0 ; i < share->base.keys ; i++,key++)
4714 if (!force && mi_too_big_key_for_sort(key,rows))
4724 if ((sort_info->new_data_file_type=share->data_file_type) ==
4725 COMPRESSED_RECORD && sort_info->param->testflag & T_UNPACK)
4729 if (share->options & HA_OPTION_PACK_RECORD)
4730 sort_info->new_data_file_type = DYNAMIC_RECORD;
4732 sort_info->new_data_file_type = STATIC_RECORD;
4735 memcpy((
char*) &tmp, share,
sizeof(*share));
4736 tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4737 mi_setup_functions(&tmp);
4738 share->delete_record=tmp.delete_record;
4765 for (; (
enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
4768 if (keyseg->null_bit)
4773 end= a+ keyseg->length;
4775 switch ((
enum ha_base_keytype) keyseg->type) {
4776 case HA_KEYTYPE_TEXT:
4777 case HA_KEYTYPE_BINARY:
4778 case HA_KEYTYPE_BIT:
4779 if (keyseg->flag & HA_SPACE_PACK)
4782 get_key_length(a_length, a);
4789 case HA_KEYTYPE_VARTEXT1:
4790 case HA_KEYTYPE_VARTEXT2:
4791 case HA_KEYTYPE_VARBINARY1:
4792 case HA_KEYTYPE_VARBINARY2:
4795 get_key_length(a_length, a);
4799 case HA_KEYTYPE_NUM:
4800 if (keyseg->flag & HA_SPACE_PACK)
4807 case HA_KEYTYPE_INT8:
4808 case HA_KEYTYPE_SHORT_INT:
4809 case HA_KEYTYPE_USHORT_INT:
4810 case HA_KEYTYPE_LONG_INT:
4811 case HA_KEYTYPE_ULONG_INT:
4812 case HA_KEYTYPE_INT24:
4813 case HA_KEYTYPE_UINT24:
4814 #ifdef HAVE_LONG_LONG
4815 case HA_KEYTYPE_LONGLONG:
4816 case HA_KEYTYPE_ULONGLONG:
4818 case HA_KEYTYPE_FLOAT:
4819 case HA_KEYTYPE_DOUBLE:
4822 case HA_KEYTYPE_END: