52
52
#ifdef HAVE_SYS_MMAN_H
53
53
#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);
57
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
58
#define my_raid_delete(A,B,C) my_delete(A,B)
61
/* Functions defined in this file */
63
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
61
64
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);
65
my_off_t page, uchar *buff, ha_rows *keys,
66
ha_checksum *key_checksum, uint level);
67
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
68
static ha_checksum calc_checksum(ha_rows count);
66
69
static int writekeys(MI_SORT_PARAM *sort_param);
67
70
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
71
74
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
75
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
76
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
75
78
static int sort_insert_key(MI_SORT_PARAM *sort_param,
76
79
register SORT_KEY_BLOCKS *key_block,
77
unsigned char *key, my_off_t prev_block);
80
uchar *key, my_off_t prev_block);
78
81
static int sort_delete_record(MI_SORT_PARAM *sort_param);
79
82
/*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);
83
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
85
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
83
86
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
85
88
void myisamchk_init(MI_CHECK *param)
117
120
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
119
122
/* Don't count this as a real warning, as check can correct this ! */
120
uint32_t save=param->warning_printed;
123
uint save=param->warning_printed;
121
124
mi_check_print_warning(param,
122
125
share->state.open_count==1 ?
123
126
"%d client is using or hasn't closed the table properly" :
133
136
/* Check delete links */
135
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
138
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
137
140
register ha_rows i;
138
uint32_t delete_link_length;
141
uint delete_link_length;
139
142
my_off_t empty, next_link, old_link= 0;
140
143
char buff[22],buff2[22];
167
170
printf(" %9s",llstr(next_link,buff));
168
171
if (next_link >= info->state->data_file_length)
170
if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
173
if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
174
next_link,MYF(MY_NABP)))
173
176
if (test_flag & T_VERBOSE) puts("");
200
203
param->record_checksum+=(ha_checksum) next_link;
201
next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
204
next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
202
205
empty+=info->s->base.pack_reclength;
240
243
/* Check delete links in index file */
242
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
245
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
244
247
my_off_t next_link;
245
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
248
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
250
char llbuff[21], llbuff2[21];
250
253
if (param->testflag & T_VERBOSE)
251
254
printf("block_size %4u:", block_size); /* purecov: tested */
290
293
if (!(buff=key_cache_read(info->s->key_cache,
291
294
info->s->kfile, next_link, DFLT_INIT_HITS,
292
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
295
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
296
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
298
/* purecov: begin tested */
393
396
int chk_key(MI_CHECK *param, register MI_INFO *info)
395
uint32_t key,found_keys=0,full_text_keys=0,result=0;
398
uint key,found_keys=0,full_text_keys=0,result=0;
397
400
ha_checksum old_record_checksum,init_checksum;
398
401
my_off_t all_keydata,all_totaldata,key_totlength,length;
520
523
/* Check that there isn't a row with auto_increment = 0 in the table */
521
524
mi_extra(info,HA_EXTRA_KEYREAD,0);
522
525
memset(info->lastkey, 0, keyinfo->seg->length);
523
if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
526
if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
524
527
(key_part_map)1, HA_READ_KEY_EXACT))
526
529
/* Don't count this as a real warning, as myisamchk can't correct it */
527
uint32_t save=param->warning_printed;
530
uint save=param->warning_printed;
528
531
mi_check_print_warning(param, "Found row where the auto_increment "
529
532
"column has the value 0");
530
533
param->warning_printed=save;
575
578
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)
579
my_off_t page, uchar *buff, ha_rows *keys,
580
ha_checksum *key_checksum, uint level)
579
582
char llbuff[22],llbuff2[22];
646
649
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
649
uint32_t first_null, kp;
650
653
first_null= ha_find_null(keyseg, key) - keyseg;
652
655
All prefix tuples that don't include keypart_{first_null} are not-null
686
689
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
unsigned char *prev_key, unsigned char *last_key)
690
uchar *prev_key, uchar *last_key)
690
uint32_t first_null_seg, kp;
693
uint first_null_seg, kp;
719
722
/* Check if index is ok */
721
724
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)
725
my_off_t page, uchar *buff, ha_rows *keys,
726
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;
729
uint used_length,comp_flag,nod_flag,key_length=0;
730
uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
731
my_off_t next_page,record;
730
uint32_t diff_pos[2];
732
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
735
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
734
737
mi_check_print_error(param,"Not enough memory for keyblock");
814
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
817
(*key_checksum)+= mi_byte_checksum((uchar*) key,
815
818
key_length- info->s->rec_reflength);
816
819
record= _mi_dpos(info,0,key+key_length);
817
820
if (record >= info->state->data_file_length)
827
830
llstr(page,llbuff), used_length, (keypos - buff));
830
my_afree((unsigned char*) temp_buff);
833
my_afree((uchar*) temp_buff);
833
my_afree((unsigned char*) temp_buff);
836
my_afree((uchar*) temp_buff);
835
838
} /* chk_index */
860
863
/* Calc length of key in normal isam */
862
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
865
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
865
868
HA_KEYSEG *keyseg;
867
870
length= info->s->rec_reflength;
881
884
ha_rows records, del_blocks;
882
885
my_off_t used, empty, pos, splits, start_recpos= 0,
883
886
del_length, link_used, start_block;
884
unsigned char *record= NULL, *to= NULL;
887
uchar *record= NULL, *to= NULL;
885
888
char llbuff[22],llbuff2[22],llbuff3[22];
886
889
ha_checksum intern_record_checksum;
887
890
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
932
935
switch (info->s->data_file_type) {
933
936
case STATIC_RECORD:
934
if (my_b_read(¶m->read_cache,(unsigned char*) record,
937
if (my_b_read(¶m->read_cache,(uchar*) record,
935
938
info->s->base.pack_reclength))
937
940
start_recpos=pos;
951
954
block_info.next_filepos=pos;
954
if (_mi_read_cache(¶m->read_cache,(unsigned char*) block_info.header,
957
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
955
958
(start_block=block_info.next_filepos),
956
959
sizeof(block_info.header),
957
960
(flag ? 0 : READING_NEXT) | READING_HEADER))
1058
if (_mi_read_cache(¶m->read_cache,(unsigned char*) to,block_info.filepos,
1061
if (_mi_read_cache(¶m->read_cache,(uchar*) to,block_info.filepos,
1059
1062
(uint) block_info.data_len,
1060
1063
flag == 1 ? READING_NEXT : 0))
1136
1139
if (mi_is_key_active(info->s->state.key_map, key))
1139
uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1142
uint key_length=_mi_make_key(info,key,info->lastkey,record,
1265
1268
printf("Lost space: %12s Linkdata: %10s\n",
1266
1269
llstr(empty,llbuff),llstr(link_used,llbuff2));
1268
free(mi_get_rec_buff_ptr(info, record));
1271
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1269
1272
return (error);
1271
1274
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));
1276
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1277
param->testflag|=T_RETRY_WITHOUT_QUICK;
1276
1279
} /* chk_data_link */
1461
1464
if (!rep_quick)
1463
1466
/* 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,
1467
if ((new_file=my_raid_create(fn_format(param->temp_filename,
1468
share->data_file_name, "",
1470
0,param->tmpfile_createflag,
1471
share->base.raid_type,
1472
share->base.raid_chunks,
1473
share->base.raid_chunksize,
1470
1476
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
param->temp_filename);
1477
param->temp_filename);
1474
1480
if (new_header_length &&
1475
1481
filecopy(param,new_file,info->dfile,0L,new_header_length,
1478
1484
info->s->state.dellink= HA_OFFSET_ERROR;
1479
1485
info->rec_cache.file=new_file;
1629
1635
if (new_file >= 0)
1631
1637
my_close(new_file,MYF(0));
1632
my_delete(param->temp_filename, MYF(MY_WME));
1638
my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1633
1640
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1635
1642
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);
1644
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1645
MYF(MY_ALLOW_ZERO_PTR));
1646
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1647
MYF(MY_ALLOW_ZERO_PTR));
1648
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1648
1649
end_io_cache(¶m->read_cache);
1649
1650
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
1651
end_io_cache(&info->rec_cache);
1651
1652
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1653
if (!got_error && param->testflag & T_UNPACK)
1654
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1655
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1656
share->pack.header_length=0;
1656
1657
share->data_file_type=sort_info.new_data_file_type;
1666
1667
static int writekeys(MI_SORT_PARAM *sort_param)
1668
register uint32_t i;
1670
1671
MI_INFO *info= sort_param->sort_info->info;
1671
unsigned char *buff= sort_param->record;
1672
uchar *buff= sort_param->record;
1672
1673
my_off_t filepos= sort_param->filepos;
1674
1675
key=info->lastkey+info->s->base.max_key_length;
1677
1678
if (mi_is_key_active(info->s->state.key_map, i))
1680
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1681
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1682
if (_mi_ck_write(info,i,key,key_length))
1694
1695
if (mi_is_key_active(info->s->state.key_map, i))
1697
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1698
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1699
if (_mi_ck_delete(info,i,key,key_length))
1711
1712
/* 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)
1714
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1715
my_off_t newpos, uint prot_key)
1716
register uint32_t i;
1718
uint32_t key_length;
1720
1721
key=info->lastkey+info->s->base.max_key_length;
1721
1722
for (i=0 ; i < info->s->base.keys; i++)
1725
1726
key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1727
if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1728
{ /* Change pointer direct */
1729
1730
MI_KEYDEF *keyinfo;
1730
1731
keyinfo=info->s->keyinfo+i;
1731
1732
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1789
1790
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1791
register uint32_t key;
1792
1793
register MI_KEYDEF *keyinfo;
1794
1795
my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
uint32_t r_locks,w_locks;
1796
uint r_locks,w_locks;
1797
1798
MYISAM_SHARE *share=info->s;
1798
1799
MI_STATE_INFO old_state;
1886
1887
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
1888
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];
1890
uint length,nod_flag,used_length, key_length;
1891
uchar *buff,*keypos,*endpos;
1892
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
1893
my_off_t new_page_pos,next_page;
1893
1894
char llbuff[22];
1895
1896
new_page_pos=param->new_file_pos;
1896
1897
param->new_file_pos+=keyinfo->block_length;
1898
if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1899
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1900
1901
mi_check_print_error(param,"Not enough memory for key block");
1932
1933
/* Fill block with zero and write it to the new index file */
1933
1934
length=mi_getint(buff);
1934
1935
memset(buff+length, 0, keyinfo->block_length-length);
1935
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1936
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
1937
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1938
1939
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1941
my_afree((unsigned char*) buff);
1942
my_afree((uchar*) buff);
1944
my_afree((unsigned char*) buff);
1945
my_afree((uchar*) buff);
1946
1947
} /* sort_one_index */
1958
1959
int change_to_newfile(const char * filename, const char * old_ext,
1959
1960
const char * new_ext,
1960
uint32_t raid_chunks __attribute__((unused)),
1961
uint raid_chunks __attribute__((unused)),
1963
1964
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1987
1988
my_seek(from,start,MY_SEEK_SET,MYF(0));
1988
1989
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))
1991
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
1992
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1993
1994
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))
1996
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
1997
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1998
1999
if (buff != tmp_buff)
2000
my_free(buff,MYF(0));
2002
2003
if (buff != tmp_buff)
2004
my_free(buff,MYF(0));
2004
2005
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2006
type,my_errno);
2082
2083
if (!rep_quick)
2084
2085
/* 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,
2086
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2087
share->data_file_name, "",
2089
0,param->tmpfile_createflag,
2090
share->base.raid_type,
2091
share->base.raid_chunks,
2092
share->base.raid_chunksize,
2091
2095
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
param->temp_filename);
2096
param->temp_filename);
2095
2099
if (new_header_length &&
2327
2331
if (new_file >= 0)
2329
2333
my_close(new_file,MYF(0));
2330
my_delete(param->temp_filename, MYF(MY_WME));
2334
my_raid_delete(param->temp_filename,share->base.raid_chunks,
2331
2336
if (info->dfile == new_file)
2334
2339
mi_mark_crashed_on_repair(info);
2337
2342
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2343
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);
2345
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2346
MYF(MY_ALLOW_ZERO_PTR));
2347
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2348
MYF(MY_ALLOW_ZERO_PTR));
2349
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2350
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2351
2351
end_io_cache(¶m->read_cache);
2352
2352
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2353
if (!got_error && (param->testflag & T_UNPACK))
2355
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2355
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2356
share->pack.header_length=0;
2358
2358
return(got_error);
2404
2404
const char * name, int rep_quick)
2407
uint32_t i,key, total_key_length, istep;
2407
uint i,key, total_key_length, istep;
2408
2408
ulong rec_length;
2409
2409
ha_rows start_records;
2410
2410
my_off_t new_header_length,del;
2492
2492
if (!rep_quick)
2494
2494
/* 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,
2495
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2496
share->data_file_name, "",
2499
0,param->tmpfile_createflag,
2500
share->base.raid_type,
2501
share->base.raid_chunks,
2502
share->base.raid_chunksize,
2502
2505
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2506
param->temp_filename);
2616
2619
sort_param[i].filepos=new_header_length;
2617
2620
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))+
2622
sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2623
(max_pack_reclength * i));
2621
2624
if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2837
2840
if (new_file >= 0)
2839
2842
my_close(new_file,MYF(0));
2840
my_delete(param->temp_filename, MYF(MY_WME));
2843
my_raid_delete(param->temp_filename,share->base.raid_chunks,
2841
2845
if (info->dfile == new_file)
2844
2848
mi_mark_crashed_on_repair(info);
2850
2854
pthread_cond_destroy (&sort_info.cond);
2851
2855
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);
2857
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2858
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2859
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2856
2860
end_io_cache(¶m->read_cache);
2857
2861
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
2862
if (!got_error && (param->testflag & T_UNPACK))
2860
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2864
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
2865
share->pack.header_length=0;
2863
2867
return(got_error);
2883
2887
sort_param->real_key_length=
2884
2888
(info->s->rec_reflength+
2885
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2889
_mi_make_key(info, sort_param->key, (uchar*) key,
2886
2890
sort_param->record, sort_param->filepos));
2887
2891
#ifdef HAVE_purify
2888
2892
memset(key+sort_param->real_key_length, 0,
2929
2933
int parallel_flag;
2930
uint32_t found_record,b_type,left_length;
2934
uint found_record,b_type,left_length;
2932
unsigned char *to= NULL;
2933
2937
MI_BLOCK_INFO block_info;
2934
2938
SORT_INFO *sort_info=sort_param->sort_info;
2935
2939
MI_CHECK *param=sort_info->param;
3005
3009
llstr(param->search_after_block,llbuff),
3006
3010
llstr(sort_param->start_recpos,llbuff2));
3007
3011
if (_mi_read_cache(&sort_param->read_cache,
3008
(unsigned char*) block_info.header,pos,
3012
(uchar*) block_info.header,pos,
3009
3013
MI_BLOCK_INFO_HEADER_LENGTH,
3010
3014
(! found_record ? READING_NEXT : 0) |
3011
3015
parallel_flag | READING_HEADER))
3032
3036
(block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3037
block_info.rec_len > (uint) share->base.max_pack_length)))
3036
3040
if (param->testflag & T_VERBOSE || searching == 0)
3037
3041
mi_check_print_info(param,
3038
3042
"Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3191
3195
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);
3198
uint header_len= (uint) (block_info.filepos - pos);
3199
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3197
3201
if (prefetch_len > block_info.data_len)
3198
3202
prefetch_len= block_info.data_len;
3295
3299
ulong block_length,reclength;
3296
unsigned char *from;
3297
3301
SORT_INFO *sort_info=sort_param->sort_info;
3298
3302
MI_CHECK *param=sort_info->param;
3299
3303
MI_INFO *info=sort_info->info;
3385
3389
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),
3393
return (ha_key_cmp(sort_param->seg, *((uchar* const *) a), *((uchar* const *) b),
3390
3394
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3395
} /* sort_key_cmp */
3394
3398
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3396
uint32_t diff_pos[2];
3397
3401
char llbuff[22],llbuff2[22];
3398
3402
SORT_INFO *sort_info=sort_param->sort_info;
3399
3403
MI_CHECK *param= sort_info->param;
3402
3406
if (sort_info->key_block->inited)
3404
3408
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3409
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3407
3411
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3412
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
(unsigned char*) a, USE_WHOLE_KEY,
3413
(uchar*) a, USE_WHOLE_KEY,
3410
3414
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3415
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3413
3417
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3418
sort_param->notnull,
3415
3419
sort_info->key_block->lastkey,
3418
3422
sort_param->unique[diff_pos[0]-1]++;
3423
3427
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3428
mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3427
3431
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3429
3433
sort_info->dupp++;
3430
3434
sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3435
sort_param->keyinfo,
3432
(unsigned char*) a);
3433
3437
mi_check_print_warning(param,
3434
3438
"Duplicate key for record at %10s against record at %10s",
3435
3439
llstr(sort_info->info->lastpos,llbuff),
3442
3446
return (sort_delete_record(sort_param));
3444
3448
return (sort_insert_key(sort_param,sort_info->key_block,
3445
(unsigned char*) a, HA_OFFSET_ERROR));
3449
(uchar*) a, HA_OFFSET_ERROR));
3446
3450
} /* sort_key_write */
3449
3453
/* get pointer to record from a key */
3451
3455
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3454
3458
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3459
} /* get_record_for_key */
3458
3462
/* Insert a key in sort-key-blocks */
3460
3464
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3465
register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3466
my_off_t prev_block)
3464
uint32_t a_length,t_length,nod_flag;
3468
uint a_length,t_length,nod_flag;
3465
3469
my_off_t filepos,key_file_length;
3466
unsigned char *anc_buff,*lastkey;
3470
uchar *anc_buff,*lastkey;
3467
3471
MI_KEY_PARAM s_temp;
3469
3473
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3496
3500
_mi_kpointer(info,key_block->end_pos,prev_block);
3498
3502
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
(unsigned char*) 0,lastkey,lastkey,key,
3503
(uchar*) 0,lastkey,lastkey,key,
3501
3505
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
3506
a_length+=t_length;
3523
3527
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3526
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3530
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
3531
(uint) keyinfo->block_length,filepos, param->myf_rw))
3577
3581
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);
3583
uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
3584
if (_mi_ck_delete(info,i,key,key_length))
3582
3586
mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3598
3602
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3600
uint32_t nod_flag,length;
3604
uint nod_flag,length;
3601
3605
my_off_t filepos,key_file_length;
3602
3606
SORT_KEY_BLOCKS *key_block;
3603
3607
SORT_INFO *sort_info= sort_param->sort_info;
3625
3629
DFLT_INIT_HITS, key_block->buff))
3628
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3632
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
3633
(uint) keyinfo->block_length,filepos, myf_rw))
3637
3641
/* 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)
3643
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3642
register uint32_t i;
3643
3647
SORT_KEY_BLOCKS *block;
3645
3649
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3682
3686
MI_COLUMNDEF *recdef,*rec,*end;
3683
3687
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
3688
MI_STATUS_INFO status_info;
3685
uint32_t unpack,key_parts;
3689
uint unpack,key_parts;
3686
3690
ha_rows max_records;
3687
3691
uint64_t file_length,tmp_length;
3688
3692
MI_CREATE_INFO create_info;
3702
3706
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
3707
(key_parts+share.base.keys))))
3705
my_afree((unsigned char*) keyinfo);
3709
my_afree((uchar*) keyinfo);
3708
3712
if (!(recdef=(MI_COLUMNDEF*)
3709
3713
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
my_afree((unsigned char*) keyinfo);
3712
my_afree((unsigned char*) keysegs);
3715
my_afree((uchar*) keyinfo);
3716
my_afree((uchar*) keysegs);
3715
3719
if (!(uniquedef=(MI_UNIQUEDEF*)
3716
3720
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);
3722
my_afree((uchar*) recdef);
3723
my_afree((uchar*) keyinfo);
3724
my_afree((uchar*) keysegs);
3835
my_afree((unsigned char*) uniquedef);
3836
my_afree((unsigned char*) keyinfo);
3837
my_afree((unsigned char*) recdef);
3838
my_afree((unsigned char*) keysegs);
3839
my_afree((uchar*) uniquedef);
3840
my_afree((uchar*) keyinfo);
3841
my_afree((uchar*) recdef);
3842
my_afree((uchar*) keysegs);
3849
3853
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3851
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3855
uchar buff[MEMMAP_EXTRA_MARGIN];
3852
3856
memset(buff, 0, sizeof(buff));
3853
3857
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3864
3868
/* Update state and myisamchk_time of indexfile */
3866
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
3870
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3868
3872
MYISAM_SHARE *share=info->s;
3875
3879
if (update & UPDATE_STAT)
3877
uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
3881
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
3882
share->state.rec_per_key_rows=info->state->records;
3879
3883
share->state.changed&= ~STATE_NOT_ANALYZED;
3880
3884
if (info->state->records)
3909
3913
{ /* Force update of status */
3911
uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
3915
uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
3916
share->r_locks= share->w_locks= share->tot_locks= 0;
3913
3917
error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
3918
share->r_locks=r_locks;
3938
3942
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3939
3943
bool repair_only)
3941
unsigned char *record= 0;
3943
3947
if (!info->s->base.auto_key ||
3944
3948
! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3968
3972
if (my_errno != HA_ERR_END_OF_FILE)
3970
3974
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
free(mi_get_rec_buff_ptr(info, record));
3975
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
3976
mi_check_print_error(param,"%d when reading last record",my_errno);
3983
3987
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3985
3989
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
free(mi_get_rec_buff_ptr(info, record));
3990
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
3991
update_state_info(param, info, UPDATE_AUTO_INC);
4086
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4090
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4088
4092
ha_checksum crc;
4089
const unsigned char *end=buf+length;
4093
const uchar *end=buf+length;
4090
4094
for (crc=0; buf != end; buf++)
4091
crc=((crc << 1) + *((unsigned char*) buf)) +
4095
crc=((crc << 1) + *((uchar*) buf)) +
4092
4096
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4096
4100
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4098
uint32_t key_maxlength=key->maxlength;
4102
uint key_maxlength=key->maxlength;
4099
4103
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4100
4104
((uint64_t) rows * key_maxlength >
4101
4105
(uint64_t) myisam_max_temp_length));