40
40
only. And it is sufficient to calculate the checksum once only.
43
#include "myisam_priv.h"
44
#include "drizzled/internal/m_string.h"
43
#include "myisamdef.h"
45
44
#include <stdarg.h>
46
#include "drizzled/option.h"
45
#include <mysys/my_getopt.h>
47
46
#ifdef HAVE_SYS_VADVISE_H
48
47
#include <sys/vadvise.h>
51
#include <sys/types.h>
53
49
#ifdef HAVE_SYS_MMAN_H
54
50
#include <sys/mman.h>
56
#include <drizzled/util/test.h>
57
#include "drizzled/error.h"
62
using namespace drizzled;
63
using namespace drizzled::internal;
66
#define my_off_t2double(A) ((double) (my_off_t) (A))
68
/* Functions defined in this file */
70
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);
71
61
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
72
my_off_t page, unsigned char *buff, ha_rows *keys,
73
ha_checksum *key_checksum, uint32_t level);
74
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);
75
65
static ha_checksum calc_checksum(ha_rows count);
76
66
static int writekeys(MI_SORT_PARAM *sort_param);
77
67
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
78
my_off_t pagepos, int new_file);
79
int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
80
int sort_get_next_record(MI_SORT_PARAM *sort_param);
81
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
82
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
83
my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
85
int sort_insert_key(MI_SORT_PARAM *sort_param,
86
register SORT_KEY_BLOCKS *key_block,
87
unsigned char *key, my_off_t prev_block);
88
int sort_delete_record(MI_SORT_PARAM *sort_param);
68
my_off_t pagepos, File new_file);
69
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
70
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
71
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
75
static int sort_insert_key(MI_SORT_PARAM *sort_param,
76
register SORT_KEY_BLOCKS *key_block,
77
uchar *key, my_off_t prev_block);
78
static int sort_delete_record(MI_SORT_PARAM *sort_param);
90
79
/*static int flush_pending_blocks(MI_CHECK *param);*/
91
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
92
uint32_t buffer_length);
93
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);
94
83
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
96
85
void myisamchk_init(MI_CHECK *param)
128
117
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
130
119
/* Don't count this as a real warning, as check can correct this ! */
131
uint32_t save=param->warning_printed;
120
uint save=param->warning_printed;
132
121
mi_check_print_warning(param,
133
share->state.open_count==1 ?
134
"%d client is using or hasn't closed the table properly" :
122
share->state.open_count==1 ?
123
"%d client is using or hasn't closed the table properly" :
135
124
"%d clients are using or haven't closed the table properly",
136
125
share->state.open_count);
137
126
/* If this will be fixed by the check, forget the warning */
251
240
/* Check delete links in index file */
253
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)
255
244
my_off_t next_link;
256
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
245
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
258
247
char llbuff[21], llbuff2[21];
261
250
if (param->testflag & T_VERBOSE)
262
printf("block_size %4u:", block_size);
251
printf("block_size %4u:", block_size); /* purecov: tested */
264
253
next_link=info->s->state.key_del[nr];
265
254
records= (ha_rows) (info->state->key_file_length / block_size);
273
262
/* Key blocks must lay within the key file length entirely. */
274
263
if (next_link + block_size > info->state->key_file_length)
265
/* purecov: begin tested */
276
266
mi_check_print_error(param, "Invalid key block position: %s "
277
267
"key block size: %u file_length: %s",
278
268
llstr(next_link, llbuff), block_size,
279
269
llstr(info->state->key_file_length, llbuff2));
283
274
/* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
284
275
if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
277
/* purecov: begin tested */
286
278
mi_check_print_error(param, "Mis-aligned key block: %s "
287
279
"minimum key block length: %u",
288
280
llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
297
290
if (!(buff=key_cache_read(info->s->key_cache,
298
291
info->s->kfile, next_link, DFLT_INIT_HITS,
299
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
292
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
300
293
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
/* purecov: begin tested */
302
296
mi_check_print_error(param, "key cache read error for block: %s",
303
297
llstr(next_link,llbuff));
306
301
next_link=mi_sizekorr(buff);
525
520
/* Check that there isn't a row with auto_increment = 0 in the table */
526
521
mi_extra(info,HA_EXTRA_KEYREAD,0);
527
522
memset(info->lastkey, 0, keyinfo->seg->length);
528
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,
529
524
(key_part_map)1, HA_READ_KEY_EXACT))
531
526
/* Don't count this as a real warning, as myisamchk can't correct it */
532
uint32_t save=param->warning_printed;
527
uint save=param->warning_printed;
533
528
mi_check_print_warning(param, "Found row where the auto_increment "
534
529
"column has the value 0");
535
530
param->warning_printed=save;
580
575
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
581
my_off_t page, unsigned char *buff, ha_rows *keys,
582
ha_checksum *key_checksum, uint32_t level)
576
my_off_t page, uchar *buff, ha_rows *keys,
577
ha_checksum *key_checksum, uint level)
584
579
char llbuff[22],llbuff2[22];
586
581
/* Key blocks must lay within the key file length entirely. */
587
582
if (page + keyinfo->block_length > info->state->key_file_length)
584
/* purecov: begin tested */
589
585
/* Give it a chance to fit in the real file size. */
590
my_off_t max_length= lseek(info->s->kfile, 0, SEEK_END);
586
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
591
588
mi_check_print_error(param, "Invalid key block position: %s "
592
589
"key block size: %u file_length: %s",
593
590
llstr(page, llbuff), keyinfo->block_length,
597
594
/* Fix the remebered key file length. */
598
595
info->state->key_file_length= (max_length &
599
596
~ (my_off_t) (keyinfo->block_length - 1));
602
600
/* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
603
601
if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
603
/* purecov: begin tested */
605
604
mi_check_print_error(param, "Mis-aligned key block: %s "
606
605
"minimum key block length: %u",
607
606
llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
611
611
if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
671
673
1. Find out which prefix tuples of last_key don't contain NULLs, and
672
674
update the array of notnull counters accordingly.
673
675
2. Find the first keypart number where the prev_key and last_key tuples
674
are different(A), or last_key has NULL value(B), and return it, so the
675
caller can count number of unique tuples for each key prefix. We don't
676
need (B) to be counted, and that is compensated back in
676
are different(A), or last_key has NULL value(B), and return it, so the
677
caller can count number of unique tuples for each key prefix. We don't
678
need (B) to be counted, and that is compensated back in
677
679
update_key_parts().
717
719
/* Check if index is ok */
719
721
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
720
my_off_t page, unsigned char *buff, ha_rows *keys,
721
ha_checksum *key_checksum, uint32_t level)
722
my_off_t page, uchar *buff, ha_rows *keys,
723
ha_checksum *key_checksum, uint level)
724
uint32_t used_length,comp_flag,nod_flag,key_length=0;
725
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;
726
728
my_off_t next_page,record;
728
uint32_t diff_pos[2];
730
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
732
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
732
734
mi_check_print_error(param,"Not enough memory for keyblock");
797
799
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
799
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
801
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
800
802
param->notnull_count,
801
803
info->lastkey, key);
803
805
param->unique_count[diff_pos[0]-1]++;
807
809
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
808
810
mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
812
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
814
(*key_checksum)+= mi_byte_checksum((uchar*) key,
813
815
key_length- info->s->rec_reflength);
814
816
record= _mi_dpos(info,0,key+key_length);
815
817
if (record >= info->state->data_file_length)
879
881
ha_rows records, del_blocks;
880
882
my_off_t used, empty, pos, splits, start_recpos= 0,
881
883
del_length, link_used, start_block;
882
unsigned char *record= NULL, *to= NULL;
884
uchar *record= NULL, *to= NULL;
883
885
char llbuff[22],llbuff2[22],llbuff3[22];
884
886
ha_checksum intern_record_checksum;
885
887
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
1263
1265
printf("Lost space: %12s Linkdata: %10s\n",
1264
1266
llstr(empty,llbuff),llstr(link_used,llbuff2));
1266
free(mi_get_rec_buff_ptr(info, record));
1268
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1267
1269
return (error);
1269
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",errno, llstr(records,llbuff));
1271
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1271
free(mi_get_rec_buff_ptr(info, record));
1273
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1272
1274
param->testflag|=T_RETRY_WITHOUT_QUICK;
1274
1276
} /* chk_data_link */
1430
1432
param->testflag|=T_REP; /* for easy checking */
1432
if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
1434
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1433
1435
param->testflag|=T_CALC_CHECKSUM;
1435
1437
if (!param->using_global_keycache)
1436
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1437
(size_t)param->use_buffers, 0, 0);
1438
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0));
1439
1441
if (init_io_cache(¶m->read_cache,info->dfile,
1440
1442
(uint) param->read_buffer_length,
1459
1461
if (!rep_quick)
1461
1463
/* Get real path for data file */
1462
if ((new_file=my_create(internal::fn_format(param->temp_filename,
1463
share->data_file_name, "",
1465
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,
1468
1473
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1469
param->temp_filename);
1474
param->temp_filename);
1472
1477
if (new_header_length &&
1473
1478
filecopy(param,new_file,info->dfile,0L,new_header_length,
1476
1481
info->s->state.dellink= HA_OFFSET_ERROR;
1477
1482
info->rec_cache.file=new_file;
1624
1629
if (! param->error_printed)
1625
mi_check_print_error(param,"%d for record at pos %s",errno,
1630
mi_check_print_error(param,"%d for record at pos %s",my_errno,
1626
1631
llstr(sort_param.start_recpos,llbuff));
1627
1632
if (new_file >= 0)
1629
internal::my_close(new_file,MYF(0));
1630
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,
1631
1637
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1633
1639
mi_mark_crashed_on_repair(info);
1636
void * rec_buff_ptr= NULL;
1637
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1638
if (rec_buff_ptr != NULL)
1640
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1641
if (rec_buff_ptr != NULL)
1645
free(sort_info.buff);
1646
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));
1647
1647
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1648
end_io_cache(&info->rec_cache);
1648
VOID(end_io_cache(&info->rec_cache));
1649
1649
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1650
1650
if (!got_error && param->testflag & T_UNPACK)
1652
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1652
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1653
1653
share->pack.header_length=0;
1654
1654
share->data_file_type=sort_info.new_data_file_type;
1754
1754
/* Tell system that we want all memory for our cache */
1756
void lock_memory(MI_CHECK *)
1756
void lock_memory(MI_CHECK *param __attribute__((unused)))
1758
#ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */
1759
if (param->opt_lock_memory)
1761
int success = mlockall(MCL_CURRENT); /* or plock(DATLOCK); */
1762
if (geteuid() == 0 && success != 0)
1763
mi_check_print_warning(param,
1764
"Failed to lock memory. errno %d",my_errno);
1758
1767
} /* lock_memory */
1761
1770
/* Flush all changed blocks to disk */
1763
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, int file)
1772
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file)
1765
1774
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
1767
mi_check_print_error(param,"%d when trying to write bufferts",errno);
1776
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
1770
1779
if (!param->using_global_keycache)
1794
1803
printf("- Sorting index for MyISAM-table '%s'\n",name);
1796
1805
/* Get real path for index file */
1797
internal::fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
1798
if ((new_file=my_create(internal::fn_format(param->temp_filename,param->temp_filename,
1806
fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
1807
if ((new_file=my_create(fn_format(param->temp_filename,param->temp_filename,
1799
1808
"", INDEX_TMP_EXT,2+4),
1800
1809
0,param->tmpfile_createflag,MYF(0))) <= 0)
1873
1882
/* Sort records recursive using one index */
1875
1884
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1876
my_off_t pagepos, int new_file)
1885
my_off_t pagepos, File new_file)
1878
uint32_t length,nod_flag,used_length, key_length;
1879
unsigned char *buff,*keypos,*endpos;
1880
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];
1881
1890
my_off_t new_page_pos,next_page;
1882
1891
char llbuff[22];
1884
1893
new_page_pos=param->new_file_pos;
1885
1894
param->new_file_pos+=keyinfo->block_length;
1887
if (!(buff=(unsigned char*) malloc(keyinfo->block_length)))
1896
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1889
1898
mi_check_print_error(param,"Not enough memory for key block");
1921
1930
/* Fill block with zero and write it to the new index file */
1922
1931
length=mi_getint(buff);
1923
1932
memset(buff+length, 0, keyinfo->block_length-length);
1924
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1933
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1925
1934
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1927
mi_check_print_error(param,"Can't write indexblock, error: %d",errno);
1936
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1939
my_afree((uchar*) buff);
1942
my_afree((uchar*) buff);
1935
1944
} /* sort_one_index */
1947
1956
int change_to_newfile(const char * filename, const char * old_ext,
1948
1957
const char * new_ext,
1949
uint32_t raid_chunks,
1958
uint raid_chunks __attribute__((unused)),
1953
1961
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1954
1962
/* Get real path to filename */
1955
(void) internal::fn_format(old_filename,filename,"",old_ext,2+4+32);
1963
(void) fn_format(old_filename,filename,"",old_ext,2+4+32);
1956
1964
return my_redel(old_filename,
1957
internal::fn_format(new_filename,old_filename,"",new_ext,2+4),
1965
fn_format(new_filename,old_filename,"",new_ext,2+4),
1958
1966
MYF(MY_WME | MY_LINK_WARNING | MyFlags));
1959
1967
} /* change_to_newfile */
1963
1971
/* Copy a block between two files */
1965
int filecopy(MI_CHECK *param, int to,int from,my_off_t start,
1973
int filecopy(MI_CHECK *param, File to,File from,my_off_t start,
1966
1974
my_off_t length, const char *type)
1968
1976
char tmp_buff[IO_SIZE],*buff;
1969
1977
ulong buff_length;
1971
buff_length=(ulong) min(param->write_buffer_length, (size_t)length);
1972
if (!(buff=(char *)malloc(buff_length)))
1979
buff_length=(ulong) min(param->write_buffer_length,length);
1980
if (!(buff=my_malloc(buff_length,MYF(0))))
1974
1982
buff=tmp_buff; buff_length=IO_SIZE;
1977
lseek(from,start,SEEK_SET);
1985
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1978
1986
while (length > buff_length)
1980
if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1981
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))
1983
1991
length-= buff_length;
1985
if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1986
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))
1988
1996
if (buff != tmp_buff)
1997
my_free(buff,MYF(0));
1992
2000
if (buff != tmp_buff)
2001
my_free(buff,MYF(0));
1994
2002
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2072
2080
if (!rep_quick)
2074
2082
/* Get real path for data file */
2075
if ((new_file=my_create(internal::fn_format(param->temp_filename,
2076
share->data_file_name, "",
2078
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,
2081
2092
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2082
param->temp_filename);
2093
param->temp_filename);
2085
2096
if (new_header_length &&
2314
2326
if (! param->error_printed)
2315
mi_check_print_error(param,"%d when fixing table",errno);
2327
mi_check_print_error(param,"%d when fixing table",my_errno);
2316
2328
if (new_file >= 0)
2318
internal::my_close(new_file,MYF(0));
2319
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,
2320
2333
if (info->dfile == new_file)
2323
2336
mi_mark_crashed_on_repair(info);
2326
2339
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2327
2340
share->state.changed|=STATE_NOT_SORTED_PAGES;
2329
void * rec_buff_ptr= NULL;
2330
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2331
if (rec_buff_ptr != NULL)
2333
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2334
if (rec_buff_ptr != NULL)
2338
free((unsigned char*) sort_info.key_block);
2339
free(sort_info.buff);
2340
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));
2341
2349
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2342
2350
if (!got_error && (param->testflag & T_UNPACK))
2344
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2352
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2345
2353
share->pack.header_length=0;
2347
2355
return(got_error);
2481
2489
if (!rep_quick)
2483
2491
/* Get real path for data file */
2484
if ((new_file=my_create(internal::fn_format(param->temp_filename,
2485
share->data_file_name, "",
2488
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,
2491
2502
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2492
2503
param->temp_filename);
2554
2565
if (share->options & HA_OPTION_COMPRESS_RECORD)
2555
2566
set_if_bigger(max_pack_reclength, share->max_pack_length);
2556
2567
if (!(sort_param=(MI_SORT_PARAM *)
2557
malloc(share->base.keys *
2558
(sizeof(MI_SORT_PARAM) + max_pack_reclength))))
2568
my_malloc((uint) share->base.keys *
2569
(sizeof(MI_SORT_PARAM) + max_pack_reclength),
2560
2572
mi_check_print_error(param,"Not enough memory for key!");
2563
memset(sort_param, 0, share->base.keys *
2564
(sizeof(MI_SORT_PARAM) + max_pack_reclength));
2565
2575
total_key_length=0;
2566
2576
rec_per_key_part= param->rec_per_key_part;
2567
2577
info->state->records=info->state->del=share->state.split=0;
2765
2776
if (ftruncate(info->dfile, skr))
2766
2777
mi_check_print_warning(param,
2767
2778
"Can't change size of datafile, error: %d",
2770
2781
if (param->testflag & T_CALC_CHECKSUM)
2771
2782
info->state->checksum=param->glob_crc;
2773
2784
if (ftruncate(share->kfile, info->state->key_file_length))
2774
2785
mi_check_print_warning(param,
2775
"Can't change size of indexfile, error: %d", errno);
2786
"Can't change size of indexfile, error: %d", my_errno);
2777
2788
if (!(param->testflag & T_SILENT))
2824
2835
if (! param->error_printed)
2825
mi_check_print_error(param,"%d when fixing table",errno);
2836
mi_check_print_error(param,"%d when fixing table",my_errno);
2826
2837
if (new_file >= 0)
2828
internal::my_close(new_file,MYF(0));
2829
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,
2830
2842
if (info->dfile == new_file)
2833
2845
mi_mark_crashed_on_repair(info);
2839
2851
pthread_cond_destroy (&sort_info.cond);
2840
2852
pthread_mutex_destroy(&sort_info.mutex);
2842
free((unsigned char*) sort_info.key_block);
2843
free((unsigned char*) sort_param);
2844
free(sort_info.buff);
2845
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));
2846
2858
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2847
2859
if (!got_error && (param->testflag & T_UNPACK))
2849
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2861
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2850
2862
share->pack.header_length=0;
2852
2864
return(got_error);
2872
2884
sort_param->real_key_length=
2873
2885
(info->s->rec_reflength+
2874
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2886
_mi_make_key(info, sort_param->key, (uchar*) key,
2875
2887
sort_param->record, sort_param->filepos));
2876
2888
#ifdef HAVE_purify
2877
memset((unsigned char *)key+sort_param->real_key_length, 0,
2889
memset(key+sort_param->real_key_length, 0,
2878
2890
(sort_param->key_length-sort_param->real_key_length));
2880
2892
return(sort_write_record(sort_param));
3380
3384
/* Compare two keys from _create_index_by_sort */
3382
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b)
3386
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3384
uint32_t not_used[2];
3385
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),
3386
3391
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3387
3392
} /* sort_key_cmp */
3390
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3395
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3392
uint32_t diff_pos[2];
3393
3398
char llbuff[22],llbuff2[22];
3394
3399
SORT_INFO *sort_info=sort_param->sort_info;
3395
3400
MI_CHECK *param= sort_info->param;
3398
3403
if (sort_info->key_block->inited)
3400
3405
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3401
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3406
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3403
3408
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3404
3409
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,
3410
(uchar*) a, USE_WHOLE_KEY,
3406
3411
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3407
3412
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3409
3414
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3410
3415
sort_param->notnull,
3411
3416
sort_info->key_block->lastkey,
3414
3419
sort_param->unique[diff_pos[0]-1]++;
3438
3443
return (sort_delete_record(sort_param));
3440
3445
return (sort_insert_key(sort_param,sort_info->key_block,
3441
(unsigned char*) a, HA_OFFSET_ERROR));
3446
(uchar*) a, HA_OFFSET_ERROR));
3442
3447
} /* sort_key_write */
3445
3450
/* get pointer to record from a key */
3447
my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3448
unsigned char *key) {
3452
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3449
3455
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3450
3456
} /* get_record_for_key */
3453
3459
/* Insert a key in sort-key-blocks */
3455
int sort_insert_key(MI_SORT_PARAM *sort_param,
3456
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3457
my_off_t prev_block)
3461
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3462
register SORT_KEY_BLOCKS *key_block, uchar *key,
3463
my_off_t prev_block)
3459
uint32_t a_length,t_length,nod_flag;
3465
uint a_length,t_length,nod_flag;
3460
3466
my_off_t filepos,key_file_length;
3461
unsigned char *anc_buff,*lastkey;
3467
uchar *anc_buff,*lastkey;
3462
3468
MI_KEY_PARAM s_temp;
3464
3470
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3688
3695
share= *(*org_info)->s;
3689
3696
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3690
3697
(param->testflag & T_UNPACK);
3691
if (!(keyinfo=(MI_KEYDEF*) malloc(sizeof(MI_KEYDEF)*share.base.keys)))
3698
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3693
3700
memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3695
3702
key_parts= share.base.all_key_parts;
3696
if (!(keysegs=(HA_KEYSEG*) malloc(sizeof(HA_KEYSEG)*
3697
(key_parts+share.base.keys))))
3703
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3704
(key_parts+share.base.keys))))
3706
my_afree((uchar*) keyinfo);
3702
3709
if (!(recdef=(MI_COLUMNDEF*)
3703
malloc(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3710
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3712
my_afree((uchar*) keyinfo);
3713
my_afree((uchar*) keysegs);
3709
3716
if (!(uniquedef=(MI_UNIQUEDEF*)
3710
malloc(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3717
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3719
my_afree((uchar*) recdef);
3720
my_afree((uchar*) keyinfo);
3721
my_afree((uchar*) keysegs);
3763
3770
(param->testflag & T_UNPACK);
3764
3771
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3766
file_length=(uint64_t) lseek(info.dfile,0L,SEEK_END);
3773
file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3767
3774
tmp_length= file_length+file_length/10;
3768
3775
set_if_bigger(file_length,param->max_data_file_length);
3769
3776
set_if_bigger(file_length,tmp_length);
3770
3777
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3772
mi_close(*org_info);
3779
VOID(mi_close(*org_info));
3773
3780
memset(&create_info, 0, sizeof(create_info));
3774
3781
create_info.max_rows=max(max_records,share.base.records);
3775
3782
create_info.reloc_rows=share.base.reloc;
3959
3966
mi_extra(info,HA_EXTRA_KEYREAD,0);
3960
3967
if (mi_rlast(info, record, info->s->base.auto_key-1))
3962
if (errno != HA_ERR_END_OF_FILE)
3969
if (my_errno != HA_ERR_END_OF_FILE)
3964
3971
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3965
free(mi_get_rec_buff_ptr(info, record));
3966
mi_check_print_error(param,"%d when reading last record",errno);
3972
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3973
mi_check_print_error(param,"%d when reading last record",my_errno);
3969
3976
if (!repair_only)
4010
4017
For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too:
4011
4018
notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL)
4012
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4019
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4013
4020
keypart{i} are not NULL)
4015
4022
For all other statistics collection methods notnull_tuples==NULL.
4017
4024
Output is an array:
4018
rec_per_key_part[k] =
4019
= E(#records in the table such that keypart_1=c_1 AND ... AND
4020
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4025
rec_per_key_part[k] =
4026
= E(#records in the table such that keypart_1=c_1 AND ... AND
4027
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4022
4029
= {assuming that values have uniform distribution and index contains all
4023
4030
tuples from the domain (or that {c_1, ..., c_k} tuple is choosen from
4026
4033
= #tuples-in-the-index / #distinct-tuples-in-the-index.
4028
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4035
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4029
4036
meaning depending on which statistics collection method is used:
4031
4038
MI_STATS_METHOD_* how are nulls compared? which tuples are counted?
4032
4039
NULLS_EQUAL NULL == NULL all tuples in table
4033
4040
NULLS_NOT_EQUAL NULL != NULL all tuples in table
4081
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)
4083
4089
ha_checksum crc;
4084
const unsigned char *end=buf+length;
4090
const uchar *end=buf+length;
4085
4091
for (crc=0; buf != end; buf++)
4086
crc=((crc << 1) + *((unsigned char*) buf)) +
4092
crc=((crc << 1) + *((uchar*) buf)) +
4087
4093
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4091
4097
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4093
uint32_t key_maxlength=key->maxlength;
4099
uint key_maxlength=key->maxlength;
4094
4100
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4095
4101
((uint64_t) rows * key_maxlength >
4096
(uint64_t) MAX_FILE_SIZE));
4102
(uint64_t) myisam_max_temp_length));