40
40
only. And it is sufficient to calculate the checksum once only.
43
#include "myisam_priv.h"
44
#include "drizzled/internal/m_string.h"
43
#include "myisamdef.h"
45
45
#include <stdarg.h>
46
#include "drizzled/option.h"
46
#include <my_getopt.h>
47
47
#ifdef HAVE_SYS_VADVISE_H
48
48
#include <sys/vadvise.h>
51
#include <sys/types.h>
53
50
#ifdef HAVE_SYS_MMAN_H
54
51
#include <sys/mman.h>
56
#include <drizzled/util/test.h>
57
#include "drizzled/error.h"
62
using namespace drizzled;
63
using namespace drizzled::internal;
66
#define my_off_t2double(A) ((double) (my_off_t) (A))
68
/* Functions defined in this file */
70
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
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);
71
62
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
72
my_off_t page, unsigned char *buff, ha_rows *keys,
73
ha_checksum *key_checksum, uint32_t level);
74
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
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);
75
66
static ha_checksum calc_checksum(ha_rows count);
76
67
static int writekeys(MI_SORT_PARAM *sort_param);
77
68
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
78
my_off_t pagepos, int new_file);
79
int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
80
int sort_get_next_record(MI_SORT_PARAM *sort_param);
81
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
82
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
83
my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
85
int sort_insert_key(MI_SORT_PARAM *sort_param,
86
register SORT_KEY_BLOCKS *key_block,
87
unsigned char *key, my_off_t prev_block);
88
int sort_delete_record(MI_SORT_PARAM *sort_param);
69
my_off_t pagepos, File new_file);
70
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
71
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
72
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
73
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
74
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
76
static int sort_insert_key(MI_SORT_PARAM *sort_param,
77
register SORT_KEY_BLOCKS *key_block,
78
uchar *key, my_off_t prev_block);
79
static int sort_delete_record(MI_SORT_PARAM *sort_param);
90
80
/*static int flush_pending_blocks(MI_CHECK *param);*/
91
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
92
uint32_t buffer_length);
93
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
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);
94
84
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
96
86
void myisamchk_init(MI_CHECK *param)
98
memset(param, 0, sizeof(*param));
88
bzero((uchar*) param,sizeof(*param));
99
89
param->opt_follow_links=1;
100
param->keys_in_use= ~(uint64_t) 0;
90
param->keys_in_use= ~(ulonglong) 0;
101
91
param->search_after_block=HA_OFFSET_ERROR;
102
92
param->auto_increment_value= 0;
103
93
param->use_buffers=USE_BUFFER_INIT;
244
235
param->testflag|=T_RETRY_WITHOUT_QUICK;
245
236
if (test_flag & T_VERBOSE) puts("");
246
237
mi_check_print_error(param,"record delete-link-chain corrupted");
251
242
/* Check delete links in index file */
253
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)
255
246
my_off_t next_link;
256
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
258
249
char llbuff[21], llbuff2[21];
251
DBUG_ENTER("check_k_link");
252
DBUG_PRINT("enter", ("block_size: %u", block_size));
261
254
if (param->testflag & T_VERBOSE)
262
printf("block_size %4u:", block_size);
255
printf("block_size %4u:", block_size); /* purecov: tested */
264
257
next_link=info->s->state.key_del[nr];
265
258
records= (ha_rows) (info->state->key_file_length / block_size);
266
259
while (next_link != HA_OFFSET_ERROR && records > 0)
268
261
if (*killed_ptr(param))
270
263
if (param->testflag & T_VERBOSE)
271
264
printf("%16s",llstr(next_link,llbuff));
273
266
/* Key blocks must lay within the key file length entirely. */
274
267
if (next_link + block_size > info->state->key_file_length)
269
/* purecov: begin tested */
276
270
mi_check_print_error(param, "Invalid key block position: %s "
277
271
"key block size: %u file_length: %s",
278
272
llstr(next_link, llbuff), block_size,
279
273
llstr(info->state->key_file_length, llbuff2));
283
278
/* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
284
279
if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
281
/* purecov: begin tested */
286
282
mi_check_print_error(param, "Mis-aligned key block: %s "
287
283
"minimum key block length: %u",
288
284
llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
351
351
if (!(param->testflag & T_VERY_SILENT) &&
352
352
! (info->s->options & HA_OPTION_COMPRESS_RECORD) &&
353
uint64_t2double(info->state->key_file_length) >
354
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)
355
355
mi_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
356
356
llstr(info->state->key_file_length,buff),
357
357
llstr(info->s->base.max_key_file_length-1,buff));
359
size=lseek(info->dfile,0L,SEEK_END);
359
size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
360
360
skr=(my_off_t) info->state->data_file_length;
361
361
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
362
362
skr+= MEMMAP_EXTRA_MARGIN;
435
436
if (! mi_is_key_active(share->state.key_map, key))
437
438
/* Remember old statistics for key */
438
assert(rec_per_key_part >= param->rec_per_key_part);
439
memcpy(rec_per_key_part,
440
(share->state.rec_per_key_part +
441
(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)),
442
442
keyinfo->keysegs*sizeof(*rec_per_key_part));
447
447
param->record_checksum=init_checksum;
449
memset(¶m->unique_count, 0, sizeof(param->unique_count));
450
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));
452
452
if ((!(param->testflag & T_SILENT)))
453
453
printf ("- check data record references index: %d\n",key+1);
454
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))
456
457
if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
457
458
DFLT_INIT_HITS,info->buff,0))
525
526
/* Check that there isn't a row with auto_increment = 0 in the table */
526
527
mi_extra(info,HA_EXTRA_KEYREAD,0);
527
memset(info->lastkey, 0, keyinfo->seg->length);
528
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,
529
530
(key_part_map)1, HA_READ_KEY_EXACT))
531
532
/* Don't count this as a real warning, as myisamchk can't correct it */
532
uint32_t save=param->warning_printed;
533
uint save=param->warning_printed;
533
534
mi_check_print_warning(param, "Found row where the auto_increment "
534
535
"column has the value 0");
535
536
param->warning_printed=save;
569
570
if (param->key_file_blocks != info->state->key_file_length &&
570
param->keys_in_use != ~(uint64_t) 0)
571
param->keys_in_use != ~(ulonglong) 0)
571
572
mi_check_print_warning(param, "Some data are unreferenced in keyfile");
572
573
if (found_keys != full_text_keys)
573
574
param->record_checksum=old_record_checksum-init_checksum; /* Remove delete links */
575
576
param->record_checksum=0;
580
581
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
581
my_off_t page, unsigned char *buff, ha_rows *keys,
582
ha_checksum *key_checksum, uint32_t level)
582
my_off_t page, uchar *buff, ha_rows *keys,
583
ha_checksum *key_checksum, uint level)
584
585
char llbuff[22],llbuff2[22];
586
DBUG_ENTER("chk_index_down");
586
588
/* Key blocks must lay within the key file length entirely. */
587
589
if (page + keyinfo->block_length > info->state->key_file_length)
591
/* purecov: begin tested */
589
592
/* Give it a chance to fit in the real file size. */
590
my_off_t max_length= lseek(info->s->kfile, 0, SEEK_END);
593
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
591
595
mi_check_print_error(param, "Invalid key block position: %s "
592
596
"key block size: %u file_length: %s",
593
597
llstr(page, llbuff), keyinfo->block_length,
717
726
/* Check if index is ok */
719
728
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
720
my_off_t page, unsigned char *buff, ha_rows *keys,
721
ha_checksum *key_checksum, uint32_t level)
729
my_off_t page, uchar *buff, ha_rows *keys,
730
ha_checksum *key_checksum, uint level)
724
uint32_t used_length,comp_flag,nod_flag,key_length=0;
725
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
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;
726
735
my_off_t next_page,record;
728
uint32_t diff_pos[2];
738
DBUG_ENTER("chk_index");
739
DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
730
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
741
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
732
743
mi_check_print_error(param,"Not enough memory for keyblock");
736
747
if (keyinfo->flag & HA_NOSAME)
797
812
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
799
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
814
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
800
815
param->notnull_count,
801
816
info->lastkey, key);
803
818
param->unique_count[diff_pos[0]-1]++;
807
822
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
808
823
mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
812
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
827
(*key_checksum)+= mi_byte_checksum((uchar*) key,
813
828
key_length- info->s->rec_reflength);
814
829
record= _mi_dpos(info,0,key+key_length);
815
830
if (record >= info->state->data_file_length)
833
char llbuff2[22], llbuff3[22];
817
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));
820
843
param->record_checksum+=(ha_checksum) record;
879
906
ha_rows records, del_blocks;
880
907
my_off_t used, empty, pos, splits, start_recpos= 0,
881
908
del_length, link_used, start_block;
882
unsigned char *record= NULL, *to= NULL;
909
uchar *record= NULL, *to= NULL;
883
910
char llbuff[22],llbuff2[22],llbuff3[22];
884
911
ha_checksum intern_record_checksum;
885
912
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
886
bool static_row_size;
913
my_bool static_row_size;
887
914
MI_KEYDEF *keyinfo;
888
915
MI_BLOCK_INFO block_info;
916
DBUG_ENTER("chk_data_link");
890
918
if (!(param->testflag & T_SILENT))
1114
1142
pos=block_info.filepos+block_info.block_len;
1116
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);
1117
1178
case BLOCK_RECORD:
1118
1179
assert(0); /* Impossible */
1247
1310
printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n",
1248
1311
llstr(records,llbuff), (long)((used-link_used)/records),
1249
1312
(info->s->base.blobs ? 0.0 :
1250
(uint64_t2double((uint64_t) info->s->base.reclength*records)-
1313
(ulonglong2double((ulonglong) info->s->base.reclength*records)-
1251
1314
my_off_t2double(used))/
1252
uint64_t2double((uint64_t) info->s->base.reclength*records)*100.0));
1315
ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1253
1316
printf("Recordspace used:%9.0f%% Empty space:%12d%% Blocks/Record: %6.2f\n",
1254
(uint64_t2double(used-link_used)/uint64_t2double(used-link_used+empty)*100.0),
1255
(!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)/
1256
1319
my_off_t2double(used)*100.0)),
1257
uint64_t2double(splits - del_blocks) / records);
1320
ulonglong2double(splits - del_blocks) / records);
1259
1322
printf("Record blocks:%12s Delete blocks:%10s\n",
1260
1323
llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1263
1326
printf("Lost space: %12s Linkdata: %10s\n",
1264
1327
llstr(empty,llbuff),llstr(link_used,llbuff2));
1266
free(mi_get_rec_buff_ptr(info, record));
1329
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1330
DBUG_RETURN (error);
1269
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",errno, llstr(records,llbuff));
1332
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1271
free(mi_get_rec_buff_ptr(info, record));
1334
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1272
1335
param->testflag|=T_RETRY_WITHOUT_QUICK;
1274
1337
} /* chk_data_link */
1430
1503
param->testflag|=T_REP; /* for easy checking */
1432
if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
1505
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1433
1506
param->testflag|=T_CALC_CHECKSUM;
1435
1508
if (!param->using_global_keycache)
1436
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1437
(size_t)param->use_buffers, 0, 0);
1509
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1510
param->use_buffers, 0, 0));
1439
1512
if (init_io_cache(¶m->read_cache,info->dfile,
1440
1513
(uint) param->read_buffer_length,
1441
1514
READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1443
memset(&info->rec_cache, 0, sizeof(info->rec_cache));
1516
bzero(&info->rec_cache,sizeof(info->rec_cache));
1446
1519
if (!rep_quick)
1459
1532
if (!rep_quick)
1461
1534
/* Get real path for data file */
1462
if ((new_file=my_create(internal::fn_format(param->temp_filename,
1463
share->data_file_name, "",
1465
0,param->tmpfile_createflag,
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,
1468
1544
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1469
param->temp_filename);
1545
param->temp_filename);
1472
1548
if (new_header_length &&
1473
1549
filecopy(param,new_file,info->dfile,0L,new_header_length,
1476
1552
info->s->state.dellink= HA_OFFSET_ERROR;
1477
1553
info->rec_cache.file=new_file;
1516
1592
if (writekeys(&sort_param))
1518
if (errno != HA_ERR_FOUND_DUPP_KEY)
1594
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1596
DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
1520
1597
mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
1521
1598
info->errkey+1,
1522
1599
llstr(sort_param.start_recpos,llbuff),
1523
1600
llstr(info->dupp_key_pos,llbuff2));
1524
1601
if (param->testflag & T_VERBOSE)
1526
_mi_make_key(info,(uint) info->errkey,info->lastkey,
1527
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,
1529
1608
sort_info.dupp++;
1530
1609
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1624
1703
if (! param->error_printed)
1625
mi_check_print_error(param,"%d for record at pos %s",errno,
1704
mi_check_print_error(param,"%d for record at pos %s",my_errno,
1626
1705
llstr(sort_param.start_recpos,llbuff));
1627
1706
if (new_file >= 0)
1629
internal::my_close(new_file,MYF(0));
1630
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,
1631
1711
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1633
1713
mi_mark_crashed_on_repair(info);
1636
void * rec_buff_ptr= NULL;
1637
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1638
if (rec_buff_ptr != NULL)
1640
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1641
if (rec_buff_ptr != NULL)
1645
free(sort_info.buff);
1646
end_io_cache(¶m->read_cache);
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));
1647
1721
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1648
end_io_cache(&info->rec_cache);
1722
VOID(end_io_cache(&info->rec_cache));
1649
1723
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1650
1724
if (!got_error && param->testflag & T_UNPACK)
1652
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1726
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1653
1727
share->pack.header_length=0;
1654
1728
share->data_file_type=sort_info.new_data_file_type;
1656
1730
share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1657
1731
STATE_NOT_ANALYZED);
1732
DBUG_RETURN(got_error);
1702
1777
/* Remove checksum that was added to glob_crc in sort_get_next_record */
1703
1778
if (sort_param->calc_checksum)
1704
1779
sort_param->sort_info->param->glob_crc-= info->checksum;
1780
DBUG_PRINT("error",("errno: %d",my_errno));
1706
1782
} /* writekeys */
1709
1785
/* Change all key-pointers that points to a records */
1711
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1712
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)
1714
register uint32_t i;
1716
uint32_t key_length;
1793
DBUG_ENTER("movepoint");
1718
1795
key=info->lastkey+info->s->base.max_key_length;
1719
1796
for (i=0 ; i < info->s->base.keys; i++)
1723
1800
key_length=_mi_make_key(info,i,key,record,oldpos);
1724
1801
if (info->s->keyinfo[i].flag & HA_NOSAME)
1725
1802
{ /* Change pointer direct */
1727
1804
MI_KEYDEF *keyinfo;
1728
1805
keyinfo=info->s->keyinfo+i;
1729
1806
if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1730
1807
(uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1731
1808
info->s->state.key_root[i]))
1733
1810
nod_flag=mi_test_if_nod(info->buff);
1734
1811
_mi_dpointer(info,info->int_keypos-nod_flag-
1735
1812
info->s->rec_reflength,newpos);
1736
1813
if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1737
1814
DFLT_INIT_HITS,info->buff))
1741
1818
{ /* Change old key to new */
1742
1819
if (_mi_ck_delete(info,i,key,key_length))
1744
1821
key_length=_mi_make_key(info,i,key,record,newpos);
1745
1822
if (_mi_ck_write(info,i,key,key_length))
1751
1828
} /* movepoint */
1754
1831
/* Tell system that we want all memory for our cache */
1756
void lock_memory(MI_CHECK *)
1833
void lock_memory(MI_CHECK *param __attribute__((unused)))
1835
#ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */
1836
if (param->opt_lock_memory)
1838
int success = mlockall(MCL_CURRENT); /* or plock(DATLOCK); */
1839
if (geteuid() == 0 && success != 0)
1840
mi_check_print_warning(param,
1841
"Failed to lock memory. errno %d",my_errno);
1758
1844
} /* lock_memory */
1761
1847
/* Flush all changed blocks to disk */
1763
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, int file)
1849
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file)
1765
1851
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
1767
mi_check_print_error(param,"%d when trying to write bufferts",errno);
1853
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
1770
1856
if (!param->using_global_keycache)
1794
1881
printf("- Sorting index for MyISAM-table '%s'\n",name);
1796
1883
/* Get real path for index file */
1797
internal::fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
1798
if ((new_file=my_create(internal::fn_format(param->temp_filename,param->temp_filename,
1884
fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
1885
if ((new_file=my_create(fn_format(param->temp_filename,param->temp_filename,
1799
1886
"", INDEX_TMP_EXT,2+4),
1800
1887
0,param->tmpfile_createflag,MYF(0))) <= 0)
1802
1889
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1803
1890
param->temp_filename);
1806
1893
if (filecopy(param, new_file,share->kfile,0L,
1807
1894
(ulong) share->base.keystart, "headerblock"))
1860
1947
info->s->state.key_del[key]= HA_OFFSET_ERROR;
1862
1949
info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
1866
internal::my_close(new_file,MYF(MY_WME));
1953
VOID(my_close(new_file,MYF(MY_WME)));
1868
my_delete(param->temp_filename,MYF(MY_WME));
1955
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
1870
1957
} /* mi_sort_index */
1873
1960
/* Sort records recursive using one index */
1875
1962
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1876
my_off_t pagepos, int new_file)
1963
my_off_t pagepos, File new_file)
1878
uint32_t length,nod_flag,used_length, key_length;
1879
unsigned char *buff,*keypos,*endpos;
1880
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
1965
uint length,nod_flag,used_length, key_length;
1966
uchar *buff,*keypos,*endpos;
1967
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1881
1968
my_off_t new_page_pos,next_page;
1882
1969
char llbuff[22];
1970
DBUG_ENTER("sort_one_index");
1884
1972
new_page_pos=param->new_file_pos;
1885
1973
param->new_file_pos+=keyinfo->block_length;
1887
if (!(buff=(unsigned char*) malloc(keyinfo->block_length)))
1975
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1889
1977
mi_check_print_error(param,"Not enough memory for key block");
1892
1980
if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
1908
1996
_mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */
1909
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);
1914
2007
if (keypos >= endpos ||
1915
2008
(key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
1917
assert(keypos <= endpos);
2010
DBUG_ASSERT(keypos <= endpos);
1921
2014
/* Fill block with zero and write it to the new index file */
1922
2015
length=mi_getint(buff);
1923
memset(buff+length, 0, keyinfo->block_length-length);
1924
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,
1925
2018
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1927
mi_check_print_error(param,"Can't write indexblock, error: %d",errno);
2020
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
2023
my_afree((uchar*) buff);
2026
my_afree((uchar*) buff);
1935
2028
} /* sort_one_index */
1947
2040
int change_to_newfile(const char * filename, const char * old_ext,
1948
2041
const char * new_ext,
1949
uint32_t raid_chunks,
2042
uint raid_chunks __attribute__((unused)),
1953
2045
char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1954
2046
/* Get real path to filename */
1955
(void) internal::fn_format(old_filename,filename,"",old_ext,2+4+32);
2047
(void) fn_format(old_filename,filename,"",old_ext,2+4+32);
1956
2048
return my_redel(old_filename,
1957
internal::fn_format(new_filename,old_filename,"",new_ext,2+4),
2049
fn_format(new_filename,old_filename,"",new_ext,2+4),
1958
2050
MYF(MY_WME | MY_LINK_WARNING | MyFlags));
1959
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 */
1963
2072
/* Copy a block between two files */
1965
int filecopy(MI_CHECK *param, int to,int from,my_off_t start,
2074
int filecopy(MI_CHECK *param, File to,File from,my_off_t start,
1966
2075
my_off_t length, const char *type)
1968
2077
char tmp_buff[IO_SIZE],*buff;
1969
2078
ulong buff_length;
2079
DBUG_ENTER("filecopy");
1971
buff_length=(ulong) min(param->write_buffer_length, (size_t)length);
1972
if (!(buff=(char *)malloc(buff_length)))
2081
buff_length=(ulong) min(param->write_buffer_length,length);
2082
if (!(buff=my_malloc(buff_length,MYF(0))))
1974
2084
buff=tmp_buff; buff_length=IO_SIZE;
1977
lseek(from,start,SEEK_SET);
2087
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1978
2088
while (length > buff_length)
1980
if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1981
my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
2090
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
2091
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1983
2093
length-= buff_length;
1985
if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1986
my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
2095
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
2096
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1988
2098
if (buff != tmp_buff)
2099
my_free(buff,MYF(0));
1992
2102
if (buff != tmp_buff)
2103
my_free(buff,MYF(0));
1994
2104
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2072
2183
if (!rep_quick)
2074
2185
/* Get real path for data file */
2075
if ((new_file=my_create(internal::fn_format(param->temp_filename,
2076
share->data_file_name, "",
2078
0,param->tmpfile_createflag,
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,
2081
2195
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2082
param->temp_filename);
2196
param->temp_filename);
2085
2199
if (new_header_length &&
2326
2444
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2327
2445
share->state.changed|=STATE_NOT_SORTED_PAGES;
2329
void * rec_buff_ptr= NULL;
2330
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2331
if (rec_buff_ptr != NULL)
2333
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2334
if (rec_buff_ptr != NULL)
2338
free((unsigned char*) sort_info.key_block);
2339
free(sort_info.buff);
2340
end_io_cache(¶m->read_cache);
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));
2341
2455
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2342
2456
if (!got_error && (param->testflag & T_UNPACK))
2344
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2458
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2345
2459
share->pack.header_length=0;
2461
DBUG_RETURN(got_error);
2481
2597
if (!rep_quick)
2483
2599
/* Get real path for data file */
2484
if ((new_file=my_create(internal::fn_format(param->temp_filename,
2485
share->data_file_name, "",
2488
0,param->tmpfile_createflag,
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,
2491
2610
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2492
2611
param->temp_filename);
2554
2673
if (share->options & HA_OPTION_COMPRESS_RECORD)
2555
2674
set_if_bigger(max_pack_reclength, share->max_pack_length);
2556
2675
if (!(sort_param=(MI_SORT_PARAM *)
2557
malloc(share->base.keys *
2558
(sizeof(MI_SORT_PARAM) + max_pack_reclength))))
2676
my_malloc((uint) share->base.keys *
2677
(sizeof(MI_SORT_PARAM) + max_pack_reclength),
2560
2680
mi_check_print_error(param,"Not enough memory for key!");
2563
memset(sort_param, 0, share->base.keys *
2564
(sizeof(MI_SORT_PARAM) + max_pack_reclength));
2565
2683
total_key_length=0;
2566
2684
rec_per_key_part= param->rec_per_key_part;
2567
2685
info->state->records=info->state->del=share->state.split=0;
2839
2961
pthread_cond_destroy (&sort_info.cond);
2840
2962
pthread_mutex_destroy(&sort_info.mutex);
2842
free((unsigned char*) sort_info.key_block);
2843
free((unsigned char*) sort_param);
2844
free(sort_info.buff);
2845
end_io_cache(¶m->read_cache);
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));
2846
2969
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2847
2970
if (!got_error && (param->testflag & T_UNPACK))
2849
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2972
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2850
2973
share->pack.header_length=0;
2975
DBUG_RETURN(got_error);
2855
2978
/* Read next record and return next key */
2857
int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
2980
static int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
2860
2983
SORT_INFO *sort_info=sort_param->sort_info;
2861
2984
MI_INFO *info=sort_info->info;
2985
DBUG_ENTER("sort_key_read");
2863
2987
if ((error=sort_get_next_record(sort_param)))
2865
2989
if (info->state->records == sort_info->max_records)
2867
2991
mi_check_print_error(sort_info->param,
2868
2992
"Key %d - Found too many records; Can't continue",
2869
2993
sort_param->key+1);
2872
2996
sort_param->real_key_length=
2873
2997
(info->s->rec_reflength+
2874
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2998
_mi_make_key(info, sort_param->key, (uchar*) key,
2875
2999
sort_param->record, sort_param->filepos));
2876
3000
#ifdef HAVE_purify
2877
memset((unsigned char *)key+sort_param->real_key_length, 0,
2878
(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));
2880
return(sort_write_record(sort_param));
3004
DBUG_RETURN(sort_write_record(sort_param));
2881
3005
} /* sort_key_read */
3258
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));
3259
3445
case BLOCK_RECORD:
3260
3446
assert(0); /* Impossible */
3262
return(1); /* Impossible */
3448
DBUG_RETURN(1); /* Impossible */
3358
3539
/* sort_info->param->glob_crc+=info->checksum; */
3360
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++;
3361
3558
case BLOCK_RECORD:
3362
3559
assert(0); /* Impossible */
3371
3568
char llbuff[22];
3372
3569
printf("%s\r", llstr(info->state->records,llbuff));
3570
VOID(fflush(stdout));
3377
3574
} /* sort_write_record */
3380
3577
/* Compare two keys from _create_index_by_sort */
3382
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b)
3579
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3384
uint32_t not_used[2];
3385
return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
3583
return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3386
3584
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3387
3585
} /* sort_key_cmp */
3390
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3588
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3392
uint32_t diff_pos[2];
3393
3591
char llbuff[22],llbuff2[22];
3394
3592
SORT_INFO *sort_info=sort_param->sort_info;
3395
3593
MI_CHECK *param= sort_info->param;
3398
3596
if (sort_info->key_block->inited)
3400
3598
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3401
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3599
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3403
3601
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3404
3602
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
(unsigned char*) a, USE_WHOLE_KEY,
3603
(uchar*) a, USE_WHOLE_KEY,
3406
3604
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3407
3605
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3409
3607
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3410
3608
sort_param->notnull,
3411
3609
sort_info->key_block->lastkey,
3414
3612
sort_param->unique[diff_pos[0]-1]++;
3437
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);
3438
3638
return (sort_delete_record(sort_param));
3643
mi_check_print_error(param,
3644
"Internal error: Keys are not in order from sort");
3440
3648
return (sort_insert_key(sort_param,sort_info->key_block,
3441
(unsigned char*) a, HA_OFFSET_ERROR));
3649
(uchar*) a, HA_OFFSET_ERROR));
3442
3650
} /* sort_key_write */
3445
3653
/* get pointer to record from a key */
3447
my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3448
unsigned char *key) {
3655
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3449
3658
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3450
3659
} /* get_record_for_key */
3453
3662
/* Insert a key in sort-key-blocks */
3455
int sort_insert_key(MI_SORT_PARAM *sort_param,
3456
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3457
my_off_t prev_block)
3664
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3665
register SORT_KEY_BLOCKS *key_block, uchar *key,
3666
my_off_t prev_block)
3459
uint32_t a_length,t_length,nod_flag;
3668
uint a_length,t_length,nod_flag;
3460
3669
my_off_t filepos,key_file_length;
3461
unsigned char *anc_buff,*lastkey;
3670
uchar *anc_buff,*lastkey;
3462
3671
MI_KEY_PARAM s_temp;
3464
3673
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3465
3674
SORT_INFO *sort_info= sort_param->sort_info;
3466
3675
MI_CHECK *param=sort_info->param;
3676
DBUG_ENTER("sort_insert_key");
3468
3678
anc_buff=key_block->buff;
3469
3679
info=sort_info->info;
3499
3709
key_block->end_pos+=t_length;
3500
3710
if (a_length <= keyinfo->block_length)
3502
_mi_move_key(keyinfo,key_block->lastkey,key);
3712
VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3503
3713
key_block->last_length=a_length-t_length;
3507
3717
/* Fill block with end-zero and write filled block */
3508
3718
mi_putint(anc_buff,key_block->last_length,nod_flag);
3509
memset(anc_buff+key_block->last_length, 0,
3510
keyinfo->block_length - key_block->last_length);
3719
bzero((uchar*) anc_buff+key_block->last_length,
3720
keyinfo->block_length- key_block->last_length);
3511
3721
key_file_length=info->state->key_file_length;
3512
3722
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3515
3725
/* If we read the page from the key cache, we have to write it back to it */
3516
3726
if (key_file_length == info->state->key_file_length)
3518
3728
if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3521
else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3731
else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3522
3732
(uint) keyinfo->block_length,filepos, param->myf_rw))
3734
DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3525
3736
/* Write separator-key to block in next level */
3526
3737
if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3529
3740
/* clear old block and write new key in it */
3530
3741
key_block->inited=0;
3531
return(sort_insert_key(sort_param, key_block,key,prev_block));
3742
DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3532
3743
} /* sort_insert_key */
3535
3746
/* Delete record when we found a duplicated key */
3537
int sort_delete_record(MI_SORT_PARAM *sort_param)
3748
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3540
3751
int old_file,error;
3542
3753
SORT_INFO *sort_info=sort_param->sort_info;
3543
3754
MI_CHECK *param=sort_info->param;
3544
3755
MI_INFO *info=sort_info->info;
3756
DBUG_ENTER("sort_delete_record");
3546
3758
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3548
3760
mi_check_print_error(param,
3549
3761
"Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3552
3764
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3554
3766
mi_check_print_error(param,
3555
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);;
3559
3771
old_file=info->dfile;
3585
3797
error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3586
3798
info->dfile=old_file; /* restore actual value */
3587
3799
info->state->records--;
3589
3801
} /* sort_delete_record */
3591
3803
/* Fix all pending blocks and flush everything to disk */
3593
3805
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3595
uint32_t nod_flag,length;
3807
uint nod_flag,length;
3596
3808
my_off_t filepos,key_file_length;
3597
3809
SORT_KEY_BLOCKS *key_block;
3598
3810
SORT_INFO *sort_info= sort_param->sort_info;
3599
3811
myf myf_rw=sort_info->param->myf_rw;
3600
3812
MI_INFO *info=sort_info->info;
3601
3813
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3814
DBUG_ENTER("flush_pending_blocks");
3603
3816
filepos= HA_OFFSET_ERROR; /* if empty file */
3610
3823
_mi_kpointer(info,key_block->end_pos,filepos);
3611
3824
key_file_length=info->state->key_file_length;
3612
memset(key_block->buff+length, 0, keyinfo->block_length-length);
3825
bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3613
3826
if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3616
3829
/* If we read the page from the key cache, we have to write it back */
3617
3830
if (key_file_length == info->state->key_file_length)
3619
3832
if (_mi_write_keypage(info, keyinfo, filepos,
3620
3833
DFLT_INIT_HITS, key_block->buff))
3623
else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3836
else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3624
3837
(uint) keyinfo->block_length,filepos, myf_rw))
3839
DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3628
3842
info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3630
3844
} /* flush_pending_blocks */
3632
3846
/* alloc space and pointers for key_blocks */
3634
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3635
uint32_t buffer_length)
3848
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3637
register uint32_t i;
3638
3852
SORT_KEY_BLOCKS *block;
3853
DBUG_ENTER("alloc_key_blocks");
3640
if (!(block=(SORT_KEY_BLOCKS*) malloc((sizeof(SORT_KEY_BLOCKS)+
3641
buffer_length+IO_SIZE)*blocks)))
3855
if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3856
buffer_length+IO_SIZE)*blocks,
3643
3859
mi_check_print_error(param,"Not enough memory for sort-key-blocks");
3688
3905
share= *(*org_info)->s;
3689
3906
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3690
3907
(param->testflag & T_UNPACK);
3691
if (!(keyinfo=(MI_KEYDEF*) malloc(sizeof(MI_KEYDEF)*share.base.keys)))
3693
memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3908
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3910
memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
3911
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3695
3913
key_parts= share.base.all_key_parts;
3696
if (!(keysegs=(HA_KEYSEG*) malloc(sizeof(HA_KEYSEG)*
3697
(key_parts+share.base.keys))))
3914
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3915
(key_parts+share.base.keys))))
3917
my_afree((uchar*) keyinfo);
3702
3920
if (!(recdef=(MI_COLUMNDEF*)
3703
malloc(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3921
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3923
my_afree((uchar*) keyinfo);
3924
my_afree((uchar*) keysegs);
3709
3927
if (!(uniquedef=(MI_UNIQUEDEF*)
3710
malloc(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3928
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3930
my_afree((uchar*) recdef);
3931
my_afree((uchar*) keyinfo);
3932
my_afree((uchar*) keysegs);
3718
3936
/* Copy the column definitions */
3719
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)));
3720
3939
for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3722
3941
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3763
3982
(param->testflag & T_UNPACK);
3764
3983
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3766
file_length=(uint64_t) lseek(info.dfile,0L,SEEK_END);
3985
file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3767
3986
tmp_length= file_length+file_length/10;
3768
3987
set_if_bigger(file_length,param->max_data_file_length);
3769
3988
set_if_bigger(file_length,tmp_length);
3770
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);
3772
mi_close(*org_info);
3773
memset(&create_info, 0, sizeof(create_info));
3991
VOID(mi_close(*org_info));
3992
bzero((char*) &create_info,sizeof(create_info));
3774
3993
create_info.max_rows=max(max_records,share.base.records);
3775
3994
create_info.reloc_rows=share.base.reloc;
3776
3995
create_info.old_options=(share.options |
4048
my_afree((uchar*) uniquedef);
4049
my_afree((uchar*) keyinfo);
4050
my_afree((uchar*) recdef);
4051
my_afree((uchar*) keysegs);
3837
4056
/* write suffix to data file if neaded */
3839
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
4058
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3841
4060
MI_INFO *info=sort_info->info;
3843
4062
if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3845
unsigned char buff[MEMMAP_EXTRA_MARGIN];
3846
memset(buff, 0, sizeof(buff));
4064
uchar buff[MEMMAP_EXTRA_MARGIN];
4065
bzero(buff,sizeof(buff));
3847
4066
if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3849
4068
mi_check_print_error(sort_info->param,
3850
"%d when writing to datafile",errno);
4069
"%d when writing to datafile",my_errno);
3853
4072
sort_info->param->read_cache.end_of_file+=sizeof(buff);
3941
4161
mi_check_print_info(param,
3942
4162
"Table: %s doesn't have an auto increment key\n",
3943
4163
param->isam_file_name);
3946
4166
if (!(param->testflag & T_SILENT) &&
3947
4167
!(param->testflag & T_REP))
3948
4168
printf("Updating MyISAM file: %s\n", param->isam_file_name);
3950
We have to use an allocated buffer instead of info->rec_buff as
4170
We have to use an allocated buffer instead of info->rec_buff as
3951
4171
_mi_put_key_in_record() may use info->rec_buff
3953
4173
if (!mi_alloc_rec_buff(info, -1, &record))
3955
4175
mi_check_print_error(param,"Not enough memory for extra record");
3959
4179
mi_extra(info,HA_EXTRA_KEYREAD,0);
3960
4180
if (mi_rlast(info, record, info->s->base.auto_key-1))
3962
if (errno != HA_ERR_END_OF_FILE)
4182
if (my_errno != HA_ERR_END_OF_FILE)
3964
4184
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3965
free(mi_get_rec_buff_ptr(info, record));
3966
mi_check_print_error(param,"%d when reading last record",errno);
4185
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
4186
mi_check_print_error(param,"%d when reading last record",my_errno);
3969
4189
if (!repair_only)
3970
4190
info->s->state.auto_increment=param->auto_increment_value;
3974
uint64_t auto_increment= retrieve_auto_increment(info, record);
4194
ulonglong auto_increment= retrieve_auto_increment(info, record);
3975
4195
set_if_bigger(info->s->state.auto_increment,auto_increment);
3976
4196
if (!repair_only)
3977
4197
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3979
4199
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3980
free(mi_get_rec_buff_ptr(info, record));
4200
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3981
4201
update_state_info(param, info, UPDATE_AUTO_INC);
4010
4230
For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too:
4011
4231
notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL)
4012
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4232
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4013
4233
keypart{i} are not NULL)
4015
4235
For all other statistics collection methods notnull_tuples==NULL.
4017
4237
Output is an array:
4018
rec_per_key_part[k] =
4019
= E(#records in the table such that keypart_1=c_1 AND ... AND
4020
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4238
rec_per_key_part[k] =
4239
= E(#records in the table such that keypart_1=c_1 AND ... AND
4240
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4022
4242
= {assuming that values have uniform distribution and index contains all
4023
4243
tuples from the domain (or that {c_1, ..., c_k} tuple is choosen from
4026
4246
= #tuples-in-the-index / #distinct-tuples-in-the-index.
4028
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4248
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4029
4249
meaning depending on which statistics collection method is used:
4031
4251
MI_STATS_METHOD_* how are nulls compared? which tuples are counted?
4032
4252
NULLS_EQUAL NULL == NULL all tuples in table
4033
4253
NULLS_NOT_EQUAL NULL != NULL all tuples in table
4037
4257
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4038
uint64_t *unique, uint64_t *notnull,
4258
ulonglong *unique, ulonglong *notnull,
4041
uint64_t count=0,tmp, unique_tuples;
4042
uint64_t tuples= records;
4261
ulonglong count=0,tmp, unique_tuples;
4262
ulonglong tuples= records;
4044
4264
for (parts=0 ; parts < keyinfo->keysegs ; parts++)
4046
4266
count+=unique[parts];
4047
unique_tuples= count + 1;
4267
unique_tuples= count + 1;
4050
4270
tuples= notnull[parts];
4052
#(unique_tuples not counting tuples with NULLs) =
4053
#(unique_tuples counting tuples with NULLs as different) -
4272
#(unique_tuples not counting tuples with NULLs) =
4273
#(unique_tuples counting tuples with NULLs as different) -
4054
4274
#(tuples with NULLs)
4056
4276
unique_tuples -= (records - notnull[parts]);
4059
4279
if (unique_tuples == 0)
4061
4281
else if (count == 0)
4081
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)
4083
4302
ha_checksum crc;
4084
const unsigned char *end=buf+length;
4303
const uchar *end=buf+length;
4085
4304
for (crc=0; buf != end; buf++)
4086
crc=((crc << 1) + *((unsigned char*) buf)) +
4305
crc=((crc << 1) + *((uchar*) buf)) +
4087
4306
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4091
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)
4093
uint32_t key_maxlength=key->maxlength;
4094
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4095
((uint64_t) rows * key_maxlength >
4096
(uint64_t) MAX_FILE_SIZE));
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));
4129
Return true if we can use repair by sorting
4348
Return TRUE if we can use repair by sorting
4130
4349
One can set the force argument to force to use sorting
4131
4350
even if the temporary file would be quite big!
4134
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4135
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)
4137
4356
MYISAM_SHARE *share=info->s;
4138
4357
MI_KEYDEF *key=share->keyinfo;
4142
4361
mi_repair_by_sort only works if we have at least one key. If we don't
4143
4362
have any keys, we should use the normal repair.
4145
4364
if (! mi_is_any_key_active(key_map))
4146
return false; /* Can't use sort */
4365
return FALSE; /* Can't use sort */
4147
4366
for (i=0 ; i < share->base.keys ; i++,key++)
4149
4368
if (!force && mi_too_big_key_for_sort(key,rows))