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
param->keys_in_use= ~(uint64_t) 0;
90
param->keys_in_use= ~(ulonglong) 0;
90
91
param->search_after_block=HA_OFFSET_ERROR;
91
92
param->auto_increment_value= 0;
92
93
param->use_buffers=USE_BUFFER_INIT;
97
98
param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
98
99
param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
99
100
param->start_check_pos=0;
100
param->max_record_length= INT64_MAX;
101
param->max_record_length= LONGLONG_MAX;
101
102
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
102
103
param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
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];
142
DBUG_ENTER("chk_del");
142
144
param->record_checksum=0;
143
145
delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
162
164
for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
164
166
if (*killed_ptr(param))
166
168
if (test_flag & T_VERBOSE)
167
169
printf(" %9s",llstr(next_link,buff));
168
170
if (next_link >= info->state->data_file_length)
170
if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
172
if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
173
next_link,MYF(MY_NABP)))
173
175
if (test_flag & T_VERBOSE) puts("");
174
176
mi_check_print_error(param,"Can't read delete-link at filepos: %s",
175
177
llstr(next_link,buff));
178
180
if (*buff != '\0')
233
235
param->testflag|=T_RETRY_WITHOUT_QUICK;
234
236
if (test_flag & T_VERBOSE) puts("");
235
237
mi_check_print_error(param,"record delete-link-chain corrupted");
240
242
/* Check delete links in index file */
242
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
244
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
244
246
my_off_t next_link;
245
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
249
char llbuff[21], llbuff2[21];
251
DBUG_ENTER("check_k_link");
252
DBUG_PRINT("enter", ("block_size: %u", block_size));
250
254
if (param->testflag & T_VERBOSE)
251
255
printf("block_size %4u:", block_size); /* purecov: tested */
290
294
if (!(buff=key_cache_read(info->s->key_cache,
291
295
info->s->kfile, next_link, DFLT_INIT_HITS,
292
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
296
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
297
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
299
/* purecov: begin tested */
296
300
mi_check_print_error(param, "key cache read error for block: %s",
297
301
llstr(next_link,llbuff));
299
303
/* purecov: end */
301
305
next_link=mi_sizekorr(buff);
346
351
if (!(param->testflag & T_VERY_SILENT) &&
347
352
! (info->s->options & HA_OPTION_COMPRESS_RECORD) &&
348
uint64_t2double(info->state->key_file_length) >
349
uint64_t2double(info->s->base.margin_key_file_length)*0.9)
353
ulonglong2double(info->state->key_file_length) >
354
ulonglong2double(info->s->base.margin_key_file_length)*0.9)
350
355
mi_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
351
356
llstr(info->state->key_file_length,buff),
352
357
llstr(info->s->base.max_key_file_length-1,buff));
380
385
if (!(param->testflag & T_VERY_SILENT) &&
381
386
!(info->s->options & HA_OPTION_COMPRESS_RECORD) &&
382
uint64_t2double(info->state->data_file_length) >
383
(uint64_t2double(info->s->base.max_data_file_length)*0.9))
387
ulonglong2double(info->state->data_file_length) >
388
(ulonglong2double(info->s->base.max_data_file_length)*0.9))
384
389
mi_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
385
390
llstr(info->state->data_file_length,buff),
386
391
llstr(info->s->base.max_data_file_length-1,buff2));
393
398
int chk_key(MI_CHECK *param, register MI_INFO *info)
395
uint32_t key,found_keys=0,full_text_keys=0,result=0;
400
uint key,found_keys=0,full_text_keys=0,result=0;
397
402
ha_checksum old_record_checksum,init_checksum;
398
403
my_off_t all_keydata,all_totaldata,key_totlength,length;
430
436
if (! mi_is_key_active(share->state.key_map, key))
432
438
/* 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)),
439
memcpy((char*) rec_per_key_part,
440
(char*) (share->state.rec_per_key_part +
441
(uint) (rec_per_key_part - param->rec_per_key_part)),
437
442
keyinfo->keysegs*sizeof(*rec_per_key_part));
442
447
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));
449
bzero((char*) ¶m->unique_count,sizeof(param->unique_count));
450
bzero((char*) ¶m->notnull_count,sizeof(param->notnull_count));
447
452
if ((!(param->testflag & T_SILENT)))
448
453
printf ("- check data record references index: %d\n",key+1);
449
if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0))
454
if (share->state.key_root[key] == HA_OFFSET_ERROR &&
455
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
451
457
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
452
458
DFLT_INIT_HITS,info->buff,0))
465
471
param->max_level=0;
466
472
if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
467
473
&keys, param->key_crc+key,1))
475
if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
471
477
if (keys != info->state->records)
473
479
mi_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
474
480
llstr(info->state->records,buff2));
475
481
if (!(param->testflag & T_INFO))
498
504
if ((uint) share->base.auto_key -1 == key)
500
506
/* Check that auto_increment key is bigger than max key value */
501
uint64_t auto_increment;
507
ulonglong auto_increment;
502
508
info->lastinx=key;
503
509
_mi_read_key_record(info, 0L, info->rec_buff);
504
510
auto_increment= retrieve_auto_increment(info, info->rec_buff);
520
526
/* Check that there isn't a row with auto_increment = 0 in the table */
521
527
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,
528
bzero(info->lastkey,keyinfo->seg->length);
529
if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
524
530
(key_part_map)1, HA_READ_KEY_EXACT))
526
532
/* Don't count this as a real warning, as myisamchk can't correct it */
527
uint32_t save=param->warning_printed;
533
uint save=param->warning_printed;
528
534
mi_check_print_warning(param, "Found row where the auto_increment "
529
535
"column has the value 0");
530
536
param->warning_printed=save;
547
553
update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
548
554
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
549
555
param->notnull_count: NULL,
550
(uint64_t)info->state->records);
556
(ulonglong)info->state->records);
552
558
if (param->testflag & T_INFO)
564
570
if (param->key_file_blocks != info->state->key_file_length &&
565
param->keys_in_use != ~(uint64_t) 0)
571
param->keys_in_use != ~(ulonglong) 0)
566
572
mi_check_print_warning(param, "Some data are unreferenced in keyfile");
567
573
if (found_keys != full_text_keys)
568
574
param->record_checksum=old_record_checksum-init_checksum; /* Remove delete links */
570
576
param->record_checksum=0;
575
581
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)
582
my_off_t page, uchar *buff, ha_rows *keys,
583
ha_checksum *key_checksum, uint level)
579
585
char llbuff[22],llbuff2[22];
586
DBUG_ENTER("chk_index_down");
581
588
/* Key blocks must lay within the key file length entirely. */
582
589
if (page + keyinfo->block_length > info->state->key_file_length)
646
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
653
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull,
649
uint32_t first_null, kp;
650
657
first_null= ha_find_null(keyseg, key) - keyseg;
652
659
All prefix tuples that don't include keypart_{first_null} are not-null
686
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
unsigned char *prev_key, unsigned char *last_key)
693
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull,
694
uchar *prev_key, uchar *last_key)
690
uint32_t first_null_seg, kp;
697
uint first_null_seg, kp;
719
726
/* Check if index is ok */
721
728
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)
729
my_off_t page, uchar *buff, ha_rows *keys,
730
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;
733
uint used_length,comp_flag,nod_flag,key_length=0;
734
uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
735
my_off_t next_page,record;
730
uint32_t diff_pos[2];
738
DBUG_ENTER("chk_index");
739
DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
732
if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
741
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
734
743
mi_check_print_error(param,"Not enough memory for keyblock");
738
747
if (keyinfo->flag & HA_NOSAME)
772
781
if (keypos >= endpos ||
773
782
(key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
775
assert(key_length <= sizeof(key));
784
DBUG_ASSERT(key_length <= sizeof(key));
776
785
if (keypos > endpos)
778
787
mi_check_print_error(param,"Wrong key block length at page: %s",llstr(page,llbuff));
782
791
(flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
783
792
comp_flag, diff_pos)) >=0)
794
DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length);
795
DBUG_DUMP("new",(uchar*) key, key_length);
796
DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
785
798
if (comp_flag & SEARCH_FIND && flag == 0)
786
799
mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff));
814
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
827
(*key_checksum)+= mi_byte_checksum((uchar*) key,
815
828
key_length- info->s->rec_reflength);
816
829
record= _mi_dpos(info,0,key+key_length);
817
830
if (record >= info->state->data_file_length)
833
char llbuff2[22], llbuff3[22];
819
835
mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
836
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
837
llstr(page,llbuff),llstr(record,llbuff2),
838
llstr(info->state->data_file_length,llbuff3)));
839
DBUG_DUMP("key",(uchar*) key,key_length);
840
DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
822
843
param->record_checksum+=(ha_checksum) record;
827
848
llstr(page,llbuff), used_length, (keypos - buff));
830
my_afree((unsigned char*) temp_buff);
851
my_afree((uchar*) temp_buff);
833
my_afree((unsigned char*) temp_buff);
854
my_afree((uchar*) temp_buff);
835
856
} /* chk_index */
856
return((ha_checksum) sum);
878
DBUG_PRINT("exit",("sum: %lx",(ulong) sum));
879
DBUG_RETURN((ha_checksum) sum);
857
880
} /* calc_checksum */
860
883
/* Calc length of key in normal isam */
862
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
885
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
865
888
HA_KEYSEG *keyseg;
889
DBUG_ENTER("isam_key_length");
867
891
length= info->s->rec_reflength;
868
892
for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++)
869
893
length+= keyseg->length;
895
DBUG_PRINT("exit",("length: %d",length));
872
897
} /* key_length */
881
906
ha_rows records, del_blocks;
882
907
my_off_t used, empty, pos, splits, start_recpos= 0,
883
908
del_length, link_used, start_block;
884
unsigned char *record= NULL, *to= NULL;
909
uchar *record= NULL, *to= NULL;
885
910
char llbuff[22],llbuff2[22],llbuff3[22];
886
911
ha_checksum intern_record_checksum;
887
912
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
888
bool static_row_size;
913
my_bool static_row_size;
889
914
MI_KEYDEF *keyinfo;
890
915
MI_BLOCK_INFO block_info;
916
DBUG_ENTER("chk_data_link");
892
918
if (!(param->testflag & T_SILENT))
926
952
pos=my_b_tell(¶m->read_cache);
927
memset(key_checksum, 0, info->s->base.keys * sizeof(key_checksum[0]));
953
bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
928
954
while (pos < info->state->data_file_length)
930
956
if (*killed_ptr(param))
932
958
switch (info->s->data_file_type) {
933
959
case STATIC_RECORD:
934
if (my_b_read(¶m->read_cache,(unsigned char*) record,
960
if (my_b_read(¶m->read_cache,(uchar*) record,
935
961
info->s->base.pack_reclength))
937
963
start_recpos=pos;
951
977
block_info.next_filepos=pos;
954
if (_mi_read_cache(¶m->read_cache,(unsigned char*) block_info.header,
980
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header,
955
981
(start_block=block_info.next_filepos),
956
982
sizeof(block_info.header),
957
983
(flag ? 0 : READING_NEXT) | READING_HEADER))
1058
if (_mi_read_cache(¶m->read_cache,(unsigned char*) to,block_info.filepos,
1084
if (_mi_read_cache(¶m->read_cache,(uchar*) to,block_info.filepos,
1059
1085
(uint) block_info.data_len,
1060
1086
flag == 1 ? READING_NEXT : 0))
1116
1142
pos=block_info.filepos+block_info.block_len;
1118
1144
case COMPRESSED_RECORD:
1145
if (_mi_read_cache(¶m->read_cache,(uchar*) block_info.header, pos,
1146
info->s->pack.ref_length, READING_NEXT))
1150
VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
1151
&info->rec_buff, -1, start_recpos));
1152
pos=block_info.filepos+block_info.rec_len;
1153
if (block_info.rec_len < (uint) info->s->min_pack_length ||
1154
block_info.rec_len > (uint) info->s->max_pack_length)
1156
mi_check_print_error(param,
1157
"Found block with wrong recordlength: %d at %s",
1158
block_info.rec_len, llstr(start_recpos,llbuff));
1162
if (_mi_read_cache(¶m->read_cache,(uchar*) info->rec_buff,
1163
block_info.filepos, block_info.rec_len, READING_NEXT))
1165
if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
1166
info->rec_buff, block_info.rec_len))
1168
mi_check_print_error(param,"Found wrong record at %s",
1169
llstr(start_recpos,llbuff));
1172
if (static_row_size)
1173
param->glob_crc+= mi_static_checksum(info,record);
1175
param->glob_crc+= mi_checksum(info,record);
1176
link_used+= (block_info.filepos - start_recpos);
1177
used+= (pos-start_recpos);
1119
1178
case BLOCK_RECORD:
1120
1179
assert(0); /* Impossible */
1126
1185
if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1128
printf("%s\r", llstr(records,llbuff)); fflush(stdout);
1187
printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1131
1190
/* Check if keys match the record */
1136
1195
if (mi_is_key_active(info->s->state.key_map, key))
1197
if(!(keyinfo->flag & HA_FULLTEXT))
1139
uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1199
uint key_length=_mi_make_key(info,key,info->lastkey,record,
1200
1260
for (key=0 ; key < info->s->base.keys; key++)
1202
if (key_checksum[key] != param->key_crc[key])
1262
if (key_checksum[key] != param->key_crc[key] &&
1263
!(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1204
1265
mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
1249
1310
printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n",
1250
1311
llstr(records,llbuff), (long)((used-link_used)/records),
1251
1312
(info->s->base.blobs ? 0.0 :
1252
(uint64_t2double((uint64_t) info->s->base.reclength*records)-
1313
(ulonglong2double((ulonglong) info->s->base.reclength*records)-
1253
1314
my_off_t2double(used))/
1254
uint64_t2double((uint64_t) info->s->base.reclength*records)*100.0));
1315
ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1255
1316
printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n",
1256
(uint64_t2double(used-link_used)/uint64_t2double(used-link_used+empty)*100.0),
1257
(!records ? 100 : (int) (uint64_t2double(del_length+empty)/
1317
(ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0),
1318
(!records ? 100 : (int) (ulonglong2double(del_length+empty)/
1258
1319
my_off_t2double(used)*100.0)),
1259
uint64_t2double(splits - del_blocks) / records);
1320
ulonglong2double(splits - del_blocks) / records);
1261
1322
printf("Record blocks:%12s Delete blocks:%10s\n",
1262
1323
llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1265
1326
printf("Lost space: %12s Linkdata: %10s\n",
1266
1327
llstr(empty,llbuff),llstr(link_used,llbuff2));
1268
free(mi_get_rec_buff_ptr(info, record));
1329
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1330
DBUG_RETURN (error);
1271
1332
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));
1334
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1335
param->testflag|=T_RETRY_WITHOUT_QUICK;
1276
1337
} /* chk_data_link */
1329
1390
then recrate all indexes.
1332
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
1393
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1334
1395
MYISAM_SHARE *share= info->s;
1335
1396
MI_STATE_INFO *state= &share->state;
1399
DBUG_ENTER("mi_drop_all_indexes");
1340
1402
If any of the disabled indexes has a key block assigned, we must
1346
1408
if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
1410
DBUG_PRINT("repair", ("creating missing indexes"));
1348
1411
for (i= 0; i < share->base.keys; i++)
1413
DBUG_PRINT("repair", ("index #: %u key_root: 0x%lx active: %d",
1414
i, (long) state->key_root[i],
1415
mi_is_key_active(state->key_map, i)));
1350
1416
if ((state->key_root[i] != HA_OFFSET_ERROR) &&
1351
1417
!mi_is_key_active(state->key_map, i))
1414
1484
char llbuff[22],llbuff2[22];
1415
1485
SORT_INFO sort_info;
1416
1486
MI_SORT_PARAM sort_param;
1487
DBUG_ENTER("mi_repair");
1418
memset(&sort_info, 0, sizeof(sort_info));
1419
memset(&sort_param, 0, sizeof(sort_param));
1489
bzero((char *)&sort_info, sizeof(sort_info));
1490
bzero((char *)&sort_param, sizeof(sort_param));
1420
1491
start_records=info->state->records;
1421
1492
new_header_length=(param->testflag & T_UNPACK) ? 0L :
1422
1493
share->pack.header_length;
1435
1506
param->testflag|=T_CALC_CHECKSUM;
1437
1508
if (!param->using_global_keycache)
1438
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0);
1509
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1510
param->use_buffers, 0, 0));
1441
1512
if (init_io_cache(¶m->read_cache,info->dfile,
1442
1513
(uint) param->read_buffer_length,
1443
1514
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1445
memset(&info->rec_cache, 0, sizeof(info->rec_cache));
1516
bzero(&info->rec_cache,sizeof(info->rec_cache));
1448
1519
if (!rep_quick)
1461
1532
if (!rep_quick)
1463
1534
/* 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,
1535
if ((new_file=my_raid_create(fn_format(param->temp_filename,
1536
share->data_file_name, "",
1538
0,param->tmpfile_createflag,
1539
share->base.raid_type,
1540
share->base.raid_chunks,
1541
share->base.raid_chunksize,
1470
1544
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
param->temp_filename);
1545
param->temp_filename);
1474
1548
if (new_header_length &&
1475
1549
filecopy(param,new_file,info->dfile,0L,new_header_length,
1478
1552
info->s->state.dellink= HA_OFFSET_ERROR;
1479
1553
info->rec_cache.file=new_file;
1491
1565
param->read_cache.end_of_file=sort_info.filelength=
1492
1566
my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1493
1567
sort_info.dupp=0;
1494
sort_param.fix_datafile= (bool) (! rep_quick);
1568
sort_param.fix_datafile= (my_bool) (! rep_quick);
1495
1569
sort_param.master=1;
1496
1570
sort_info.max_records= ~(ha_rows) 0;
1508
1582
/* This function always recreates all enabled indexes. */
1509
1583
if (param->testflag & T_CREATE_MISSING_KEYS)
1510
1584
mi_set_all_keys_active(share->state.key_map, share->base.keys);
1511
mi_drop_all_indexes(param, info, true);
1585
mi_drop_all_indexes(param, info, TRUE);
1513
1587
lock_memory(param); /* Everything is alloced */
1520
1594
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1596
DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
1522
1597
mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
1523
1598
info->errkey+1,
1524
1599
llstr(sort_param.start_recpos,llbuff),
1525
1600
llstr(info->dupp_key_pos,llbuff2));
1526
1601
if (param->testflag & T_VERBOSE)
1528
_mi_make_key(info,(uint) info->errkey,info->lastkey,
1529
sort_param.record,0L);
1603
VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
1604
sort_param.record,0L));
1605
_mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
1531
1608
sort_info.dupp++;
1532
1609
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1540
1617
if (sort_write_record(&sort_param))
1543
if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
1620
if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1544
1621
flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1547
1624
if (param->testflag & T_WRITE_LOOP)
1549
fputs(" \r",stdout); fflush(stdout);
1626
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1551
1628
if (ftruncate(share->kfile, info->state->key_file_length))
1628
1705
llstr(sort_param.start_recpos,llbuff));
1629
1706
if (new_file >= 0)
1631
my_close(new_file,MYF(0));
1632
my_delete(param->temp_filename, MYF(MY_WME));
1708
VOID(my_close(new_file,MYF(0)));
1709
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1633
1711
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1635
1713
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);
1715
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1716
MYF(MY_ALLOW_ZERO_PTR));
1717
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1718
MYF(MY_ALLOW_ZERO_PTR));
1719
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1720
VOID(end_io_cache(¶m->read_cache));
1649
1721
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
end_io_cache(&info->rec_cache);
1722
VOID(end_io_cache(&info->rec_cache));
1651
1723
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1724
if (!got_error && param->testflag & T_UNPACK)
1654
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1726
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1727
share->pack.header_length=0;
1656
1728
share->data_file_type=sort_info.new_data_file_type;
1658
1730
share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1659
1731
STATE_NOT_ANALYZED);
1732
DBUG_RETURN(got_error);
1666
1738
static int writekeys(MI_SORT_PARAM *sort_param)
1668
register uint32_t i;
1670
1742
MI_INFO *info= sort_param->sort_info->info;
1671
unsigned char *buff= sort_param->record;
1743
uchar *buff= sort_param->record;
1672
1744
my_off_t filepos= sort_param->filepos;
1745
DBUG_ENTER("writekeys");
1674
1747
key=info->lastkey+info->s->base.max_key_length;
1675
1748
for (i=0 ; i < info->s->base.keys ; i++)
1677
1750
if (mi_is_key_active(info->s->state.key_map, i))
1680
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1753
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1754
if (_mi_ck_write(info,i,key,key_length))
1689
1762
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
1694
1767
if (mi_is_key_active(info->s->state.key_map, i))
1697
uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1770
uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1771
if (_mi_ck_delete(info,i,key,key_length))
1704
1777
/* Remove checksum that was added to glob_crc in sort_get_next_record */
1705
1778
if (sort_param->calc_checksum)
1706
1779
sort_param->sort_info->param->glob_crc-= info->checksum;
1780
DBUG_PRINT("error",("errno: %d",my_errno));
1708
1782
} /* writekeys */
1711
1785
/* 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)
1787
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1788
my_off_t newpos, uint prot_key)
1716
register uint32_t i;
1718
uint32_t key_length;
1793
DBUG_ENTER("movepoint");
1720
1795
key=info->lastkey+info->s->base.max_key_length;
1721
1796
for (i=0 ; i < info->s->base.keys; i++)
1725
1800
key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1801
if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1802
{ /* Change pointer direct */
1729
1804
MI_KEYDEF *keyinfo;
1730
1805
keyinfo=info->s->keyinfo+i;
1731
1806
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1732
1807
(uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1733
1808
info->s->state.key_root[i]))
1735
1810
nod_flag=mi_test_if_nod(info->buff);
1736
1811
_mi_dpointer(info,info->int_keypos-nod_flag-
1737
1812
info->s->rec_reflength,newpos);
1738
1813
if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1739
1814
DFLT_INIT_HITS,info->buff))
1743
1818
{ /* Change old key to new */
1744
1819
if (_mi_ck_delete(info,i,key,key_length))
1746
1821
key_length=_mi_make_key(info,i,key,record,newpos);
1747
1822
if (_mi_ck_write(info,i,key,key_length))
1753
1828
} /* movepoint */
1789
1864
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1791
register uint32_t key;
1792
1867
register MI_KEYDEF *keyinfo;
1794
1869
my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
uint32_t r_locks,w_locks;
1870
uint r_locks,w_locks;
1797
1872
MYISAM_SHARE *share=info->s;
1798
1873
MI_STATE_INFO old_state;
1874
DBUG_ENTER("mi_sort_index");
1800
1876
/* cannot sort index files with R-tree indexes */
1801
1877
for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1813
1889
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1814
1890
param->temp_filename);
1817
1893
if (filecopy(param, new_file,share->kfile,0L,
1818
1894
(ulong) share->base.keystart, "headerblock"))
1848
1924
/* Put same locks as old file */
1849
1925
share->r_locks= share->w_locks= share->tot_locks= 0;
1850
1926
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1851
my_close(share->kfile,MYF(MY_WME));
1927
VOID(my_close(share->kfile,MYF(MY_WME)));
1852
1928
share->kfile = -1;
1853
my_close(new_file,MYF(MY_WME));
1929
VOID(my_close(new_file,MYF(MY_WME)));
1854
1930
if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1856
1932
mi_open_keyfile(share))
1871
1947
info->s->state.key_del[key]= HA_OFFSET_ERROR;
1873
1949
info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
1877
my_close(new_file,MYF(MY_WME));
1953
VOID(my_close(new_file,MYF(MY_WME)));
1879
my_delete(param->temp_filename,MYF(MY_WME));
1955
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
1881
1957
} /* mi_sort_index */
1886
1962
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
1963
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];
1965
uint length,nod_flag,used_length, key_length;
1966
uchar *buff,*keypos,*endpos;
1967
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
1968
my_off_t new_page_pos,next_page;
1893
1969
char llbuff[22];
1970
DBUG_ENTER("sort_one_index");
1895
1972
new_page_pos=param->new_file_pos;
1896
1973
param->new_file_pos+=keyinfo->block_length;
1898
if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
1975
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1900
1977
mi_check_print_error(param,"Not enough memory for key block");
1903
1980
if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
1919
1996
_mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */
1920
1997
if (sort_one_index(param,info,keyinfo,next_page,new_file))
2000
("From page: %ld, keyoffset: %lu used_length: %d",
2001
(ulong) pagepos, (ulong) (keypos - buff),
2002
(int) used_length));
2003
DBUG_DUMP("buff",(uchar*) buff,used_length);
1925
2007
if (keypos >= endpos ||
1926
2008
(key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
1928
assert(keypos <= endpos);
2010
DBUG_ASSERT(keypos <= endpos);
1932
2014
/* Fill block with zero and write it to the new index file */
1933
2015
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,
2016
bzero((uchar*) buff+length,keyinfo->block_length-length);
2017
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
2018
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1938
2020
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1941
my_afree((unsigned char*) buff);
2023
my_afree((uchar*) buff);
1944
my_afree((unsigned char*) buff);
2026
my_afree((uchar*) buff);
1946
2028
} /* sort_one_index */
1958
2040
int change_to_newfile(const char * filename, const char * old_ext,
1959
2041
const char * new_ext,
1960
uint32_t raid_chunks __attribute__((unused)),
2042
uint raid_chunks __attribute__((unused)),
1963
2045
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1969
2051
} /* change_to_newfile */
2054
/* Locks a whole file */
2055
/* Gives an error-message if file can't be locked */
2057
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
2058
const char *filetype, const char *filename)
2060
if (my_lock(file,lock_type,start,F_TO_EOF,
2061
param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
2062
MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT)))
2064
mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename);
2065
param->error_printed=2; /* Don't give that data is crashed */
1973
2072
/* Copy a block between two files */
1978
2077
char tmp_buff[IO_SIZE],*buff;
1979
2078
ulong buff_length;
2079
DBUG_ENTER("filecopy");
1981
buff_length=(ulong) cmin(param->write_buffer_length,length);
2081
buff_length=(ulong) min(param->write_buffer_length,length);
1982
2082
if (!(buff=my_malloc(buff_length,MYF(0))))
1984
2084
buff=tmp_buff; buff_length=IO_SIZE;
1987
my_seek(from,start,MY_SEEK_SET,MYF(0));
2087
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1988
2088
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))
2090
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
2091
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1993
2093
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))
2095
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
2096
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1998
2098
if (buff != tmp_buff)
2099
my_free(buff,MYF(0));
2002
2102
if (buff != tmp_buff)
2103
my_free(buff,MYF(0));
2004
2104
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2105
type,my_errno);
2054
2155
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2055
2156
param->testflag|=T_CALC_CHECKSUM;
2057
memset(&sort_info, 0, sizeof(sort_info));
2058
memset(&sort_param, 0, sizeof(sort_param));
2158
bzero((char*)&sort_info,sizeof(sort_info));
2159
bzero((char *)&sort_param, sizeof(sort_param));
2059
2160
if (!(sort_info.key_block=
2060
2161
alloc_key_blocks(param,
2061
2162
(uint) param->sort_key_blocks,
2082
2183
if (!rep_quick)
2084
2185
/* 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,
2186
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2187
share->data_file_name, "",
2189
0,param->tmpfile_createflag,
2190
share->base.raid_type,
2191
share->base.raid_chunks,
2192
share->base.raid_chunksize,
2091
2195
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
param->temp_filename);
2196
param->temp_filename);
2095
2199
if (new_header_length &&
2108
2212
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2110
2214
/* Optionally drop indexes and optionally modify the key_map. */
2111
mi_drop_all_indexes(param, info, false);
2215
mi_drop_all_indexes(param, info, FALSE);
2112
2216
key_map= share->state.key_map;
2113
2217
if (param->testflag & T_CREATE_MISSING_KEYS)
2129
2233
sort_param.wordlist=NULL;
2131
2235
if (share->data_file_type == DYNAMIC_RECORD)
2132
length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2236
length=max(share->base.min_pack_length+1,share->base.min_block_length);
2133
2237
else if (share->data_file_type == COMPRESSED_RECORD)
2134
2238
length=share->base.min_block_length;
2163
2267
if (! mi_is_key_active(key_map, sort_param.key))
2165
2269
/* 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)),
2270
memcpy((char*) rec_per_key_part,
2271
(char*) (share->state.rec_per_key_part +
2272
(uint) (rec_per_key_part - param->rec_per_key_part)),
2170
2273
sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
2274
DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
2175
2280
printf ("- Fixing index %d\n",sort_param.key+1);
2176
2281
sort_param.max_pos=sort_param.pos=share->pack.header_length;
2177
2282
keyseg=sort_param.seg;
2178
memset(sort_param.unique, 0, sizeof(sort_param.unique));
2283
bzero((char*) sort_param.unique,sizeof(sort_param.unique));
2179
2284
sort_param.key_length=share->rec_reflength;
2180
2285
for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
2213
2318
update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
2214
2319
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
2215
2320
sort_param.notnull: NULL,
2216
(uint64_t) info->state->records);
2321
(ulonglong) info->state->records);
2217
2322
/* Enable this index in the permanent (not the copied) key_map. */
2218
2323
mi_set_key_active(share->state.key_map, sort_param.key);
2324
DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
2220
2326
if (sort_param.fix_datafile)
2326
2432
mi_check_print_error(param,"%d when fixing table",my_errno);
2327
2433
if (new_file >= 0)
2329
my_close(new_file,MYF(0));
2330
my_delete(param->temp_filename, MYF(MY_WME));
2435
VOID(my_close(new_file,MYF(0)));
2436
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2331
2438
if (info->dfile == new_file)
2334
2441
mi_mark_crashed_on_repair(info);
2337
2444
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2445
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);
2447
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2448
MYF(MY_ALLOW_ZERO_PTR));
2449
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2450
MYF(MY_ALLOW_ZERO_PTR));
2451
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2452
my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
2453
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2454
VOID(end_io_cache(¶m->read_cache));
2352
2455
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2456
if (!got_error && (param->testflag & T_UNPACK))
2355
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2458
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2459
share->pack.header_length=0;
2461
DBUG_RETURN(got_error);
2404
2507
const char * name, int rep_quick)
2407
uint32_t i,key, total_key_length, istep;
2510
uint i,key, total_key_length, istep;
2408
2511
ulong rec_length;
2409
2512
ha_rows start_records;
2410
2513
my_off_t new_header_length,del;
2464
2568
position 'new_header_length'.
2467
memset(&sort_info, 0, sizeof(sort_info));
2571
DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
2572
bzero((char*)&sort_info,sizeof(sort_info));
2468
2573
/* Initialize pthread structures before goto err. */
2469
2574
pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2470
2575
pthread_cond_init(&sort_info.cond, 0);
2492
2597
if (!rep_quick)
2494
2599
/* 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,
2600
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2601
share->data_file_name, "",
2604
0,param->tmpfile_createflag,
2605
share->base.raid_type,
2606
share->base.raid_chunks,
2607
share->base.raid_chunksize,
2502
2610
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2611
param->temp_filename);
2519
2627
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2521
2629
/* Optionally drop indexes and optionally modify the key_map. */
2522
mi_drop_all_indexes(param, info, false);
2630
mi_drop_all_indexes(param, info, FALSE);
2523
2631
key_map= share->state.key_map;
2524
2632
if (param->testflag & T_CREATE_MISSING_KEYS)
2537
2645
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2539
2647
if (share->data_file_type == DYNAMIC_RECORD)
2540
rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
2648
rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2649
else if (share->data_file_type == COMPRESSED_RECORD)
2542
2650
rec_length=share->base.min_block_length;
2590
2698
if (! mi_is_key_active(key_map, key))
2592
2700
/* 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)),
2701
memcpy((char*) rec_per_key_part,
2702
(char*) (share->state.rec_per_key_part+
2703
(uint) (rec_per_key_part - param->rec_per_key_part)),
2597
2704
sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2616
2723
sort_param[i].filepos=new_header_length;
2617
2724
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))+
2726
sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2727
(max_pack_reclength * i));
2621
2728
if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2806
2916
the share by remove_io_thread() or it was not yet started (if the
2807
2917
error happend before creating the thread).
2809
end_io_cache(&info->rec_cache);
2919
VOID(end_io_cache(&info->rec_cache));
2811
2921
Destroy the new data cache in case of non-quick repair. All slave
2812
2922
threads did either detach from the share by remove_io_thread()
2836
2946
mi_check_print_error(param,"%d when fixing table",my_errno);
2837
2947
if (new_file >= 0)
2839
my_close(new_file,MYF(0));
2840
my_delete(param->temp_filename, MYF(MY_WME));
2949
VOID(my_close(new_file,MYF(0)));
2950
VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2841
2952
if (info->dfile == new_file)
2844
2955
mi_mark_crashed_on_repair(info);
2850
2961
pthread_cond_destroy (&sort_info.cond);
2851
2962
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);
2964
my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
2965
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2966
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2967
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2968
VOID(end_io_cache(¶m->read_cache));
2857
2969
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
2970
if (!got_error && (param->testflag & T_UNPACK))
2860
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2972
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
2973
share->pack.header_length=0;
2975
DBUG_RETURN(got_error);
2866
2978
/* Read next record and return next key */
2871
2983
SORT_INFO *sort_info=sort_param->sort_info;
2872
2984
MI_INFO *info=sort_info->info;
2985
DBUG_ENTER("sort_key_read");
2874
2987
if ((error=sort_get_next_record(sort_param)))
2876
2989
if (info->state->records == sort_info->max_records)
2878
2991
mi_check_print_error(sort_info->param,
2879
2992
"Key %d - Found too many records; Can't continue",
2880
2993
sort_param->key+1);
2883
2996
sort_param->real_key_length=
2884
2997
(info->s->rec_reflength+
2885
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2998
_mi_make_key(info, sort_param->key, (uchar*) key,
2886
2999
sort_param->record, sort_param->filepos));
2887
3000
#ifdef HAVE_purify
2888
memset(key+sort_param->real_key_length, 0,
2889
(sort_param->key_length-sort_param->real_key_length));
3001
bzero(key+sort_param->real_key_length,
3002
(sort_param->key_length-sort_param->real_key_length));
2891
return(sort_write_record(sort_param));
3004
DBUG_RETURN(sort_write_record(sort_param));
2892
3005
} /* sort_key_read */
2929
3042
int parallel_flag;
2930
uint32_t found_record,b_type,left_length;
3043
uint found_record,b_type,left_length;
2932
unsigned char *to= NULL;
2933
3046
MI_BLOCK_INFO block_info;
2934
3047
SORT_INFO *sort_info=sort_param->sort_info;
2935
3048
MI_CHECK *param=sort_info->param;
2936
3049
MI_INFO *info=sort_info->info;
2937
3050
MYISAM_SHARE *share=info->s;
2938
3051
char llbuff[22],llbuff2[22];
3052
DBUG_ENTER("sort_get_next_record");
2940
3054
if (*killed_ptr(param))
2943
3057
switch (share->data_file_type) {
2944
3058
case STATIC_RECORD:
3005
3119
llstr(param->search_after_block,llbuff),
3006
3120
llstr(sort_param->start_recpos,llbuff2));
3007
3121
if (_mi_read_cache(&sort_param->read_cache,
3008
(unsigned char*) block_info.header,pos,
3122
(uchar*) block_info.header,pos,
3009
3123
MI_BLOCK_INFO_HEADER_LENGTH,
3010
3124
(! found_record ? READING_NEXT : 0) |
3011
3125
parallel_flag | READING_HEADER))
3017
3131
llstr(sort_param->start_recpos,llbuff),errno);
3022
3136
if (searching && ! sort_param->fix_datafile)
3024
3138
param->error_printed=1;
3025
3139
param->retry_repair=1;
3026
3140
param->testflag|=T_RETRY_WITHOUT_QUICK;
3027
return(1); /* Something wrong with data */
3141
DBUG_RETURN(1); /* Something wrong with data */
3029
3143
b_type=_mi_get_block_info(&block_info,-1,pos);
3030
3144
if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3032
3146
(block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3147
block_info.rec_len > (uint) share->base.max_pack_length)))
3036
3150
if (param->testflag & T_VERBOSE || searching == 0)
3037
3151
mi_check_print_info(param,
3038
3152
"Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3191
3305
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);
3308
uint header_len= (uint) (block_info.filepos - pos);
3309
uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3197
3311
if (prefetch_len > block_info.data_len)
3198
3312
prefetch_len= block_info.data_len;
3269
3383
case COMPRESSED_RECORD:
3384
for (searching=0 ;; searching=1, sort_param->pos++)
3386
if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
3388
share->pack.ref_length,READING_NEXT))
3390
if (searching && ! sort_param->fix_datafile)
3392
param->error_printed=1;
3393
param->retry_repair=1;
3394
param->testflag|=T_RETRY_WITHOUT_QUICK;
3395
DBUG_RETURN(1); /* Something wrong with data */
3397
sort_param->start_recpos=sort_param->pos;
3398
if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
3399
&sort_param->rec_buff, -1, sort_param->pos))
3401
if (!block_info.rec_len &&
3402
sort_param->pos + MEMMAP_EXTRA_MARGIN ==
3403
sort_param->read_cache.end_of_file)
3405
if (block_info.rec_len < (uint) share->min_pack_length ||
3406
block_info.rec_len > (uint) share->max_pack_length)
3409
mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
3411
llstr(sort_param->pos,llbuff));
3414
if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
3415
block_info.filepos, block_info.rec_len,
3419
mi_check_print_info(param,"Couldn't read whole record from %s",
3420
llstr(sort_param->pos,llbuff));
3423
if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
3424
sort_param->rec_buff, block_info.rec_len))
3427
mi_check_print_info(param,"Found wrong record at %s",
3428
llstr(sort_param->pos,llbuff));
3431
if (!sort_param->fix_datafile)
3433
sort_param->filepos=sort_param->pos;
3434
if (sort_param->master)
3435
share->state.split++;
3437
sort_param->max_pos=(sort_param->pos=block_info.filepos+
3438
block_info.rec_len);
3439
info->packed_length=block_info.rec_len;
3440
if (sort_param->calc_checksum)
3441
param->glob_crc+= (info->checksum=
3442
mi_checksum(info, sort_param->record));
3270
3445
case BLOCK_RECORD:
3271
3446
assert(0); /* Impossible */
3273
return(1); /* Impossible */
3448
DBUG_RETURN(1); /* Impossible */
3292
3467
int sort_write_record(MI_SORT_PARAM *sort_param)
3295
3471
ulong block_length,reclength;
3296
unsigned char *from;
3473
uchar block_buff[8];
3297
3474
SORT_INFO *sort_info=sort_param->sort_info;
3298
3475
MI_CHECK *param=sort_info->param;
3299
3476
MI_INFO *info=sort_info->info;
3300
3477
MYISAM_SHARE *share=info->s;
3478
DBUG_ENTER("sort_write_record");
3302
3480
if (sort_param->fix_datafile)
3361
3539
/* sort_info->param->glob_crc+=info->checksum; */
3363
3541
case COMPRESSED_RECORD:
3542
reclength=info->packed_length;
3543
length= save_pack_length((uint) share->pack.version, block_buff,
3545
if (info->s->base.blobs)
3546
length+= save_pack_length((uint) share->pack.version,
3547
block_buff + length, info->blob_length);
3548
if (my_b_write(&info->rec_cache,block_buff,length) ||
3549
my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
3551
mi_check_print_error(param,"%d when writing to datafile",my_errno);
3554
/* sort_info->param->glob_crc+=info->checksum; */
3555
sort_param->filepos+=reclength+length;
3556
info->s->state.split++;
3364
3558
case BLOCK_RECORD:
3365
3559
assert(0); /* Impossible */
3385
3579
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),
3583
return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3390
3584
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3585
} /* sort_key_cmp */
3394
3588
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3396
uint32_t diff_pos[2];
3397
3591
char llbuff[22],llbuff2[22];
3398
3592
SORT_INFO *sort_info=sort_param->sort_info;
3399
3593
MI_CHECK *param= sort_info->param;
3402
3596
if (sort_info->key_block->inited)
3404
3598
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3599
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3407
3601
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3602
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
(unsigned char*) a, USE_WHOLE_KEY,
3603
(uchar*) a, USE_WHOLE_KEY,
3410
3604
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3605
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3413
3607
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3608
sort_param->notnull,
3415
3609
sort_info->key_block->lastkey,
3418
3612
sort_param->unique[diff_pos[0]-1]++;
3423
3617
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3618
mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3427
3621
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3429
3623
sort_info->dupp++;
3430
3624
sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3625
sort_param->keyinfo,
3432
(unsigned char*) a);
3433
3627
mi_check_print_warning(param,
3434
3628
"Duplicate key for record at %10s against record at %10s",
3435
3629
llstr(sort_info->info->lastpos,llbuff),
3441
3635
param->testflag|=T_RETRY_WITHOUT_QUICK;
3636
if (sort_info->param->testflag & T_VERBOSE)
3637
_mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3442
3638
return (sort_delete_record(sort_param));
3643
mi_check_print_error(param,
3644
"Internal error: Keys are not in order from sort");
3444
3648
return (sort_insert_key(sort_param,sort_info->key_block,
3445
(unsigned char*) a, HA_OFFSET_ERROR));
3649
(uchar*) a, HA_OFFSET_ERROR));
3446
3650
} /* sort_key_write */
3449
3653
/* get pointer to record from a key */
3451
3655
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3454
3658
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3659
} /* get_record_for_key */
3458
3662
/* Insert a key in sort-key-blocks */
3460
3664
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3665
register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3666
my_off_t prev_block)
3464
uint32_t a_length,t_length,nod_flag;
3668
uint a_length,t_length,nod_flag;
3465
3669
my_off_t filepos,key_file_length;
3466
unsigned char *anc_buff,*lastkey;
3670
uchar *anc_buff,*lastkey;
3467
3671
MI_KEY_PARAM s_temp;
3469
3673
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3470
3674
SORT_INFO *sort_info= sort_param->sort_info;
3471
3675
MI_CHECK *param=sort_info->param;
3676
DBUG_ENTER("sort_insert_key");
3473
3678
anc_buff=key_block->buff;
3474
3679
info=sort_info->info;
3496
3701
_mi_kpointer(info,key_block->end_pos,prev_block);
3498
3703
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
(unsigned char*) 0,lastkey,lastkey,key,
3704
(uchar*) 0,lastkey,lastkey,key,
3501
3706
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
3707
a_length+=t_length;
3504
3709
key_block->end_pos+=t_length;
3505
3710
if (a_length <= keyinfo->block_length)
3507
_mi_move_key(keyinfo,key_block->lastkey,key);
3712
VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
3713
key_block->last_length=a_length-t_length;
3512
3717
/* Fill block with end-zero and write filled block */
3513
3718
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);
3719
bzero((uchar*) anc_buff+key_block->last_length,
3720
keyinfo->block_length- key_block->last_length);
3516
3721
key_file_length=info->state->key_file_length;
3517
3722
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3520
3725
/* If we read the page from the key cache, we have to write it back to it */
3521
3726
if (key_file_length == info->state->key_file_length)
3523
3728
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3526
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3731
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
3732
(uint) keyinfo->block_length,filepos, param->myf_rw))
3734
DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3530
3736
/* Write separator-key to block in next level */
3531
3737
if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3534
3740
/* clear old block and write new key in it */
3535
3741
key_block->inited=0;
3536
return(sort_insert_key(sort_param, key_block,key,prev_block));
3742
DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3537
3743
} /* sort_insert_key */
3542
3748
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3545
3751
int old_file,error;
3547
3753
SORT_INFO *sort_info=sort_param->sort_info;
3548
3754
MI_CHECK *param=sort_info->param;
3549
3755
MI_INFO *info=sort_info->info;
3756
DBUG_ENTER("sort_delete_record");
3551
3758
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3553
3760
mi_check_print_error(param,
3554
3761
"Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3557
3764
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3559
3766
mi_check_print_error(param,
3560
3767
"Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'myisamchk --safe-recover' to fix it\n",stderr);;
3564
3771
old_file=info->dfile;
3572
3779
mi_check_print_error(param,"Can't read record to be removed");
3573
3780
info->dfile=old_file;
3577
3784
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);
3786
uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
3787
if (_mi_ck_delete(info,i,key,key_length))
3582
3789
mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3583
3790
info->dfile=old_file;
3587
3794
if (sort_param->calc_checksum)
3590
3797
error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3591
3798
info->dfile=old_file; /* restore actual value */
3592
3799
info->state->records--;
3594
3801
} /* sort_delete_record */
3596
3803
/* Fix all pending blocks and flush everything to disk */
3598
3805
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3600
uint32_t nod_flag,length;
3807
uint nod_flag,length;
3601
3808
my_off_t filepos,key_file_length;
3602
3809
SORT_KEY_BLOCKS *key_block;
3603
3810
SORT_INFO *sort_info= sort_param->sort_info;
3604
3811
myf myf_rw=sort_info->param->myf_rw;
3605
3812
MI_INFO *info=sort_info->info;
3606
3813
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3814
DBUG_ENTER("flush_pending_blocks");
3608
3816
filepos= HA_OFFSET_ERROR; /* if empty file */
3615
3823
_mi_kpointer(info,key_block->end_pos,filepos);
3616
3824
key_file_length=info->state->key_file_length;
3617
memset(key_block->buff+length, 0, keyinfo->block_length-length);
3825
bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3618
3826
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3621
3829
/* If we read the page from the key cache, we have to write it back */
3622
3830
if (key_file_length == info->state->key_file_length)
3624
3832
if (_mi_write_keypage(info, keyinfo, filepos,
3625
3833
DFLT_INIT_HITS, key_block->buff))
3628
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3836
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
3837
(uint) keyinfo->block_length,filepos, myf_rw))
3839
DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3633
3842
info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3635
3844
} /* flush_pending_blocks */
3637
3846
/* 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)
3848
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3642
register uint32_t i;
3643
3852
SORT_KEY_BLOCKS *block;
3853
DBUG_ENTER("alloc_key_blocks");
3645
3855
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3646
3856
buffer_length+IO_SIZE)*blocks,
3682
3892
MI_COLUMNDEF *recdef,*rec,*end;
3683
3893
MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
3894
MI_STATUS_INFO status_info;
3685
uint32_t unpack,key_parts;
3895
uint unpack,key_parts;
3686
3896
ha_rows max_records;
3687
uint64_t file_length,tmp_length;
3897
ulonglong file_length,tmp_length;
3688
3898
MI_CREATE_INFO create_info;
3899
DBUG_ENTER("recreate_table");
3690
3901
error=1; /* Default error */
3691
3902
info= **org_info;
3695
3906
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3696
3907
(param->testflag & T_UNPACK);
3697
3908
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3699
memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3910
memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
3911
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3701
3913
key_parts= share.base.all_key_parts;
3702
3914
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
3915
(key_parts+share.base.keys))))
3705
my_afree((unsigned char*) keyinfo);
3917
my_afree((uchar*) keyinfo);
3708
3920
if (!(recdef=(MI_COLUMNDEF*)
3709
3921
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
my_afree((unsigned char*) keyinfo);
3712
my_afree((unsigned char*) keysegs);
3923
my_afree((uchar*) keyinfo);
3924
my_afree((uchar*) keysegs);
3715
3927
if (!(uniquedef=(MI_UNIQUEDEF*)
3716
3928
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);
3930
my_afree((uchar*) recdef);
3931
my_afree((uchar*) keyinfo);
3932
my_afree((uchar*) keysegs);
3724
3936
/* Copy the column definitions */
3725
memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
3937
memcpy((uchar*) recdef,(uchar*) share.rec,
3938
(size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3726
3939
for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3728
3941
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3735
3948
/* 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));
3949
memcpy((uchar*) keysegs,(uchar*) share.keyparts,
3950
(size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
3951
share.state.header.uniques)));
3739
3952
keyseg=keysegs;
3740
3953
for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3751
3964
/* 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));
3966
memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
3967
(size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3755
3968
for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3756
3969
u_ptr != u_end ; u_ptr++)
3769
3982
(param->testflag & T_UNPACK);
3770
3983
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3772
file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3985
file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3773
3986
tmp_length= file_length+file_length/10;
3774
3987
set_if_bigger(file_length,param->max_data_file_length);
3775
3988
set_if_bigger(file_length,tmp_length);
3776
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3989
set_if_bigger(file_length,(ulonglong) 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);
3991
VOID(mi_close(*org_info));
3992
bzero((char*) &create_info,sizeof(create_info));
3993
create_info.max_rows=max(max_records,share.base.records);
3781
3994
create_info.reloc_rows=share.base.reloc;
3782
3995
create_info.old_options=(share.options |
3783
3996
(unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3817
4030
/* We are modifing */
3818
4031
(*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
_mi_readinfo(*org_info,F_WRLCK,0);
4032
VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
4033
(*org_info)->state->records=info.state->records;
3821
4034
if (share.state.create_time)
3822
4035
(*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);
4048
my_afree((uchar*) uniquedef);
4049
my_afree((uchar*) keyinfo);
4050
my_afree((uchar*) recdef);
4051
my_afree((uchar*) keysegs);
3843
4056
/* write suffix to data file if neaded */
3845
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
4058
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3847
4060
MI_INFO *info=sort_info->info;
3849
4062
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3851
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
memset(buff, 0, sizeof(buff));
4064
uchar buff[MEMMAP_EXTRA_MARGIN];
4065
bzero(buff,sizeof(buff));
3853
4066
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3855
4068
mi_check_print_error(sort_info->param,
3864
4077
/* Update state and myisamchk_time of indexfile */
3866
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
4079
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3868
4081
MYISAM_SHARE *share=info->s;
3875
4088
if (update & UPDATE_STAT)
3877
uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
4090
uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
4091
share->state.rec_per_key_rows=info->state->records;
3879
4092
share->state.changed&= ~STATE_NOT_ANALYZED;
3880
4093
if (info->state->records)
3909
4122
{ /* Force update of status */
3911
uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
4124
uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
4125
share->r_locks= share->w_locks= share->tot_locks= 0;
3913
4126
error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
4127
share->r_locks=r_locks;
3938
4151
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
4152
my_bool repair_only)
3941
unsigned char *record= 0;
4155
DBUG_ENTER("update_auto_increment_key");
3943
4157
if (!info->s->base.auto_key ||
3944
4158
! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3968
4182
if (my_errno != HA_ERR_END_OF_FILE)
3970
4184
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
free(mi_get_rec_buff_ptr(info, record));
4185
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
4186
mi_check_print_error(param,"%d when reading last record",my_errno);
3975
4189
if (!repair_only)
3976
4190
info->s->state.auto_increment=param->auto_increment_value;
3980
uint64_t auto_increment= retrieve_auto_increment(info, record);
4194
ulonglong auto_increment= retrieve_auto_increment(info, record);
3981
4195
set_if_bigger(info->s->state.auto_increment,auto_increment);
3982
4196
if (!repair_only)
3983
4197
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3985
4199
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
free(mi_get_rec_buff_ptr(info, record));
4200
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4201
update_state_info(param, info, UPDATE_AUTO_INC);
4043
4257
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4044
uint64_t *unique, uint64_t *notnull,
4258
ulonglong *unique, ulonglong *notnull,
4047
uint64_t count=0,tmp, unique_tuples;
4048
uint64_t tuples= records;
4261
ulonglong count=0,tmp, unique_tuples;
4262
ulonglong tuples= records;
4050
4264
for (parts=0 ; parts < keyinfo->keysegs ; parts++)
4052
4266
count+=unique[parts];
4086
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4300
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4088
4302
ha_checksum crc;
4089
const unsigned char *end=buf+length;
4303
const uchar *end=buf+length;
4090
4304
for (crc=0; buf != end; buf++)
4091
crc=((crc << 1) + *((unsigned char*) buf)) +
4305
crc=((crc << 1) + *((uchar*) buf)) +
4092
4306
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)
4310
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) &&
4100
((uint64_t) rows * key_maxlength >
4101
(uint64_t) myisam_max_temp_length));
4312
uint key_maxlength=key->maxlength;
4313
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
4314
((ulonglong) rows * key_maxlength >
4315
(ulonglong) myisam_max_temp_length));
4115
4329
MYISAM_SHARE *share=info->s;
4116
4330
MI_KEYDEF *key=share->keyinfo;
4119
assert(info->state->records == 0 &&
4333
DBUG_ASSERT(info->state->records == 0 &&
4120
4334
(!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4121
4335
for (i=0 ; i < share->base.keys ; i++,key++)
4123
if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
4337
if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4124
4338
! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4126
4340
mi_clear_key_active(share->state.key_map, i);
4134
Return true if we can use repair by sorting
4348
Return TRUE if we can use repair by sorting
4135
4349
One can set the force argument to force to use sorting
4136
4350
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)
4353
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4354
ulonglong key_map, my_bool force)
4142
4356
MYISAM_SHARE *share=info->s;
4143
4357
MI_KEYDEF *key=share->keyinfo;
4147
4361
mi_repair_by_sort only works if we have at least one key. If we don't
4148
4362
have any keys, we should use the normal repair.
4150
4364
if (! mi_is_any_key_active(key_map))
4151
return false; /* Can't use sort */
4365
return FALSE; /* Can't use sort */
4152
4366
for (i=0 ; i < share->base.keys ; i++,key++)
4154
4368
if (!force && mi_too_big_key_for_sort(key,rows))
4172
4386
sort_info->new_data_file_type = STATIC_RECORD;
4174
4388
/* Set delete_function for sort_delete_record() */
4175
memcpy(&tmp, share, sizeof(*share));
4389
memcpy((char*) &tmp, share, sizeof(*share));
4176
4390
tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4177
4391
mi_setup_functions(&tmp);
4178
4392
share->delete_record=tmp.delete_record;