43
43
#include "myisamdef.h"
44
45
#include <stdarg.h>
45
#include <mysys/my_getopt.h>
46
#include <my_getopt.h>
46
47
#ifdef HAVE_SYS_VADVISE_H
47
48
#include <sys/vadvise.h>
50
#include <sys/types.h>
52
50
#ifdef HAVE_SYS_MMAN_H
53
51
#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);
55
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
56
#define my_raid_delete(A,B,C) my_delete(A,B)
59
/* Functions defined in this file */
61
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
61
62
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);
63
my_off_t page, uchar *buff, ha_rows *keys,
64
ha_checksum *key_checksum, uint level);
65
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
66
static ha_checksum calc_checksum(ha_rows count);
66
67
static int writekeys(MI_SORT_PARAM *sort_param);
67
68
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
71
72
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
73
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
74
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
75
76
static int sort_insert_key(MI_SORT_PARAM *sort_param,
76
77
register SORT_KEY_BLOCKS *key_block,
77
unsigned char *key, my_off_t prev_block);
78
uchar *key, my_off_t prev_block);
78
79
static int sort_delete_record(MI_SORT_PARAM *sort_param);
79
80
/*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);
81
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
83
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
83
84
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
85
86
void myisamchk_init(MI_CHECK *param)
87
memset(param, 0, sizeof(*param));
88
bzero((uchar*) param,sizeof(*param));
88
89
param->opt_follow_links=1;
89
90
param->keys_in_use= ~(uint64_t) 0;
90
91
param->search_after_block=HA_OFFSET_ERROR;
117
118
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
119
120
/* Don't count this as a real warning, as check can correct this ! */
120
uint32_t save=param->warning_printed;
121
uint save=param->warning_printed;
121
122
mi_check_print_warning(param,
122
123
share->state.open_count==1 ?
123
124
"%d client is using or hasn't closed the table properly" :
133
134
/* Check delete links */
135
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
136
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
137
138
register ha_rows i;
138
uint32_t delete_link_length;
139
uint delete_link_length;
139
140
my_off_t empty, next_link, old_link= 0;
140
141
char buff[22],buff2[22];
167
168
printf(" %9s",llstr(next_link,buff));
168
169
if (next_link >= info->state->data_file_length)
170
if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
171
if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
172
next_link,MYF(MY_NABP)))
173
174
if (test_flag & T_VERBOSE) puts("");
240
241
/* Check delete links in index file */
242
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
243
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
244
245
my_off_t next_link;
245
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
246
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
248
char llbuff[21], llbuff2[21];
250
251
if (param->testflag & T_VERBOSE)
251
252
printf("block_size %4u:", block_size); /* purecov: tested */
290
291
if (!(buff=key_cache_read(info->s->key_cache,
291
292
info->s->kfile, next_link, DFLT_INIT_HITS,
292
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
294
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
296
/* purecov: begin tested */
393
394
int chk_key(MI_CHECK *param, register MI_INFO *info)
395
uint32_t key,found_keys=0,full_text_keys=0,result=0;
396
uint key,found_keys=0,full_text_keys=0,result=0;
397
398
ha_checksum old_record_checksum,init_checksum;
398
399
my_off_t all_keydata,all_totaldata,key_totlength,length;
430
431
if (! mi_is_key_active(share->state.key_map, key))
432
433
/* Remember old statistics for key */
433
assert(rec_per_key_part >= param->rec_per_key_part);
434
memcpy(rec_per_key_part,
435
(share->state.rec_per_key_part +
436
(rec_per_key_part - param->rec_per_key_part)),
434
memcpy((char*) rec_per_key_part,
435
(char*) (share->state.rec_per_key_part +
436
(uint) (rec_per_key_part - param->rec_per_key_part)),
437
437
keyinfo->keysegs*sizeof(*rec_per_key_part));
442
442
param->record_checksum=init_checksum;
444
memset(¶m->unique_count, 0, sizeof(param->unique_count));
445
memset(¶m->notnull_count, 0, sizeof(param->notnull_count));
444
bzero((char*) ¶m->unique_count,sizeof(param->unique_count));
445
bzero((char*) ¶m->notnull_count,sizeof(param->notnull_count));
447
447
if ((!(param->testflag & T_SILENT)))
448
448
printf ("- check data record references index: %d\n",key+1);
449
if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0))
449
if (share->state.key_root[key] == HA_OFFSET_ERROR &&
450
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
451
452
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
452
453
DFLT_INIT_HITS,info->buff,0))
466
467
if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
467
468
&keys, param->key_crc+key,1))
470
if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
471
472
if (keys != info->state->records)
520
521
/* Check that there isn't a row with auto_increment = 0 in the table */
521
522
mi_extra(info,HA_EXTRA_KEYREAD,0);
522
memset(info->lastkey, 0, keyinfo->seg->length);
523
if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
523
bzero(info->lastkey,keyinfo->seg->length);
524
if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
524
525
(key_part_map)1, HA_READ_KEY_EXACT))
526
527
/* Don't count this as a real warning, as myisamchk can't correct it */
527
uint32_t save=param->warning_printed;
528
uint save=param->warning_printed;
528
529
mi_check_print_warning(param, "Found row where the auto_increment "
529
530
"column has the value 0");
530
531
param->warning_printed=save;
575
576
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)
577
my_off_t page, uchar *buff, ha_rows *keys,
578
ha_checksum *key_checksum, uint level)
579
580
char llbuff[22],llbuff2[22];
686
687
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
unsigned char *prev_key, unsigned char *last_key)
688
uchar *prev_key, uchar *last_key)
690
uint32_t first_null_seg, kp;
691
uint first_null_seg, kp;
719
720
/* Check if index is ok */
721
722
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)
723
my_off_t page, uchar *buff, ha_rows *keys,
724
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;
727
uint used_length,comp_flag,nod_flag,key_length=0;
728
uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
729
my_off_t next_page,record;
730
uint32_t diff_pos[2];
732
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
733
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
734
735
mi_check_print_error(param,"Not enough memory for keyblock");
814
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
815
(*key_checksum)+= mi_byte_checksum((uchar*) key,
815
816
key_length- info->s->rec_reflength);
816
817
record= _mi_dpos(info,0,key+key_length);
817
818
if (record >= info->state->data_file_length)
827
828
llstr(page,llbuff), used_length, (keypos - buff));
830
my_afree((unsigned char*) temp_buff);
831
my_afree((uchar*) temp_buff);
833
my_afree((unsigned char*) temp_buff);
834
my_afree((uchar*) temp_buff);
835
836
} /* chk_index */
881
882
ha_rows records, del_blocks;
882
883
my_off_t used, empty, pos, splits, start_recpos= 0,
883
884
del_length, link_used, start_block;
884
unsigned char *record= NULL, *to= NULL;
885
uchar *record= NULL, *to= NULL;
885
886
char llbuff[22],llbuff2[22],llbuff3[22];
886
887
ha_checksum intern_record_checksum;
887
888
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
888
bool static_row_size;
889
my_bool static_row_size;
889
890
MI_KEYDEF *keyinfo;
890
891
MI_BLOCK_INFO block_info;
926
927
pos=my_b_tell(¶m->read_cache);
927
memset(key_checksum, 0, info->s->base.keys * sizeof(key_checksum[0]));
928
bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
928
929
while (pos < info->state->data_file_length)
930
931
if (*killed_ptr(param))
932
933
switch (info->s->data_file_type) {
933
934
case STATIC_RECORD:
934
if (my_b_read(¶m->read_cache,(unsigned char*) record,
935
if (my_b_read(¶m->read_cache,(uchar*) record,
935
936
info->s->base.pack_reclength))
937
938
start_recpos=pos;
951
952
block_info.next_filepos=pos;
954
if (_mi_read_cache(¶m->read_cache,(unsigned char*) block_info.header,
955
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
955
956
(start_block=block_info.next_filepos),
956
957
sizeof(block_info.header),
957
958
(flag ? 0 : READING_NEXT) | READING_HEADER))
1058
if (_mi_read_cache(¶m->read_cache,(unsigned char*) to,block_info.filepos,
1059
if (_mi_read_cache(¶m->read_cache,(uchar*) to,block_info.filepos,
1059
1060
(uint) block_info.data_len,
1060
1061
flag == 1 ? READING_NEXT : 0))
1116
1117
pos=block_info.filepos+block_info.block_len;
1118
1119
case COMPRESSED_RECORD:
1120
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header, pos,
1121
info->s->pack.ref_length, READING_NEXT))
1125
VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
1126
&info->rec_buff, -1, start_recpos));
1127
pos=block_info.filepos+block_info.rec_len;
1128
if (block_info.rec_len < (uint) info->s->min_pack_length ||
1129
block_info.rec_len > (uint) info->s->max_pack_length)
1131
mi_check_print_error(param,
1132
"Found block with wrong recordlength: %d at %s",
1133
block_info.rec_len, llstr(start_recpos,llbuff));
1137
if (_mi_read_cache(¶m->read_cache,(uchar*) info->rec_buff,
1138
block_info.filepos, block_info.rec_len, READING_NEXT))
1140
if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
1141
info->rec_buff, block_info.rec_len))
1143
mi_check_print_error(param,"Found wrong record at %s",
1144
llstr(start_recpos,llbuff));
1147
if (static_row_size)
1148
param->glob_crc+= mi_static_checksum(info,record);
1150
param->glob_crc+= mi_checksum(info,record);
1151
link_used+= (block_info.filepos - start_recpos);
1152
used+= (pos-start_recpos);
1119
1153
case BLOCK_RECORD:
1120
1154
assert(0); /* Impossible */
1126
1160
if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1128
printf("%s\r", llstr(records,llbuff)); fflush(stdout);
1162
printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1131
1165
/* Check if keys match the record */
1136
1170
if (mi_is_key_active(info->s->state.key_map, key))
1172
if(!(keyinfo->flag & HA_FULLTEXT))
1139
uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1174
uint key_length=_mi_make_key(info,key,info->lastkey,record,
1200
1235
for (key=0 ; key < info->s->base.keys; key++)
1202
if (key_checksum[key] != param->key_crc[key])
1237
if (key_checksum[key] != param->key_crc[key] &&
1238
!(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1204
1240
mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
1265
1301
printf("Lost space: %12s Linkdata: %10s\n",
1266
1302
llstr(empty,llbuff),llstr(link_used,llbuff2));
1268
free(mi_get_rec_buff_ptr(info, record));
1304
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1269
1305
return (error);
1271
1307
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));
1309
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1310
param->testflag|=T_RETRY_WITHOUT_QUICK;
1276
1312
} /* chk_data_link */
1329
1365
then recrate all indexes.
1332
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
1368
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1334
1370
MYISAM_SHARE *share= info->s;
1335
1371
MI_STATE_INFO *state= &share->state;
1415
1451
SORT_INFO sort_info;
1416
1452
MI_SORT_PARAM sort_param;
1418
memset(&sort_info, 0, sizeof(sort_info));
1419
memset(&sort_param, 0, sizeof(sort_param));
1454
bzero((char *)&sort_info, sizeof(sort_info));
1455
bzero((char *)&sort_param, sizeof(sort_param));
1420
1456
start_records=info->state->records;
1421
1457
new_header_length=(param->testflag & T_UNPACK) ? 0L :
1422
1458
share->pack.header_length;
1435
1471
param->testflag|=T_CALC_CHECKSUM;
1437
1473
if (!param->using_global_keycache)
1438
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0);
1474
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1475
param->use_buffers, 0, 0));
1441
1477
if (init_io_cache(¶m->read_cache,info->dfile,
1442
1478
(uint) param->read_buffer_length,
1443
1479
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1445
memset(&info->rec_cache, 0, sizeof(info->rec_cache));
1481
bzero(&info->rec_cache,sizeof(info->rec_cache));
1448
1484
if (!rep_quick)
1461
1497
if (!rep_quick)
1463
1499
/* 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,
1500
if ((new_file=my_raid_create(fn_format(param->temp_filename,
1501
share->data_file_name, "",
1503
0,param->tmpfile_createflag,
1504
share->base.raid_type,
1505
share->base.raid_chunks,
1506
share->base.raid_chunksize,
1470
1509
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
param->temp_filename);
1510
param->temp_filename);
1474
1513
if (new_header_length &&
1475
1514
filecopy(param,new_file,info->dfile,0L,new_header_length,
1478
1517
info->s->state.dellink= HA_OFFSET_ERROR;
1479
1518
info->rec_cache.file=new_file;
1491
1530
param->read_cache.end_of_file=sort_info.filelength=
1492
1531
my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1493
1532
sort_info.dupp=0;
1494
sort_param.fix_datafile= (bool) (! rep_quick);
1533
sort_param.fix_datafile= (my_bool) (! rep_quick);
1495
1534
sort_param.master=1;
1496
1535
sort_info.max_records= ~(ha_rows) 0;
1525
1564
llstr(info->dupp_key_pos,llbuff2));
1526
1565
if (param->testflag & T_VERBOSE)
1528
_mi_make_key(info,(uint) info->errkey,info->lastkey,
1529
sort_param.record,0L);
1567
VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
1568
sort_param.record,0L));
1531
1570
sort_info.dupp++;
1532
1571
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1540
1579
if (sort_write_record(&sort_param))
1543
if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
1582
if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1544
1583
flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1547
1586
if (param->testflag & T_WRITE_LOOP)
1549
fputs(" \r",stdout); fflush(stdout);
1588
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1551
1590
if (ftruncate(share->kfile, info->state->key_file_length))
1628
1667
llstr(sort_param.start_recpos,llbuff));
1629
1668
if (new_file >= 0)
1631
my_close(new_file,MYF(0));
1632
my_delete(param->temp_filename, MYF(MY_WME));
1670
VOID(my_close(new_file,MYF(0)));
1671
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1633
1673
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1635
1675
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);
1677
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1678
MYF(MY_ALLOW_ZERO_PTR));
1679
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1680
MYF(MY_ALLOW_ZERO_PTR));
1681
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1682
VOID(end_io_cache(¶m->read_cache));
1649
1683
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
end_io_cache(&info->rec_cache);
1684
VOID(end_io_cache(&info->rec_cache));
1651
1685
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1686
if (!got_error && param->testflag & T_UNPACK)
1654
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1688
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1689
share->pack.header_length=0;
1656
1690
share->data_file_type=sort_info.new_data_file_type;
1666
1700
static int writekeys(MI_SORT_PARAM *sort_param)
1668
register uint32_t i;
1670
1704
MI_INFO *info= sort_param->sort_info->info;
1671
unsigned char *buff= sort_param->record;
1705
uchar *buff= sort_param->record;
1672
1706
my_off_t filepos= sort_param->filepos;
1674
1708
key=info->lastkey+info->s->base.max_key_length;
1677
1711
if (mi_is_key_active(info->s->state.key_map, i))
1680
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1714
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1715
if (_mi_ck_write(info,i,key,key_length))
1694
1728
if (mi_is_key_active(info->s->state.key_map, i))
1697
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1731
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1732
if (_mi_ck_delete(info,i,key,key_length))
1711
1745
/* 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)
1747
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1748
my_off_t newpos, uint prot_key)
1716
register uint32_t i;
1718
uint32_t key_length;
1720
1754
key=info->lastkey+info->s->base.max_key_length;
1721
1755
for (i=0 ; i < info->s->base.keys; i++)
1725
1759
key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1760
if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1761
{ /* Change pointer direct */
1729
1763
MI_KEYDEF *keyinfo;
1730
1764
keyinfo=info->s->keyinfo+i;
1731
1765
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1789
1823
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1791
register uint32_t key;
1792
1826
register MI_KEYDEF *keyinfo;
1794
1828
my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
uint32_t r_locks,w_locks;
1829
uint r_locks,w_locks;
1797
1831
MYISAM_SHARE *share=info->s;
1798
1832
MI_STATE_INFO old_state;
1848
1882
/* Put same locks as old file */
1849
1883
share->r_locks= share->w_locks= share->tot_locks= 0;
1850
1884
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1851
my_close(share->kfile,MYF(MY_WME));
1885
VOID(my_close(share->kfile,MYF(MY_WME)));
1852
1886
share->kfile = -1;
1853
my_close(new_file,MYF(MY_WME));
1887
VOID(my_close(new_file,MYF(MY_WME)));
1854
1888
if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1856
1890
mi_open_keyfile(share))
1877
my_close(new_file,MYF(MY_WME));
1911
VOID(my_close(new_file,MYF(MY_WME)));
1879
my_delete(param->temp_filename,MYF(MY_WME));
1913
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
1881
1915
} /* mi_sort_index */
1886
1920
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
1921
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];
1923
uint length,nod_flag,used_length, key_length;
1924
uchar *buff,*keypos,*endpos;
1925
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
1926
my_off_t new_page_pos,next_page;
1893
1927
char llbuff[22];
1895
1929
new_page_pos=param->new_file_pos;
1896
1930
param->new_file_pos+=keyinfo->block_length;
1898
if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1932
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1900
1934
mi_check_print_error(param,"Not enough memory for key block");
1932
1966
/* Fill block with zero and write it to the new index file */
1933
1967
length=mi_getint(buff);
1934
memset(buff+length, 0, keyinfo->block_length-length);
1935
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1968
bzero((uchar*) buff+length,keyinfo->block_length-length);
1969
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
1970
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1938
1972
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1941
my_afree((unsigned char*) buff);
1975
my_afree((uchar*) buff);
1944
my_afree((unsigned char*) buff);
1978
my_afree((uchar*) buff);
1946
1980
} /* sort_one_index */
1958
1992
int change_to_newfile(const char * filename, const char * old_ext,
1959
1993
const char * new_ext,
1960
uint32_t raid_chunks __attribute__((unused)),
1994
uint raid_chunks __attribute__((unused)),
1963
1997
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1978
2012
char tmp_buff[IO_SIZE],*buff;
1979
2013
ulong buff_length;
1981
buff_length=(ulong) cmin(param->write_buffer_length,length);
2015
buff_length=(ulong) min(param->write_buffer_length,length);
1982
2016
if (!(buff=my_malloc(buff_length,MYF(0))))
1984
2018
buff=tmp_buff; buff_length=IO_SIZE;
1987
my_seek(from,start,MY_SEEK_SET,MYF(0));
2021
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1988
2022
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))
2024
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
2025
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1993
2027
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))
2029
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
2030
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1998
2032
if (buff != tmp_buff)
2033
my_free(buff,MYF(0));
2002
2036
if (buff != tmp_buff)
2037
my_free(buff,MYF(0));
2004
2038
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2039
type,my_errno);
2054
2088
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2055
2089
param->testflag|=T_CALC_CHECKSUM;
2057
memset(&sort_info, 0, sizeof(sort_info));
2058
memset(&sort_param, 0, sizeof(sort_param));
2091
bzero((char*)&sort_info,sizeof(sort_info));
2092
bzero((char *)&sort_param, sizeof(sort_param));
2059
2093
if (!(sort_info.key_block=
2060
2094
alloc_key_blocks(param,
2061
2095
(uint) param->sort_key_blocks,
2082
2116
if (!rep_quick)
2084
2118
/* 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,
2119
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2120
share->data_file_name, "",
2122
0,param->tmpfile_createflag,
2123
share->base.raid_type,
2124
share->base.raid_chunks,
2125
share->base.raid_chunksize,
2091
2128
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
param->temp_filename);
2129
param->temp_filename);
2095
2132
if (new_header_length &&
2129
2166
sort_param.wordlist=NULL;
2131
2168
if (share->data_file_type == DYNAMIC_RECORD)
2132
length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2169
length=max(share->base.min_pack_length+1,share->base.min_block_length);
2133
2170
else if (share->data_file_type == COMPRESSED_RECORD)
2134
2171
length=share->base.min_block_length;
2163
2200
if (! mi_is_key_active(key_map, sort_param.key))
2165
2202
/* Remember old statistics for key */
2166
assert(rec_per_key_part >= param->rec_per_key_part);
2167
memcpy(rec_per_key_part,
2168
(share->state.rec_per_key_part +
2169
(rec_per_key_part - param->rec_per_key_part)),
2203
memcpy((char*) rec_per_key_part,
2204
(char*) (share->state.rec_per_key_part +
2205
(uint) (rec_per_key_part - param->rec_per_key_part)),
2170
2206
sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
2175
2211
printf ("- Fixing index %d\n",sort_param.key+1);
2176
2212
sort_param.max_pos=sort_param.pos=share->pack.header_length;
2177
2213
keyseg=sort_param.seg;
2178
memset(sort_param.unique, 0, sizeof(sort_param.unique));
2214
bzero((char*) sort_param.unique,sizeof(sort_param.unique));
2179
2215
sort_param.key_length=share->rec_reflength;
2180
2216
for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
2326
2362
mi_check_print_error(param,"%d when fixing table",my_errno);
2327
2363
if (new_file >= 0)
2329
my_close(new_file,MYF(0));
2330
my_delete(param->temp_filename, MYF(MY_WME));
2365
VOID(my_close(new_file,MYF(0)));
2366
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2331
2368
if (info->dfile == new_file)
2334
2371
mi_mark_crashed_on_repair(info);
2337
2374
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2375
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);
2377
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2378
MYF(MY_ALLOW_ZERO_PTR));
2379
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2380
MYF(MY_ALLOW_ZERO_PTR));
2381
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2382
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2383
VOID(end_io_cache(¶m->read_cache));
2352
2384
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2385
if (!got_error && (param->testflag & T_UNPACK))
2355
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2387
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2388
share->pack.header_length=0;
2358
2390
return(got_error);
2404
2436
const char * name, int rep_quick)
2407
uint32_t i,key, total_key_length, istep;
2439
uint i,key, total_key_length, istep;
2408
2440
ulong rec_length;
2409
2441
ha_rows start_records;
2410
2442
my_off_t new_header_length,del;
2464
2496
position 'new_header_length'.
2467
memset(&sort_info, 0, sizeof(sort_info));
2499
bzero((char*)&sort_info,sizeof(sort_info));
2468
2500
/* Initialize pthread structures before goto err. */
2469
2501
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2470
2502
pthread_cond_init(&sort_info.cond, 0);
2492
2524
if (!rep_quick)
2494
2526
/* 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,
2527
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2528
share->data_file_name, "",
2531
0,param->tmpfile_createflag,
2532
share->base.raid_type,
2533
share->base.raid_chunks,
2534
share->base.raid_chunksize,
2502
2537
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2538
param->temp_filename);
2537
2572
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2539
2574
if (share->data_file_type == DYNAMIC_RECORD)
2540
rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2575
rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2576
else if (share->data_file_type == COMPRESSED_RECORD)
2542
2577
rec_length=share->base.min_block_length;
2590
2625
if (! mi_is_key_active(key_map, key))
2592
2627
/* Remember old statistics for key */
2593
assert(rec_per_key_part >= param->rec_per_key_part);
2594
memcpy(rec_per_key_part,
2595
(share->state.rec_per_key_part +
2596
(rec_per_key_part - param->rec_per_key_part)),
2628
memcpy((char*) rec_per_key_part,
2629
(char*) (share->state.rec_per_key_part+
2630
(uint) (rec_per_key_part - param->rec_per_key_part)),
2597
2631
sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2616
2650
sort_param[i].filepos=new_header_length;
2617
2651
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))+
2653
sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2654
(max_pack_reclength * i));
2621
2655
if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2806
2840
the share by remove_io_thread() or it was not yet started (if the
2807
2841
error happend before creating the thread).
2809
end_io_cache(&info->rec_cache);
2843
VOID(end_io_cache(&info->rec_cache));
2811
2845
Destroy the new data cache in case of non-quick repair. All slave
2812
2846
threads did either detach from the share by remove_io_thread()
2836
2870
mi_check_print_error(param,"%d when fixing table",my_errno);
2837
2871
if (new_file >= 0)
2839
my_close(new_file,MYF(0));
2840
my_delete(param->temp_filename, MYF(MY_WME));
2873
VOID(my_close(new_file,MYF(0)));
2874
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2841
2876
if (info->dfile == new_file)
2844
2879
mi_mark_crashed_on_repair(info);
2850
2885
pthread_cond_destroy (&sort_info.cond);
2851
2886
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);
2888
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2889
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2890
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2891
VOID(end_io_cache(¶m->read_cache));
2857
2892
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
2893
if (!got_error && (param->testflag & T_UNPACK))
2860
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2895
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
2896
share->pack.header_length=0;
2863
2898
return(got_error);
2883
2918
sort_param->real_key_length=
2884
2919
(info->s->rec_reflength+
2885
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2920
_mi_make_key(info, sort_param->key, (uchar*) key,
2886
2921
sort_param->record, sort_param->filepos));
2887
2922
#ifdef HAVE_purify
2888
memset(key+sort_param->real_key_length, 0,
2889
(sort_param->key_length-sort_param->real_key_length));
2923
bzero(key+sort_param->real_key_length,
2924
(sort_param->key_length-sort_param->real_key_length));
2891
2926
return(sort_write_record(sort_param));
2892
2927
} /* sort_key_read */
2929
2964
int parallel_flag;
2930
uint32_t found_record,b_type,left_length;
2965
uint found_record,b_type,left_length;
2932
unsigned char *to= NULL;
2933
2968
MI_BLOCK_INFO block_info;
2934
2969
SORT_INFO *sort_info=sort_param->sort_info;
2935
2970
MI_CHECK *param=sort_info->param;
3005
3040
llstr(param->search_after_block,llbuff),
3006
3041
llstr(sort_param->start_recpos,llbuff2));
3007
3042
if (_mi_read_cache(&sort_param->read_cache,
3008
(unsigned char*) block_info.header,pos,
3043
(uchar*) block_info.header,pos,
3009
3044
MI_BLOCK_INFO_HEADER_LENGTH,
3010
3045
(! found_record ? READING_NEXT : 0) |
3011
3046
parallel_flag | READING_HEADER))
3032
3067
(block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3068
block_info.rec_len > (uint) share->base.max_pack_length)))
3036
3071
if (param->testflag & T_VERBOSE || searching == 0)
3037
3072
mi_check_print_info(param,
3038
3073
"Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3191
3226
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);
3229
uint header_len= (uint) (block_info.filepos - pos);
3230
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3197
3232
if (prefetch_len > block_info.data_len)
3198
3233
prefetch_len= block_info.data_len;
3269
3304
case COMPRESSED_RECORD:
3305
for (searching=0 ;; searching=1, sort_param->pos++)
3307
if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
3309
share->pack.ref_length,READING_NEXT))
3311
if (searching && ! sort_param->fix_datafile)
3313
param->error_printed=1;
3314
param->retry_repair=1;
3315
param->testflag|=T_RETRY_WITHOUT_QUICK;
3316
return(1); /* Something wrong with data */
3318
sort_param->start_recpos=sort_param->pos;
3319
if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
3320
&sort_param->rec_buff, -1, sort_param->pos))
3322
if (!block_info.rec_len &&
3323
sort_param->pos + MEMMAP_EXTRA_MARGIN ==
3324
sort_param->read_cache.end_of_file)
3326
if (block_info.rec_len < (uint) share->min_pack_length ||
3327
block_info.rec_len > (uint) share->max_pack_length)
3330
mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
3332
llstr(sort_param->pos,llbuff));
3335
if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
3336
block_info.filepos, block_info.rec_len,
3340
mi_check_print_info(param,"Couldn't read whole record from %s",
3341
llstr(sort_param->pos,llbuff));
3344
if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
3345
sort_param->rec_buff, block_info.rec_len))
3348
mi_check_print_info(param,"Found wrong record at %s",
3349
llstr(sort_param->pos,llbuff));
3352
if (!sort_param->fix_datafile)
3354
sort_param->filepos=sort_param->pos;
3355
if (sort_param->master)
3356
share->state.split++;
3358
sort_param->max_pos=(sort_param->pos=block_info.filepos+
3359
block_info.rec_len);
3360
info->packed_length=block_info.rec_len;
3361
if (sort_param->calc_checksum)
3362
param->glob_crc+= (info->checksum=
3363
mi_checksum(info, sort_param->record));
3270
3366
case BLOCK_RECORD:
3271
3367
assert(0); /* Impossible */
3361
3459
/* sort_info->param->glob_crc+=info->checksum; */
3363
3461
case COMPRESSED_RECORD:
3462
reclength=info->packed_length;
3463
length= save_pack_length((uint) share->pack.version, block_buff,
3465
if (info->s->base.blobs)
3466
length+= save_pack_length((uint) share->pack.version,
3467
block_buff + length, info->blob_length);
3468
if (my_b_write(&info->rec_cache,block_buff,length) ||
3469
my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
3471
mi_check_print_error(param,"%d when writing to datafile",my_errno);
3474
/* sort_info->param->glob_crc+=info->checksum; */
3475
sort_param->filepos+=reclength+length;
3476
info->s->state.split++;
3364
3478
case BLOCK_RECORD:
3365
3479
assert(0); /* Impossible */
3385
3499
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),
3503
return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3390
3504
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3505
} /* sort_key_cmp */
3394
3508
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3396
uint32_t diff_pos[2];
3397
3511
char llbuff[22],llbuff2[22];
3398
3512
SORT_INFO *sort_info=sort_param->sort_info;
3399
3513
MI_CHECK *param= sort_info->param;
3402
3516
if (sort_info->key_block->inited)
3404
3518
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3519
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3407
3521
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3522
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
(unsigned char*) a, USE_WHOLE_KEY,
3523
(uchar*) a, USE_WHOLE_KEY,
3410
3524
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3525
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3413
3527
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3528
sort_param->notnull,
3415
3529
sort_info->key_block->lastkey,
3418
3532
sort_param->unique[diff_pos[0]-1]++;
3423
3537
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3538
mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3427
3541
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3429
3543
sort_info->dupp++;
3430
3544
sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3545
sort_param->keyinfo,
3432
(unsigned char*) a);
3433
3547
mi_check_print_warning(param,
3434
3548
"Duplicate key for record at %10s against record at %10s",
3435
3549
llstr(sort_info->info->lastpos,llbuff),
3442
3556
return (sort_delete_record(sort_param));
3444
3558
return (sort_insert_key(sort_param,sort_info->key_block,
3445
(unsigned char*) a, HA_OFFSET_ERROR));
3559
(uchar*) a, HA_OFFSET_ERROR));
3446
3560
} /* sort_key_write */
3449
3563
/* get pointer to record from a key */
3451
3565
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3454
3568
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3569
} /* get_record_for_key */
3458
3572
/* Insert a key in sort-key-blocks */
3460
3574
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3575
register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3576
my_off_t prev_block)
3464
uint32_t a_length,t_length,nod_flag;
3578
uint a_length,t_length,nod_flag;
3465
3579
my_off_t filepos,key_file_length;
3466
unsigned char *anc_buff,*lastkey;
3580
uchar *anc_buff,*lastkey;
3467
3581
MI_KEY_PARAM s_temp;
3469
3583
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3496
3610
_mi_kpointer(info,key_block->end_pos,prev_block);
3498
3612
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
(unsigned char*) 0,lastkey,lastkey,key,
3613
(uchar*) 0,lastkey,lastkey,key,
3501
3615
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
3616
a_length+=t_length;
3504
3618
key_block->end_pos+=t_length;
3505
3619
if (a_length <= keyinfo->block_length)
3507
_mi_move_key(keyinfo,key_block->lastkey,key);
3621
VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
3622
key_block->last_length=a_length-t_length;
3512
3626
/* Fill block with end-zero and write filled block */
3513
3627
mi_putint(anc_buff,key_block->last_length,nod_flag);
3514
memset(anc_buff+key_block->last_length, 0,
3515
keyinfo->block_length - key_block->last_length);
3628
bzero((uchar*) anc_buff+key_block->last_length,
3629
keyinfo->block_length- key_block->last_length);
3516
3630
key_file_length=info->state->key_file_length;
3517
3631
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3523
3637
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3526
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3640
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
3641
(uint) keyinfo->block_length,filepos, param->myf_rw))
3577
3691
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);
3693
uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
3694
if (_mi_ck_delete(info,i,key,key_length))
3582
3696
mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3598
3712
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3600
uint32_t nod_flag,length;
3714
uint nod_flag,length;
3601
3715
my_off_t filepos,key_file_length;
3602
3716
SORT_KEY_BLOCKS *key_block;
3603
3717
SORT_INFO *sort_info= sort_param->sort_info;
3615
3729
_mi_kpointer(info,key_block->end_pos,filepos);
3616
3730
key_file_length=info->state->key_file_length;
3617
memset(key_block->buff+length, 0, keyinfo->block_length-length);
3731
bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3618
3732
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3625
3739
DFLT_INIT_HITS, key_block->buff))
3628
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3742
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
3743
(uint) keyinfo->block_length,filepos, myf_rw))
3637
3751
/* 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)
3753
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3642
register uint32_t i;
3643
3757
SORT_KEY_BLOCKS *block;
3645
3759
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3682
3796
MI_COLUMNDEF *recdef,*rec,*end;
3683
3797
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
3798
MI_STATUS_INFO status_info;
3685
uint32_t unpack,key_parts;
3799
uint unpack,key_parts;
3686
3800
ha_rows max_records;
3687
3801
uint64_t file_length,tmp_length;
3688
3802
MI_CREATE_INFO create_info;
3696
3810
(param->testflag & T_UNPACK);
3697
3811
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3699
memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3813
memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
3814
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3701
3816
key_parts= share.base.all_key_parts;
3702
3817
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
3818
(key_parts+share.base.keys))))
3705
my_afree((unsigned char*) keyinfo);
3820
my_afree((uchar*) keyinfo);
3708
3823
if (!(recdef=(MI_COLUMNDEF*)
3709
3824
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
my_afree((unsigned char*) keyinfo);
3712
my_afree((unsigned char*) keysegs);
3826
my_afree((uchar*) keyinfo);
3827
my_afree((uchar*) keysegs);
3715
3830
if (!(uniquedef=(MI_UNIQUEDEF*)
3716
3831
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);
3833
my_afree((uchar*) recdef);
3834
my_afree((uchar*) keyinfo);
3835
my_afree((uchar*) keysegs);
3724
3839
/* Copy the column definitions */
3725
memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
3840
memcpy((uchar*) recdef,(uchar*) share.rec,
3841
(size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3726
3842
for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3728
3844
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3735
3851
/* Change the new key to point at the saved key segments */
3736
memcpy(keysegs,share.keyparts,
3737
sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
3738
share.state.header.uniques));
3852
memcpy((uchar*) keysegs,(uchar*) share.keyparts,
3853
(size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
3854
share.state.header.uniques)));
3739
3855
keyseg=keysegs;
3740
3856
for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3751
3867
/* Copy the unique definitions and change them to point at the new key
3753
memcpy(uniquedef,share.uniqueinfo,
3754
sizeof(MI_UNIQUEDEF)*(share.state.header.uniques));
3869
memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
3870
(size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3755
3871
for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3756
3872
u_ptr != u_end ; u_ptr++)
3775
3891
set_if_bigger(file_length,tmp_length);
3776
3892
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3778
mi_close(*org_info);
3779
memset(&create_info, 0, sizeof(create_info));
3780
create_info.max_rows=cmax(max_records,share.base.records);
3894
VOID(mi_close(*org_info));
3895
bzero((char*) &create_info,sizeof(create_info));
3896
create_info.max_rows=max(max_records,share.base.records);
3781
3897
create_info.reloc_rows=share.base.reloc;
3782
3898
create_info.old_options=(share.options |
3783
3899
(unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3817
3933
/* We are modifing */
3818
3934
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
_mi_readinfo(*org_info,F_WRLCK,0);
3935
VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
3936
(*org_info)->state->records=info.state->records;
3821
3937
if (share.state.create_time)
3822
3938
(*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);
3951
my_afree((uchar*) uniquedef);
3952
my_afree((uchar*) keyinfo);
3953
my_afree((uchar*) recdef);
3954
my_afree((uchar*) keysegs);
3843
3959
/* write suffix to data file if neaded */
3845
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
3961
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3847
3963
MI_INFO *info=sort_info->info;
3849
3965
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3851
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
memset(buff, 0, sizeof(buff));
3967
uchar buff[MEMMAP_EXTRA_MARGIN];
3968
bzero(buff,sizeof(buff));
3853
3969
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3855
3971
mi_check_print_error(sort_info->param,
3864
3980
/* Update state and myisamchk_time of indexfile */
3866
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
3982
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3868
3984
MYISAM_SHARE *share=info->s;
3875
3991
if (update & UPDATE_STAT)
3877
uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
3993
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
3994
share->state.rec_per_key_rows=info->state->records;
3879
3995
share->state.changed&= ~STATE_NOT_ANALYZED;
3880
3996
if (info->state->records)
3909
4025
{ /* Force update of status */
3911
uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
4027
uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
4028
share->r_locks= share->w_locks= share->tot_locks= 0;
3913
4029
error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
4030
share->r_locks=r_locks;
3968
4084
if (my_errno != HA_ERR_END_OF_FILE)
3970
4086
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
free(mi_get_rec_buff_ptr(info, record));
4087
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
4088
mi_check_print_error(param,"%d when reading last record",my_errno);
3983
4099
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3985
4101
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
free(mi_get_rec_buff_ptr(info, record));
4102
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4103
update_state_info(param, info, UPDATE_AUTO_INC);
4086
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4202
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4088
4204
ha_checksum crc;
4089
const unsigned char *end=buf+length;
4205
const uchar *end=buf+length;
4090
4206
for (crc=0; buf != end; buf++)
4091
crc=((crc << 1) + *((unsigned char*) buf)) +
4207
crc=((crc << 1) + *((uchar*) buf)) +
4092
4208
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4096
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4212
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4098
uint32_t key_maxlength=key->maxlength;
4099
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4214
uint key_maxlength=key->maxlength;
4215
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
4100
4216
((uint64_t) rows * key_maxlength >
4101
4217
(uint64_t) myisam_max_temp_length));
4115
4231
MYISAM_SHARE *share=info->s;
4116
4232
MI_KEYDEF *key=share->keyinfo;
4119
4235
assert(info->state->records == 0 &&
4120
4236
(!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4121
4237
for (i=0 ; i < share->base.keys ; i++,key++)
4123
if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
4239
if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4124
4240
! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4126
4242
mi_clear_key_active(share->state.key_map, i);
4136
4252
even if the temporary file would be quite big!
4139
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4140
uint64_t key_map, bool force)
4255
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4256
uint64_t key_map, my_bool force)
4142
4258
MYISAM_SHARE *share=info->s;
4143
4259
MI_KEYDEF *key=share->keyinfo;
4147
4263
mi_repair_by_sort only works if we have at least one key. If we don't
4172
4288
sort_info->new_data_file_type = STATIC_RECORD;
4174
4290
/* Set delete_function for sort_delete_record() */
4175
memcpy(&tmp, share, sizeof(*share));
4291
memcpy((char*) &tmp, share, sizeof(*share));
4176
4292
tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4177
4293
mi_setup_functions(&tmp);
4178
4294
share->delete_record=tmp.delete_record;