~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mi_check.cc

  • Committer: Brian Aker
  • Date: 2009-10-01 22:56:26 UTC
  • mto: (1154.1.1 staging)
  • mto: This revision was merged to the branch mainline in revision 1155.
  • Revision ID: brian@gaz-20091001225626-sb1pdykpxlnkheaj
Remove Factory/make scheduler work like everything else.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
*/
42
42
 
43
43
#include "myisamdef.h"
 
44
#include <mystrings/m_string.h>
44
45
#include <stdarg.h>
45
46
#include <mysys/my_getopt.h>
46
47
#ifdef HAVE_SYS_VADVISE_H
47
48
#include <sys/vadvise.h>
48
49
#endif
 
50
#ifdef HAVE_SYS_TYPES
 
51
#include <sys/types.h>
 
52
#endif
49
53
#ifdef HAVE_SYS_MMAN_H
50
54
#include <sys/mman.h>
51
55
#endif
52
 
 
53
 
#ifndef USE_RAID
54
 
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
55
 
#define my_raid_delete(A,B,C) my_delete(A,B)
56
 
#endif
57
 
 
58
 
        /* Functions defined in this file */
59
 
 
60
 
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
 
56
#include <drizzled/util/test.h>
 
57
 
 
58
#include <algorithm>
 
59
 
 
60
using namespace std;
 
61
 
 
62
 
 
63
/* Functions defined in this file */
 
64
 
 
65
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
61
66
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
62
 
                     my_off_t page, uchar *buff, ha_rows *keys,
63
 
                     ha_checksum *key_checksum, uint level);
64
 
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
 
67
                     my_off_t page, unsigned char *buff, ha_rows *keys,
 
68
                     ha_checksum *key_checksum, uint32_t level);
 
69
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
70
static ha_checksum calc_checksum(ha_rows count);
66
71
static int writekeys(MI_SORT_PARAM *sort_param);
67
72
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
68
73
                          my_off_t pagepos, File new_file);
69
 
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
70
 
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
71
 
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
 
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
 
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
74
 
                                uchar *key);
75
 
static int sort_insert_key(MI_SORT_PARAM  *sort_param,
76
 
                           register SORT_KEY_BLOCKS *key_block,
77
 
                           uchar *key, my_off_t prev_block);
78
 
static int sort_delete_record(MI_SORT_PARAM *sort_param);
 
74
extern "C"
 
75
{
 
76
  int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
 
77
  int sort_get_next_record(MI_SORT_PARAM *sort_param);
 
78
  int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
 
79
  int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
 
80
  my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
 
81
                              unsigned char *key);
 
82
  int sort_insert_key(MI_SORT_PARAM  *sort_param,
 
83
                      register SORT_KEY_BLOCKS *key_block,
 
84
                      unsigned char *key, my_off_t prev_block);
 
85
  int sort_delete_record(MI_SORT_PARAM *sort_param);
 
86
}
79
87
/*static int flush_pending_blocks(MI_CHECK *param);*/
80
 
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint blocks,
81
 
                                          uint buffer_length);
82
 
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
 
88
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
 
89
                                          uint32_t buffer_length);
 
90
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
83
91
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
84
92
 
85
93
void myisamchk_init(MI_CHECK *param)
117
125
  if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
118
126
  {
119
127
    /* Don't count this as a real warning, as check can correct this ! */
120
 
    uint save=param->warning_printed;
 
128
    uint32_t save=param->warning_printed;
121
129
    mi_check_print_warning(param,
122
 
                           share->state.open_count==1 ? 
123
 
                           "%d client is using or hasn't closed the table properly" : 
 
130
                           share->state.open_count==1 ?
 
131
                           "%d client is using or hasn't closed the table properly" :
124
132
                           "%d clients are using or haven't closed the table properly",
125
133
                           share->state.open_count);
126
134
    /* If this will be fixed by the check, forget the warning */
132
140
 
133
141
        /* Check delete links */
134
142
 
135
 
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
 
143
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
136
144
{
137
145
  register ha_rows i;
138
 
  uint delete_link_length;
 
146
  uint32_t delete_link_length;
139
147
  my_off_t empty, next_link, old_link= 0;
140
148
  char buff[22],buff2[22];
141
149
 
167
175
        printf(" %9s",llstr(next_link,buff));
168
176
      if (next_link >= info->state->data_file_length)
169
177
        goto wrong;
170
 
      if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
 
178
      if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
171
179
                   next_link,MYF(MY_NABP)))
172
180
      {
173
181
        if (test_flag & T_VERBOSE) puts("");
198
206
      else
199
207
      {
200
208
        param->record_checksum+=(ha_checksum) next_link;
201
 
        next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
 
209
        next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
202
210
        empty+=info->s->base.pack_reclength;
203
211
      }
204
212
    }
239
247
 
240
248
        /* Check delete links in index file */
241
249
 
242
 
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
 
250
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
243
251
{
244
252
  my_off_t next_link;
245
 
  uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
 
253
  uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
246
254
  ha_rows records;
247
255
  char llbuff[21], llbuff2[21];
248
 
  uchar *buff;
 
256
  unsigned char *buff;
249
257
 
250
258
  if (param->testflag & T_VERBOSE)
251
 
    printf("block_size %4u:", block_size); /* purecov: tested */
 
259
    printf("block_size %4u:", block_size);
252
260
 
253
261
  next_link=info->s->state.key_del[nr];
254
262
  records= (ha_rows) (info->state->key_file_length / block_size);
262
270
    /* Key blocks must lay within the key file length entirely. */
263
271
    if (next_link + block_size > info->state->key_file_length)
264
272
    {
265
 
      /* purecov: begin tested */
266
273
      mi_check_print_error(param, "Invalid key block position: %s  "
267
274
                           "key block size: %u  file_length: %s",
268
275
                           llstr(next_link, llbuff), block_size,
269
276
                           llstr(info->state->key_file_length, llbuff2));
270
277
      return(1);
271
 
      /* purecov: end */
272
278
    }
273
279
 
274
280
    /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
275
281
    if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
276
282
    {
277
 
      /* purecov: begin tested */
278
283
      mi_check_print_error(param, "Mis-aligned key block: %s  "
279
284
                           "minimum key block length: %u",
280
285
                           llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
281
286
      return(1);
282
 
      /* purecov: end */
283
287
    }
284
288
 
285
289
    /*
289
293
    */
290
294
    if (!(buff=key_cache_read(info->s->key_cache,
291
295
                              info->s->kfile, next_link, DFLT_INIT_HITS,
292
 
                              (uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
 
296
                              (unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
297
                              MI_MIN_KEY_BLOCK_LENGTH, 1)))
294
298
    {
295
 
      /* purecov: begin tested */
296
299
      mi_check_print_error(param, "key cache read error for block: %s",
297
300
                           llstr(next_link,llbuff));
298
301
      return(1);
299
 
      /* purecov: end */
300
302
    }
301
303
    next_link=mi_sizekorr(buff);
302
304
    records--;
327
329
  flush_key_blocks(info->s->key_cache,
328
330
                   info->s->kfile, FLUSH_FORCE_WRITE);
329
331
 
330
 
  size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
 
332
  size= lseek(info->s->kfile, 0, SEEK_END);
331
333
  if ((skr=(my_off_t) info->state->key_file_length) != size)
332
334
  {
333
335
    /* Don't give error if file generated by myisampack */
351
353
                           llstr(info->state->key_file_length,buff),
352
354
                           llstr(info->s->base.max_key_file_length-1,buff));
353
355
 
354
 
  size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
 
356
  size=lseek(info->dfile,0L,SEEK_END);
355
357
  skr=(my_off_t) info->state->data_file_length;
356
358
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
357
359
    skr+= MEMMAP_EXTRA_MARGIN;
392
394
 
393
395
int chk_key(MI_CHECK *param, register MI_INFO *info)
394
396
{
395
 
  uint key,found_keys=0,full_text_keys=0,result=0;
 
397
  uint32_t key,found_keys=0,full_text_keys=0,result=0;
396
398
  ha_rows keys;
397
399
  ha_checksum old_record_checksum,init_checksum;
398
400
  my_off_t all_keydata,all_totaldata,key_totlength,length;
440
442
    found_keys++;
441
443
 
442
444
    param->record_checksum=init_checksum;
443
 
    
 
445
 
444
446
    memset(&param->unique_count, 0, sizeof(param->unique_count));
445
447
    memset(&param->notnull_count, 0, sizeof(param->notnull_count));
446
448
 
520
522
      /* Check that there isn't a row with auto_increment = 0 in the table */
521
523
      mi_extra(info,HA_EXTRA_KEYREAD,0);
522
524
      memset(info->lastkey, 0, keyinfo->seg->length);
523
 
      if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
 
525
      if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
524
526
                   (key_part_map)1, HA_READ_KEY_EXACT))
525
527
      {
526
528
        /* Don't count this as a real warning, as myisamchk can't correct it */
527
 
        uint save=param->warning_printed;
 
529
        uint32_t save=param->warning_printed;
528
530
        mi_check_print_warning(param, "Found row where the auto_increment "
529
531
                               "column has the value 0");
530
532
        param->warning_printed=save;
546
548
    if (param->testflag & T_STATISTICS)
547
549
      update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
548
550
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
549
 
                       param->notnull_count: NULL, 
 
551
                       param->notnull_count: NULL,
550
552
                       (uint64_t)info->state->records);
551
553
  }
552
554
  if (param->testflag & T_INFO)
573
575
 
574
576
 
575
577
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
576
 
                     my_off_t page, uchar *buff, ha_rows *keys,
577
 
                     ha_checksum *key_checksum, uint level)
 
578
                     my_off_t page, unsigned char *buff, ha_rows *keys,
 
579
                     ha_checksum *key_checksum, uint32_t level)
578
580
{
579
581
  char llbuff[22],llbuff2[22];
580
582
 
581
583
  /* Key blocks must lay within the key file length entirely. */
582
584
  if (page + keyinfo->block_length > info->state->key_file_length)
583
585
  {
584
 
    /* purecov: begin tested */
585
586
    /* Give it a chance to fit in the real file size. */
586
 
    my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
587
 
                                 MYF(MY_THREADSAFE));
 
587
    my_off_t max_length= lseek(info->s->kfile, 0, SEEK_END);
588
588
    mi_check_print_error(param, "Invalid key block position: %s  "
589
589
                         "key block size: %u  file_length: %s",
590
590
                         llstr(page, llbuff), keyinfo->block_length,
594
594
    /* Fix the remebered key file length. */
595
595
    info->state->key_file_length= (max_length &
596
596
                                   ~ (my_off_t) (keyinfo->block_length - 1));
597
 
    /* purecov: end */
598
597
  }
599
598
 
600
599
  /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
601
600
  if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
602
601
  {
603
 
    /* purecov: begin tested */
604
602
    mi_check_print_error(param, "Mis-aligned key block: %s  "
605
603
                         "minimum key block length: %u",
606
604
                         llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
607
605
    goto err;
608
 
    /* purecov: end */
609
606
  }
610
607
 
611
608
  if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
620
617
 
621
618
  return(0);
622
619
 
623
 
  /* purecov: begin tested */
624
620
err:
625
621
  return(1);
626
 
  /* purecov: end */
627
622
}
628
623
 
629
624
 
644
639
 
645
640
static
646
641
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
647
 
                                    uchar *key)
 
642
                                    unsigned char *key)
648
643
{
649
 
  uint first_null, kp;
 
644
  uint32_t first_null, kp;
650
645
  first_null= ha_find_null(keyseg, key) - keyseg;
651
646
  /*
652
647
    All prefix tuples that don't include keypart_{first_null} are not-null
673
668
    1. Find out which prefix tuples of last_key don't contain NULLs, and
674
669
       update the array of notnull counters accordingly.
675
670
    2. Find the first keypart number where the prev_key and last_key tuples
676
 
       are different(A), or last_key has NULL value(B), and return it, so the 
677
 
       caller can count number of unique tuples for each key prefix. We don't 
678
 
       need (B) to be counted, and that is compensated back in 
 
671
       are different(A), or last_key has NULL value(B), and return it, so the
 
672
       caller can count number of unique tuples for each key prefix. We don't
 
673
       need (B) to be counted, and that is compensated back in
679
674
       update_key_parts().
680
675
 
681
676
  RETURN
684
679
 
685
680
static
686
681
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
 
                                  uchar *prev_key, uchar *last_key)
 
682
                                  unsigned char *prev_key, unsigned char *last_key)
688
683
{
689
 
  uint diffs[2];
690
 
  uint first_null_seg, kp;
 
684
  uint32_t diffs[2];
 
685
  uint32_t first_null_seg, kp;
691
686
  HA_KEYSEG *seg;
692
687
 
693
 
  /* 
 
688
  /*
694
689
     Find the first keypart where values are different or either of them is
695
690
     NULL. We get results in diffs array:
696
691
     diffs[0]= 1 + number of first different keypart
698
693
                      last_key that is NULL or different from corresponding
699
694
                      value in prev_key.
700
695
  */
701
 
  ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY, 
 
696
  ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY,
702
697
             SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diffs);
703
698
  seg= keyseg + diffs[0] - 1;
704
699
 
707
702
  for (kp= 0; kp < first_null_seg; kp++)
708
703
    notnull[kp]++;
709
704
 
710
 
  /* 
 
705
  /*
711
706
    Return 1+ number of first key part where values differ. Don't care if
712
707
    these were NULLs and not .... We compensate for that in
713
708
    update_key_parts.
719
714
        /* Check if index is ok */
720
715
 
721
716
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
722
 
                     my_off_t page, uchar *buff, ha_rows *keys,
723
 
                     ha_checksum *key_checksum, uint level)
 
717
                     my_off_t page, unsigned char *buff, ha_rows *keys,
 
718
                     ha_checksum *key_checksum, uint32_t level)
724
719
{
725
720
  int flag;
726
 
  uint used_length,comp_flag,nod_flag,key_length=0;
727
 
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
 
721
  uint32_t used_length,comp_flag,nod_flag,key_length=0;
 
722
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
723
  my_off_t next_page,record;
729
724
  char llbuff[22];
730
 
  uint diff_pos[2];
 
725
  uint32_t diff_pos[2];
731
726
 
732
 
  if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
 
727
  if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
733
728
  {
734
729
    mi_check_print_error(param,"Not enough memory for keyblock");
735
730
    return(-1);
798
793
                     diff_pos);
799
794
        else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
800
795
        {
801
 
          diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg, 
 
796
          diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
802
797
                                                  param->notnull_count,
803
798
                                                  info->lastkey, key);
804
799
        }
805
800
        param->unique_count[diff_pos[0]-1]++;
806
801
      }
807
802
      else
808
 
      {  
 
803
      {
809
804
        if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
810
805
          mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
811
806
                                         key);
812
807
      }
813
808
    }
814
 
    (*key_checksum)+= mi_byte_checksum((uchar*) key,
 
809
    (*key_checksum)+= mi_byte_checksum((unsigned char*) key,
815
810
                                       key_length- info->s->rec_reflength);
816
811
    record= _mi_dpos(info,0,key+key_length);
817
812
    if (record >= info->state->data_file_length)
827
822
                llstr(page,llbuff), used_length, (keypos - buff));
828
823
    goto err;
829
824
  }
830
 
  my_afree((uchar*) temp_buff);
 
825
  free(temp_buff);
831
826
  return(0);
832
827
 err:
833
 
  my_afree((uchar*) temp_buff);
 
828
  free(temp_buff);
834
829
  return(1);
835
830
} /* chk_index */
836
831
 
859
854
 
860
855
        /* Calc length of key in normal isam */
861
856
 
862
 
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
 
857
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
863
858
{
864
 
  uint length;
 
859
  uint32_t length;
865
860
  HA_KEYSEG *keyseg;
866
861
 
867
862
  length= info->s->rec_reflength;
881
876
  ha_rows records, del_blocks;
882
877
  my_off_t used, empty, pos, splits, start_recpos= 0,
883
878
           del_length, link_used, start_block;
884
 
  uchar *record= NULL, *to= NULL;
 
879
  unsigned char *record= NULL, *to= NULL;
885
880
  char llbuff[22],llbuff2[22],llbuff3[22];
886
881
  ha_checksum intern_record_checksum;
887
882
  ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
931
926
      goto err2;
932
927
    switch (info->s->data_file_type) {
933
928
    case STATIC_RECORD:
934
 
      if (my_b_read(&param->read_cache,(uchar*) record,
 
929
      if (my_b_read(&param->read_cache,(unsigned char*) record,
935
930
                    info->s->base.pack_reclength))
936
931
        goto err;
937
932
      start_recpos=pos;
951
946
      block_info.next_filepos=pos;
952
947
      do
953
948
      {
954
 
        if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header,
 
949
        if (_mi_read_cache(&param->read_cache,(unsigned char*) block_info.header,
955
950
                           (start_block=block_info.next_filepos),
956
951
                           sizeof(block_info.header),
957
952
                           (flag ? 0 : READING_NEXT) | READING_HEADER))
1055
1050
          got_error=1;
1056
1051
          break;
1057
1052
        }
1058
 
        if (_mi_read_cache(&param->read_cache,(uchar*) to,block_info.filepos,
 
1053
        if (_mi_read_cache(&param->read_cache,(unsigned char*) to,block_info.filepos,
1059
1054
                           (uint) block_info.data_len,
1060
1055
                           flag == 1 ? READING_NEXT : 0))
1061
1056
          goto err;
1125
1120
      records++;
1126
1121
      if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1127
1122
      {
1128
 
        printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
 
1123
        printf("%s\r", llstr(records,llbuff)); fflush(stdout);
1129
1124
      }
1130
1125
 
1131
1126
      /* Check if keys match the record */
1136
1131
        if (mi_is_key_active(info->s->state.key_map, key))
1137
1132
        {
1138
1133
          {
1139
 
            uint key_length=_mi_make_key(info,key,info->lastkey,record,
 
1134
            uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
1140
1135
                                         start_recpos);
1141
1136
            if (extend)
1142
1137
            {
1156
1151
              }
1157
1152
            }
1158
1153
            else
1159
 
              key_checksum[key]+=mi_byte_checksum((uchar*) info->lastkey,
 
1154
              key_checksum[key]+=mi_byte_checksum((unsigned char*) info->lastkey,
1160
1155
                                                  key_length);
1161
1156
          }
1162
1157
        }
1172
1167
  }
1173
1168
  if (param->testflag & T_WRITE_LOOP)
1174
1169
  {
1175
 
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
 
1170
    fputs("          \r",stdout); fflush(stdout);
1176
1171
  }
1177
1172
  if (records != info->state->records)
1178
1173
  {
1189
1184
  }
1190
1185
  else if (param->glob_crc != info->state->checksum &&
1191
1186
           (info->s->options &
1192
 
            (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
 
1187
            (HA_OPTION_COMPRESS_RECORD)))
1193
1188
  {
1194
1189
    mi_check_print_warning(param,
1195
1190
                           "Record checksum is not the same as checksum stored in the index file\n");
1265
1260
    printf("Lost space:   %12s    Linkdata:     %10s\n",
1266
1261
           llstr(empty,llbuff),llstr(link_used,llbuff2));
1267
1262
  }
1268
 
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
1263
  free(mi_get_rec_buff_ptr(info, record));
1269
1264
  return (error);
1270
1265
 err:
1271
1266
  mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1272
1267
 err2:
1273
 
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
1268
  free(mi_get_rec_buff_ptr(info, record));
1274
1269
  param->testflag|=T_RETRY_WITHOUT_QUICK;
1275
1270
  return(1);
1276
1271
} /* chk_data_link */
1333
1328
{
1334
1329
  MYISAM_SHARE *share= info->s;
1335
1330
  MI_STATE_INFO *state= &share->state;
1336
 
  uint i;
 
1331
  uint32_t i;
1337
1332
  int error;
1338
1333
 
1339
1334
  /*
1380
1375
  /* Remove all key blocks of this index file from key cache. */
1381
1376
  if ((error= flush_key_blocks(share->key_cache, share->kfile,
1382
1377
                               FLUSH_IGNORE_CHANGED)))
1383
 
    goto end; /* purecov: inspected */
 
1378
    goto end;
1384
1379
 
1385
1380
  /* Clear index root block pointers. */
1386
1381
  for (i= 0; i < share->base.keys; i++)
1431
1426
  }
1432
1427
  param->testflag|=T_REP; /* for easy checking */
1433
1428
 
1434
 
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
1429
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
1435
1430
    param->testflag|=T_CALC_CHECKSUM;
1436
1431
 
1437
1432
  if (!param->using_global_keycache)
1438
 
    VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
 
                        param->use_buffers, 0, 0));
 
1433
    init_key_cache(dflt_key_cache, param->key_cache_block_size,
 
1434
                   (size_t)param->use_buffers, 0, 0);
1440
1435
 
1441
1436
  if (init_io_cache(&param->read_cache,info->dfile,
1442
1437
                    (uint) param->read_buffer_length,
1461
1456
  if (!rep_quick)
1462
1457
  {
1463
1458
    /* Get real path for data file */
1464
 
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
1465
 
                                           share->data_file_name, "",
1466
 
                                           DATA_TMP_EXT, 2+4),
1467
 
                                 0,param->tmpfile_createflag,
1468
 
                                 share->base.raid_type,
1469
 
                                 share->base.raid_chunks,
1470
 
                                 share->base.raid_chunksize,
1471
 
                                 MYF(0))) < 0)
 
1459
    if ((new_file=my_create(fn_format(param->temp_filename,
 
1460
                                      share->data_file_name, "",
 
1461
                                      DATA_TMP_EXT, 2+4),
 
1462
                            0,param->tmpfile_createflag,
 
1463
                            MYF(0))) < 0)
1472
1464
    {
1473
1465
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
1474
 
                           param->temp_filename);
 
1466
                           param->temp_filename);
1475
1467
      goto err;
1476
1468
    }
1477
1469
    if (new_header_length &&
1478
1470
        filecopy(param,new_file,info->dfile,0L,new_header_length,
1479
 
                 "datafile-header"))
 
1471
                 "datafile-header"))
1480
1472
      goto err;
1481
1473
    info->s->state.dellink= HA_OFFSET_ERROR;
1482
1474
    info->rec_cache.file=new_file;
1492
1484
  sort_param.pos=sort_param.max_pos=share->pack.header_length;
1493
1485
  sort_param.filepos=new_header_length;
1494
1486
  param->read_cache.end_of_file=sort_info.filelength=
1495
 
    my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
 
1487
    lseek(info->dfile,0L,SEEK_END);
1496
1488
  sort_info.dupp=0;
1497
1489
  sort_param.fix_datafile= (bool) (! rep_quick);
1498
1490
  sort_param.master=1;
1528
1520
                          llstr(info->dupp_key_pos,llbuff2));
1529
1521
      if (param->testflag & T_VERBOSE)
1530
1522
      {
1531
 
        VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
1532
 
                          sort_param.record,0L));
 
1523
        _mi_make_key(info,(uint) info->errkey,info->lastkey,
 
1524
                     sort_param.record,0L);
1533
1525
      }
1534
1526
      sort_info.dupp++;
1535
1527
      if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1549
1541
 
1550
1542
  if (param->testflag & T_WRITE_LOOP)
1551
1543
  {
1552
 
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
 
1544
    fputs("          \r",stdout); fflush(stdout);
1553
1545
  }
1554
1546
  if (ftruncate(share->kfile, info->state->key_file_length))
1555
1547
  {
1631
1623
                  llstr(sort_param.start_recpos,llbuff));
1632
1624
    if (new_file >= 0)
1633
1625
    {
1634
 
      VOID(my_close(new_file,MYF(0)));
1635
 
      VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1636
 
                          MYF(MY_WME)));
 
1626
      my_close(new_file,MYF(0));
 
1627
      my_delete(param->temp_filename, MYF(MY_WME));
1637
1628
      info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1638
1629
    }
1639
1630
    mi_mark_crashed_on_repair(info);
1640
1631
  }
1641
 
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1642
 
                            MYF(MY_ALLOW_ZERO_PTR));
1643
 
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1644
 
          MYF(MY_ALLOW_ZERO_PTR));
1645
 
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1646
 
  VOID(end_io_cache(&param->read_cache));
 
1632
 
 
1633
  void * rec_buff_ptr= NULL;
 
1634
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
 
1635
  if (rec_buff_ptr != NULL)
 
1636
    free(rec_buff_ptr);
 
1637
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
 
1638
  if (rec_buff_ptr != NULL)
 
1639
    free(rec_buff_ptr);
 
1640
  rec_buff_ptr= NULL;
 
1641
 
 
1642
  free(sort_info.buff);
 
1643
  end_io_cache(&param->read_cache);
1647
1644
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1648
 
  VOID(end_io_cache(&info->rec_cache));
 
1645
  end_io_cache(&info->rec_cache);
1649
1646
  got_error|=flush_blocks(param, share->key_cache, share->kfile);
1650
1647
  if (!got_error && param->testflag & T_UNPACK)
1651
1648
  {
1652
 
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
 
1649
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1653
1650
    share->pack.header_length=0;
1654
1651
    share->data_file_type=sort_info.new_data_file_type;
1655
1652
  }
1663
1660
 
1664
1661
static int writekeys(MI_SORT_PARAM *sort_param)
1665
1662
{
1666
 
  register uint i;
1667
 
  uchar    *key;
 
1663
  register uint32_t i;
 
1664
  unsigned char    *key;
1668
1665
  MI_INFO  *info=   sort_param->sort_info->info;
1669
 
  uchar    *buff=   sort_param->record;
 
1666
  unsigned char    *buff=   sort_param->record;
1670
1667
  my_off_t filepos= sort_param->filepos;
1671
1668
 
1672
1669
  key=info->lastkey+info->s->base.max_key_length;
1675
1672
    if (mi_is_key_active(info->s->state.key_map, i))
1676
1673
    {
1677
1674
      {
1678
 
        uint key_length=_mi_make_key(info,i,key,buff,filepos);
 
1675
        uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1679
1676
        if (_mi_ck_write(info,i,key,key_length))
1680
1677
          goto err;
1681
1678
      }
1692
1689
      if (mi_is_key_active(info->s->state.key_map, i))
1693
1690
      {
1694
1691
        {
1695
 
          uint key_length=_mi_make_key(info,i,key,buff,filepos);
 
1692
          uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
1696
1693
          if (_mi_ck_delete(info,i,key,key_length))
1697
1694
            break;
1698
1695
        }
1708
1705
 
1709
1706
        /* Change all key-pointers that points to a records */
1710
1707
 
1711
 
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
1712
 
              my_off_t newpos, uint prot_key)
 
1708
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
 
1709
              my_off_t newpos, uint32_t prot_key)
1713
1710
{
1714
 
  register uint i;
1715
 
  uchar *key;
1716
 
  uint key_length;
 
1711
  register uint32_t i;
 
1712
  unsigned char *key;
 
1713
  uint32_t key_length;
1717
1714
 
1718
1715
  key=info->lastkey+info->s->base.max_key_length;
1719
1716
  for (i=0 ; i < info->s->base.keys; i++)
1723
1720
      key_length=_mi_make_key(info,i,key,record,oldpos);
1724
1721
      if (info->s->keyinfo[i].flag & HA_NOSAME)
1725
1722
      {                                 /* Change pointer direct */
1726
 
        uint nod_flag;
 
1723
        uint32_t nod_flag;
1727
1724
        MI_KEYDEF *keyinfo;
1728
1725
        keyinfo=info->s->keyinfo+i;
1729
1726
        if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1753
1750
 
1754
1751
        /* Tell system that we want all memory for our cache */
1755
1752
 
1756
 
void lock_memory(MI_CHECK *param __attribute__((unused)))
 
1753
void lock_memory(MI_CHECK *param)
1757
1754
{
1758
1755
#ifdef SUN_OS                           /* Key-cacheing thrases on sun 4.1 */
1759
1756
  if (param->opt_lock_memory)
1763
1760
      mi_check_print_warning(param,
1764
1761
                             "Failed to lock memory. errno %d",my_errno);
1765
1762
  }
 
1763
#else
 
1764
  (void)param;
1766
1765
#endif
1767
1766
} /* lock_memory */
1768
1767
 
1786
1785
 
1787
1786
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1788
1787
{
1789
 
  register uint key;
 
1788
  register uint32_t key;
1790
1789
  register MI_KEYDEF *keyinfo;
1791
1790
  File new_file;
1792
1791
  my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1793
 
  uint r_locks,w_locks;
 
1792
  uint32_t r_locks,w_locks;
1794
1793
  int old_lock;
1795
1794
  MYISAM_SHARE *share=info->s;
1796
1795
  MI_STATE_INFO old_state;
1846
1845
        /* Put same locks as old file */
1847
1846
  share->r_locks= share->w_locks= share->tot_locks= 0;
1848
1847
  (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1849
 
  VOID(my_close(share->kfile,MYF(MY_WME)));
 
1848
  my_close(share->kfile,MYF(MY_WME));
1850
1849
  share->kfile = -1;
1851
 
  VOID(my_close(new_file,MYF(MY_WME)));
 
1850
  my_close(new_file,MYF(MY_WME));
1852
1851
  if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1853
1852
                        MYF(0)) ||
1854
1853
      mi_open_keyfile(share))
1872
1871
  return(0);
1873
1872
 
1874
1873
err:
1875
 
  VOID(my_close(new_file,MYF(MY_WME)));
 
1874
  my_close(new_file,MYF(MY_WME));
1876
1875
err2:
1877
 
  VOID(my_delete(param->temp_filename,MYF(MY_WME)));
 
1876
  my_delete(param->temp_filename,MYF(MY_WME));
1878
1877
  return(-1);
1879
1878
} /* mi_sort_index */
1880
1879
 
1884
1883
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1885
1884
                          my_off_t pagepos, File new_file)
1886
1885
{
1887
 
  uint length,nod_flag,used_length, key_length;
1888
 
  uchar *buff,*keypos,*endpos;
1889
 
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
 
1886
  uint32_t length,nod_flag,used_length, key_length;
 
1887
  unsigned char *buff,*keypos,*endpos;
 
1888
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
1890
1889
  my_off_t new_page_pos,next_page;
1891
1890
  char llbuff[22];
1892
1891
 
1893
1892
  new_page_pos=param->new_file_pos;
1894
1893
  param->new_file_pos+=keyinfo->block_length;
1895
1894
 
1896
 
  if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
 
1895
  if (!(buff=(unsigned char*) malloc(keyinfo->block_length)))
1897
1896
  {
1898
1897
    mi_check_print_error(param,"Not enough memory for key block");
1899
1898
    return(-1);
1930
1929
  /* Fill block with zero and write it to the new index file */
1931
1930
  length=mi_getint(buff);
1932
1931
  memset(buff+length, 0, keyinfo->block_length-length);
1933
 
  if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
 
1932
  if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1934
1933
                new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1935
1934
  {
1936
1935
    mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1937
1936
    goto err;
1938
1937
  }
1939
 
  my_afree((uchar*) buff);
 
1938
  free(buff);
1940
1939
  return(0);
1941
1940
err:
1942
 
  my_afree((uchar*) buff);
 
1941
  free(buff);
1943
1942
  return(1);
1944
1943
} /* sort_one_index */
1945
1944
 
1955
1954
 
1956
1955
int change_to_newfile(const char * filename, const char * old_ext,
1957
1956
                      const char * new_ext,
1958
 
                      uint raid_chunks __attribute__((unused)),
 
1957
                      uint32_t raid_chunks,
1959
1958
                      myf MyFlags)
1960
1959
{
 
1960
  (void)raid_chunks;
1961
1961
  char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1962
1962
  /* Get real path to filename */
1963
1963
  (void) fn_format(old_filename,filename,"",old_ext,2+4+32);
1976
1976
  char tmp_buff[IO_SIZE],*buff;
1977
1977
  ulong buff_length;
1978
1978
 
1979
 
  buff_length=(ulong) min(param->write_buffer_length,length);
1980
 
  if (!(buff=my_malloc(buff_length,MYF(0))))
 
1979
  buff_length=(ulong) min(param->write_buffer_length, (size_t)length);
 
1980
  if (!(buff=(char *)malloc(buff_length)))
1981
1981
  {
1982
1982
    buff=tmp_buff; buff_length=IO_SIZE;
1983
1983
  }
1984
1984
 
1985
 
  VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
 
1985
  lseek(from,start,SEEK_SET);
1986
1986
  while (length > buff_length)
1987
1987
  {
1988
 
    if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
1989
 
        my_write(to,(uchar*) buff,buff_length,param->myf_rw))
 
1988
    if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
 
1989
        my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
1990
1990
      goto err;
1991
1991
    length-= buff_length;
1992
1992
  }
1993
 
  if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
1994
 
      my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
 
1993
  if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
 
1994
      my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
1995
1995
    goto err;
1996
1996
  if (buff != tmp_buff)
1997
 
    my_free(buff,MYF(0));
 
1997
    free(buff);
1998
1998
  return(0);
1999
1999
err:
2000
2000
  if (buff != tmp_buff)
2001
 
    my_free(buff,MYF(0));
 
2001
    free(buff);
2002
2002
  mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2003
2003
                       type,my_errno);
2004
2004
  return(1);
2024
2024
                      const char * name, int rep_quick)
2025
2025
{
2026
2026
  int got_error;
2027
 
  uint i;
 
2027
  uint32_t i;
2028
2028
  ulong length;
2029
2029
  ha_rows start_records;
2030
2030
  my_off_t new_header_length,del;
2049
2049
  }
2050
2050
  param->testflag|=T_REP; /* for easy checking */
2051
2051
 
2052
 
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
2052
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
2053
2053
    param->testflag|=T_CALC_CHECKSUM;
2054
2054
 
2055
2055
  memset(&sort_info, 0, sizeof(sort_info));
2080
2080
  if (!rep_quick)
2081
2081
  {
2082
2082
    /* Get real path for data file */
2083
 
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
2084
 
                                           share->data_file_name, "",
2085
 
                                           DATA_TMP_EXT, 2+4),
2086
 
                                 0,param->tmpfile_createflag,
2087
 
                                 share->base.raid_type,
2088
 
                                 share->base.raid_chunks,
2089
 
                                 share->base.raid_chunksize,
2090
 
                                 MYF(0))) < 0)
 
2083
    if ((new_file=my_create(fn_format(param->temp_filename,
 
2084
                                      share->data_file_name, "",
 
2085
                                      DATA_TMP_EXT, 2+4),
 
2086
                            0,param->tmpfile_createflag,
 
2087
                            MYF(0))) < 0)
2091
2088
    {
2092
2089
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2093
 
                           param->temp_filename);
 
2090
                           param->temp_filename);
2094
2091
      goto err;
2095
2092
    }
2096
2093
    if (new_header_length &&
2125
2122
  sort_info.dupp=0;
2126
2123
  sort_info.buff=0;
2127
2124
  param->read_cache.end_of_file=sort_info.filelength=
2128
 
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
 
2125
    lseek(param->read_cache.file,0L,SEEK_END);
2129
2126
 
2130
2127
  sort_param.wordlist=NULL;
2131
2128
 
2140
2137
     (ha_rows) (sort_info.filelength/length+1));
2141
2138
  sort_param.key_cmp=sort_key_cmp;
2142
2139
  sort_param.lock_in_memory=lock_memory;
2143
 
  sort_param.tmpdir=param->tmpdir;
2144
2140
  sort_param.sort_info=&sort_info;
2145
2141
  sort_param.fix_datafile= (bool) (! rep_quick);
2146
2142
  sort_param.master =1;
2147
 
  
 
2143
 
2148
2144
  del=info->state->del;
2149
2145
  param->glob_crc=0;
2150
2146
  if (param->testflag & T_CALC_CHECKSUM)
2252
2248
 
2253
2249
  if (param->testflag & T_WRITE_LOOP)
2254
2250
  {
2255
 
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
 
2251
    fputs("          \r",stdout); fflush(stdout);
2256
2252
  }
2257
2253
 
2258
2254
  if (rep_quick && del+sort_info.dupp != info->state->del)
2305
2301
 
2306
2302
err:
2307
2303
  got_error|= flush_blocks(param, share->key_cache, share->kfile);
2308
 
  VOID(end_io_cache(&info->rec_cache));
 
2304
  end_io_cache(&info->rec_cache);
2309
2305
  if (!got_error)
2310
2306
  {
2311
2307
    /* Replace the actual file with the temporary file */
2327
2323
      mi_check_print_error(param,"%d when fixing table",my_errno);
2328
2324
    if (new_file >= 0)
2329
2325
    {
2330
 
      VOID(my_close(new_file,MYF(0)));
2331
 
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2332
 
                          MYF(MY_WME)));
 
2326
      my_close(new_file,MYF(0));
 
2327
      my_delete(param->temp_filename, MYF(MY_WME));
2333
2328
      if (info->dfile == new_file)
2334
 
        info->dfile= -1;
 
2329
        info->dfile= -1;
2335
2330
    }
2336
2331
    mi_mark_crashed_on_repair(info);
2337
2332
  }
2339
2334
    share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2340
2335
  share->state.changed|=STATE_NOT_SORTED_PAGES;
2341
2336
 
2342
 
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2343
 
                            MYF(MY_ALLOW_ZERO_PTR));
2344
 
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2345
 
          MYF(MY_ALLOW_ZERO_PTR));
2346
 
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2347
 
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2348
 
  VOID(end_io_cache(&param->read_cache));
 
2337
  void * rec_buff_ptr= NULL;
 
2338
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
 
2339
  if (rec_buff_ptr != NULL)
 
2340
    free(rec_buff_ptr);
 
2341
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
 
2342
  if (rec_buff_ptr != NULL)
 
2343
    free(rec_buff_ptr);
 
2344
  rec_buff_ptr= NULL;
 
2345
 
 
2346
  free((unsigned char*) sort_info.key_block);
 
2347
  free(sort_info.buff);
 
2348
  end_io_cache(&param->read_cache);
2349
2349
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2350
2350
  if (!got_error && (param->testflag & T_UNPACK))
2351
2351
  {
2352
 
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
 
2352
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2353
2353
    share->pack.header_length=0;
2354
2354
  }
2355
2355
  return(got_error);
2401
2401
                        const char * name, int rep_quick)
2402
2402
{
2403
2403
  int got_error;
2404
 
  uint i,key, total_key_length, istep;
 
2404
  uint32_t i,key, total_key_length, istep;
2405
2405
  ulong rec_length;
2406
2406
  ha_rows start_records;
2407
2407
  my_off_t new_header_length,del;
2430
2430
  }
2431
2431
  param->testflag|=T_REP; /* for easy checking */
2432
2432
 
2433
 
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
 
2433
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
2434
2434
    param->testflag|=T_CALC_CHECKSUM;
2435
2435
 
2436
2436
  /*
2489
2489
  if (!rep_quick)
2490
2490
  {
2491
2491
    /* Get real path for data file */
2492
 
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
2493
 
                                           share->data_file_name, "",
2494
 
                                           DATA_TMP_EXT,
2495
 
                                           2+4),
2496
 
                                 0,param->tmpfile_createflag,
2497
 
                                 share->base.raid_type,
2498
 
                                 share->base.raid_chunks,
2499
 
                                 share->base.raid_chunksize,
2500
 
                                 MYF(0))) < 0)
 
2492
    if ((new_file=my_create(fn_format(param->temp_filename,
 
2493
                                      share->data_file_name, "",
 
2494
                                      DATA_TMP_EXT,
 
2495
                                      2+4),
 
2496
                            0,param->tmpfile_createflag,
 
2497
                            MYF(0))) < 0)
2501
2498
    {
2502
2499
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2500
                           param->temp_filename);
2534
2531
  sort_info.dupp=0;
2535
2532
  sort_info.buff=0;
2536
2533
  param->read_cache.end_of_file=sort_info.filelength=
2537
 
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
 
2534
    lseek(param->read_cache.file,0L,SEEK_END);
2538
2535
 
2539
2536
  if (share->data_file_type == DYNAMIC_RECORD)
2540
2537
    rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2565
2562
  if (share->options & HA_OPTION_COMPRESS_RECORD)
2566
2563
    set_if_bigger(max_pack_reclength, share->max_pack_length);
2567
2564
  if (!(sort_param=(MI_SORT_PARAM *)
2568
 
        my_malloc((uint) share->base.keys *
2569
 
                  (sizeof(MI_SORT_PARAM) + max_pack_reclength),
2570
 
                  MYF(MY_ZEROFILL))))
 
2565
        malloc(share->base.keys *
 
2566
               (sizeof(MI_SORT_PARAM) + max_pack_reclength))))
2571
2567
  {
2572
2568
    mi_check_print_error(param,"Not enough memory for key!");
2573
2569
    goto err;
2574
2570
  }
 
2571
  memset(sort_param, 0, share->base.keys *
 
2572
                        (sizeof(MI_SORT_PARAM) + max_pack_reclength));
2575
2573
  total_key_length=0;
2576
2574
  rec_per_key_part= param->rec_per_key_part;
2577
2575
  info->state->records=info->state->del=share->state.split=0;
2607
2605
    }
2608
2606
    sort_param[i].key_cmp=sort_key_cmp;
2609
2607
    sort_param[i].lock_in_memory=lock_memory;
2610
 
    sort_param[i].tmpdir=param->tmpdir;
2611
2608
    sort_param[i].sort_info=&sort_info;
2612
2609
    sort_param[i].master=0;
2613
2610
    sort_param[i].fix_datafile=0;
2616
2613
    sort_param[i].filepos=new_header_length;
2617
2614
    sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2618
2615
 
2619
 
    sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
 
2616
    sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
2620
2617
                           (max_pack_reclength * i));
2621
2618
    if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2622
2619
    {
2806
2803
    the share by remove_io_thread() or it was not yet started (if the
2807
2804
    error happend before creating the thread).
2808
2805
  */
2809
 
  VOID(end_io_cache(&info->rec_cache));
 
2806
  end_io_cache(&info->rec_cache);
2810
2807
  /*
2811
2808
    Destroy the new data cache in case of non-quick repair. All slave
2812
2809
    threads did either detach from the share by remove_io_thread()
2814
2811
    creating the threads).
2815
2812
  */
2816
2813
  if (!rep_quick)
2817
 
    VOID(end_io_cache(&new_data_cache));
 
2814
    end_io_cache(&new_data_cache);
2818
2815
  if (!got_error)
2819
2816
  {
2820
2817
    /* Replace the actual file with the temporary file */
2836
2833
      mi_check_print_error(param,"%d when fixing table",my_errno);
2837
2834
    if (new_file >= 0)
2838
2835
    {
2839
 
      VOID(my_close(new_file,MYF(0)));
2840
 
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
2841
 
                          MYF(MY_WME)));
 
2836
      my_close(new_file,MYF(0));
 
2837
      my_delete(param->temp_filename, MYF(MY_WME));
2842
2838
      if (info->dfile == new_file)
2843
 
        info->dfile= -1;
 
2839
        info->dfile= -1;
2844
2840
    }
2845
2841
    mi_mark_crashed_on_repair(info);
2846
2842
  }
2851
2847
  pthread_cond_destroy (&sort_info.cond);
2852
2848
  pthread_mutex_destroy(&sort_info.mutex);
2853
2849
 
2854
 
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2855
 
  my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2856
 
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2857
 
  VOID(end_io_cache(&param->read_cache));
 
2850
  free((unsigned char*) sort_info.key_block);
 
2851
  free((unsigned char*) sort_param);
 
2852
  free(sort_info.buff);
 
2853
  end_io_cache(&param->read_cache);
2858
2854
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2859
2855
  if (!got_error && (param->testflag & T_UNPACK))
2860
2856
  {
2861
 
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
 
2857
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2862
2858
    share->pack.header_length=0;
2863
2859
  }
2864
2860
  return(got_error);
2866
2862
 
2867
2863
        /* Read next record and return next key */
2868
2864
 
2869
 
static int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
 
2865
int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
2870
2866
{
2871
2867
  int error;
2872
2868
  SORT_INFO *sort_info=sort_param->sort_info;
2883
2879
  }
2884
2880
  sort_param->real_key_length=
2885
2881
    (info->s->rec_reflength+
2886
 
     _mi_make_key(info, sort_param->key, (uchar*) key,
 
2882
     _mi_make_key(info, sort_param->key, (unsigned char*) key,
2887
2883
                  sort_param->record, sort_param->filepos));
2888
2884
#ifdef HAVE_purify
2889
 
  memset(key+sort_param->real_key_length, 0,
 
2885
  memset((unsigned char *)key+sort_param->real_key_length, 0,
2890
2886
         (sort_param->key_length-sort_param->real_key_length));
2891
2887
#endif
2892
2888
  return(sort_write_record(sort_param));
2924
2920
    > 0         error
2925
2921
*/
2926
2922
 
2927
 
static int sort_get_next_record(MI_SORT_PARAM *sort_param)
 
2923
int sort_get_next_record(MI_SORT_PARAM *sort_param)
2928
2924
{
2929
2925
  int searching;
2930
2926
  int parallel_flag;
2931
 
  uint found_record,b_type,left_length;
 
2927
  uint32_t found_record,b_type,left_length;
2932
2928
  my_off_t pos;
2933
 
  uchar *to= NULL;
 
2929
  unsigned char *to= NULL;
2934
2930
  MI_BLOCK_INFO block_info;
2935
2931
  SORT_INFO *sort_info=sort_param->sort_info;
2936
2932
  MI_CHECK *param=sort_info->param;
3006
3002
                     llstr(param->search_after_block,llbuff),
3007
3003
                     llstr(sort_param->start_recpos,llbuff2));
3008
3004
        if (_mi_read_cache(&sort_param->read_cache,
3009
 
                           (uchar*) block_info.header,pos,
 
3005
                           (unsigned char*) block_info.header,pos,
3010
3006
                           MI_BLOCK_INFO_HEADER_LENGTH,
3011
3007
                           (! found_record ? READING_NEXT : 0) |
3012
3008
                           parallel_flag | READING_HEADER))
3033
3029
             (block_info.rec_len < (uint) share->base.min_pack_length ||
3034
3030
              block_info.rec_len > (uint) share->base.max_pack_length)))
3035
3031
        {
3036
 
          uint i;
 
3032
          uint32_t i;
3037
3033
          if (param->testflag & T_VERBOSE || searching == 0)
3038
3034
            mi_check_print_info(param,
3039
3035
                                "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3192
3188
          streched over the end of the previous buffer contents.
3193
3189
        */
3194
3190
        {
3195
 
          uint header_len= (uint) (block_info.filepos - pos);
3196
 
          uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
 
3191
          uint32_t header_len= (uint) (block_info.filepos - pos);
 
3192
          uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3197
3193
 
3198
3194
          if (prefetch_len > block_info.data_len)
3199
3195
            prefetch_len= block_info.data_len;
3294
3290
{
3295
3291
  int flag;
3296
3292
  ulong block_length,reclength;
3297
 
  uchar *from;
 
3293
  unsigned char *from;
3298
3294
  SORT_INFO *sort_info=sort_param->sort_info;
3299
3295
  MI_CHECK *param=sort_info->param;
3300
3296
  MI_INFO *info=sort_info->info;
3326
3322
          MI_DYN_DELETE_BLOCK_HEADER;
3327
3323
        if (sort_info->buff_length < reclength)
3328
3324
        {
3329
 
          if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3330
 
                                           MYF(MY_FREE_ON_ERROR |
3331
 
                                               MY_ALLOW_ZERO_PTR))))
3332
 
            return(1);
3333
 
          sort_info->buff_length=reclength;
 
3325
          void *tmpptr= NULL;
 
3326
          tmpptr= realloc(sort_info->buff, reclength);
 
3327
          if(tmpptr)
 
3328
          {
 
3329
            sort_info->buff_length=reclength;
 
3330
            sort_info->buff= (unsigned char *)tmpptr;
 
3331
          }
 
3332
          else
 
3333
          {
 
3334
            mi_check_print_error(param,"Could not realloc() sort_info->buff "
 
3335
                                 " to %ul bytes", reclength);
 
3336
            return(1);
 
3337
          }
3334
3338
        }
3335
3339
        from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3336
3340
      }
3374
3378
    {
3375
3379
      char llbuff[22];
3376
3380
      printf("%s\r", llstr(info->state->records,llbuff));
3377
 
      VOID(fflush(stdout));
 
3381
      fflush(stdout);
3378
3382
    }
3379
3383
  }
3380
3384
  return(0);
3383
3387
 
3384
3388
        /* Compare two keys from _create_index_by_sort */
3385
3389
 
3386
 
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3387
 
                        const void *b)
 
3390
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b)
3388
3391
{
3389
 
  uint not_used[2];
3390
 
  return (ha_key_cmp(sort_param->seg, *((uchar* const *) a), *((uchar* const *) b),
 
3392
  uint32_t not_used[2];
 
3393
  return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
3391
3394
                     USE_WHOLE_KEY, SEARCH_SAME, not_used));
3392
3395
} /* sort_key_cmp */
3393
3396
 
3394
3397
 
3395
 
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
 
3398
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3396
3399
{
3397
 
  uint diff_pos[2];
 
3400
  uint32_t diff_pos[2];
3398
3401
  char llbuff[22],llbuff2[22];
3399
3402
  SORT_INFO *sort_info=sort_param->sort_info;
3400
3403
  MI_CHECK *param= sort_info->param;
3403
3406
  if (sort_info->key_block->inited)
3404
3407
  {
3405
3408
    cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3406
 
                   (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
 
3409
                   (unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3407
3410
                   diff_pos);
3408
3411
    if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3409
3412
      ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3410
 
                 (uchar*) a, USE_WHOLE_KEY, 
 
3413
                 (unsigned char*) a, USE_WHOLE_KEY,
3411
3414
                 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3412
3415
    else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3413
3416
    {
3414
3417
      diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3415
3418
                                                 sort_param->notnull,
3416
3419
                                                 sort_info->key_block->lastkey,
3417
 
                                                 (uchar*)a);
 
3420
                                                 (unsigned char*)a);
3418
3421
    }
3419
3422
    sort_param->unique[diff_pos[0]-1]++;
3420
3423
  }
3423
3426
    cmp= -1;
3424
3427
    if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3425
3428
      mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3426
 
                                     (uchar*)a);
 
3429
                                     (unsigned char*)a);
3427
3430
  }
3428
3431
  if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3429
3432
  {
3430
3433
    sort_info->dupp++;
3431
3434
    sort_info->info->lastpos=get_record_for_key(sort_info->info,
3432
3435
                                                sort_param->keyinfo,
3433
 
                                                (uchar*) a);
 
3436
                                                (unsigned char*) a);
3434
3437
    mi_check_print_warning(param,
3435
3438
                           "Duplicate key for record at %10s against record at %10s",
3436
3439
                           llstr(sort_info->info->lastpos,llbuff),
3443
3446
    return (sort_delete_record(sort_param));
3444
3447
  }
3445
3448
  return (sort_insert_key(sort_param,sort_info->key_block,
3446
 
                          (uchar*) a, HA_OFFSET_ERROR));
 
3449
                          (unsigned char*) a, HA_OFFSET_ERROR));
3447
3450
} /* sort_key_write */
3448
3451
 
3449
3452
 
3450
3453
        /* get pointer to record from a key */
3451
3454
 
3452
 
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3453
 
                                   uchar *key)
3454
 
{
 
3455
my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
 
3456
                            unsigned char *key) {
3455
3457
  return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3456
3458
} /* get_record_for_key */
3457
3459
 
3458
3460
 
3459
3461
        /* Insert a key in sort-key-blocks */
3460
3462
 
3461
 
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3462
 
                           register SORT_KEY_BLOCKS *key_block, uchar *key,
3463
 
                           my_off_t prev_block)
 
3463
int sort_insert_key(MI_SORT_PARAM *sort_param,
 
3464
                    register SORT_KEY_BLOCKS *key_block, unsigned char *key,
 
3465
                    my_off_t prev_block)
3464
3466
{
3465
 
  uint a_length,t_length,nod_flag;
 
3467
  uint32_t a_length,t_length,nod_flag;
3466
3468
  my_off_t filepos,key_file_length;
3467
 
  uchar *anc_buff,*lastkey;
 
3469
  unsigned char *anc_buff,*lastkey;
3468
3470
  MI_KEY_PARAM s_temp;
3469
3471
  MI_INFO *info;
3470
3472
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
3497
3499
    _mi_kpointer(info,key_block->end_pos,prev_block);
3498
3500
 
3499
3501
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3500
 
                                (uchar*) 0,lastkey,lastkey,key,
 
3502
                                (unsigned char*) 0,lastkey,lastkey,key,
3501
3503
                                 &s_temp);
3502
3504
  (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3503
3505
  a_length+=t_length;
3505
3507
  key_block->end_pos+=t_length;
3506
3508
  if (a_length <= keyinfo->block_length)
3507
3509
  {
3508
 
    VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
 
3510
    _mi_move_key(keyinfo,key_block->lastkey,key);
3509
3511
    key_block->last_length=a_length-t_length;
3510
3512
    return(0);
3511
3513
  }
3524
3526
    if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3525
3527
      return(1);
3526
3528
  }
3527
 
  else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
 
3529
  else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
3528
3530
                     (uint) keyinfo->block_length,filepos, param->myf_rw))
3529
3531
    return(1);
3530
3532
 
3540
3542
 
3541
3543
        /* Delete record when we found a duplicated key */
3542
3544
 
3543
 
static int sort_delete_record(MI_SORT_PARAM *sort_param)
 
3545
int sort_delete_record(MI_SORT_PARAM *sort_param)
3544
3546
{
3545
 
  uint i;
 
3547
  uint32_t i;
3546
3548
  int old_file,error;
3547
 
  uchar *key;
 
3549
  unsigned char *key;
3548
3550
  SORT_INFO *sort_info=sort_param->sort_info;
3549
3551
  MI_CHECK *param=sort_info->param;
3550
3552
  MI_INFO *info=sort_info->info;
3577
3579
 
3578
3580
    for (i=0 ; i < sort_info->current_key ; i++)
3579
3581
    {
3580
 
      uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
 
3582
      uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3581
3583
      if (_mi_ck_delete(info,i,key,key_length))
3582
3584
      {
3583
3585
        mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3598
3600
 
3599
3601
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3600
3602
{
3601
 
  uint nod_flag,length;
 
3603
  uint32_t nod_flag,length;
3602
3604
  my_off_t filepos,key_file_length;
3603
3605
  SORT_KEY_BLOCKS *key_block;
3604
3606
  SORT_INFO *sort_info= sort_param->sort_info;
3626
3628
                            DFLT_INIT_HITS, key_block->buff))
3627
3629
        return(1);
3628
3630
    }
3629
 
    else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
 
3631
    else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
3630
3632
                       (uint) keyinfo->block_length,filepos, myf_rw))
3631
3633
      return(1);
3632
3634
    nod_flag=1;
3637
3639
 
3638
3640
        /* alloc space and pointers for key_blocks */
3639
3641
 
3640
 
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
3641
 
                                         uint buffer_length)
 
3642
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
 
3643
                                         uint32_t buffer_length)
3642
3644
{
3643
 
  register uint i;
 
3645
  register uint32_t i;
3644
3646
  SORT_KEY_BLOCKS *block;
3645
3647
 
3646
 
  if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3647
 
                                            buffer_length+IO_SIZE)*blocks,
3648
 
                                           MYF(0))))
 
3648
  if (!(block=(SORT_KEY_BLOCKS*) malloc((sizeof(SORT_KEY_BLOCKS)+
 
3649
                                        buffer_length+IO_SIZE)*blocks)))
3649
3650
  {
3650
3651
    mi_check_print_error(param,"Not enough memory for sort-key-blocks");
3651
3652
    return(0);
3653
3654
  for (i=0 ; i < blocks ; i++)
3654
3655
  {
3655
3656
    block[i].inited=0;
3656
 
    block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
 
3657
    block[i].buff=(unsigned char*) (block+blocks)+(buffer_length+IO_SIZE)*i;
3657
3658
  }
3658
3659
  return(block);
3659
3660
} /* alloc_key_blocks */
3665
3666
{
3666
3667
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3667
3668
    return 0;
3668
 
  return my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)) / 10 * 9 >
 
3669
  return (my_off_t)(lseek(info->s->kfile, 0L, SEEK_END) / 10 * 9) >
3669
3670
         (my_off_t) info->s->base.max_key_file_length ||
3670
 
         my_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
 
3671
         (my_off_t)(lseek(info->dfile, 0L, SEEK_END) / 10 * 9) >
3671
3672
         (my_off_t) info->s->base.max_data_file_length;
3672
3673
}
3673
3674
 
3683
3684
  MI_COLUMNDEF *recdef,*rec,*end;
3684
3685
  MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3685
3686
  MI_STATUS_INFO status_info;
3686
 
  uint unpack,key_parts;
 
3687
  uint32_t unpack,key_parts;
3687
3688
  ha_rows max_records;
3688
3689
  uint64_t file_length,tmp_length;
3689
3690
  MI_CREATE_INFO create_info;
3695
3696
  share= *(*org_info)->s;
3696
3697
  unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3697
3698
    (param->testflag & T_UNPACK);
3698
 
  if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
 
3699
  if (!(keyinfo=(MI_KEYDEF*) malloc(sizeof(MI_KEYDEF)*share.base.keys)))
3699
3700
    return(0);
3700
3701
  memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3701
3702
 
3702
3703
  key_parts= share.base.all_key_parts;
3703
 
  if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3704
 
                                       (key_parts+share.base.keys))))
 
3704
  if (!(keysegs=(HA_KEYSEG*) malloc(sizeof(HA_KEYSEG)*
 
3705
                                    (key_parts+share.base.keys))))
3705
3706
  {
3706
 
    my_afree((uchar*) keyinfo);
 
3707
    free(keyinfo);
3707
3708
    return(1);
3708
3709
  }
3709
3710
  if (!(recdef=(MI_COLUMNDEF*)
3710
 
        my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
 
3711
        malloc(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
3712
  {
3712
 
    my_afree((uchar*) keyinfo);
3713
 
    my_afree((uchar*) keysegs);
 
3713
    free(keyinfo);
 
3714
    free(keysegs);
3714
3715
    return(1);
3715
3716
  }
3716
3717
  if (!(uniquedef=(MI_UNIQUEDEF*)
3717
 
        my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
 
3718
        malloc(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3718
3719
  {
3719
 
    my_afree((uchar*) recdef);
3720
 
    my_afree((uchar*) keyinfo);
3721
 
    my_afree((uchar*) keysegs);
 
3720
    free(recdef);
 
3721
    free(keyinfo);
 
3722
    free(keysegs);
3722
3723
    return(1);
3723
3724
  }
3724
3725
 
3762
3763
  if (share.options & HA_OPTION_COMPRESS_RECORD)
3763
3764
    share.base.records=max_records=info.state->records;
3764
3765
  else if (share.base.min_pack_length)
3765
 
    max_records=(ha_rows) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) /
 
3766
    max_records=(ha_rows) (lseek(info.dfile,0L,SEEK_END) /
3766
3767
                           (ulong) share.base.min_pack_length);
3767
3768
  else
3768
3769
    max_records=0;
3770
3771
    (param->testflag & T_UNPACK);
3771
3772
  share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3772
3773
 
3773
 
  file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
 
3774
  file_length=(uint64_t) lseek(info.dfile,0L,SEEK_END);
3774
3775
  tmp_length= file_length+file_length/10;
3775
3776
  set_if_bigger(file_length,param->max_data_file_length);
3776
3777
  set_if_bigger(file_length,tmp_length);
3777
3778
  set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3778
3779
 
3779
 
  VOID(mi_close(*org_info));
 
3780
  mi_close(*org_info);
3780
3781
  memset(&create_info, 0, sizeof(create_info));
3781
3782
  create_info.max_rows=max(max_records,share.base.records);
3782
3783
  create_info.reloc_rows=share.base.reloc;
3817
3818
  }
3818
3819
  /* We are modifing */
3819
3820
  (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3820
 
  VOID(_mi_readinfo(*org_info,F_WRLCK,0));
 
3821
  _mi_readinfo(*org_info,F_WRLCK,0);
3821
3822
  (*org_info)->state->records=info.state->records;
3822
3823
  if (share.state.create_time)
3823
3824
    (*org_info)->s->state.create_time=share.state.create_time;
3833
3834
    goto end;
3834
3835
  error=0;
3835
3836
end:
3836
 
  my_afree((uchar*) uniquedef);
3837
 
  my_afree((uchar*) keyinfo);
3838
 
  my_afree((uchar*) recdef);
3839
 
  my_afree((uchar*) keysegs);
 
3837
  free(uniquedef);
 
3838
  free(keyinfo);
 
3839
  free(recdef);
 
3840
  free(keysegs);
3840
3841
  return(error);
3841
3842
}
3842
3843
 
3849
3850
 
3850
3851
  if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3851
3852
  {
3852
 
    uchar buff[MEMMAP_EXTRA_MARGIN];
 
3853
    unsigned char buff[MEMMAP_EXTRA_MARGIN];
3853
3854
    memset(buff, 0, sizeof(buff));
3854
3855
    if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3855
3856
    {
3864
3865
 
3865
3866
        /* Update state and myisamchk_time of indexfile */
3866
3867
 
3867
 
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
 
3868
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
3868
3869
{
3869
3870
  MYISAM_SHARE *share=info->s;
3870
3871
 
3875
3876
  }
3876
3877
  if (update & UPDATE_STAT)
3877
3878
  {
3878
 
    uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
 
3879
    uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
3879
3880
    share->state.rec_per_key_rows=info->state->records;
3880
3881
    share->state.changed&= ~STATE_NOT_ANALYZED;
3881
3882
    if (info->state->records)
3909
3910
  }
3910
3911
  {                                             /* Force update of status */
3911
3912
    int error;
3912
 
    uint r_locks=share->r_locks,w_locks=share->w_locks;
 
3913
    uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
3913
3914
    share->r_locks= share->w_locks= share->tot_locks= 0;
3914
3915
    error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3915
3916
    share->r_locks=r_locks;
3939
3940
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3940
3941
                               bool repair_only)
3941
3942
{
3942
 
  uchar *record= 0;
 
3943
  unsigned char *record= 0;
3943
3944
 
3944
3945
  if (!info->s->base.auto_key ||
3945
3946
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3954
3955
      !(param->testflag & T_REP))
3955
3956
    printf("Updating MyISAM file: %s\n", param->isam_file_name);
3956
3957
  /*
3957
 
    We have to use an allocated buffer instead of info->rec_buff as 
 
3958
    We have to use an allocated buffer instead of info->rec_buff as
3958
3959
    _mi_put_key_in_record() may use info->rec_buff
3959
3960
  */
3960
3961
  if (!mi_alloc_rec_buff(info, -1, &record))
3969
3970
    if (my_errno != HA_ERR_END_OF_FILE)
3970
3971
    {
3971
3972
      mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3972
 
      my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
3973
      free(mi_get_rec_buff_ptr(info, record));
3973
3974
      mi_check_print_error(param,"%d when reading last record",my_errno);
3974
3975
      return;
3975
3976
    }
3984
3985
      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3985
3986
  }
3986
3987
  mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3987
 
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
3988
  free(mi_get_rec_buff_ptr(info, record));
3988
3989
  update_state_info(param, info, UPDATE_AUTO_INC);
3989
3990
  return;
3990
3991
}
4002
4003
      records               Number of records in the table
4003
4004
 
4004
4005
  DESCRIPTION
4005
 
    This function is called produce index statistics values from unique and 
 
4006
    This function is called produce index statistics values from unique and
4006
4007
    notnull_tuples arrays after these arrays were produced with sequential
4007
4008
    index scan (the scan is done in two places: chk_index() and
4008
4009
    sort_key_write()).
4016
4017
 
4017
4018
    For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too:
4018
4019
      notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL)
4019
 
      notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all 
 
4020
      notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4020
4021
                          keypart{i} are not NULL)
4021
4022
      ...
4022
4023
    For all other statistics collection methods notnull_tuples==NULL.
4023
4024
 
4024
4025
    Output is an array:
4025
 
    rec_per_key_part[k] = 
4026
 
     = E(#records in the table such that keypart_1=c_1 AND ... AND 
4027
 
         keypart_k=c_k for arbitrary constants c_1 ... c_k) 
4028
 
     
 
4026
    rec_per_key_part[k] =
 
4027
     = E(#records in the table such that keypart_1=c_1 AND ... AND
 
4028
         keypart_k=c_k for arbitrary constants c_1 ... c_k)
 
4029
 
4029
4030
     = {assuming that values have uniform distribution and index contains all
4030
4031
        tuples from the domain (or that {c_1, ..., c_k} tuple is choosen from
4031
4032
        index tuples}
4032
 
     
 
4033
 
4033
4034
     = #tuples-in-the-index / #distinct-tuples-in-the-index.
4034
 
    
4035
 
    The #tuples-in-the-index and #distinct-tuples-in-the-index have different 
 
4035
 
 
4036
    The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4036
4037
    meaning depending on which statistics collection method is used:
4037
 
    
 
4038
 
4038
4039
    MI_STATS_METHOD_*  how are nulls compared?  which tuples are counted?
4039
4040
     NULLS_EQUAL            NULL == NULL           all tuples in table
4040
4041
     NULLS_NOT_EQUAL        NULL != NULL           all tuples in table
4047
4048
{
4048
4049
  uint64_t count=0,tmp, unique_tuples;
4049
4050
  uint64_t tuples= records;
4050
 
  uint parts;
 
4051
  uint32_t parts;
4051
4052
  for (parts=0 ; parts < keyinfo->keysegs  ; parts++)
4052
4053
  {
4053
4054
    count+=unique[parts];
4054
 
    unique_tuples= count + 1;    
 
4055
    unique_tuples= count + 1;
4055
4056
    if (notnull)
4056
4057
    {
4057
4058
      tuples= notnull[parts];
4058
 
      /* 
4059
 
        #(unique_tuples not counting tuples with NULLs) = 
4060
 
          #(unique_tuples counting tuples with NULLs as different) - 
 
4059
      /*
 
4060
        #(unique_tuples not counting tuples with NULLs) =
 
4061
          #(unique_tuples counting tuples with NULLs as different) -
4061
4062
          #(tuples with NULLs)
4062
4063
      */
4063
4064
      unique_tuples -= (records - notnull[parts]);
4064
4065
    }
4065
 
    
 
4066
 
4066
4067
    if (unique_tuples == 0)
4067
4068
      tmp= 1;
4068
4069
    else if (count == 0)
4070
4071
    else
4071
4072
      tmp= (tuples + unique_tuples/2) / unique_tuples;
4072
4073
 
4073
 
    /* 
4074
 
      for some weird keys (e.g. FULLTEXT) tmp can be <1 here. 
 
4074
    /*
 
4075
      for some weird keys (e.g. FULLTEXT) tmp can be <1 here.
4075
4076
      let's ensure it is not
4076
4077
    */
4077
 
    set_if_bigger(tmp,1);
 
4078
    if (tmp < 1)
 
4079
      tmp= 1;
4078
4080
    if (tmp >= (uint64_t) ~(ulong) 0)
4079
4081
      tmp=(uint64_t) ~(ulong) 0;
4080
4082
 
4084
4086
}
4085
4087
 
4086
4088
 
4087
 
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
 
4089
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4088
4090
{
4089
4091
  ha_checksum crc;
4090
 
  const uchar *end=buf+length;
 
4092
  const unsigned char *end=buf+length;
4091
4093
  for (crc=0; buf != end; buf++)
4092
 
    crc=((crc << 1) + *((uchar*) buf)) +
 
4094
    crc=((crc << 1) + *((unsigned char*) buf)) +
4093
4095
      test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4094
4096
  return crc;
4095
4097
}
4096
4098
 
4097
4099
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4098
4100
{
4099
 
  uint key_maxlength=key->maxlength;
 
4101
  uint32_t key_maxlength=key->maxlength;
4100
4102
  return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4101
4103
          ((uint64_t) rows * key_maxlength >
4102
 
           (uint64_t) myisam_max_temp_length));
 
4104
           (uint64_t) MAX_FILE_SIZE));
4103
4105
}
4104
4106
 
4105
4107
/*
4115
4117
{
4116
4118
  MYISAM_SHARE *share=info->s;
4117
4119
  MI_KEYDEF    *key=share->keyinfo;
4118
 
  uint          i;
 
4120
  uint32_t          i;
4119
4121
 
4120
4122
  assert(info->state->records == 0 &&
4121
4123
              (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4142
4144
{
4143
4145
  MYISAM_SHARE *share=info->s;
4144
4146
  MI_KEYDEF *key=share->keyinfo;
4145
 
  uint i;
 
4147
  uint32_t i;
4146
4148
 
4147
4149
  /*
4148
4150
    mi_repair_by_sort only works if we have at least one key. If we don't