46
46
#ifdef HAVE_SYS_VADVISE_H
47
47
#include <sys/vadvise.h>
50
#include <sys/types.h>
52
49
#ifdef HAVE_SYS_MMAN_H
53
50
#include <sys/mman.h>
55
#include <drizzled/util/test.h>
58
/* Functions defined in this file */
60
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
54
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
55
#define my_raid_delete(A,B,C) my_delete(A,B)
58
/* Functions defined in this file */
60
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
61
61
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
62
my_off_t page, unsigned char *buff, ha_rows *keys,
63
ha_checksum *key_checksum, uint32_t level);
64
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);
65
65
static ha_checksum calc_checksum(ha_rows count);
66
66
static int writekeys(MI_SORT_PARAM *sort_param);
67
67
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
71
71
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
72
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
73
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
75
75
static int sort_insert_key(MI_SORT_PARAM *sort_param,
76
76
register SORT_KEY_BLOCKS *key_block,
77
unsigned char *key, my_off_t prev_block);
77
uchar *key, my_off_t prev_block);
78
78
static int sort_delete_record(MI_SORT_PARAM *sort_param);
79
79
/*static int flush_pending_blocks(MI_CHECK *param);*/
80
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
81
uint32_t buffer_length);
82
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);
83
83
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
85
85
void myisamchk_init(MI_CHECK *param)
117
117
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
119
119
/* Don't count this as a real warning, as check can correct this ! */
120
uint32_t save=param->warning_printed;
120
uint save=param->warning_printed;
121
121
mi_check_print_warning(param,
122
122
share->state.open_count==1 ?
123
123
"%d client is using or hasn't closed the table properly" :
133
133
/* Check delete links */
135
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)
137
137
register ha_rows i;
138
uint32_t delete_link_length;
138
uint delete_link_length;
139
139
my_off_t empty, next_link, old_link= 0;
140
140
char buff[22],buff2[22];
167
167
printf(" %9s",llstr(next_link,buff));
168
168
if (next_link >= info->state->data_file_length)
170
if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
170
if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
171
next_link,MYF(MY_NABP)))
173
173
if (test_flag & T_VERBOSE) puts("");
200
200
param->record_checksum+=(ha_checksum) next_link;
201
next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
201
next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
202
202
empty+=info->s->base.pack_reclength;
240
240
/* Check delete links in index file */
242
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)
244
244
my_off_t next_link;
245
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
245
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
247
char llbuff[21], llbuff2[21];
250
250
if (param->testflag & T_VERBOSE)
251
251
printf("block_size %4u:", block_size); /* purecov: tested */
290
290
if (!(buff=key_cache_read(info->s->key_cache,
291
291
info->s->kfile, next_link, DFLT_INIT_HITS,
292
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
292
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
293
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
295
/* purecov: begin tested */
393
393
int chk_key(MI_CHECK *param, register MI_INFO *info)
395
uint32_t key,found_keys=0,full_text_keys=0,result=0;
395
uint key,found_keys=0,full_text_keys=0,result=0;
397
397
ha_checksum old_record_checksum,init_checksum;
398
398
my_off_t all_keydata,all_totaldata,key_totlength,length;
520
520
/* Check that there isn't a row with auto_increment = 0 in the table */
521
521
mi_extra(info,HA_EXTRA_KEYREAD,0);
522
522
memset(info->lastkey, 0, keyinfo->seg->length);
523
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,
524
524
(key_part_map)1, HA_READ_KEY_EXACT))
526
526
/* Don't count this as a real warning, as myisamchk can't correct it */
527
uint32_t save=param->warning_printed;
527
uint save=param->warning_printed;
528
528
mi_check_print_warning(param, "Found row where the auto_increment "
529
529
"column has the value 0");
530
530
param->warning_printed=save;
575
575
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
576
my_off_t page, unsigned char *buff, ha_rows *keys,
577
ha_checksum *key_checksum, uint32_t level)
576
my_off_t page, uchar *buff, ha_rows *keys,
577
ha_checksum *key_checksum, uint level)
579
579
char llbuff[22],llbuff2[22];
646
646
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
649
uint32_t first_null, kp;
650
650
first_null= ha_find_null(keyseg, key) - keyseg;
652
652
All prefix tuples that don't include keypart_{first_null} are not-null
686
686
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
unsigned char *prev_key, unsigned char *last_key)
687
uchar *prev_key, uchar *last_key)
690
uint32_t first_null_seg, kp;
690
uint first_null_seg, kp;
719
719
/* Check if index is ok */
721
721
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
722
my_off_t page, unsigned char *buff, ha_rows *keys,
723
ha_checksum *key_checksum, uint32_t level)
722
my_off_t page, uchar *buff, ha_rows *keys,
723
ha_checksum *key_checksum, uint level)
726
uint32_t used_length,comp_flag,nod_flag,key_length=0;
727
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;
728
728
my_off_t next_page,record;
730
uint32_t diff_pos[2];
732
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
732
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
734
734
mi_check_print_error(param,"Not enough memory for keyblock");
814
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
814
(*key_checksum)+= mi_byte_checksum((uchar*) key,
815
815
key_length- info->s->rec_reflength);
816
816
record= _mi_dpos(info,0,key+key_length);
817
817
if (record >= info->state->data_file_length)
827
827
llstr(page,llbuff), used_length, (keypos - buff));
830
my_afree((unsigned char*) temp_buff);
830
my_afree((uchar*) temp_buff);
833
my_afree((unsigned char*) temp_buff);
833
my_afree((uchar*) temp_buff);
835
835
} /* chk_index */
860
860
/* Calc length of key in normal isam */
862
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
862
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
865
865
HA_KEYSEG *keyseg;
867
867
length= info->s->rec_reflength;
881
881
ha_rows records, del_blocks;
882
882
my_off_t used, empty, pos, splits, start_recpos= 0,
883
883
del_length, link_used, start_block;
884
unsigned char *record= NULL, *to= NULL;
884
uchar *record= NULL, *to= NULL;
885
885
char llbuff[22],llbuff2[22],llbuff3[22];
886
886
ha_checksum intern_record_checksum;
887
887
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
932
932
switch (info->s->data_file_type) {
933
933
case STATIC_RECORD:
934
if (my_b_read(¶m->read_cache,(unsigned char*) record,
934
if (my_b_read(¶m->read_cache,(uchar*) record,
935
935
info->s->base.pack_reclength))
937
937
start_recpos=pos;
951
951
block_info.next_filepos=pos;
954
if (_mi_read_cache(¶m->read_cache,(unsigned char*) block_info.header,
954
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
955
955
(start_block=block_info.next_filepos),
956
956
sizeof(block_info.header),
957
957
(flag ? 0 : READING_NEXT) | READING_HEADER))
1058
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,
1059
1059
(uint) block_info.data_len,
1060
1060
flag == 1 ? READING_NEXT : 0))
1126
1126
if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1128
printf("%s\r", llstr(records,llbuff)); fflush(stdout);
1128
printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1131
1131
/* Check if keys match the record */
1136
1136
if (mi_is_key_active(info->s->state.key_map, key))
1139
uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1139
uint key_length=_mi_make_key(info,key,info->lastkey,record,
1173
1173
if (param->testflag & T_WRITE_LOOP)
1175
fputs(" \r",stdout); fflush(stdout);
1175
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1177
1177
if (records != info->state->records)
1265
1265
printf("Lost space: %12s Linkdata: %10s\n",
1266
1266
llstr(empty,llbuff),llstr(link_used,llbuff2));
1268
free(mi_get_rec_buff_ptr(info, record));
1268
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1269
1269
return (error);
1271
1271
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1273
free(mi_get_rec_buff_ptr(info, record));
1273
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1274
param->testflag|=T_RETRY_WITHOUT_QUICK;
1276
1276
} /* chk_data_link */
1435
1435
param->testflag|=T_CALC_CHECKSUM;
1437
1437
if (!param->using_global_keycache)
1438
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0);
1438
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0));
1441
1441
if (init_io_cache(¶m->read_cache,info->dfile,
1442
1442
(uint) param->read_buffer_length,
1461
1461
if (!rep_quick)
1463
1463
/* Get real path for data file */
1464
if ((new_file=my_create(fn_format(param->temp_filename,
1465
share->data_file_name, "",
1467
0,param->tmpfile_createflag,
1464
if ((new_file=my_raid_create(fn_format(param->temp_filename,
1465
share->data_file_name, "",
1467
0,param->tmpfile_createflag,
1468
share->base.raid_type,
1469
share->base.raid_chunks,
1470
share->base.raid_chunksize,
1470
1473
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
param->temp_filename);
1474
param->temp_filename);
1474
1477
if (new_header_length &&
1475
1478
filecopy(param,new_file,info->dfile,0L,new_header_length,
1478
1481
info->s->state.dellink= HA_OFFSET_ERROR;
1479
1482
info->rec_cache.file=new_file;
1525
1528
llstr(info->dupp_key_pos,llbuff2));
1526
1529
if (param->testflag & T_VERBOSE)
1528
_mi_make_key(info,(uint) info->errkey,info->lastkey,
1529
sort_param.record,0L);
1531
VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
1532
sort_param.record,0L));
1531
1534
sort_info.dupp++;
1532
1535
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1547
1550
if (param->testflag & T_WRITE_LOOP)
1549
fputs(" \r",stdout); fflush(stdout);
1552
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1551
1554
if (ftruncate(share->kfile, info->state->key_file_length))
1628
1631
llstr(sort_param.start_recpos,llbuff));
1629
1632
if (new_file >= 0)
1631
my_close(new_file,MYF(0));
1632
my_delete(param->temp_filename, MYF(MY_WME));
1634
VOID(my_close(new_file,MYF(0)));
1635
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1633
1637
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1635
1639
mi_mark_crashed_on_repair(info);
1638
void * rec_buff_ptr= NULL;
1639
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1640
if (rec_buff_ptr != NULL)
1642
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1643
if (rec_buff_ptr != NULL)
1647
free(sort_info.buff);
1648
end_io_cache(¶m->read_cache);
1641
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1642
MYF(MY_ALLOW_ZERO_PTR));
1643
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1644
MYF(MY_ALLOW_ZERO_PTR));
1645
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1646
VOID(end_io_cache(¶m->read_cache));
1649
1647
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
end_io_cache(&info->rec_cache);
1648
VOID(end_io_cache(&info->rec_cache));
1651
1649
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1650
if (!got_error && param->testflag & T_UNPACK)
1654
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1652
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1653
share->pack.header_length=0;
1656
1654
share->data_file_type=sort_info.new_data_file_type;
1666
1664
static int writekeys(MI_SORT_PARAM *sort_param)
1668
register uint32_t i;
1670
1668
MI_INFO *info= sort_param->sort_info->info;
1671
unsigned char *buff= sort_param->record;
1669
uchar *buff= sort_param->record;
1672
1670
my_off_t filepos= sort_param->filepos;
1674
1672
key=info->lastkey+info->s->base.max_key_length;
1677
1675
if (mi_is_key_active(info->s->state.key_map, i))
1680
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1678
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1679
if (_mi_ck_write(info,i,key,key_length))
1694
1692
if (mi_is_key_active(info->s->state.key_map, i))
1697
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1695
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1696
if (_mi_ck_delete(info,i,key,key_length))
1711
1709
/* Change all key-pointers that points to a records */
1713
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1714
my_off_t newpos, uint32_t prot_key)
1711
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1712
my_off_t newpos, uint prot_key)
1716
register uint32_t i;
1718
uint32_t key_length;
1720
1718
key=info->lastkey+info->s->base.max_key_length;
1721
1719
for (i=0 ; i < info->s->base.keys; i++)
1725
1723
key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1724
if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1725
{ /* Change pointer direct */
1729
1727
MI_KEYDEF *keyinfo;
1730
1728
keyinfo=info->s->keyinfo+i;
1731
1729
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1789
1787
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1791
register uint32_t key;
1792
1790
register MI_KEYDEF *keyinfo;
1794
1792
my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
uint32_t r_locks,w_locks;
1793
uint r_locks,w_locks;
1797
1795
MYISAM_SHARE *share=info->s;
1798
1796
MI_STATE_INFO old_state;
1848
1846
/* Put same locks as old file */
1849
1847
share->r_locks= share->w_locks= share->tot_locks= 0;
1850
1848
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1851
my_close(share->kfile,MYF(MY_WME));
1849
VOID(my_close(share->kfile,MYF(MY_WME)));
1852
1850
share->kfile = -1;
1853
my_close(new_file,MYF(MY_WME));
1851
VOID(my_close(new_file,MYF(MY_WME)));
1854
1852
if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1856
1854
mi_open_keyfile(share))
1877
my_close(new_file,MYF(MY_WME));
1875
VOID(my_close(new_file,MYF(MY_WME)));
1879
my_delete(param->temp_filename,MYF(MY_WME));
1877
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
1881
1879
} /* mi_sort_index */
1886
1884
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
1885
my_off_t pagepos, File new_file)
1889
uint32_t length,nod_flag,used_length, key_length;
1890
unsigned char *buff,*keypos,*endpos;
1891
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
1887
uint length,nod_flag,used_length, key_length;
1888
uchar *buff,*keypos,*endpos;
1889
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
1890
my_off_t new_page_pos,next_page;
1893
1891
char llbuff[22];
1895
1893
new_page_pos=param->new_file_pos;
1896
1894
param->new_file_pos+=keyinfo->block_length;
1898
if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1896
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1900
1898
mi_check_print_error(param,"Not enough memory for key block");
1932
1930
/* Fill block with zero and write it to the new index file */
1933
1931
length=mi_getint(buff);
1934
1932
memset(buff+length, 0, keyinfo->block_length-length);
1935
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1933
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
1934
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1938
1936
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1941
my_afree((unsigned char*) buff);
1939
my_afree((uchar*) buff);
1944
my_afree((unsigned char*) buff);
1942
my_afree((uchar*) buff);
1946
1944
} /* sort_one_index */
1958
1956
int change_to_newfile(const char * filename, const char * old_ext,
1959
1957
const char * new_ext,
1960
uint32_t raid_chunks __attribute__((unused)),
1958
uint raid_chunks __attribute__((unused)),
1963
1961
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1978
1976
char tmp_buff[IO_SIZE],*buff;
1979
1977
ulong buff_length;
1981
buff_length=(ulong) cmin(param->write_buffer_length,length);
1979
buff_length=(ulong) min(param->write_buffer_length,length);
1982
1980
if (!(buff=my_malloc(buff_length,MYF(0))))
1984
1982
buff=tmp_buff; buff_length=IO_SIZE;
1987
my_seek(from,start,MY_SEEK_SET,MYF(0));
1985
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1988
1986
while (length > buff_length)
1990
if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1991
my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
1988
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
1989
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1993
1991
length-= buff_length;
1995
if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1996
my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
1993
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
1994
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1998
1996
if (buff != tmp_buff)
1997
my_free(buff,MYF(0));
2002
2000
if (buff != tmp_buff)
2001
my_free(buff,MYF(0));
2004
2002
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2003
type,my_errno);
2082
2080
if (!rep_quick)
2084
2082
/* Get real path for data file */
2085
if ((new_file=my_create(fn_format(param->temp_filename,
2086
share->data_file_name, "",
2088
0,param->tmpfile_createflag,
2083
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2084
share->data_file_name, "",
2086
0,param->tmpfile_createflag,
2087
share->base.raid_type,
2088
share->base.raid_chunks,
2089
share->base.raid_chunksize,
2091
2092
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
param->temp_filename);
2093
param->temp_filename);
2095
2096
if (new_header_length &&
2129
2130
sort_param.wordlist=NULL;
2131
2132
if (share->data_file_type == DYNAMIC_RECORD)
2132
length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2133
length=max(share->base.min_pack_length+1,share->base.min_block_length);
2133
2134
else if (share->data_file_type == COMPRESSED_RECORD)
2134
2135
length=share->base.min_block_length;
2252
2253
if (param->testflag & T_WRITE_LOOP)
2254
fputs(" \r",stdout); fflush(stdout);
2255
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
2257
2258
if (rep_quick && del+sort_info.dupp != info->state->del)
2306
2307
got_error|= flush_blocks(param, share->key_cache, share->kfile);
2307
end_io_cache(&info->rec_cache);
2308
VOID(end_io_cache(&info->rec_cache));
2308
2309
if (!got_error)
2310
2311
/* Replace the actual file with the temporary file */
2326
2327
mi_check_print_error(param,"%d when fixing table",my_errno);
2327
2328
if (new_file >= 0)
2329
my_close(new_file,MYF(0));
2330
my_delete(param->temp_filename, MYF(MY_WME));
2330
VOID(my_close(new_file,MYF(0)));
2331
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2331
2333
if (info->dfile == new_file)
2334
2336
mi_mark_crashed_on_repair(info);
2337
2339
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2340
share->state.changed|=STATE_NOT_SORTED_PAGES;
2340
void * rec_buff_ptr= NULL;
2341
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2342
if (rec_buff_ptr != NULL)
2344
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2345
if (rec_buff_ptr != NULL)
2349
free((unsigned char*) sort_info.key_block);
2350
free(sort_info.buff);
2351
end_io_cache(¶m->read_cache);
2342
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2343
MYF(MY_ALLOW_ZERO_PTR));
2344
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2345
MYF(MY_ALLOW_ZERO_PTR));
2346
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2347
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2348
VOID(end_io_cache(¶m->read_cache));
2352
2349
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2350
if (!got_error && (param->testflag & T_UNPACK))
2355
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2352
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2353
share->pack.header_length=0;
2358
2355
return(got_error);
2404
2401
const char * name, int rep_quick)
2407
uint32_t i,key, total_key_length, istep;
2404
uint i,key, total_key_length, istep;
2408
2405
ulong rec_length;
2409
2406
ha_rows start_records;
2410
2407
my_off_t new_header_length,del;
2492
2489
if (!rep_quick)
2494
2491
/* Get real path for data file */
2495
if ((new_file=my_create(fn_format(param->temp_filename,
2496
share->data_file_name, "",
2499
0,param->tmpfile_createflag,
2492
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2493
share->data_file_name, "",
2496
0,param->tmpfile_createflag,
2497
share->base.raid_type,
2498
share->base.raid_chunks,
2499
share->base.raid_chunksize,
2502
2502
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2503
param->temp_filename);
2537
2537
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2539
2539
if (share->data_file_type == DYNAMIC_RECORD)
2540
rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2540
rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2541
else if (share->data_file_type == COMPRESSED_RECORD)
2542
2542
rec_length=share->base.min_block_length;
2616
2616
sort_param[i].filepos=new_header_length;
2617
2617
sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2619
sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
2619
sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2620
(max_pack_reclength * i));
2621
2621
if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2806
2806
the share by remove_io_thread() or it was not yet started (if the
2807
2807
error happend before creating the thread).
2809
end_io_cache(&info->rec_cache);
2809
VOID(end_io_cache(&info->rec_cache));
2811
2811
Destroy the new data cache in case of non-quick repair. All slave
2812
2812
threads did either detach from the share by remove_io_thread()
2836
2836
mi_check_print_error(param,"%d when fixing table",my_errno);
2837
2837
if (new_file >= 0)
2839
my_close(new_file,MYF(0));
2840
my_delete(param->temp_filename, MYF(MY_WME));
2839
VOID(my_close(new_file,MYF(0)));
2840
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2841
2842
if (info->dfile == new_file)
2844
2845
mi_mark_crashed_on_repair(info);
2850
2851
pthread_cond_destroy (&sort_info.cond);
2851
2852
pthread_mutex_destroy(&sort_info.mutex);
2853
free((unsigned char*) sort_info.key_block);
2854
free((unsigned char*) sort_param);
2855
free(sort_info.buff);
2856
end_io_cache(¶m->read_cache);
2854
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2855
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2856
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2857
VOID(end_io_cache(¶m->read_cache));
2857
2858
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
2859
if (!got_error && (param->testflag & T_UNPACK))
2860
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2861
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
2862
share->pack.header_length=0;
2863
2864
return(got_error);
2883
2884
sort_param->real_key_length=
2884
2885
(info->s->rec_reflength+
2885
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2886
_mi_make_key(info, sort_param->key, (uchar*) key,
2886
2887
sort_param->record, sort_param->filepos));
2887
2888
#ifdef HAVE_purify
2888
2889
memset(key+sort_param->real_key_length, 0,
2929
2930
int parallel_flag;
2930
uint32_t found_record,b_type,left_length;
2931
uint found_record,b_type,left_length;
2932
unsigned char *to= NULL;
2933
2934
MI_BLOCK_INFO block_info;
2934
2935
SORT_INFO *sort_info=sort_param->sort_info;
2935
2936
MI_CHECK *param=sort_info->param;
3005
3006
llstr(param->search_after_block,llbuff),
3006
3007
llstr(sort_param->start_recpos,llbuff2));
3007
3008
if (_mi_read_cache(&sort_param->read_cache,
3008
(unsigned char*) block_info.header,pos,
3009
(uchar*) block_info.header,pos,
3009
3010
MI_BLOCK_INFO_HEADER_LENGTH,
3010
3011
(! found_record ? READING_NEXT : 0) |
3011
3012
parallel_flag | READING_HEADER))
3032
3033
(block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3034
block_info.rec_len > (uint) share->base.max_pack_length)))
3036
3037
if (param->testflag & T_VERBOSE || searching == 0)
3037
3038
mi_check_print_info(param,
3038
3039
"Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3191
3192
streched over the end of the previous buffer contents.
3194
uint32_t header_len= (uint) (block_info.filepos - pos);
3195
uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3195
uint header_len= (uint) (block_info.filepos - pos);
3196
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3197
3198
if (prefetch_len > block_info.data_len)
3198
3199
prefetch_len= block_info.data_len;
3295
3296
ulong block_length,reclength;
3296
unsigned char *from;
3297
3298
SORT_INFO *sort_info=sort_param->sort_info;
3298
3299
MI_CHECK *param=sort_info->param;
3299
3300
MI_INFO *info=sort_info->info;
3385
3386
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3388
uint32_t not_used[2];
3389
return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
3390
return (ha_key_cmp(sort_param->seg, *((uchar* const *) a), *((uchar* const *) b),
3390
3391
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3392
} /* sort_key_cmp */
3394
3395
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3396
uint32_t diff_pos[2];
3397
3398
char llbuff[22],llbuff2[22];
3398
3399
SORT_INFO *sort_info=sort_param->sort_info;
3399
3400
MI_CHECK *param= sort_info->param;
3402
3403
if (sort_info->key_block->inited)
3404
3405
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3406
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3407
3408
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3409
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
(unsigned char*) a, USE_WHOLE_KEY,
3410
(uchar*) a, USE_WHOLE_KEY,
3410
3411
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3412
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3413
3414
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3415
sort_param->notnull,
3415
3416
sort_info->key_block->lastkey,
3418
3419
sort_param->unique[diff_pos[0]-1]++;
3423
3424
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3425
mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3427
3428
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3429
3430
sort_info->dupp++;
3430
3431
sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3432
sort_param->keyinfo,
3432
(unsigned char*) a);
3433
3434
mi_check_print_warning(param,
3434
3435
"Duplicate key for record at %10s against record at %10s",
3435
3436
llstr(sort_info->info->lastpos,llbuff),
3442
3443
return (sort_delete_record(sort_param));
3444
3445
return (sort_insert_key(sort_param,sort_info->key_block,
3445
(unsigned char*) a, HA_OFFSET_ERROR));
3446
(uchar*) a, HA_OFFSET_ERROR));
3446
3447
} /* sort_key_write */
3449
3450
/* get pointer to record from a key */
3451
3452
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3454
3455
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3456
} /* get_record_for_key */
3458
3459
/* Insert a key in sort-key-blocks */
3460
3461
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3462
register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3463
my_off_t prev_block)
3464
uint32_t a_length,t_length,nod_flag;
3465
uint a_length,t_length,nod_flag;
3465
3466
my_off_t filepos,key_file_length;
3466
unsigned char *anc_buff,*lastkey;
3467
uchar *anc_buff,*lastkey;
3467
3468
MI_KEY_PARAM s_temp;
3469
3470
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3496
3497
_mi_kpointer(info,key_block->end_pos,prev_block);
3498
3499
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
(unsigned char*) 0,lastkey,lastkey,key,
3500
(uchar*) 0,lastkey,lastkey,key,
3501
3502
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
3503
a_length+=t_length;
3504
3505
key_block->end_pos+=t_length;
3505
3506
if (a_length <= keyinfo->block_length)
3507
_mi_move_key(keyinfo,key_block->lastkey,key);
3508
VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
3509
key_block->last_length=a_length-t_length;
3523
3524
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3526
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3527
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
3528
(uint) keyinfo->block_length,filepos, param->myf_rw))
3577
3578
for (i=0 ; i < sort_info->current_key ; i++)
3579
uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
3581
if (_mi_ck_delete(info,i,key,key_length))
3582
3583
mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3598
3599
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3600
uint32_t nod_flag,length;
3601
uint nod_flag,length;
3601
3602
my_off_t filepos,key_file_length;
3602
3603
SORT_KEY_BLOCKS *key_block;
3603
3604
SORT_INFO *sort_info= sort_param->sort_info;
3625
3626
DFLT_INIT_HITS, key_block->buff))
3628
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3629
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
3630
(uint) keyinfo->block_length,filepos, myf_rw))
3637
3638
/* alloc space and pointers for key_blocks */
3639
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3640
uint32_t buffer_length)
3640
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3642
register uint32_t i;
3643
3644
SORT_KEY_BLOCKS *block;
3645
3646
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3682
3683
MI_COLUMNDEF *recdef,*rec,*end;
3683
3684
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
3685
MI_STATUS_INFO status_info;
3685
uint32_t unpack,key_parts;
3686
uint unpack,key_parts;
3686
3687
ha_rows max_records;
3687
3688
uint64_t file_length,tmp_length;
3688
3689
MI_CREATE_INFO create_info;
3702
3703
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
3704
(key_parts+share.base.keys))))
3705
my_afree((unsigned char*) keyinfo);
3706
my_afree((uchar*) keyinfo);
3708
3709
if (!(recdef=(MI_COLUMNDEF*)
3709
3710
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
my_afree((unsigned char*) keyinfo);
3712
my_afree((unsigned char*) keysegs);
3712
my_afree((uchar*) keyinfo);
3713
my_afree((uchar*) keysegs);
3715
3716
if (!(uniquedef=(MI_UNIQUEDEF*)
3716
3717
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3718
my_afree((unsigned char*) recdef);
3719
my_afree((unsigned char*) keyinfo);
3720
my_afree((unsigned char*) keysegs);
3719
my_afree((uchar*) recdef);
3720
my_afree((uchar*) keyinfo);
3721
my_afree((uchar*) keysegs);
3775
3776
set_if_bigger(file_length,tmp_length);
3776
3777
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3778
mi_close(*org_info);
3779
VOID(mi_close(*org_info));
3779
3780
memset(&create_info, 0, sizeof(create_info));
3780
create_info.max_rows=cmax(max_records,share.base.records);
3781
create_info.max_rows=max(max_records,share.base.records);
3781
3782
create_info.reloc_rows=share.base.reloc;
3782
3783
create_info.old_options=(share.options |
3783
3784
(unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3817
3818
/* We are modifing */
3818
3819
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
_mi_readinfo(*org_info,F_WRLCK,0);
3820
VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
3821
(*org_info)->state->records=info.state->records;
3821
3822
if (share.state.create_time)
3822
3823
(*org_info)->s->state.create_time=share.state.create_time;
3835
my_afree((unsigned char*) uniquedef);
3836
my_afree((unsigned char*) keyinfo);
3837
my_afree((unsigned char*) recdef);
3838
my_afree((unsigned char*) keysegs);
3836
my_afree((uchar*) uniquedef);
3837
my_afree((uchar*) keyinfo);
3838
my_afree((uchar*) recdef);
3839
my_afree((uchar*) keysegs);
3849
3850
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3851
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
uchar buff[MEMMAP_EXTRA_MARGIN];
3852
3853
memset(buff, 0, sizeof(buff));
3853
3854
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3864
3865
/* Update state and myisamchk_time of indexfile */
3866
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
3867
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3868
3869
MYISAM_SHARE *share=info->s;
3875
3876
if (update & UPDATE_STAT)
3877
uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
3879
share->state.rec_per_key_rows=info->state->records;
3879
3880
share->state.changed&= ~STATE_NOT_ANALYZED;
3880
3881
if (info->state->records)
3909
3910
{ /* Force update of status */
3911
uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
3912
uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
3913
share->r_locks= share->w_locks= share->tot_locks= 0;
3913
3914
error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
3915
share->r_locks=r_locks;
3938
3939
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3939
3940
bool repair_only)
3941
unsigned char *record= 0;
3943
3944
if (!info->s->base.auto_key ||
3944
3945
! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3968
3969
if (my_errno != HA_ERR_END_OF_FILE)
3970
3971
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
free(mi_get_rec_buff_ptr(info, record));
3972
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
3973
mi_check_print_error(param,"%d when reading last record",my_errno);
3983
3984
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3985
3986
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
free(mi_get_rec_buff_ptr(info, record));
3987
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
3988
update_state_info(param, info, UPDATE_AUTO_INC);
4086
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4087
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4088
4089
ha_checksum crc;
4089
const unsigned char *end=buf+length;
4090
const uchar *end=buf+length;
4090
4091
for (crc=0; buf != end; buf++)
4091
crc=((crc << 1) + *((unsigned char*) buf)) +
4092
crc=((crc << 1) + *((uchar*) buf)) +
4092
4093
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4096
4097
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4098
uint32_t key_maxlength=key->maxlength;
4099
uint key_maxlength=key->maxlength;
4099
4100
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4100
4101
((uint64_t) rows * key_maxlength >
4101
4102
(uint64_t) myisam_max_temp_length));