diff options
Diffstat (limited to 'myisam/mi_check.c')
-rw-r--r-- | myisam/mi_check.c | 914 |
1 files changed, 630 insertions, 284 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c index bae47061a04..8441666641c 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -45,26 +45,22 @@ static int writekeys(MI_CHECK *param, MI_INFO *info,byte *buff, my_off_t filepos); static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo, my_off_t pagepos, File new_file); -static int sort_key_read(SORT_INFO *sort_info,void *key); -static int sort_ft_key_read(SORT_INFO *sort_info,void *key); -static int sort_get_next_record(SORT_INFO *sort_info); -static int sort_key_cmp(SORT_INFO *sort_info, const void *a,const void *b); -static int sort_key_write(SORT_INFO *sort_info, const void *a); +static int sort_key_read(MI_SORT_PARAM *sort_param,void *key); +static int sort_ft_key_read(MI_SORT_PARAM *sort_param,void *key); +static int sort_get_next_record(MI_SORT_PARAM *sort_param); +static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b); +static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a); static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo, uchar *key); -static int sort_insert_key(MI_CHECK *param, reg1 SORT_KEY_BLOCKS *key_block, +static int sort_insert_key(MI_SORT_PARAM *sort_param, + reg1 SORT_KEY_BLOCKS *key_block, uchar *key, my_off_t prev_block); -static int sort_delete_record(MI_CHECK *param); +static int sort_delete_record(MI_SORT_PARAM *sort_param); /*static int flush_pending_blocks(MI_CHECK *param);*/ static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks, uint buffer_length); -static void update_key_parts(MI_KEYDEF *keyinfo, - ulong *rec_per_key_part, - ulonglong *unique, - ulonglong records); static ha_checksum mi_byte_checksum(const byte *buf, uint length); -static void set_data_file_type(MI_CHECK *param, SORT_INFO *info, - MYISAM_SHARE *share); +static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share); #ifdef __WIN__ static double ulonglong2double(ulonglong value) @@ -80,7 +76,7 @@ static double ulonglong2double(ulonglong value) #else #define my_off_t2double(A) ((double) (A)) #endif /* SIZEOF_OFF_T > 4 */ -#endif +#endif /* __WIN__ */ void myisamchk_init(MI_CHECK *param) { @@ -96,7 +92,6 @@ void myisamchk_init(MI_CHECK *param) param->sort_key_blocks=BUFFERS_WHEN_SORTING; param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL); - param->sort_info.param=param; param->start_check_pos=0; } @@ -1070,7 +1065,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) if (used != 0 && ! param->error_printed) { printf("Records:%18s M.recordlength:%9lu Packed:%14.0f%%\n", - llstr(records,llbuff), (long)((used-link_used)/records), + llstr(records,llbuff), (long)((used-link_used)/records), (info->s->base.blobs ? 0.0 : (ulonglong2double((ulonglong) info->s->base.reclength*records)- my_off_t2double(used))/ @@ -1112,18 +1107,18 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, File new_file; MYISAM_SHARE *share=info->s; char llbuff[22],llbuff2[22]; - SORT_INFO *sort_info= ¶m->sort_info; + SORT_INFO sort_info; + MI_SORT_PARAM sort_param; DBUG_ENTER("mi_repair"); - sort_info->buff=sort_info->record=0; + bzero((char *)&sort_info, sizeof(sort_info)); + bzero((char *)&sort_param, sizeof(sort_param)); start_records=info->state->records; new_header_length=(param->testflag & T_UNPACK) ? 0L : share->pack.header_length; got_error=1; new_file= -1; - sort_info->buff=0; - sort_info->buff_length=0; - sort_info->record=0; + sort_param.sort_info=&sort_info; if (!(param->testflag & T_SILENT)) { @@ -1147,8 +1142,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, MYF(MY_WME | MY_WAIT_IF_FULL))) goto err; info->opt_flag|=WRITE_CACHE_USED; - sort_info->start_recpos=0; - if (!(sort_info->record=(byte*) my_malloc((uint) share->base.pack_reclength, + if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, MYF(0)))) { mi_check_print_error(param,"Not enough memory for extra record"); @@ -1161,8 +1155,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32); if ((new_file=my_raid_create(fn_format(param->temp_filename, param->temp_filename,"", - DATA_TMP_EXT, - 2+4), + DATA_TMP_EXT, 2+4), 0,param->tmpfile_createflag, share->base.raid_type, share->base.raid_chunks, @@ -1184,16 +1177,18 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, mi_int2store(share->state.header.options,share->options); } } - sort_info->info=info; - sort_info->pos=sort_info->max_pos=share->pack.header_length; - sort_info->filepos=new_header_length; - param->read_cache.end_of_file=sort_info->filelength= + sort_info.info=info; + sort_info.param = param; + sort_param.read_cache=param->read_cache; + sort_param.pos=sort_param.max_pos=share->pack.header_length; + sort_param.filepos=new_header_length; + param->read_cache.end_of_file=sort_info.filelength= my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)); - sort_info->dupp=0; - sort_info->fix_datafile= (my_bool) (! rep_quick); - sort_info->max_records= ~(ha_rows) 0; + sort_info.dupp=0; + sort_param.fix_datafile= (my_bool) (! rep_quick); + sort_info.max_records= ~(ha_rows) 0; - set_data_file_type(param, sort_info, share); + set_data_file_type(&sort_info, share); del=info->state->del; info->state->records=info->state->del=share->state.split=0; info->state->empty=0; @@ -1210,7 +1205,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, /* I think mi_repair and mi_repair_by_sort should do the same (according, e.g. to ha_myisam::repair), but as mi_repair doesn't touch key_map it cannot be used to T_CREATE_MISSING_KEYS. - That is the next line for... (serg) + That is what the next line is for... (serg) */ share->state.key_map= ((((ulonglong) 1L << share->base.keys)-1) & @@ -1219,25 +1214,25 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->state->key_file_length=share->base.keystart; lock_memory(param); /* Everything is alloced */ - while (!(error=sort_get_next_record(sort_info))) + while (!(error=sort_get_next_record(&sort_param))) { - if (writekeys(param, info,(byte*) sort_info->record,sort_info->filepos)) + if (writekeys(param,info,(byte*)sort_param.record,sort_param.filepos)) { if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err; - DBUG_DUMP("record",(byte*) sort_info->record,share->base.pack_reclength); + DBUG_DUMP("record",(byte*) sort_param.record,share->base.pack_reclength); mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s", info->errkey+1, - llstr(sort_info->start_recpos,llbuff), + llstr(sort_param.start_recpos,llbuff), llstr(info->dupp_key_pos,llbuff2)); if (param->testflag & T_VERBOSE) { VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey, - sort_info->record,0L)); + sort_param.record,0L)); _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey, USE_WHOLE_KEY); } - sort_info->dupp++; + sort_info.dupp++; if (!(rep_quick & T_FORCE_UNIQUENESS)) { param->testflag|=T_RETRY_WITHOUT_QUICK; @@ -1246,10 +1241,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, } continue; } - if (sort_write_record(sort_info)) + if (sort_write_record(&sort_param)) goto err; } - if (error > 0 || write_data_suffix(param,info) || + if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) || flush_io_cache(&info->rec_cache) || param->read_cache.error < 0) goto err; @@ -1265,7 +1260,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, goto err; } - if (rep_quick && del+sort_info->dupp != info->state->del) + if (rep_quick && del+sort_info.dupp != info->state->del) { mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Run recovery again without -q"); @@ -1289,12 +1284,12 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, { my_close(info->dfile,MYF(0)); info->dfile=new_file; - info->state->data_file_length=sort_info->filepos; + info->state->data_file_length=sort_param.filepos; share->state.version=(ulong) time((time_t*) 0); /* Force reopen */ } else { - info->state->data_file_length=sort_info->max_pos; + info->state->data_file_length=sort_param.max_pos; } if (param->testflag & T_CALC_CHECKSUM) share->state.checksum=param->glob_crc; @@ -1303,10 +1298,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, { if (start_records != info->state->records) printf("Data records: %s\n", llstr(info->state->records,llbuff)); - if (sort_info->dupp) + if (sort_info.dupp) mi_check_print_warning(param, "%s records have been removed", - llstr(sort_info->dupp,llbuff)); + llstr(sort_info.dupp,llbuff)); } got_error=0; @@ -1334,7 +1329,7 @@ err: { if (! param->error_printed) mi_check_print_error(param,"%d for record at pos %s",my_errno, - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param.start_recpos,llbuff)); if (new_file >= 0) { VOID(my_close(new_file,MYF(0))); @@ -1343,8 +1338,8 @@ err: } mi_mark_crashed_on_repair(info); } - my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR)); - my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); VOID(end_io_cache(&info->rec_cache)); @@ -1353,7 +1348,7 @@ err: { share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; share->pack.header_length=0; - share->data_file_type=sort_info->new_data_file_type; + share->data_file_type=sort_info.new_data_file_type; } share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES | STATE_NOT_ANALYZED); @@ -1741,7 +1736,6 @@ err: type,my_errno); DBUG_RETURN(1); } - /* Fix table or given index using sorting */ /* saves new table in temp_filename */ @@ -1756,9 +1750,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, File new_file; MI_SORT_PARAM sort_param; MYISAM_SHARE *share=info->s; + MI_KEYSEG *keyseg; ulong *rec_per_key_part; char llbuff[22]; - SORT_INFO *sort_info= ¶m->sort_info; + SORT_INFO sort_info; ulonglong key_map=share->state.key_map; DBUG_ENTER("mi_repair_by_sort"); @@ -1773,8 +1768,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, printf("Data records: %s\n", llstr(start_records,llbuff)); } - bzero((char*) sort_info,sizeof(*sort_info)); - if (!(sort_info->key_block= + bzero((char*)&sort_info,sizeof(sort_info)); + if (!(sort_info.key_block= alloc_key_blocks(param, (uint) param->sort_key_blocks, share->base.max_key_block_length)) @@ -1787,11 +1782,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, WRITE_CACHE,new_header_length,1, MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) goto err; - sort_info->key_block_end=sort_info->key_block+param->sort_key_blocks; + sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; info->opt_flag|=WRITE_CACHE_USED; info->rec_cache.file=info->dfile; /* for sort_delete_record */ - if (!(sort_info->record=(byte*) my_malloc((uint) share->base.pack_reclength, + if (!(sort_param.record=(byte*) my_malloc((uint) share->base.pack_reclength, MYF(0)))) { mi_check_print_error(param,"Not enough memory for extra record"); @@ -1849,17 +1844,17 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, key_map= ~key_map; /* Create the missing keys */ } - sort_info->info=info; - sort_info->param = param; + sort_info.info=info; + sort_info.param = param; - set_data_file_type(param, sort_info, share); - sort_info->filepos=new_header_length; - sort_info->dupp=0; - sort_info->buff=0; - param->read_cache.end_of_file=sort_info->filelength= + set_data_file_type(&sort_info, share); + sort_param.filepos=new_header_length; + sort_info.dupp=0; + sort_info.buff=0; + param->read_cache.end_of_file=sort_info.filelength= my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); - sort_info->wordlist=NULL; + sort_param.wordlist=NULL; if (share->data_file_type == DYNAMIC_RECORD) length=max(share->base.min_pack_length+1,share->base.min_block_length); @@ -1867,15 +1862,15 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, length=share->base.min_block_length; else length=share->base.pack_reclength; - sort_param.max_records=sort_info->max_records= + sort_info.max_records= ((param->testflag & T_TRUST_HEADER) ? info->state->records : - (ha_rows) (sort_info->filelength/length+1)); + (ha_rows) (sort_info.filelength/length+1)); sort_param.key_cmp=sort_key_cmp; sort_param.key_write=sort_key_write; sort_param.lock_in_memory=lock_memory; sort_param.tmpdir=param->tmpdir; - sort_param.myf_rw=param->myf_rw; - sort_param.sort_info=sort_info; + sort_param.sort_info=&sort_info; + sort_param.fix_datafile= (my_bool) (! rep_quick); del=info->state->del; param->glob_crc=0; @@ -1883,44 +1878,44 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->calc_checksum=1; rec_per_key_part= param->rec_per_key_part; - for (sort_info->key=0 ; sort_info->key < share->base.keys ; - rec_per_key_part+=sort_info->keyinfo->keysegs, sort_info->key++) + for (sort_param.key=0 ; sort_param.key < share->base.keys ; + rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++) { - sort_info->keyinfo=share->keyinfo+sort_info->key; - if (!(((ulonglong) 1 << sort_info->key) & key_map)) + sort_param.read_cache=param->read_cache; + sort_param.keyinfo=share->keyinfo+sort_param.key; + if (!(((ulonglong) 1 << sort_param.key) & key_map)) { /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, (char*) share->state.rec_per_key_part+ (uint) (rec_per_key_part - param->rec_per_key_part), - sort_info->keyinfo->keysegs*sizeof(*rec_per_key_part)); + sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part)); continue; } if ((!(param->testflag & T_SILENT))) - printf ("- Fixing index %d\n",sort_info->key+1); - sort_info->max_pos=sort_info->pos=share->pack.header_length; - sort_info->keyseg=sort_info->keyinfo->seg; - sort_info->fix_datafile= (my_bool) (sort_info->key == 0 && ! rep_quick); - bzero((char*) sort_info->unique,sizeof(sort_info->unique)); + printf ("- Fixing index %d\n",sort_param.key+1); + sort_param.max_pos=sort_param.pos=share->pack.header_length; + keyseg=sort_param.keyinfo->seg; + bzero((char*) sort_param.unique,sizeof(sort_param.unique)); sort_param.key_length=share->rec_reflength; - for (i=0 ; sort_info->keyseg[i].type != HA_KEYTYPE_END; i++) + for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++) { - sort_param.key_length+=sort_info->keyseg[i].length; - if (sort_info->keyseg[i].flag & HA_SPACE_PACK) - sort_param.key_length+=get_pack_length(sort_info->keyseg[i].length); - if (sort_info->keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH)) - sort_param.key_length+=2 + test(sort_info->keyseg[i].length >= 127); - if (sort_info->keyseg[i].flag & HA_NULL_PART) + sort_param.key_length+=keyseg[i].length; + if (keyseg[i].flag & HA_SPACE_PACK) + sort_param.key_length+=get_pack_length(keyseg[i].length); + if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH)) + sort_param.key_length+=2 + test(keyseg[i].length >= 127); + if (keyseg[i].flag & HA_NULL_PART) sort_param.key_length++; } info->state->records=info->state->del=share->state.split=0; info->state->empty=0; - if (sort_info->keyinfo->flag & HA_FULLTEXT) + if (sort_param.keyinfo->flag & HA_FULLTEXT) { - sort_param.max_records=sort_info->max_records= - (ha_rows) (sort_info->filelength/ft_max_word_len_for_sort+1); + sort_info.max_records= + (ha_rows) (sort_info.filelength/ft_max_word_len_for_sort+1); sort_param.key_read=sort_ft_key_read; sort_param.key_length+=ft_max_word_len_for_sort-ft_max_word_len; @@ -1938,18 +1933,17 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->calc_checksum=0; /* No need to calc glob_crc */ /* Set for next loop */ - sort_param.max_records=sort_info->max_records= - (ha_rows) info->state->records; + sort_info.max_records= (ha_rows) info->state->records; if (param->testflag & T_STATISTICS) - update_key_parts(sort_info->keyinfo, rec_per_key_part, sort_info->unique, + update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, (ulonglong) info->state->records); - share->state.key_map|=(ulonglong) 1 << sort_info->key; + share->state.key_map|=(ulonglong) 1 << sort_param.key; - if (sort_info->fix_datafile) + if (sort_param.fix_datafile) { - param->read_cache.end_of_file=sort_info->filepos; - if (write_data_suffix(param,info) || end_io_cache(&info->rec_cache)) + param->read_cache.end_of_file=sort_param.filepos; + if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) goto err; if (param->testflag & T_SAFE_REPAIR) { @@ -1961,23 +1955,24 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, } } share->state.state.data_file_length = info->state->data_file_length - = sort_info->filepos; + = sort_param.filepos; /* Only whole records */ share->state.version=(ulong) time((time_t*) 0); my_close(info->dfile,MYF(0)); info->dfile=new_file; - share->data_file_type=sort_info->new_data_file_type; + share->data_file_type=sort_info.new_data_file_type; share->pack.header_length=(ulong) new_header_length; + sort_param.fix_datafile=0; } else - info->state->data_file_length=sort_info->max_pos; + info->state->data_file_length=sort_param.max_pos; /*if (flush_pending_blocks(param)) goto err;*/ param->read_cache.file=info->dfile; /* re-init read cache */ - reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length,1, - 1); + reinit_io_cache(¶m->read_cache,READ_CACHE,share->pack.header_length, + 1,1); } if (param->testflag & T_WRITE_LOOP) @@ -1985,7 +1980,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, VOID(fputs(" \r",stdout)); VOID(fflush(stdout)); } - if (rep_quick && del+sort_info->dupp != info->state->del) + if (rep_quick && del+sort_info.dupp != info->state->del) { mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Run recovery again without -q"); @@ -2005,7 +2000,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, skr < share->base.reloc*share->base.min_pack_length) skr=share->base.reloc*share->base.min_pack_length; #endif - if (skr != sort_info->filelength && !info->s->base.raid_type) + if (skr != sort_info.filelength && !info->s->base.raid_type) if (my_chsize(info->dfile,skr,MYF(0))) mi_check_print_warning(param, "Can't change size of datafile, error: %d", @@ -2023,10 +2018,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, { if (start_records != info->state->records) printf("Data records: %s\n", llstr(info->state->records,llbuff)); - if (sort_info->dupp) + if (sort_info.dupp) mi_check_print_warning(param, "%s records have been removed", - llstr(sort_info->dupp,llbuff)); + llstr(sort_info.dupp,llbuff)); } got_error=0; @@ -2069,9 +2064,9 @@ err: share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; share->state.changed|=STATE_NOT_SORTED_PAGES; - my_free((gptr) sort_info->key_block,MYF(MY_ALLOW_ZERO_PTR)); - my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR)); - my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR)); + my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); VOID(end_io_cache(¶m->read_cache)); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); if (!got_error && (param->testflag & T_UNPACK)) @@ -2082,18 +2077,376 @@ err: DBUG_RETURN(got_error); } + /* same as mi_repair_by_sort */ + /* but do it multithreaded */ + +int mi_repair_by_sort_r(MI_CHECK *param, register MI_INFO *info, + const char * name, int rep_quick) +{ + int got_error; + uint i,key; + ulong length; + ha_rows start_records; + my_off_t new_header_length,del; + File new_file; + MI_SORT_PARAM *sort_param=0, *sinfo; + MYISAM_SHARE *share=info->s; + ulong *rec_per_key_part; + MI_KEYSEG *keyseg; + char llbuff[22]; + IO_CACHE_SHARE io_share; + SORT_INFO sort_info; + ulonglong key_map=share->state.key_map; + DBUG_ENTER("mi_repair_by_sort_r"); + + start_records=info->state->records; + got_error=1; + new_file= -1; + new_header_length=(param->testflag & T_UNPACK) ? 0 : + share->pack.header_length; + if (!(param->testflag & T_SILENT)) + { + printf("- parallel recovering (with sort) MyISAM-table '%s'\n",name); + printf("Data records: %s\n", llstr(start_records,llbuff)); + } + + bzero((char*)&sort_info,sizeof(sort_info)); + if (!(sort_info.key_block= + alloc_key_blocks(param, + (uint) param->sort_key_blocks, + share->base.max_key_block_length)) + || init_io_cache(¶m->read_cache,info->dfile, + (uint) param->read_buffer_length, + READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) || + (! rep_quick && + init_io_cache(&info->rec_cache,info->dfile, + (uint) param->write_buffer_length, + WRITE_CACHE,new_header_length,1, + MYF(MY_WME | MY_WAIT_IF_FULL) & param->myf_rw))) + goto err; + sort_info.key_block_end=sort_info.key_block+param->sort_key_blocks; + info->opt_flag|=WRITE_CACHE_USED; + info->rec_cache.file=info->dfile; /* for sort_delete_record */ + + if (!rep_quick) + { + /* Get real path for data file */ + fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32); + if ((new_file=my_raid_create(fn_format(param->temp_filename, + param->temp_filename, "", + DATA_TMP_EXT, + 2+4), + 0,param->tmpfile_createflag, + share->base.raid_type, + share->base.raid_chunks, + share->base.raid_chunksize, + MYF(0))) < 0) + { + mi_check_print_error(param,"Can't create new tempfile: '%s'", + param->temp_filename); + goto err; + } + if (filecopy(param, new_file,info->dfile,0L,new_header_length, + "datafile-header")) + goto err; + if (param->testflag & T_UNPACK) + { + share->options&= ~HA_OPTION_COMPRESS_RECORD; + mi_int2store(share->state.header.options,share->options); + } + share->state.dellink= HA_OFFSET_ERROR; + info->rec_cache.file=new_file; + } + + info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); + if (!(param->testflag & T_CREATE_MISSING_KEYS)) + { + /* + Flush key cache for this file if we are calling this outside + myisamchk + */ + flush_key_blocks(share->kfile, FLUSH_IGNORE_CHANGED); + /* Clear the pointers to the given rows */ + for (i=0 ; i < share->base.keys ; i++) + share->state.key_root[i]= HA_OFFSET_ERROR; + for (i=0 ; i < share->state.header.max_block_size ; i++) + share->state.key_del[i]= HA_OFFSET_ERROR; + info->state->key_file_length=share->base.keystart; + } + else + { + if (flush_key_blocks(share->kfile, FLUSH_FORCE_WRITE)) + goto err; + key_map= ~key_map; /* Create the missing keys */ + } + + sort_info.info=info; + sort_info.param = param; + + set_data_file_type(&sort_info, share); + sort_info.dupp=0; + sort_info.buff=0; + param->read_cache.end_of_file=sort_info.filelength= + my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0)); + + if (share->data_file_type == DYNAMIC_RECORD) + length=max(share->base.min_pack_length+1,share->base.min_block_length); + else if (share->data_file_type == COMPRESSED_RECORD) + length=share->base.min_block_length; + else + length=share->base.pack_reclength; + sort_info.max_records= + ((param->testflag & T_TRUST_HEADER) ? info->state->records : + (ha_rows) (sort_info.filelength/length+1)); + + del=info->state->del; + param->glob_crc=0; + if (param->testflag & T_CALC_CHECKSUM) + param->calc_checksum=1; + + if (!(sort_param=(MI_SORT_PARAM *) + my_malloc((uint) share->base.keys * + (sizeof(MI_SORT_PARAM) + share->base.pack_reclength), + MYF(MY_ZEROFILL)))) + { + mi_check_print_error(param,"Not enough memory!"); + goto err; + } + length=0; + rec_per_key_part= param->rec_per_key_part; + info->state->records=info->state->del=share->state.split=0; + info->state->empty=0; + + for (i=key=0 ; key < share->base.keys ; + rec_per_key_part+=sort_param[i].keyinfo->keysegs, i++, key++) + { + sort_param[i].key=key; + sort_param[i].keyinfo=share->keyinfo+key; + if (!(((ulonglong) 1 << key) & key_map)) + { + /* Remember old statistics for key */ + memcpy((char*) rec_per_key_part, + (char*) share->state.rec_per_key_part+ + (uint) (rec_per_key_part - param->rec_per_key_part), + sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part)); + i--; + continue; + } + if ((!(param->testflag & T_SILENT))) + printf ("- Fixing index %d\n",key+1); + sort_param[i].key_read=(sort_param[i].keyinfo->flag & HA_FULLTEXT) ? + sort_ft_key_read : sort_key_read; + sort_param[i].key_cmp=sort_key_cmp; + sort_param[i].key_write=sort_key_write; + sort_param[i].lock_in_memory=lock_memory; + sort_param[i].tmpdir=param->tmpdir; + sort_param[i].sort_info=&sort_info; + sort_param[i].fix_datafile=0; + + sort_param[i].filepos=new_header_length; + sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length; + + sort_param[i].record=((char *)(sort_param+share->base.keys))+ + (share->base.pack_reclength * i); + + sort_param[i].key_length=share->rec_reflength; + for (keyseg=sort_param[i].keyinfo->seg; keyseg->type != HA_KEYTYPE_END; + keyseg++) + { + sort_param[i].key_length+=keyseg->length; + if (keyseg->flag & HA_SPACE_PACK) + sort_param[i].key_length+=get_pack_length(keyseg->length); + if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH)) + sort_param[i].key_length+=2 + test(keyseg->length >= 127); + if (keyseg->flag & HA_NULL_PART) + sort_param[i].key_length++; + } + + length+=sort_param[i].key_length; + + if (sort_param[i].keyinfo->flag & HA_FULLTEXT) + sort_param[i].key_length+=ft_max_word_len_for_sort-ft_max_word_len; + } + sort_info.total_keys=i; + sort_param[0].fix_datafile= ! rep_quick; + + sort_info.got_error=0; + pthread_mutex_init(& sort_info.mutex, MY_MUTEX_INIT_FAST); + pthread_cond_init(& sort_info.cond, 0); + pthread_mutex_lock(& sort_info.mutex); + + init_io_cache_share(& param->read_cache, &io_share, i); + for (i=0 ; i<sort_info.total_keys ; i++) + { + sort_param[i].read_cache=param->read_cache; + sort_param[i].sortbuff_size= + /* + two approaches: the same amount of memory for each thread + or the memory for the same number of keys for each thread... + In the second one all the threads will fill their sort_buffers + (and call write_keys) at the same time, putting more stress on i/o. + */ +#if 1 + param->sort_buffer_length/sort_info.total_keys; +#else + param->sort_buffer_length*sort_param[i].key_length/length; +#endif + if (pthread_create(& sort_param[i].thr, 0, + (void *(*)(void*))_thr_find_all_keys, sort_param+i)) + { + mi_check_print_error(param,"Cannot start a repair thread"); + remove_io_thread(& param->read_cache); + sort_info.got_error=1; + } + else + sort_info.threads_running++; + } + + /* waiting for all threads to finish */ + while (sort_info.threads_running) + pthread_cond_wait(& sort_info.cond, &sort_info.mutex); + pthread_mutex_unlock(& sort_info.mutex); + + if (got_error=_thr_write_keys(sort_param)) + { + param->retry_repair=1; + goto err; + } + got_error=1; + + if (sort_param[0].fix_datafile) + { + if (write_data_suffix(&sort_info,1) || end_io_cache(&info->rec_cache)) + goto err; + if (param->testflag & T_SAFE_REPAIR) + { + /* Don't repair if we loosed more than one row */ + if (info->state->records+1 < start_records) + { + info->state->records=start_records; + goto err; + } + } + share->state.state.data_file_length = info->state->data_file_length + = sort_param->filepos; + /* Only whole records */ + share->state.version=(ulong) time((time_t*) 0); + my_close(info->dfile,MYF(0)); + info->dfile=new_file; + share->data_file_type=sort_info.new_data_file_type; + share->pack.header_length=(ulong) new_header_length; + } + else + info->state->data_file_length=sort_param->max_pos; + + if (rep_quick && del+sort_info.dupp != info->state->del) + { + mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); + mi_check_print_error(param,"Run recovery again without -q"); + param->retry_repair=1; + param->testflag|=T_RETRY_WITHOUT_QUICK; + goto err; + } + + if (rep_quick & T_FORCE_UNIQUENESS) + { + my_off_t skr=info->state->data_file_length+ + (share->options & HA_OPTION_COMPRESS_RECORD ? + MEMMAP_EXTRA_MARGIN : 0); +#ifdef USE_RELOC + if (share->data_file_type == STATIC_RECORD && + skr < share->base.reloc*share->base.min_pack_length) + skr=share->base.reloc*share->base.min_pack_length; +#endif + if (skr != sort_info.filelength && !info->s->base.raid_type) + if (my_chsize(info->dfile,skr,MYF(0))) + mi_check_print_warning(param, + "Can't change size of datafile, error: %d", + my_errno); + } + if (param->testflag & T_CALC_CHECKSUM) + share->state.checksum=param->glob_crc; + + if (my_chsize(share->kfile,info->state->key_file_length,MYF(0))) + mi_check_print_warning(param, + "Can't change size of indexfile, error: %d", my_errno); + + if (!(param->testflag & T_SILENT)) + { + if (start_records != info->state->records) + printf("Data records: %s\n", llstr(info->state->records,llbuff)); + if (sort_info.dupp) + mi_check_print_warning(param, + "%s records have been removed", + llstr(sort_info.dupp,llbuff)); + } + got_error=0; + + if (&share->state.state != info->state) + memcpy( &share->state.state, info->state, sizeof(*info->state)); + +err: + got_error|= flush_blocks(param,share->kfile); + VOID(end_io_cache(&info->rec_cache)); + if (!got_error) + { + /* Replace the actual file with the temporary file */ + if (new_file >= 0) + { + my_close(new_file,MYF(0)); + info->dfile=new_file= -1; + if (change_to_newfile(share->data_file_name,MI_NAME_DEXT, + DATA_TMP_EXT, share->base.raid_chunks, + (param->testflag & T_BACKUP_DATA ? + MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || + mi_open_datafile(info,share,-1)) + got_error=1; + } + } + if (got_error) + { + if (! param->error_printed) + mi_check_print_error(param,"%d when fixing table",my_errno); + if (new_file >= 0) + { + VOID(my_close(new_file,MYF(0))); + VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks, + MYF(MY_WME))); + if (info->dfile == new_file) + info->dfile= -1; + } + mi_mark_crashed_on_repair(info); + } + else if (key_map == share->state.key_map) + share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; + share->state.changed|=STATE_NOT_SORTED_PAGES; + + pthread_cond_destroy (& sort_info.cond); + pthread_mutex_destroy(& sort_info.mutex); + + my_free((gptr) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); + my_free((gptr) sort_param,MYF(MY_ALLOW_ZERO_PTR)); + my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); + VOID(end_io_cache(¶m->read_cache)); + info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); + if (!got_error && (param->testflag & T_UNPACK)) + { + share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; + share->pack.header_length=0; + } + DBUG_RETURN(got_error); +} /* Read next record and return next key */ -static int sort_key_read(SORT_INFO *sort_info, void *key) +static int sort_key_read(MI_SORT_PARAM *sort_param, void *key) { int error; - MI_INFO *info; + SORT_INFO *sort_info=sort_param->sort_info; + MI_INFO *info=sort_info->info; DBUG_ENTER("sort_key_read"); - info=sort_info->info; - - if ((error=sort_get_next_record(sort_info))) + if ((error=sort_get_next_record(sort_param))) DBUG_RETURN(error); if (info->state->records == sort_info->max_records) { @@ -2101,52 +2454,51 @@ static int sort_key_read(SORT_INFO *sort_info, void *key) "Found too many records; Can`t continue"); DBUG_RETURN(1); } - sort_info->real_key_length=(info->s->rec_reflength+ - _mi_make_key(info, sort_info->key, - (uchar*) key, sort_info->record, - sort_info->filepos)); - DBUG_RETURN(sort_write_record(sort_info)); + sort_param->real_key_length=(info->s->rec_reflength+ + _mi_make_key(info, sort_param->key, (uchar*) key, + sort_param->record, sort_param->filepos)); + DBUG_RETURN(sort_write_record(sort_param)); } /* sort_key_read */ -static int sort_ft_key_read(SORT_INFO *sort_info, void *key) +static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) { int error; - MI_INFO *info; + SORT_INFO *sort_info=sort_param->sort_info; + MI_INFO *info=sort_info->info; FT_WORD *wptr=0; DBUG_ENTER("sort_ft_key_read"); - info=sort_info->info; - - if (!sort_info->wordlist) + if (!sort_param->wordlist) { do { my_free((char*) wptr, MYF(MY_ALLOW_ZERO_PTR)); - if ((error=sort_get_next_record(sort_info))) + if ((error=sort_get_next_record(sort_param))) DBUG_RETURN(error); - if (!(wptr=_mi_ft_parserecord(info,sort_info->key,key,sort_info->record))) + if (!(wptr=_mi_ft_parserecord(info,sort_param->key, + key,sort_param->record))) DBUG_RETURN(1); - error=sort_write_record(sort_info); + error=sort_write_record(sort_param); } while (!wptr->pos); - sort_info->wordptr=sort_info->wordlist=wptr; + sort_param->wordptr=sort_param->wordlist=wptr; } else { error=0; - wptr=(FT_WORD*)(sort_info->wordptr); + wptr=(FT_WORD*)(sort_param->wordptr); } - sort_info->real_key_length=info->s->rec_reflength+_ft_make_key(info, - sort_info->key,key,wptr++,sort_info->filepos); + sort_param->real_key_length=info->s->rec_reflength+_ft_make_key(info, + sort_param->key,key,wptr++,sort_param->filepos); if (!wptr->pos) { - my_free((char*) sort_info->wordlist, MYF(0)); - sort_info->wordlist=0; + my_free((char*) sort_param->wordlist, MYF(0)); + sort_param->wordlist=0; } else - sort_info->wordptr=(void*)wptr; + sort_param->wordptr=(void*)wptr; DBUG_RETURN(error); @@ -2155,7 +2507,7 @@ static int sort_ft_key_read(SORT_INFO *sort_info, void *key) /* Read next record from file using parameters in sort_info */ /* Return -1 if end of file, 0 if ok and > 0 if error */ -static int sort_get_next_record(SORT_INFO *sort_info) +static int sort_get_next_record(MI_SORT_PARAM *sort_param) { int searching; uint found_record,b_type,left_length; @@ -2164,6 +2516,7 @@ static int sort_get_next_record(SORT_INFO *sort_info) MI_BLOCK_INFO block_info; MI_INFO *info; MYISAM_SHARE *share; + SORT_INFO *sort_info=sort_param->sort_info; MI_CHECK *param=sort_info->param; char llbuff[22],llbuff2[22]; DBUG_ENTER("sort_get_next_record"); @@ -2174,30 +2527,30 @@ static int sort_get_next_record(SORT_INFO *sort_info) case STATIC_RECORD: for (;;) { - if (my_b_read(¶m->read_cache,sort_info->record, + if (my_b_read(&sort_param->read_cache,sort_param->record, share->base.pack_reclength)) { - if (param->read_cache.error) + if (sort_param->read_cache.error) param->out_flag |= O_DATA_LOST; param->retry_repair=1; param->testflag|=T_RETRY_WITHOUT_QUICK; DBUG_RETURN(-1); } - sort_info->start_recpos=sort_info->pos; - if (!sort_info->fix_datafile) + sort_param->start_recpos=sort_param->pos; + if (!sort_param->fix_datafile) { - sort_info->filepos=sort_info->pos; + sort_param->filepos=sort_param->pos; share->state.split++; } - sort_info->max_pos=(sort_info->pos+=share->base.pack_reclength); - if (*sort_info->record) + sort_param->max_pos=(sort_param->pos+=share->base.pack_reclength); + if (*sort_param->record) { if (param->calc_checksum) param->glob_crc+= (info->checksum= - mi_static_checksum(info,sort_info->record)); + mi_static_checksum(info,sort_param->record)); DBUG_RETURN(0); } - if (!sort_info->fix_datafile) + if (!sort_param->fix_datafile) { info->state->del++; info->state->empty+=share->base.pack_reclength; @@ -2205,8 +2558,8 @@ static int sort_get_next_record(SORT_INFO *sort_info) } case DYNAMIC_RECORD: LINT_INIT(to); - pos=sort_info->pos; - searching=(sort_info->fix_datafile && (param->testflag & T_EXTEND)); + pos=sort_param->pos; + searching=(sort_param->fix_datafile && (param->testflag & T_EXTEND)); for (;;) { found_record=block_info.second_read= 0; @@ -2215,12 +2568,12 @@ static int sort_get_next_record(SORT_INFO *sort_info) { pos=MY_ALIGN(pos,MI_DYN_ALIGN_SIZE); param->testflag|=T_RETRY_WITHOUT_QUICK; - sort_info->start_recpos=pos; + sort_param->start_recpos=pos; } do { - if (pos > sort_info->max_pos) - sort_info->max_pos=pos; + if (pos > sort_param->max_pos) + sort_param->max_pos=pos; if (pos & (MI_DYN_ALIGN_SIZE-1)) { if ((param->testflag & T_VERBOSE) || searching == 0) @@ -2232,8 +2585,9 @@ static int sort_get_next_record(SORT_INFO *sort_info) if (found_record && pos == param->search_after_block) mi_check_print_info(param,"Block: %s used by record at %s", llstr(param->search_after_block,llbuff), - llstr(sort_info->start_recpos,llbuff2)); - if (_mi_read_cache(¶m->read_cache,(byte*) block_info.header,pos, + llstr(sort_param->start_recpos,llbuff2)); + if (_mi_read_cache(&sort_param->read_cache, + (byte*) block_info.header,pos, MI_BLOCK_INFO_HEADER_LENGTH, (! found_record ? READING_NEXT : 0) | READING_HEADER)) @@ -2242,12 +2596,12 @@ static int sort_get_next_record(SORT_INFO *sort_info) { mi_check_print_info(param, "Can't read whole record at %s (errno: %d)", - llstr(sort_info->start_recpos,llbuff),errno); + llstr(sort_param->start_recpos,llbuff),errno); goto try_next; } DBUG_RETURN(-1); } - if (searching && ! sort_info->fix_datafile) + if (searching && ! sort_param->fix_datafile) { param->error_printed=1; param->retry_repair=1; @@ -2278,7 +2632,7 @@ static int sort_get_next_record(SORT_INFO *sort_info) block_info.header[i] <= MI_MAX_DYN_HEADER_BYTE) break; pos+=(ulong) i; - sort_info->start_recpos=pos; + sort_param->start_recpos=pos; continue; } if (b_type & BLOCK_DELETED) @@ -2314,7 +2668,7 @@ static int sort_get_next_record(SORT_INFO *sort_info) goto try_next; searching=1; pos+= MI_DYN_ALIGN_SIZE; - sort_info->start_recpos=pos; + sort_param->start_recpos=pos; block_info.second_read=0; continue; } @@ -2335,14 +2689,14 @@ static int sort_get_next_record(SORT_INFO *sort_info) goto try_next; searching=1; pos+= MI_DYN_ALIGN_SIZE; - sort_info->start_recpos=pos; + sort_param->start_recpos=pos; block_info.second_read=0; continue; } } if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR)) { - if (!sort_info->fix_datafile && (b_type & BLOCK_DELETED)) + if (!sort_param->fix_datafile && (b_type & BLOCK_DELETED)) { info->state->empty+=block_info.block_len; info->state->del++; @@ -2353,7 +2707,7 @@ static int sort_get_next_record(SORT_INFO *sort_info) if (searching) { pos+=MI_DYN_ALIGN_SIZE; - sort_info->start_recpos=pos; + sort_param->start_recpos=pos; } else pos=block_info.filepos+block_info.block_len; @@ -2361,24 +2715,24 @@ static int sort_get_next_record(SORT_INFO *sort_info) continue; } - if (!sort_info->fix_datafile) + if (!sort_param->fix_datafile) share->state.split++; if (! found_record++) { - sort_info->find_length=left_length=block_info.rec_len; - sort_info->start_recpos=pos; - if (!sort_info->fix_datafile) - sort_info->filepos=sort_info->start_recpos; - if (sort_info->fix_datafile && (param->testflag & T_EXTEND)) - sort_info->pos=block_info.filepos+1; + sort_param->find_length=left_length=block_info.rec_len; + sort_param->start_recpos=pos; + if (!sort_param->fix_datafile) + sort_param->filepos=sort_param->start_recpos; + if (sort_param->fix_datafile && (param->testflag & T_EXTEND)) + sort_param->pos=block_info.filepos+1; else - sort_info->pos=block_info.filepos+block_info.block_len; + sort_param->pos=block_info.filepos+block_info.block_len; if (share->base.blobs) { if (!(to=mi_fix_rec_buff_for_blob(info,block_info.rec_len))) { mi_check_print_error(param,"Not enough memory for blob at %s", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); DBUG_RETURN(1); } } @@ -2388,17 +2742,17 @@ static int sort_get_next_record(SORT_INFO *sort_info) if (left_length < block_info.data_len || ! block_info.data_len) { mi_check_print_info(param,"Found block with too small length at %s; Skipped", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); goto try_next; } if (block_info.filepos + block_info.data_len > - param->read_cache.end_of_file) + sort_param->read_cache.end_of_file) { mi_check_print_info(param,"Found block that points outside data file at %s", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); goto try_next; } - if (_mi_read_cache(¶m->read_cache,to,block_info.filepos, + if (_mi_read_cache(&sort_param->read_cache,to,block_info.filepos, block_info.data_len, (found_record == 1 ? READING_NEXT : 0))) { @@ -2413,31 +2767,31 @@ static int sort_get_next_record(SORT_INFO *sort_info) if (pos == HA_OFFSET_ERROR && left_length) { mi_check_print_info(param,"Wrong block with wrong total length starting at %s", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); goto try_next; } - if (pos + MI_BLOCK_INFO_HEADER_LENGTH > param->read_cache.end_of_file) + if (pos + MI_BLOCK_INFO_HEADER_LENGTH > sort_param->read_cache.end_of_file) { mi_check_print_info(param,"Found link that points at %s (outside data file) at %s", llstr(pos,llbuff2), - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); goto try_next; } } while (left_length); - if (_mi_rec_unpack(info,sort_info->record,info->rec_buff, - sort_info->find_length) != MY_FILE_ERROR) + if (_mi_rec_unpack(info,sort_param->record,info->rec_buff, + sort_param->find_length) != MY_FILE_ERROR) { - if (param->read_cache.error < 0) + if (sort_param->read_cache.error < 0) DBUG_RETURN(1); if (info->s->calc_checksum) - info->checksum=mi_checksum(info,sort_info->record); + info->checksum=mi_checksum(info,sort_param->record); if ((param->testflag & (T_EXTEND | T_REP)) || searching) { - if (_mi_rec_check(info, sort_info->record)) + if (_mi_rec_check(info, sort_param->record)) { mi_check_print_info(param,"Found wrong packed record at %s", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); goto try_next; } } @@ -2447,31 +2801,31 @@ static int sort_get_next_record(SORT_INFO *sort_info) } if (!searching) mi_check_print_info(param,"Found wrong stored record at %s", - llstr(sort_info->start_recpos,llbuff)); + llstr(sort_param->start_recpos,llbuff)); try_next: - pos=(sort_info->start_recpos+=MI_DYN_ALIGN_SIZE); + pos=(sort_param->start_recpos+=MI_DYN_ALIGN_SIZE); searching=1; } case COMPRESSED_RECORD: - for (searching=0 ;; searching=1, sort_info->pos++) + for (searching=0 ;; searching=1, sort_param->pos++) { - if (_mi_read_cache(¶m->read_cache,(byte*) block_info.header, - sort_info->pos, + if (_mi_read_cache(&sort_param->read_cache,(byte*) block_info.header, + sort_param->pos, share->pack.ref_length,READING_NEXT)) DBUG_RETURN(-1); - if (searching && ! sort_info->fix_datafile) + if (searching && ! sort_param->fix_datafile) { param->error_printed=1; param->retry_repair=1; param->testflag|=T_RETRY_WITHOUT_QUICK; DBUG_RETURN(1); /* Something wrong with data */ } - sort_info->start_recpos=sort_info->pos; - if (_mi_pack_get_block_info(info,&block_info,-1,sort_info->pos, NullS)) + sort_param->start_recpos=sort_param->pos; + if (_mi_pack_get_block_info(info,&block_info,-1,sort_param->pos, NullS)) DBUG_RETURN(-1); if (!block_info.rec_len && - sort_info->pos + MEMMAP_EXTRA_MARGIN == - param->read_cache.end_of_file) + sort_param->pos + MEMMAP_EXTRA_MARGIN == + sort_param->read_cache.end_of_file) DBUG_RETURN(-1); if (block_info.rec_len < (uint) share->min_pack_length || block_info.rec_len > (uint) share->max_pack_length) @@ -2479,33 +2833,33 @@ static int sort_get_next_record(SORT_INFO *sort_info) if (! searching) mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n", block_info.rec_len, - llstr(sort_info->pos,llbuff)); + llstr(sort_param->pos,llbuff)); continue; } - if (_mi_read_cache(¶m->read_cache,(byte*) info->rec_buff, + if (_mi_read_cache(&sort_param->read_cache,(byte*) info->rec_buff, block_info.filepos, block_info.rec_len, READING_NEXT)) { if (! searching) mi_check_print_info(param,"Couldn't read whole record from %s", - llstr(sort_info->pos,llbuff)); + llstr(sort_param->pos,llbuff)); continue; } - if (_mi_pack_rec_unpack(info,sort_info->record,info->rec_buff, + if (_mi_pack_rec_unpack(info,sort_param->record,info->rec_buff, block_info.rec_len)) { if (! searching) mi_check_print_info(param,"Found wrong record at %s", - llstr(sort_info->pos,llbuff)); + llstr(sort_param->pos,llbuff)); continue; } - info->checksum=mi_checksum(info,sort_info->record); - if (!sort_info->fix_datafile) + info->checksum=mi_checksum(info,sort_param->record); + if (!sort_param->fix_datafile) { - sort_info->filepos=sort_info->pos; + sort_param->filepos=sort_param->pos; share->state.split++; } - sort_info->max_pos=(sort_info->pos=block_info.filepos+ + sort_param->max_pos=(sort_param->pos=block_info.filepos+ block_info.rec_len); info->packed_length=block_info.rec_len; if (param->calc_checksum) @@ -2519,7 +2873,7 @@ static int sort_get_next_record(SORT_INFO *sort_info) /* Write record to new file */ -int sort_write_record(SORT_INFO *sort_info) +int sort_write_record(MI_SORT_PARAM *sort_param) { int flag; uint length; @@ -2527,25 +2881,26 @@ int sort_write_record(SORT_INFO *sort_info) byte *from; byte block_buff[8]; MI_INFO *info; + SORT_INFO *sort_info=sort_param->sort_info; MYISAM_SHARE *share; MI_CHECK *param=sort_info->param; DBUG_ENTER("sort_write_record"); info=sort_info->info; share=info->s; - if (sort_info->fix_datafile) + if (sort_param->fix_datafile) { switch (sort_info->new_data_file_type) { case STATIC_RECORD: - if (my_b_write(&info->rec_cache,sort_info->record, + if (my_b_write(&info->rec_cache,sort_param->record, share->base.pack_reclength)) { mi_check_print_error(param,"%d when writing to datafile",my_errno); DBUG_RETURN(1); } - sort_info->filepos+=share->base.pack_reclength; + sort_param->filepos+=share->base.pack_reclength; info->s->state.split++; - /* sort_info->param->glob_crc+=mi_static_checksum(info, sort_info->record); */ + /* sort_info->param->glob_crc+=mi_static_checksum(info, sort_param->record); */ break; case DYNAMIC_RECORD: if (! info->blobs) @@ -2554,7 +2909,7 @@ int sort_write_record(SORT_INFO *sort_info) { /* must be sure that local buffer is big enough */ reclength=info->s->base.pack_reclength+ - _my_calc_total_blob_length(info,sort_info->record)+ + _my_calc_total_blob_length(info,sort_param->record)+ ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_DYN_DELETE_BLOCK_HEADER; if (sort_info->buff_length < reclength) @@ -2567,8 +2922,8 @@ int sort_write_record(SORT_INFO *sort_info) } from=sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER); } - info->checksum=mi_checksum(info,sort_info->record); - reclength=_mi_rec_pack(info,from,sort_info->record); + info->checksum=mi_checksum(info,sort_param->record); + reclength=_mi_rec_pack(info,from,sort_param->record); flag=0; /* sort_info->param->glob_crc+=info->checksum; */ @@ -2582,13 +2937,13 @@ int sort_write_record(SORT_INFO *sort_info) if (block_length > MI_MAX_BLOCK_LENGTH) block_length=MI_MAX_BLOCK_LENGTH; if (_mi_write_part_record(info,0L,block_length, - sort_info->filepos+block_length, + sort_param->filepos+block_length, &from,&reclength,&flag)) { mi_check_print_error(param,"%d when writing to datafile",my_errno); DBUG_RETURN(1); } - sort_info->filepos+=block_length; + sort_param->filepos+=block_length; info->s->state.split++; } while (reclength); /* sort_info->param->glob_crc+=info->checksum; */ @@ -2605,7 +2960,7 @@ int sort_write_record(SORT_INFO *sort_info) DBUG_RETURN(1); } /* sort_info->param->glob_crc+=info->checksum; */ - sort_info->filepos+=reclength+length; + sort_param->filepos+=reclength+length; info->s->state.split++; break; } @@ -2623,49 +2978,47 @@ int sort_write_record(SORT_INFO *sort_info) /* Compare two keys from _create_index_by_sort */ -static int sort_key_cmp(SORT_INFO *sort_info, const void *a, const void *b) +static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b) { uint not_used; - return (_mi_key_cmp(sort_info->keyseg,*((uchar**) a),*((uchar**) b), + return (_mi_key_cmp(sort_param->keyinfo->seg,*((uchar**) a),*((uchar**) b), USE_WHOLE_KEY, SEARCH_SAME,¬_used)); } /* sort_key_cmp */ -static int sort_key_write(SORT_INFO *sort_info, const void *a) +static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) { uint diff_pos; char llbuff[22],llbuff2[22]; + SORT_INFO *sort_info=sort_param->sort_info; MI_CHECK *param= sort_info->param; int cmp; if (sort_info->key_block->inited) { - cmp=_mi_key_cmp(sort_info->keyseg,sort_info->key_block->lastkey,(uchar*) a, - USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE ,&diff_pos); - sort_info->unique[diff_pos-1]++; + cmp=_mi_key_cmp(sort_param->keyinfo->seg,sort_info->key_block->lastkey, + (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE ,&diff_pos); + sort_param->unique[diff_pos-1]++; } else { cmp= -1; } - if ((sort_info->keyinfo->flag & HA_NOSAME) && cmp == 0) + if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0) { sort_info->dupp++; sort_info->info->lastpos=get_record_for_key(sort_info->info, - sort_info->keyinfo, + sort_param->keyinfo, (uchar*) a); mi_check_print_warning(param, - "Duplicate key for record at %10s against record at %10s", - llstr(sort_info->info->lastpos,llbuff), - llstr(get_record_for_key(sort_info->info, - sort_info->keyinfo, - sort_info->key_block-> - lastkey), - llbuff2)); + "Duplicate key for record at %10s against record at %10s", + llstr(sort_info->info->lastpos,llbuff), + llstr(get_record_for_key(sort_info->info, sort_param->keyinfo, + sort_info->key_block->lastkey), llbuff2)); param->testflag|=T_RETRY_WITHOUT_QUICK; if (sort_info->param->testflag & T_VERBOSE) - _mi_print_key(stdout,sort_info->keyseg,(uchar*) a, USE_WHOLE_KEY); - return (sort_delete_record(param)); + _mi_print_key(stdout,sort_param->keyinfo->seg,(uchar*) a, USE_WHOLE_KEY); + return (sort_delete_record(sort_param)); } #ifndef DBUG_OFF if (cmp > 0) @@ -2675,8 +3028,8 @@ static int sort_key_write(SORT_INFO *sort_info, const void *a) return(1); } #endif - return (sort_insert_key(param,sort_info->key_block,(uchar*) a, - HA_OFFSET_ERROR)); + return (sort_insert_key(sort_param,sort_info->key_block, + (uchar*) a, HA_OFFSET_ERROR)); } /* sort_key_write */ @@ -2691,7 +3044,7 @@ static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo, /* Insert a key in sort-key-blocks */ -static int sort_insert_key(MI_CHECK *param, +static int sort_insert_key(MI_SORT_PARAM *sort_param, register SORT_KEY_BLOCKS *key_block, uchar *key, my_off_t prev_block) { @@ -2700,14 +3053,16 @@ static int sort_insert_key(MI_CHECK *param, uchar *anc_buff,*lastkey; MI_KEY_PARAM s_temp; MI_INFO *info; - SORT_INFO *sort_info= ¶m->sort_info; + MI_KEYDEF *keyinfo=sort_param->keyinfo; + SORT_INFO *sort_info= sort_param->sort_info; + MI_CHECK *param=sort_info->param; DBUG_ENTER("sort_insert_key"); anc_buff=key_block->buff; info=sort_info->info; lastkey=key_block->lastkey; nod_flag= (key_block == sort_info->key_block ? 0 : - sort_info->info->s->base.key_reflength); + info->s->base.key_reflength); if (!key_block->inited) { @@ -2728,17 +3083,16 @@ static int sort_insert_key(MI_CHECK *param, if (nod_flag) _mi_kpointer(info,key_block->end_pos,prev_block); - t_length=(*sort_info->keyinfo->pack_key)(sort_info->keyinfo,nod_flag, - (uchar*) 0,lastkey,lastkey,key, - &s_temp); - (*sort_info->keyinfo->store_key)(sort_info->keyinfo, - key_block->end_pos+nod_flag,&s_temp); + t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, + (uchar*) 0,lastkey,lastkey,key, + &s_temp); + (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp); a_length+=t_length; mi_putint(anc_buff,a_length,nod_flag); key_block->end_pos+=t_length; - if (a_length <= sort_info->keyinfo->block_length) + if (a_length <= keyinfo->block_length) { - VOID(_mi_move_key(sort_info->keyinfo,key_block->lastkey,key)); + VOID(_mi_move_key(keyinfo,key_block->lastkey,key)); key_block->last_length=a_length-t_length; DBUG_RETURN(0); } @@ -2746,43 +3100,42 @@ static int sort_insert_key(MI_CHECK *param, /* Fill block with end-zero and write filled block */ mi_putint(anc_buff,key_block->last_length,nod_flag); bzero((byte*) anc_buff+key_block->last_length, - sort_info->keyinfo->block_length- key_block->last_length); + keyinfo->block_length- key_block->last_length); key_file_length=info->state->key_file_length; - if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR) + if ((filepos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) DBUG_RETURN(1); /* If we read the page from the key cache, we have to write it back to it */ if (key_file_length == info->state->key_file_length) { - if (_mi_write_keypage(info, sort_info->keyinfo, filepos, - anc_buff)) + if (_mi_write_keypage(info, keyinfo, filepos, anc_buff)) DBUG_RETURN(1); } else if (my_pwrite(info->s->kfile,(byte*) anc_buff, - (uint) sort_info->keyinfo->block_length,filepos, - param->myf_rw)) + (uint) keyinfo->block_length,filepos, param->myf_rw)) DBUG_RETURN(1); DBUG_DUMP("buff",(byte*) anc_buff,mi_getint(anc_buff)); /* Write separator-key to block in next level */ - if (sort_insert_key(param,key_block+1,key_block->lastkey,filepos)) + if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos)) DBUG_RETURN(1); /* clear old block and write new key in it */ key_block->inited=0; - DBUG_RETURN(sort_insert_key(param, key_block,key,prev_block)); + DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block)); } /* sort_insert_key */ /* Delete record when we found a duplicated key */ -static int sort_delete_record(MI_CHECK *param) +static int sort_delete_record(MI_SORT_PARAM *sort_param) { uint i; int old_file,error; uchar *key; - MI_INFO *info; - SORT_INFO *sort_info= ¶m->sort_info; + SORT_INFO *sort_info=sort_param->sort_info; + MI_CHECK *param=sort_info->param; + MI_INFO *info=sort_info->info; DBUG_ENTER("sort_delete_record"); if (!(param->testflag & T_FORCE_UNIQUENESS)) @@ -2791,7 +3144,6 @@ static int sort_delete_record(MI_CHECK *param) "Quick-recover aborted; Run recovery without switch -q or with switch -qq"); DBUG_RETURN(1); } - info=sort_info->info; if (info->s->options & HA_OPTION_COMPRESS_RECORD) { mi_check_print_error(param, @@ -2801,10 +3153,10 @@ static int sort_delete_record(MI_CHECK *param) old_file=info->dfile; info->dfile=info->rec_cache.file; - if (sort_info->key) + if (sort_info->kei) { key=info->lastkey+info->s->base.max_key_length; - if ((error=(*info->s->read_rnd)(info,sort_info->record,info->lastpos,0)) && + if ((error=(*info->s->read_rnd)(info,sort_param->record,info->lastpos,0)) && error != HA_ERR_RECORD_DELETED) { mi_check_print_error(param,"Can't read record to be removed"); @@ -2812,9 +3164,9 @@ static int sort_delete_record(MI_CHECK *param) DBUG_RETURN(1); } - for (i=0 ; i < sort_info->key ; i++) + for (i=0 ; i < sort_info->kei ; i++) { - uint key_length=_mi_make_key(info,i,key,sort_info->record,info->lastpos); + uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos); if (_mi_ck_delete(info,i,key,key_length)) { mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1); @@ -2823,8 +3175,7 @@ static int sort_delete_record(MI_CHECK *param) } } if (param->calc_checksum) - param->glob_crc-=(*info->s->calc_checksum)(info, - sort_info->record); + param->glob_crc-=(*info->s->calc_checksum)(info, sort_param->record); } error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info); info->dfile=old_file; /* restore actual value */ @@ -2832,20 +3183,20 @@ static int sort_delete_record(MI_CHECK *param) DBUG_RETURN(error); } /* sort_delete_record */ - /* Fix all pending blocks and flush everything to disk */ -int flush_pending_blocks(MI_CHECK *param) +int flush_pending_blocks(MI_SORT_PARAM *sort_param) { uint nod_flag,length; my_off_t filepos,key_file_length; - MI_INFO *info; SORT_KEY_BLOCKS *key_block; - SORT_INFO *sort_info= ¶m->sort_info; + SORT_INFO *sort_info= sort_param->sort_info; + MI_CHECK *param=sort_info->param; + MI_INFO *info=sort_info->info; + MI_KEYDEF *keyinfo=sort_param->keyinfo; DBUG_ENTER("flush_pending_blocks"); filepos= HA_OFFSET_ERROR; /* if empty file */ - info=sort_info->info; nod_flag=0; for (key_block=sort_info->key_block ; key_block->inited ; key_block++) { @@ -2854,30 +3205,26 @@ int flush_pending_blocks(MI_CHECK *param) if (nod_flag) _mi_kpointer(info,key_block->end_pos,filepos); key_file_length=info->state->key_file_length; - bzero((byte*) key_block->buff+length, - sort_info->keyinfo->block_length-length); - if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR) + bzero((byte*) key_block->buff+length, keyinfo->block_length-length); + if ((filepos=_mi_new(info,keyinfo)) == HA_OFFSET_ERROR) DBUG_RETURN(1); /* If we read the page from the key cache, we have to write it back */ if (key_file_length == info->state->key_file_length) { - if (_mi_write_keypage(info, sort_info->keyinfo, filepos, - key_block->buff)) + if (_mi_write_keypage(info, keyinfo, filepos, key_block->buff)) DBUG_RETURN(1); } else if (my_pwrite(info->s->kfile,(byte*) key_block->buff, - (uint) sort_info->keyinfo->block_length,filepos, - param->myf_rw)) + (uint) keyinfo->block_length,filepos, param->myf_rw)) DBUG_RETURN(1); DBUG_DUMP("buff",(byte*) key_block->buff,length); nod_flag=1; } - info->s->state.key_root[sort_info->key]=filepos; /* Last is root for tree */ + info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */ DBUG_RETURN(0); } /* flush_pending_blocks */ - /* alloc space and pointers for key_blocks */ static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks, @@ -3087,24 +3434,25 @@ end: /* write suffix to data file if neaded */ -int write_data_suffix(MI_CHECK *param, MI_INFO *info) +int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile) { - if (info->s->options & HA_OPTION_COMPRESS_RECORD && - param->sort_info.fix_datafile) + MI_INFO *info=sort_info->info; + + if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile) { char buff[MEMMAP_EXTRA_MARGIN]; bzero(buff,sizeof(buff)); if (my_b_write(&info->rec_cache,buff,sizeof(buff))) { - mi_check_print_error(param,"%d when writing to datafile",my_errno); + mi_check_print_error(sort_info->param, + "%d when writing to datafile",my_errno); return 1; } - param->read_cache.end_of_file+=sizeof(buff); + sort_info->param->read_cache.end_of_file+=sizeof(buff); } return 0; } - /* Update state and myisamchk_time of indexfile */ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) @@ -3210,10 +3558,8 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, /* calculate unique keys for each part key */ -static void update_key_parts(MI_KEYDEF *keyinfo, - ulong *rec_per_key_part, - ulonglong *unique, - ulonglong records) +void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, + ulonglong *unique, ulonglong records) { ulonglong count=0,tmp; uint parts; @@ -3288,7 +3634,7 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows) even if the temporary file would be quite big! */ -my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, +my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, my_bool force) { @@ -3297,7 +3643,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, uint i; /* - repair_by_sort only works if we have at least one key. If we don't + mi_repair_by_sort only works if we have at least one key. If we don't have any keys, we should use the normal repair. */ if (!key_map) @@ -3312,10 +3658,10 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, static void -set_data_file_type(MI_CHECK *param, SORT_INFO *sort_info, MYISAM_SHARE *share) +set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share) { if ((sort_info->new_data_file_type=share->data_file_type) == - COMPRESSED_RECORD && param->testflag & T_UNPACK) + COMPRESSED_RECORD && sort_info->param->testflag & T_UNPACK) { MYISAM_SHARE tmp; |