61
58
/* Functions defined in this file */
63
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
60
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
64
61
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
65
my_off_t page, unsigned char *buff, ha_rows *keys,
66
ha_checksum *key_checksum, uint32_t level);
67
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
62
my_off_t page, uchar *buff, ha_rows *keys,
63
ha_checksum *key_checksum, uint level);
64
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
68
65
static ha_checksum calc_checksum(ha_rows count);
69
66
static int writekeys(MI_SORT_PARAM *sort_param);
70
67
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
74
71
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
75
72
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
76
73
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
78
75
static int sort_insert_key(MI_SORT_PARAM *sort_param,
79
76
register SORT_KEY_BLOCKS *key_block,
80
unsigned char *key, my_off_t prev_block);
77
uchar *key, my_off_t prev_block);
81
78
static int sort_delete_record(MI_SORT_PARAM *sort_param);
82
79
/*static int flush_pending_blocks(MI_CHECK *param);*/
83
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
84
uint32_t buffer_length);
85
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
80
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
82
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
86
83
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
88
85
void myisamchk_init(MI_CHECK *param)
120
117
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
122
119
/* Don't count this as a real warning, as check can correct this ! */
123
uint32_t save=param->warning_printed;
120
uint save=param->warning_printed;
124
121
mi_check_print_warning(param,
125
122
share->state.open_count==1 ?
126
123
"%d client is using or hasn't closed the table properly" :
136
133
/* Check delete links */
138
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
135
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
140
137
register ha_rows i;
141
uint32_t delete_link_length;
138
uint delete_link_length;
142
139
my_off_t empty, next_link, old_link= 0;
143
140
char buff[22],buff2[22];
170
167
printf(" %9s",llstr(next_link,buff));
171
168
if (next_link >= info->state->data_file_length)
173
if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
170
if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
174
171
next_link,MYF(MY_NABP)))
176
173
if (test_flag & T_VERBOSE) puts("");
243
240
/* Check delete links in index file */
245
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
242
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
247
244
my_off_t next_link;
248
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
245
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
250
247
char llbuff[21], llbuff2[21];
253
250
if (param->testflag & T_VERBOSE)
254
251
printf("block_size %4u:", block_size); /* purecov: tested */
293
290
if (!(buff=key_cache_read(info->s->key_cache,
294
291
info->s->kfile, next_link, DFLT_INIT_HITS,
295
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
292
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
296
293
MI_MIN_KEY_BLOCK_LENGTH, 1)))
298
295
/* purecov: begin tested */
396
393
int chk_key(MI_CHECK *param, register MI_INFO *info)
398
uint32_t key,found_keys=0,full_text_keys=0,result=0;
395
uint key,found_keys=0,full_text_keys=0,result=0;
400
397
ha_checksum old_record_checksum,init_checksum;
401
398
my_off_t all_keydata,all_totaldata,key_totlength,length;
523
520
/* Check that there isn't a row with auto_increment = 0 in the table */
524
521
mi_extra(info,HA_EXTRA_KEYREAD,0);
525
522
memset(info->lastkey, 0, keyinfo->seg->length);
526
if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
523
if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
527
524
(key_part_map)1, HA_READ_KEY_EXACT))
529
526
/* Don't count this as a real warning, as myisamchk can't correct it */
530
uint32_t save=param->warning_printed;
527
uint save=param->warning_printed;
531
528
mi_check_print_warning(param, "Found row where the auto_increment "
532
529
"column has the value 0");
533
530
param->warning_printed=save;
578
575
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
579
my_off_t page, unsigned char *buff, ha_rows *keys,
580
ha_checksum *key_checksum, uint32_t level)
576
my_off_t page, uchar *buff, ha_rows *keys,
577
ha_checksum *key_checksum, uint level)
582
579
char llbuff[22],llbuff2[22];
689
686
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
690
unsigned char *prev_key, unsigned char *last_key)
687
uchar *prev_key, uchar *last_key)
693
uint32_t first_null_seg, kp;
690
uint first_null_seg, kp;
722
719
/* Check if index is ok */
724
721
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
725
my_off_t page, unsigned char *buff, ha_rows *keys,
726
ha_checksum *key_checksum, uint32_t level)
722
my_off_t page, uchar *buff, ha_rows *keys,
723
ha_checksum *key_checksum, uint level)
729
uint32_t used_length,comp_flag,nod_flag,key_length=0;
730
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
726
uint used_length,comp_flag,nod_flag,key_length=0;
727
uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
731
728
my_off_t next_page,record;
733
uint32_t diff_pos[2];
735
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
732
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
737
734
mi_check_print_error(param,"Not enough memory for keyblock");
817
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
814
(*key_checksum)+= mi_byte_checksum((uchar*) key,
818
815
key_length- info->s->rec_reflength);
819
816
record= _mi_dpos(info,0,key+key_length);
820
817
if (record >= info->state->data_file_length)
830
827
llstr(page,llbuff), used_length, (keypos - buff));
833
my_afree((unsigned char*) temp_buff);
830
my_afree((uchar*) temp_buff);
836
my_afree((unsigned char*) temp_buff);
833
my_afree((uchar*) temp_buff);
838
835
} /* chk_index */
884
881
ha_rows records, del_blocks;
885
882
my_off_t used, empty, pos, splits, start_recpos= 0,
886
883
del_length, link_used, start_block;
887
unsigned char *record= NULL, *to= NULL;
884
uchar *record= NULL, *to= NULL;
888
885
char llbuff[22],llbuff2[22],llbuff3[22];
889
886
ha_checksum intern_record_checksum;
890
887
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
891
bool static_row_size;
888
my_bool static_row_size;
892
889
MI_KEYDEF *keyinfo;
893
890
MI_BLOCK_INFO block_info;
935
932
switch (info->s->data_file_type) {
936
933
case STATIC_RECORD:
937
if (my_b_read(¶m->read_cache,(unsigned char*) record,
934
if (my_b_read(¶m->read_cache,(uchar*) record,
938
935
info->s->base.pack_reclength))
940
937
start_recpos=pos;
954
951
block_info.next_filepos=pos;
957
if (_mi_read_cache(¶m->read_cache,(unsigned char*) block_info.header,
954
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
958
955
(start_block=block_info.next_filepos),
959
956
sizeof(block_info.header),
960
957
(flag ? 0 : READING_NEXT) | READING_HEADER))
1061
if (_mi_read_cache(¶m->read_cache,(unsigned char*) to,block_info.filepos,
1058
if (_mi_read_cache(¶m->read_cache,(uchar*) to,block_info.filepos,
1062
1059
(uint) block_info.data_len,
1063
1060
flag == 1 ? READING_NEXT : 0))
1119
1116
pos=block_info.filepos+block_info.block_len;
1121
1118
case COMPRESSED_RECORD:
1119
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header, pos,
1120
info->s->pack.ref_length, READING_NEXT))
1124
VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
1125
&info->rec_buff, -1, start_recpos));
1126
pos=block_info.filepos+block_info.rec_len;
1127
if (block_info.rec_len < (uint) info->s->min_pack_length ||
1128
block_info.rec_len > (uint) info->s->max_pack_length)
1130
mi_check_print_error(param,
1131
"Found block with wrong recordlength: %d at %s",
1132
block_info.rec_len, llstr(start_recpos,llbuff));
1136
if (_mi_read_cache(¶m->read_cache,(uchar*) info->rec_buff,
1137
block_info.filepos, block_info.rec_len, READING_NEXT))
1139
if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
1140
info->rec_buff, block_info.rec_len))
1142
mi_check_print_error(param,"Found wrong record at %s",
1143
llstr(start_recpos,llbuff));
1146
if (static_row_size)
1147
param->glob_crc+= mi_static_checksum(info,record);
1149
param->glob_crc+= mi_checksum(info,record);
1150
link_used+= (block_info.filepos - start_recpos);
1151
used+= (pos-start_recpos);
1122
1152
case BLOCK_RECORD:
1123
1153
assert(0); /* Impossible */
1129
1159
if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1131
printf("%s\r", llstr(records,llbuff)); fflush(stdout);
1161
printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1134
1164
/* Check if keys match the record */
1139
1169
if (mi_is_key_active(info->s->state.key_map, key))
1142
uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1172
uint key_length=_mi_make_key(info,key,info->lastkey,record,
1268
1298
printf("Lost space: %12s Linkdata: %10s\n",
1269
1299
llstr(empty,llbuff),llstr(link_used,llbuff2));
1271
free(mi_get_rec_buff_ptr(info, record));
1301
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1272
1302
return (error);
1274
1304
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1276
free(mi_get_rec_buff_ptr(info, record));
1306
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1277
1307
param->testflag|=T_RETRY_WITHOUT_QUICK;
1279
1309
} /* chk_data_link */
1332
1362
then recrate all indexes.
1335
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
1365
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1337
1367
MYISAM_SHARE *share= info->s;
1338
1368
MI_STATE_INFO *state= &share->state;
1438
1468
param->testflag|=T_CALC_CHECKSUM;
1440
1470
if (!param->using_global_keycache)
1441
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1442
param->use_buffers, 0, 0);
1471
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1472
param->use_buffers, 0, 0));
1444
1474
if (init_io_cache(¶m->read_cache,info->dfile,
1445
1475
(uint) param->read_buffer_length,
1497
1527
param->read_cache.end_of_file=sort_info.filelength=
1498
1528
my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1499
1529
sort_info.dupp=0;
1500
sort_param.fix_datafile= (bool) (! rep_quick);
1530
sort_param.fix_datafile= (my_bool) (! rep_quick);
1501
1531
sort_param.master=1;
1502
1532
sort_info.max_records= ~(ha_rows) 0;
1531
1561
llstr(info->dupp_key_pos,llbuff2));
1532
1562
if (param->testflag & T_VERBOSE)
1534
_mi_make_key(info,(uint) info->errkey,info->lastkey,
1535
sort_param.record,0L);
1564
VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
1565
sort_param.record,0L));
1537
1567
sort_info.dupp++;
1538
1568
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1546
1576
if (sort_write_record(&sort_param))
1549
if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
1579
if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1550
1580
flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1553
1583
if (param->testflag & T_WRITE_LOOP)
1555
fputs(" \r",stdout); fflush(stdout);
1585
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1557
1587
if (ftruncate(share->kfile, info->state->key_file_length))
1634
1664
llstr(sort_param.start_recpos,llbuff));
1635
1665
if (new_file >= 0)
1637
my_close(new_file,MYF(0));
1638
my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1667
VOID(my_close(new_file,MYF(0)));
1668
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1640
1670
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1642
1672
mi_mark_crashed_on_repair(info);
1645
void * rec_buff_ptr= NULL;
1646
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1647
if (rec_buff_ptr != NULL)
1649
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1650
if (rec_buff_ptr != NULL)
1654
free(sort_info.buff);
1655
end_io_cache(¶m->read_cache);
1674
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1675
MYF(MY_ALLOW_ZERO_PTR));
1676
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1677
MYF(MY_ALLOW_ZERO_PTR));
1678
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1679
VOID(end_io_cache(¶m->read_cache));
1656
1680
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1657
end_io_cache(&info->rec_cache);
1681
VOID(end_io_cache(&info->rec_cache));
1658
1682
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1659
1683
if (!got_error && param->testflag & T_UNPACK)
1661
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1685
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1662
1686
share->pack.header_length=0;
1663
1687
share->data_file_type=sort_info.new_data_file_type;
1673
1697
static int writekeys(MI_SORT_PARAM *sort_param)
1675
register uint32_t i;
1677
1701
MI_INFO *info= sort_param->sort_info->info;
1678
unsigned char *buff= sort_param->record;
1702
uchar *buff= sort_param->record;
1679
1703
my_off_t filepos= sort_param->filepos;
1681
1705
key=info->lastkey+info->s->base.max_key_length;
1684
1708
if (mi_is_key_active(info->s->state.key_map, i))
1687
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1711
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1688
1712
if (_mi_ck_write(info,i,key,key_length))
1701
1725
if (mi_is_key_active(info->s->state.key_map, i))
1704
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1728
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1705
1729
if (_mi_ck_delete(info,i,key,key_length))
1718
1742
/* Change all key-pointers that points to a records */
1720
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1721
my_off_t newpos, uint32_t prot_key)
1744
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1745
my_off_t newpos, uint prot_key)
1723
register uint32_t i;
1725
uint32_t key_length;
1727
1751
key=info->lastkey+info->s->base.max_key_length;
1728
1752
for (i=0 ; i < info->s->base.keys; i++)
1732
1756
key_length=_mi_make_key(info,i,key,record,oldpos);
1733
1757
if (info->s->keyinfo[i].flag & HA_NOSAME)
1734
1758
{ /* Change pointer direct */
1736
1760
MI_KEYDEF *keyinfo;
1737
1761
keyinfo=info->s->keyinfo+i;
1738
1762
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1796
1820
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1798
register uint32_t key;
1799
1823
register MI_KEYDEF *keyinfo;
1801
1825
my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1802
uint32_t r_locks,w_locks;
1826
uint r_locks,w_locks;
1804
1828
MYISAM_SHARE *share=info->s;
1805
1829
MI_STATE_INFO old_state;
1855
1879
/* Put same locks as old file */
1856
1880
share->r_locks= share->w_locks= share->tot_locks= 0;
1857
1881
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1858
my_close(share->kfile,MYF(MY_WME));
1882
VOID(my_close(share->kfile,MYF(MY_WME)));
1859
1883
share->kfile = -1;
1860
my_close(new_file,MYF(MY_WME));
1884
VOID(my_close(new_file,MYF(MY_WME)));
1861
1885
if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1863
1887
mi_open_keyfile(share))
1884
my_close(new_file,MYF(MY_WME));
1908
VOID(my_close(new_file,MYF(MY_WME)));
1886
my_delete(param->temp_filename,MYF(MY_WME));
1910
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
1888
1912
} /* mi_sort_index */
1893
1917
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1894
1918
my_off_t pagepos, File new_file)
1896
uint32_t length,nod_flag,used_length, key_length;
1897
unsigned char *buff,*keypos,*endpos;
1898
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
1920
uint length,nod_flag,used_length, key_length;
1921
uchar *buff,*keypos,*endpos;
1922
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1899
1923
my_off_t new_page_pos,next_page;
1900
1924
char llbuff[22];
1902
1926
new_page_pos=param->new_file_pos;
1903
1927
param->new_file_pos+=keyinfo->block_length;
1905
if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1929
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1907
1931
mi_check_print_error(param,"Not enough memory for key block");
1939
1963
/* Fill block with zero and write it to the new index file */
1940
1964
length=mi_getint(buff);
1941
1965
memset(buff+length, 0, keyinfo->block_length-length);
1942
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1966
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1943
1967
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1945
1969
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1948
my_afree((unsigned char*) buff);
1972
my_afree((uchar*) buff);
1951
my_afree((unsigned char*) buff);
1975
my_afree((uchar*) buff);
1953
1977
} /* sort_one_index */
1965
1989
int change_to_newfile(const char * filename, const char * old_ext,
1966
1990
const char * new_ext,
1967
uint32_t raid_chunks __attribute__((unused)),
1991
uint raid_chunks __attribute__((unused)),
1970
1994
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1985
2009
char tmp_buff[IO_SIZE],*buff;
1986
2010
ulong buff_length;
1988
buff_length=(ulong) cmin(param->write_buffer_length,length);
2012
buff_length=(ulong) min(param->write_buffer_length,length);
1989
2013
if (!(buff=my_malloc(buff_length,MYF(0))))
1991
2015
buff=tmp_buff; buff_length=IO_SIZE;
1994
my_seek(from,start,MY_SEEK_SET,MYF(0));
2018
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1995
2019
while (length > buff_length)
1997
if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1998
my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
2021
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
2022
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
2000
2024
length-= buff_length;
2002
if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
2003
my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
2026
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
2027
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
2005
2029
if (buff != tmp_buff)
2030
my_free(buff,MYF(0));
2009
2033
if (buff != tmp_buff)
2034
my_free(buff,MYF(0));
2011
2035
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2012
2036
type,my_errno);
2139
2163
sort_param.wordlist=NULL;
2141
2165
if (share->data_file_type == DYNAMIC_RECORD)
2142
length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2166
length=max(share->base.min_pack_length+1,share->base.min_block_length);
2143
2167
else if (share->data_file_type == COMPRESSED_RECORD)
2144
2168
length=share->base.min_block_length;
2336
2360
mi_check_print_error(param,"%d when fixing table",my_errno);
2337
2361
if (new_file >= 0)
2339
my_close(new_file,MYF(0));
2340
my_raid_delete(param->temp_filename,share->base.raid_chunks,
2363
VOID(my_close(new_file,MYF(0)));
2364
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2342
2366
if (info->dfile == new_file)
2343
2367
info->dfile= -1;
2348
2372
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2349
2373
share->state.changed|=STATE_NOT_SORTED_PAGES;
2351
void * rec_buff_ptr= NULL;
2352
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2353
if (rec_buff_ptr != NULL)
2355
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2356
if (rec_buff_ptr != NULL)
2360
free((unsigned char*) sort_info.key_block);
2361
free(sort_info.buff);
2362
end_io_cache(¶m->read_cache);
2375
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2376
MYF(MY_ALLOW_ZERO_PTR));
2377
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2378
MYF(MY_ALLOW_ZERO_PTR));
2379
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2380
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2381
VOID(end_io_cache(¶m->read_cache));
2363
2382
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2364
2383
if (!got_error && (param->testflag & T_UNPACK))
2366
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2385
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2367
2386
share->pack.header_length=0;
2369
2388
return(got_error);
2415
2434
const char * name, int rep_quick)
2418
uint32_t i,key, total_key_length, istep;
2437
uint i,key, total_key_length, istep;
2419
2438
ulong rec_length;
2420
2439
ha_rows start_records;
2421
2440
my_off_t new_header_length,del;
2551
2570
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2553
2572
if (share->data_file_type == DYNAMIC_RECORD)
2554
rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2573
rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2555
2574
else if (share->data_file_type == COMPRESSED_RECORD)
2556
2575
rec_length=share->base.min_block_length;
2630
2649
sort_param[i].filepos=new_header_length;
2631
2650
sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2633
sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
2652
sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2634
2653
(max_pack_reclength * i));
2635
2654
if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2820
2839
the share by remove_io_thread() or it was not yet started (if the
2821
2840
error happend before creating the thread).
2823
end_io_cache(&info->rec_cache);
2842
VOID(end_io_cache(&info->rec_cache));
2825
2844
Destroy the new data cache in case of non-quick repair. All slave
2826
2845
threads did either detach from the share by remove_io_thread()
2850
2869
mi_check_print_error(param,"%d when fixing table",my_errno);
2851
2870
if (new_file >= 0)
2853
my_close(new_file,MYF(0));
2854
my_raid_delete(param->temp_filename,share->base.raid_chunks,
2872
VOID(my_close(new_file,MYF(0)));
2873
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2856
2875
if (info->dfile == new_file)
2857
2876
info->dfile= -1;
2865
2884
pthread_cond_destroy (&sort_info.cond);
2866
2885
pthread_mutex_destroy(&sort_info.mutex);
2868
free((unsigned char*) sort_info.key_block);
2869
free((unsigned char*) sort_param);
2870
free(sort_info.buff);
2871
end_io_cache(¶m->read_cache);
2887
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2888
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2889
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2890
VOID(end_io_cache(¶m->read_cache));
2872
2891
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2873
2892
if (!got_error && (param->testflag & T_UNPACK))
2875
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2894
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2876
2895
share->pack.header_length=0;
2878
2897
return(got_error);
2898
2917
sort_param->real_key_length=
2899
2918
(info->s->rec_reflength+
2900
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2919
_mi_make_key(info, sort_param->key, (uchar*) key,
2901
2920
sort_param->record, sort_param->filepos));
2902
2921
#ifdef HAVE_purify
2903
2922
memset(key+sort_param->real_key_length, 0,
2944
2963
int parallel_flag;
2945
uint32_t found_record,b_type,left_length;
2964
uint found_record,b_type,left_length;
2947
unsigned char *to= NULL;
2948
2967
MI_BLOCK_INFO block_info;
2949
2968
SORT_INFO *sort_info=sort_param->sort_info;
2950
2969
MI_CHECK *param=sort_info->param;
3020
3039
llstr(param->search_after_block,llbuff),
3021
3040
llstr(sort_param->start_recpos,llbuff2));
3022
3041
if (_mi_read_cache(&sort_param->read_cache,
3023
(unsigned char*) block_info.header,pos,
3042
(uchar*) block_info.header,pos,
3024
3043
MI_BLOCK_INFO_HEADER_LENGTH,
3025
3044
(! found_record ? READING_NEXT : 0) |
3026
3045
parallel_flag | READING_HEADER))
3047
3066
(block_info.rec_len < (uint) share->base.min_pack_length ||
3048
3067
block_info.rec_len > (uint) share->base.max_pack_length)))
3051
3070
if (param->testflag & T_VERBOSE || searching == 0)
3052
3071
mi_check_print_info(param,
3053
3072
"Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3206
3225
streched over the end of the previous buffer contents.
3209
uint32_t header_len= (uint) (block_info.filepos - pos);
3210
uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3228
uint header_len= (uint) (block_info.filepos - pos);
3229
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3212
3231
if (prefetch_len > block_info.data_len)
3213
3232
prefetch_len= block_info.data_len;
3284
3303
case COMPRESSED_RECORD:
3304
for (searching=0 ;; searching=1, sort_param->pos++)
3306
if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
3308
share->pack.ref_length,READING_NEXT))
3310
if (searching && ! sort_param->fix_datafile)
3312
param->error_printed=1;
3313
param->retry_repair=1;
3314
param->testflag|=T_RETRY_WITHOUT_QUICK;
3315
return(1); /* Something wrong with data */
3317
sort_param->start_recpos=sort_param->pos;
3318
if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
3319
&sort_param->rec_buff, -1, sort_param->pos))
3321
if (!block_info.rec_len &&
3322
sort_param->pos + MEMMAP_EXTRA_MARGIN ==
3323
sort_param->read_cache.end_of_file)
3325
if (block_info.rec_len < (uint) share->min_pack_length ||
3326
block_info.rec_len > (uint) share->max_pack_length)
3329
mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
3331
llstr(sort_param->pos,llbuff));
3334
if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
3335
block_info.filepos, block_info.rec_len,
3339
mi_check_print_info(param,"Couldn't read whole record from %s",
3340
llstr(sort_param->pos,llbuff));
3343
if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
3344
sort_param->rec_buff, block_info.rec_len))
3347
mi_check_print_info(param,"Found wrong record at %s",
3348
llstr(sort_param->pos,llbuff));
3351
if (!sort_param->fix_datafile)
3353
sort_param->filepos=sort_param->pos;
3354
if (sort_param->master)
3355
share->state.split++;
3357
sort_param->max_pos=(sort_param->pos=block_info.filepos+
3358
block_info.rec_len);
3359
info->packed_length=block_info.rec_len;
3360
if (sort_param->calc_checksum)
3361
param->glob_crc+= (info->checksum=
3362
mi_checksum(info, sort_param->record));
3285
3365
case BLOCK_RECORD:
3286
3366
assert(0); /* Impossible */
3376
3458
/* sort_info->param->glob_crc+=info->checksum; */
3378
3460
case COMPRESSED_RECORD:
3461
reclength=info->packed_length;
3462
length= save_pack_length((uint) share->pack.version, block_buff,
3464
if (info->s->base.blobs)
3465
length+= save_pack_length((uint) share->pack.version,
3466
block_buff + length, info->blob_length);
3467
if (my_b_write(&info->rec_cache,block_buff,length) ||
3468
my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
3470
mi_check_print_error(param,"%d when writing to datafile",my_errno);
3473
/* sort_info->param->glob_crc+=info->checksum; */
3474
sort_param->filepos+=reclength+length;
3475
info->s->state.split++;
3379
3477
case BLOCK_RECORD:
3380
3478
assert(0); /* Impossible */
3400
3498
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3403
uint32_t not_used[2];
3404
return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
3502
return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3405
3503
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3406
3504
} /* sort_key_cmp */
3409
3507
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3411
uint32_t diff_pos[2];
3412
3510
char llbuff[22],llbuff2[22];
3413
3511
SORT_INFO *sort_info=sort_param->sort_info;
3414
3512
MI_CHECK *param= sort_info->param;
3417
3515
if (sort_info->key_block->inited)
3419
3517
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3420
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3518
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3422
3520
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3423
3521
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3424
(unsigned char*) a, USE_WHOLE_KEY,
3522
(uchar*) a, USE_WHOLE_KEY,
3425
3523
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3426
3524
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3428
3526
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3429
3527
sort_param->notnull,
3430
3528
sort_info->key_block->lastkey,
3433
3531
sort_param->unique[diff_pos[0]-1]++;
3438
3536
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3439
3537
mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3442
3540
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3444
3542
sort_info->dupp++;
3445
3543
sort_info->info->lastpos=get_record_for_key(sort_info->info,
3446
3544
sort_param->keyinfo,
3447
(unsigned char*) a);
3448
3546
mi_check_print_warning(param,
3449
3547
"Duplicate key for record at %10s against record at %10s",
3450
3548
llstr(sort_info->info->lastpos,llbuff),
3457
3555
return (sort_delete_record(sort_param));
3459
3557
return (sort_insert_key(sort_param,sort_info->key_block,
3460
(unsigned char*) a, HA_OFFSET_ERROR));
3558
(uchar*) a, HA_OFFSET_ERROR));
3461
3559
} /* sort_key_write */
3464
3562
/* get pointer to record from a key */
3466
3564
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3469
3567
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3470
3568
} /* get_record_for_key */
3473
3571
/* Insert a key in sort-key-blocks */
3475
3573
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3476
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3574
register SORT_KEY_BLOCKS *key_block, uchar *key,
3477
3575
my_off_t prev_block)
3479
uint32_t a_length,t_length,nod_flag;
3577
uint a_length,t_length,nod_flag;
3480
3578
my_off_t filepos,key_file_length;
3481
unsigned char *anc_buff,*lastkey;
3579
uchar *anc_buff,*lastkey;
3482
3580
MI_KEY_PARAM s_temp;
3484
3582
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3511
3609
_mi_kpointer(info,key_block->end_pos,prev_block);
3513
3611
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3514
(unsigned char*) 0,lastkey,lastkey,key,
3612
(uchar*) 0,lastkey,lastkey,key,
3516
3614
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3517
3615
a_length+=t_length;
3519
3617
key_block->end_pos+=t_length;
3520
3618
if (a_length <= keyinfo->block_length)
3522
_mi_move_key(keyinfo,key_block->lastkey,key);
3620
VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3523
3621
key_block->last_length=a_length-t_length;
3538
3636
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3541
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3639
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3542
3640
(uint) keyinfo->block_length,filepos, param->myf_rw))
3592
3690
for (i=0 ; i < sort_info->current_key ; i++)
3594
uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3692
uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3595
3693
if (_mi_ck_delete(info,i,key,key_length))
3597
3695
mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3613
3711
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3615
uint32_t nod_flag,length;
3713
uint nod_flag,length;
3616
3714
my_off_t filepos,key_file_length;
3617
3715
SORT_KEY_BLOCKS *key_block;
3618
3716
SORT_INFO *sort_info= sort_param->sort_info;
3640
3738
DFLT_INIT_HITS, key_block->buff))
3643
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3741
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3644
3742
(uint) keyinfo->block_length,filepos, myf_rw))
3652
3750
/* alloc space and pointers for key_blocks */
3654
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3655
uint32_t buffer_length)
3752
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3657
register uint32_t i;
3658
3756
SORT_KEY_BLOCKS *block;
3660
3758
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3697
3795
MI_COLUMNDEF *recdef,*rec,*end;
3698
3796
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3699
3797
MI_STATUS_INFO status_info;
3700
uint32_t unpack,key_parts;
3798
uint unpack,key_parts;
3701
3799
ha_rows max_records;
3702
3800
uint64_t file_length,tmp_length;
3703
3801
MI_CREATE_INFO create_info;
3717
3815
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3718
3816
(key_parts+share.base.keys))))
3720
my_afree((unsigned char*) keyinfo);
3818
my_afree((uchar*) keyinfo);
3723
3821
if (!(recdef=(MI_COLUMNDEF*)
3724
3822
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3726
my_afree((unsigned char*) keyinfo);
3727
my_afree((unsigned char*) keysegs);
3824
my_afree((uchar*) keyinfo);
3825
my_afree((uchar*) keysegs);
3730
3828
if (!(uniquedef=(MI_UNIQUEDEF*)
3731
3829
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3733
my_afree((unsigned char*) recdef);
3734
my_afree((unsigned char*) keyinfo);
3735
my_afree((unsigned char*) keysegs);
3831
my_afree((uchar*) recdef);
3832
my_afree((uchar*) keyinfo);
3833
my_afree((uchar*) keysegs);
3790
3888
set_if_bigger(file_length,tmp_length);
3791
3889
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3793
mi_close(*org_info);
3891
VOID(mi_close(*org_info));
3794
3892
memset(&create_info, 0, sizeof(create_info));
3795
create_info.max_rows=cmax(max_records,share.base.records);
3893
create_info.max_rows=max(max_records,share.base.records);
3796
3894
create_info.reloc_rows=share.base.reloc;
3797
3895
create_info.old_options=(share.options |
3798
3896
(unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3832
3930
/* We are modifing */
3833
3931
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3834
_mi_readinfo(*org_info,F_WRLCK,0);
3932
VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3835
3933
(*org_info)->state->records=info.state->records;
3836
3934
if (share.state.create_time)
3837
3935
(*org_info)->s->state.create_time=share.state.create_time;
3850
my_afree((unsigned char*) uniquedef);
3851
my_afree((unsigned char*) keyinfo);
3852
my_afree((unsigned char*) recdef);
3853
my_afree((unsigned char*) keysegs);
3948
my_afree((uchar*) uniquedef);
3949
my_afree((uchar*) keyinfo);
3950
my_afree((uchar*) recdef);
3951
my_afree((uchar*) keysegs);
3858
3956
/* write suffix to data file if neaded */
3860
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
3958
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3862
3960
MI_INFO *info=sort_info->info;
3864
3962
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3866
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3964
uchar buff[MEMMAP_EXTRA_MARGIN];
3867
3965
memset(buff, 0, sizeof(buff));
3868
3966
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3879
3977
/* Update state and myisamchk_time of indexfile */
3881
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
3979
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3883
3981
MYISAM_SHARE *share=info->s;
3890
3988
if (update & UPDATE_STAT)
3892
uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
3990
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3893
3991
share->state.rec_per_key_rows=info->state->records;
3894
3992
share->state.changed&= ~STATE_NOT_ANALYZED;
3895
3993
if (info->state->records)
3924
4022
{ /* Force update of status */
3926
uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
4024
uint r_locks=share->r_locks,w_locks=share->w_locks;
3927
4025
share->r_locks= share->w_locks= share->tot_locks= 0;
3928
4026
error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3929
4027
share->r_locks=r_locks;
3983
4081
if (my_errno != HA_ERR_END_OF_FILE)
3985
4083
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
free(mi_get_rec_buff_ptr(info, record));
4084
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4085
mi_check_print_error(param,"%d when reading last record",my_errno);
3998
4096
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
4000
4098
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
4001
free(mi_get_rec_buff_ptr(info, record));
4099
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
4002
4100
update_state_info(param, info, UPDATE_AUTO_INC);
4101
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4199
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4103
4201
ha_checksum crc;
4104
const unsigned char *end=buf+length;
4202
const uchar *end=buf+length;
4105
4203
for (crc=0; buf != end; buf++)
4106
crc=((crc << 1) + *((unsigned char*) buf)) +
4204
crc=((crc << 1) + *((uchar*) buf)) +
4107
4205
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4111
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4209
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4113
uint32_t key_maxlength=key->maxlength;
4211
uint key_maxlength=key->maxlength;
4114
4212
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4115
4213
((uint64_t) rows * key_maxlength >
4116
4214
(uint64_t) myisam_max_temp_length));
4151
4249
even if the temporary file would be quite big!
4154
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4155
uint64_t key_map, bool force)
4252
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4253
uint64_t key_map, my_bool force)
4157
4255
MYISAM_SHARE *share=info->s;
4158
4256
MI_KEYDEF *key=share->keyinfo;
4162
4260
mi_repair_by_sort only works if we have at least one key. If we don't