~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_check.c

  • Committer: Brian Aker
  • Date: 2008-07-13 21:20:24 UTC
  • Revision ID: brian@tangent.org-20080713212024-o6263c1vha7yxdeu
More bool removal. More cow bell!

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
*/
42
42
 
43
43
#include "myisamdef.h"
 
44
#include <m_ctype.h>
44
45
#include <stdarg.h>
45
 
#include <mysys/my_getopt.h>
 
46
#include <my_getopt.h>
46
47
#ifdef HAVE_SYS_VADVISE_H
47
48
#include <sys/vadvise.h>
48
49
#endif
49
 
#ifdef HAVE_SYS_TYPES
50
 
#include <sys/types.h>
51
 
#endif
52
50
#ifdef HAVE_SYS_MMAN_H
53
51
#include <sys/mman.h>
54
52
#endif
55
 
#include <drizzled/util/test.h>
56
 
 
57
 
 
58
 
/* Functions defined in this file */
59
 
 
60
 
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
 
53
 
 
54
#ifndef USE_RAID
 
55
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
 
56
#define my_raid_delete(A,B,C) my_delete(A,B)
 
57
#endif
 
58
 
 
59
        /* Functions defined in this file */
 
60
 
 
61
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
61
62
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
62
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
63
 
                     ha_checksum *key_checksum, uint32_t level);
64
 
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
 
63
                     my_off_t page, uchar *buff, ha_rows *keys,
 
64
                     ha_checksum *key_checksum, uint level);
 
65
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
66
static ha_checksum calc_checksum(ha_rows count);
66
67
static int writekeys(MI_SORT_PARAM *sort_param);
67
68
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
71
72
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
73
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
74
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
74
 
                                unsigned char *key);
 
75
                                uchar *key);
75
76
static int sort_insert_key(MI_SORT_PARAM  *sort_param,
76
77
                           register SORT_KEY_BLOCKS *key_block,
77
 
                           unsigned char *key, my_off_t prev_block);
 
78
                           uchar *key, my_off_t prev_block);
78
79
static int sort_delete_record(MI_SORT_PARAM *sort_param);
79
80
/*static int flush_pending_blocks(MI_CHECK *param);*/
80
 
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
81
 
                                          uint32_t buffer_length);
82
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
 
81
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
82
                                          uint buffer_length);
 
83
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
83
84
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
84
85
 
85
86
void myisamchk_init(MI_CHECK *param)
86
87
{
87
 
  memset(param, 0, sizeof(*param));
 
88
  bzero((uchar*) param,sizeof(*param));
88
89
  param->opt_follow_links=1;
89
 
  param->keys_in_use= ~(uint64_t) 0;
 
90
  param->keys_in_use= ~(ulonglong) 0;
90
91
  param->search_after_block=HA_OFFSET_ERROR;
91
92
  param->auto_increment_value= 0;
92
93
  param->use_buffers=USE_BUFFER_INIT;
97
98
  param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
98
99
  param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
99
100
  param->start_check_pos=0;
100
 
  param->max_record_length= INT64_MAX;
 
101
  param->max_record_length= LONGLONG_MAX;
101
102
  param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
102
103
  param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
103
104
}
117
118
  if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
118
119
  {
119
120
    /* Don't count this as a real warning, as check can correct this ! */
120
 
    uint32_t save=param->warning_printed;
 
121
    uint save=param->warning_printed;
121
122
    mi_check_print_warning(param,
122
123
                           share->state.open_count==1 ? 
123
124
                           "%d client is using or hasn't closed the table properly" : 
132
133
 
133
134
        /* Check delete links */
134
135
 
135
 
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
 
136
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
136
137
{
137
138
  register ha_rows i;
138
 
  uint32_t delete_link_length;
 
139
  uint delete_link_length;
139
140
  my_off_t empty, next_link, old_link= 0;
140
141
  char buff[22],buff2[22];
 
142
  DBUG_ENTER("chk_del");
141
143
 
142
144
  param->record_checksum=0;
143
145
  delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
162
164
    for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
163
165
    {
164
166
      if (*killed_ptr(param))
165
 
        return(1);
 
167
        DBUG_RETURN(1);
166
168
      if (test_flag & T_VERBOSE)
167
169
        printf(" %9s",llstr(next_link,buff));
168
170
      if (next_link >= info->state->data_file_length)
169
171
        goto wrong;
170
 
      if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
 
172
      if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
173
                   next_link,MYF(MY_NABP)))
172
174
      {
173
175
        if (test_flag & T_VERBOSE) puts("");
174
176
        mi_check_print_error(param,"Can't read delete-link at filepos: %s",
175
177
                    llstr(next_link,buff));
176
 
        return(1);
 
178
        DBUG_RETURN(1);
177
179
      }
178
180
      if (*buff != '\0')
179
181
      {
198
200
      else
199
201
      {
200
202
        param->record_checksum+=(ha_checksum) next_link;
201
 
        next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
 
203
        next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
202
204
        empty+=info->s->base.pack_reclength;
203
205
      }
204
206
    }
227
229
      goto wrong;
228
230
    }
229
231
  }
230
 
  return(0);
 
232
  DBUG_RETURN(0);
231
233
 
232
234
wrong:
233
235
  param->testflag|=T_RETRY_WITHOUT_QUICK;
234
236
  if (test_flag & T_VERBOSE) puts("");
235
237
  mi_check_print_error(param,"record delete-link-chain corrupted");
236
 
  return(1);
 
238
  DBUG_RETURN(1);
237
239
} /* chk_del */
238
240
 
239
241
 
240
242
        /* Check delete links in index file */
241
243
 
242
 
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
 
244
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
243
245
{
244
246
  my_off_t next_link;
245
 
  uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
 
247
  uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
246
248
  ha_rows records;
247
249
  char llbuff[21], llbuff2[21];
248
 
  unsigned char *buff;
 
250
  uchar *buff;
 
251
  DBUG_ENTER("check_k_link");
 
252
  DBUG_PRINT("enter", ("block_size: %u", block_size));
249
253
 
250
254
  if (param->testflag & T_VERBOSE)
251
255
    printf("block_size %4u:", block_size); /* purecov: tested */
255
259
  while (next_link != HA_OFFSET_ERROR && records > 0)
256
260
  {
257
261
    if (*killed_ptr(param))
258
 
      return(1);
 
262
      DBUG_RETURN(1);
259
263
    if (param->testflag & T_VERBOSE)
260
264
      printf("%16s",llstr(next_link,llbuff));
261
265
 
267
271
                           "key block size: %u  file_length: %s",
268
272
                           llstr(next_link, llbuff), block_size,
269
273
                           llstr(info->state->key_file_length, llbuff2));
270
 
      return(1);
 
274
      DBUG_RETURN(1);
271
275
      /* purecov: end */
272
276
    }
273
277
 
278
282
      mi_check_print_error(param, "Mis-aligned key block: %s  "
279
283
                           "minimum key block length: %u",
280
284
                           llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
281
 
      return(1);
 
285
      DBUG_RETURN(1);
282
286
      /* purecov: end */
283
287
    }
284
288
 
289
293
    */
290
294
    if (!(buff=key_cache_read(info->s->key_cache,
291
295
                              info->s->kfile, next_link, DFLT_INIT_HITS,
292
 
                              (unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
 
296
                              (uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
297
                              MI_MIN_KEY_BLOCK_LENGTH, 1)))
294
298
    {
295
299
      /* purecov: begin tested */
296
300
      mi_check_print_error(param, "key cache read error for block: %s",
297
301
                           llstr(next_link,llbuff));
298
 
      return(1);
 
302
      DBUG_RETURN(1);
299
303
      /* purecov: end */
300
304
    }
301
305
    next_link=mi_sizekorr(buff);
309
313
    else
310
314
      puts("");
311
315
  }
312
 
  return (next_link != HA_OFFSET_ERROR);
 
316
  DBUG_RETURN (next_link != HA_OFFSET_ERROR);
313
317
} /* check_k_link */
314
318
 
315
319
 
320
324
  int error=0;
321
325
  register my_off_t skr,size;
322
326
  char buff[22],buff2[22];
 
327
  DBUG_ENTER("chk_size");
323
328
 
324
329
  if (!(param->testflag & T_SILENT)) puts("- check file-size");
325
330
 
345
350
  }
346
351
  if (!(param->testflag & T_VERY_SILENT) &&
347
352
      ! (info->s->options & HA_OPTION_COMPRESS_RECORD) &&
348
 
      uint64_t2double(info->state->key_file_length) >
349
 
      uint64_t2double(info->s->base.margin_key_file_length)*0.9)
 
353
      ulonglong2double(info->state->key_file_length) >
 
354
      ulonglong2double(info->s->base.margin_key_file_length)*0.9)
350
355
    mi_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
351
356
                           llstr(info->state->key_file_length,buff),
352
357
                           llstr(info->s->base.max_key_file_length-1,buff));
379
384
  }
380
385
  if (!(param->testflag & T_VERY_SILENT) &&
381
386
      !(info->s->options & HA_OPTION_COMPRESS_RECORD) &&
382
 
      uint64_t2double(info->state->data_file_length) >
383
 
      (uint64_t2double(info->s->base.max_data_file_length)*0.9))
 
387
      ulonglong2double(info->state->data_file_length) >
 
388
      (ulonglong2double(info->s->base.max_data_file_length)*0.9))
384
389
    mi_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
385
390
                           llstr(info->state->data_file_length,buff),
386
391
                           llstr(info->s->base.max_data_file_length-1,buff2));
387
 
  return(error);
 
392
  DBUG_RETURN(error);
388
393
} /* chk_size */
389
394
 
390
395
 
392
397
 
393
398
int chk_key(MI_CHECK *param, register MI_INFO *info)
394
399
{
395
 
  uint32_t key,found_keys=0,full_text_keys=0,result=0;
 
400
  uint key,found_keys=0,full_text_keys=0,result=0;
396
401
  ha_rows keys;
397
402
  ha_checksum old_record_checksum,init_checksum;
398
403
  my_off_t all_keydata,all_totaldata,key_totlength,length;
400
405
  MYISAM_SHARE *share=info->s;
401
406
  MI_KEYDEF *keyinfo;
402
407
  char buff[22],buff2[22];
 
408
  DBUG_ENTER("chk_key");
403
409
 
404
410
  if (!(param->testflag & T_SILENT))
405
411
    puts("- check key delete-chain");
410
416
    {
411
417
      if (param->testflag & T_VERBOSE) puts("");
412
418
      mi_check_print_error(param,"key delete-link-chain corrupted");
413
 
      return(-1);
 
419
      DBUG_RETURN(-1);
414
420
    }
415
421
 
416
422
  if (!(param->testflag & T_SILENT)) puts("- check index reference");
430
436
    if (! mi_is_key_active(share->state.key_map, key))
431
437
    {
432
438
      /* Remember old statistics for key */
433
 
      assert(rec_per_key_part >= param->rec_per_key_part);
434
 
      memcpy(rec_per_key_part,
435
 
             (share->state.rec_per_key_part +
436
 
              (rec_per_key_part - param->rec_per_key_part)),
 
439
      memcpy((char*) rec_per_key_part,
 
440
             (char*) (share->state.rec_per_key_part +
 
441
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
437
442
             keyinfo->keysegs*sizeof(*rec_per_key_part));
438
443
      continue;
439
444
    }
441
446
 
442
447
    param->record_checksum=init_checksum;
443
448
    
444
 
    memset(&param->unique_count, 0, sizeof(param->unique_count));
445
 
    memset(&param->notnull_count, 0, sizeof(param->notnull_count));
 
449
    bzero((char*) &param->unique_count,sizeof(param->unique_count));
 
450
    bzero((char*) &param->notnull_count,sizeof(param->notnull_count));
446
451
 
447
452
    if ((!(param->testflag & T_SILENT)))
448
453
      printf ("- check data record references index: %d\n",key+1);
449
 
    if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0))
 
454
    if (share->state.key_root[key] == HA_OFFSET_ERROR &&
 
455
        (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
450
456
      goto do_stat;
451
457
    if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
452
458
                           DFLT_INIT_HITS,info->buff,0))
454
460
      mi_check_print_error(param,"Can't read indexpage from filepos: %s",
455
461
                  llstr(share->state.key_root[key],buff));
456
462
      if (!(param->testflag & T_INFO))
457
 
        return(-1);
 
463
        DBUG_RETURN(-1);
458
464
      result= -1;
459
465
      continue;
460
466
    }
465
471
    param->max_level=0;
466
472
    if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
467
473
                  &keys, param->key_crc+key,1))
468
 
      return(-1);
469
 
    if(!(0))
 
474
      DBUG_RETURN(-1);
 
475
    if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
470
476
    {
471
477
      if (keys != info->state->records)
472
478
      {
473
479
        mi_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
474
480
                    llstr(info->state->records,buff2));
475
481
        if (!(param->testflag & T_INFO))
476
 
        return(-1);
 
482
        DBUG_RETURN(-1);
477
483
        result= -1;
478
484
        continue;
479
485
      }
490
496
        else
491
497
          mi_check_print_error(param,"Key 1 doesn't point at all records");
492
498
        if (!(param->testflag & T_INFO))
493
 
          return(-1);
 
499
          DBUG_RETURN(-1);
494
500
        result= -1;
495
501
        continue;
496
502
      }
498
504
    if ((uint) share->base.auto_key -1 == key)
499
505
    {
500
506
      /* Check that auto_increment key is bigger than max key value */
501
 
      uint64_t auto_increment;
 
507
      ulonglong auto_increment;
502
508
      info->lastinx=key;
503
509
      _mi_read_key_record(info, 0L, info->rec_buff);
504
510
      auto_increment= retrieve_auto_increment(info, info->rec_buff);
519
525
 
520
526
      /* Check that there isn't a row with auto_increment = 0 in the table */
521
527
      mi_extra(info,HA_EXTRA_KEYREAD,0);
522
 
      memset(info->lastkey, 0, keyinfo->seg->length);
523
 
      if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
 
528
      bzero(info->lastkey,keyinfo->seg->length);
 
529
      if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
524
530
                   (key_part_map)1, HA_READ_KEY_EXACT))
525
531
      {
526
532
        /* Don't count this as a real warning, as myisamchk can't correct it */
527
 
        uint32_t save=param->warning_printed;
 
533
        uint save=param->warning_printed;
528
534
        mi_check_print_warning(param, "Found row where the auto_increment "
529
535
                               "column has the value 0");
530
536
        param->warning_printed=save;
547
553
      update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
548
554
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
549
555
                       param->notnull_count: NULL, 
550
 
                       (uint64_t)info->state->records);
 
556
                       (ulonglong)info->state->records);
551
557
  }
552
558
  if (param->testflag & T_INFO)
553
559
  {
562
568
      puts("");
563
569
  }
564
570
  if (param->key_file_blocks != info->state->key_file_length &&
565
 
      param->keys_in_use != ~(uint64_t) 0)
 
571
      param->keys_in_use != ~(ulonglong) 0)
566
572
    mi_check_print_warning(param, "Some data are unreferenced in keyfile");
567
573
  if (found_keys != full_text_keys)
568
574
    param->record_checksum=old_record_checksum-init_checksum;   /* Remove delete links */
569
575
  else
570
576
    param->record_checksum=0;
571
 
  return(result);
 
577
  DBUG_RETURN(result);
572
578
} /* chk_key */
573
579
 
574
580
 
575
581
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
576
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
577
 
                     ha_checksum *key_checksum, uint32_t level)
 
582
                     my_off_t page, uchar *buff, ha_rows *keys,
 
583
                     ha_checksum *key_checksum, uint level)
578
584
{
579
585
  char llbuff[22],llbuff2[22];
 
586
  DBUG_ENTER("chk_index_down");
580
587
 
581
588
  /* Key blocks must lay within the key file length entirely. */
582
589
  if (page + keyinfo->block_length > info->state->key_file_length)
618
625
  if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
619
626
    goto err;
620
627
 
621
 
  return(0);
 
628
  DBUG_RETURN(0);
622
629
 
623
630
  /* purecov: begin tested */
624
631
err:
625
 
  return(1);
 
632
  DBUG_RETURN(1);
626
633
  /* purecov: end */
627
634
}
628
635
 
643
650
*/
644
651
 
645
652
static
646
 
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
647
 
                                    unsigned char *key)
 
653
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull,
 
654
                                    uchar *key)
648
655
{
649
 
  uint32_t first_null, kp;
 
656
  uint first_null, kp;
650
657
  first_null= ha_find_null(keyseg, key) - keyseg;
651
658
  /*
652
659
    All prefix tuples that don't include keypart_{first_null} are not-null
683
690
*/
684
691
 
685
692
static
686
 
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
 
                                  unsigned char *prev_key, unsigned char *last_key)
 
693
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull,
 
694
                                  uchar *prev_key, uchar *last_key)
688
695
{
689
 
  uint32_t diffs[2];
690
 
  uint32_t first_null_seg, kp;
 
696
  uint diffs[2];
 
697
  uint first_null_seg, kp;
691
698
  HA_KEYSEG *seg;
692
699
 
693
700
  /* 
719
726
        /* Check if index is ok */
720
727
 
721
728
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
722
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
723
 
                     ha_checksum *key_checksum, uint32_t level)
 
729
                     my_off_t page, uchar *buff, ha_rows *keys,
 
730
                     ha_checksum *key_checksum, uint level)
724
731
{
725
732
  int flag;
726
 
  uint32_t used_length,comp_flag,nod_flag,key_length=0;
727
 
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
 
733
  uint used_length,comp_flag,nod_flag,key_length=0;
 
734
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
735
  my_off_t next_page,record;
729
736
  char llbuff[22];
730
 
  uint32_t diff_pos[2];
 
737
  uint diff_pos[2];
 
738
  DBUG_ENTER("chk_index");
 
739
  DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
731
740
 
732
 
  if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
 
741
  if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
733
742
  {
734
743
    mi_check_print_error(param,"Not enough memory for keyblock");
735
 
    return(-1);
 
744
    DBUG_RETURN(-1);
736
745
  }
737
746
 
738
747
  if (keyinfo->flag & HA_NOSAME)
759
768
  {
760
769
    if (*killed_ptr(param))
761
770
      goto err;
762
 
    memcpy(info->lastkey,key,key_length);
 
771
    memcpy((char*) info->lastkey,(char*) key,key_length);
763
772
    info->lastkey_length=key_length;
764
773
    if (nod_flag)
765
774
    {
772
781
    if (keypos >= endpos ||
773
782
        (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
774
783
      break;
775
 
    assert(key_length <= sizeof(key));
 
784
    DBUG_ASSERT(key_length <= sizeof(key));
776
785
    if (keypos > endpos)
777
786
    {
778
787
      mi_check_print_error(param,"Wrong key block length at page: %s",llstr(page,llbuff));
782
791
        (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
783
792
                         comp_flag, diff_pos)) >=0)
784
793
    {
 
794
      DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length);
 
795
      DBUG_DUMP("new",(uchar*) key, key_length);
 
796
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
 
797
 
785
798
      if (comp_flag & SEARCH_FIND && flag == 0)
786
799
        mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff));
787
800
      else
811
824
                                         key);
812
825
      }
813
826
    }
814
 
    (*key_checksum)+= mi_byte_checksum((unsigned char*) key,
 
827
    (*key_checksum)+= mi_byte_checksum((uchar*) key,
815
828
                                       key_length- info->s->rec_reflength);
816
829
    record= _mi_dpos(info,0,key+key_length);
817
830
    if (record >= info->state->data_file_length)
818
831
    {
 
832
#ifndef DBUG_OFF
 
833
      char llbuff2[22], llbuff3[22];
 
834
#endif
819
835
      mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
 
836
      DBUG_PRINT("test",("page: %s  record: %s  filelength: %s",
 
837
                         llstr(page,llbuff),llstr(record,llbuff2),
 
838
                         llstr(info->state->data_file_length,llbuff3)));
 
839
      DBUG_DUMP("key",(uchar*) key,key_length);
 
840
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
820
841
      goto err;
821
842
    }
822
843
    param->record_checksum+=(ha_checksum) record;
827
848
                llstr(page,llbuff), used_length, (keypos - buff));
828
849
    goto err;
829
850
  }
830
 
  my_afree((unsigned char*) temp_buff);
831
 
  return(0);
 
851
  my_afree((uchar*) temp_buff);
 
852
  DBUG_RETURN(0);
832
853
 err:
833
 
  my_afree((unsigned char*) temp_buff);
834
 
  return(1);
 
854
  my_afree((uchar*) temp_buff);
 
855
  DBUG_RETURN(1);
835
856
} /* chk_index */
836
857
 
837
858
 
839
860
 
840
861
static ha_checksum calc_checksum(ha_rows count)
841
862
{
842
 
  uint64_t sum,a,b;
 
863
  ulonglong sum,a,b;
 
864
  DBUG_ENTER("calc_checksum");
843
865
 
844
866
  sum=0;
845
867
  a=count; b=count+1;
853
875
      sum+=a;
854
876
    a<<=1; b>>=1;
855
877
  }
856
 
  return((ha_checksum) sum);
 
878
  DBUG_PRINT("exit",("sum: %lx",(ulong) sum));
 
879
  DBUG_RETURN((ha_checksum) sum);
857
880
} /* calc_checksum */
858
881
 
859
882
 
860
883
        /* Calc length of key in normal isam */
861
884
 
862
 
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
 
885
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
863
886
{
864
 
  uint32_t length;
 
887
  uint length;
865
888
  HA_KEYSEG *keyseg;
 
889
  DBUG_ENTER("isam_key_length");
866
890
 
867
891
  length= info->s->rec_reflength;
868
892
  for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++)
869
893
    length+= keyseg->length;
870
894
 
871
 
  return(length);
 
895
  DBUG_PRINT("exit",("length: %d",length));
 
896
  DBUG_RETURN(length);
872
897
} /* key_length */
873
898
 
874
899
 
881
906
  ha_rows records, del_blocks;
882
907
  my_off_t used, empty, pos, splits, start_recpos= 0,
883
908
           del_length, link_used, start_block;
884
 
  unsigned char *record= NULL, *to= NULL;
 
909
  uchar *record= NULL, *to= NULL;
885
910
  char llbuff[22],llbuff2[22],llbuff3[22];
886
911
  ha_checksum intern_record_checksum;
887
912
  ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
888
 
  bool static_row_size;
 
913
  my_bool static_row_size;
889
914
  MI_KEYDEF *keyinfo;
890
915
  MI_BLOCK_INFO block_info;
 
916
  DBUG_ENTER("chk_data_link");
891
917
 
892
918
  if (!(param->testflag & T_SILENT))
893
919
  {
900
926
  if (!mi_alloc_rec_buff(info, -1, &record))
901
927
  {
902
928
    mi_check_print_error(param,"Not enough memory for record");
903
 
    return(-1);
 
929
    DBUG_RETURN(-1);
904
930
  }
905
931
  records=del_blocks=0;
906
932
  used=link_used=splits=del_length=0;
924
950
  }
925
951
 
926
952
  pos=my_b_tell(&param->read_cache);
927
 
  memset(key_checksum, 0, info->s->base.keys * sizeof(key_checksum[0]));
 
953
  bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
928
954
  while (pos < info->state->data_file_length)
929
955
  {
930
956
    if (*killed_ptr(param))
931
957
      goto err2;
932
958
    switch (info->s->data_file_type) {
933
959
    case STATIC_RECORD:
934
 
      if (my_b_read(&param->read_cache,(unsigned char*) record,
 
960
      if (my_b_read(&param->read_cache,(uchar*) record,
935
961
                    info->s->base.pack_reclength))
936
962
        goto err;
937
963
      start_recpos=pos;
951
977
      block_info.next_filepos=pos;
952
978
      do
953
979
      {
954
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) block_info.header,
 
980
        if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header,
955
981
                           (start_block=block_info.next_filepos),
956
982
                           sizeof(block_info.header),
957
983
                           (flag ? 0 : READING_NEXT) | READING_HEADER))
1055
1081
          got_error=1;
1056
1082
          break;
1057
1083
        }
1058
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) to,block_info.filepos,
 
1084
        if (_mi_read_cache(&param->read_cache,(uchar*) to,block_info.filepos,
1059
1085
                           (uint) block_info.data_len,
1060
1086
                           flag == 1 ? READING_NEXT : 0))
1061
1087
          goto err;
1116
1142
        pos=block_info.filepos+block_info.block_len;
1117
1143
      break;
1118
1144
    case COMPRESSED_RECORD:
 
1145
      if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header, pos,
 
1146
                         info->s->pack.ref_length, READING_NEXT))
 
1147
        goto err;
 
1148
      start_recpos=pos;
 
1149
      splits++;
 
1150
      VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
 
1151
                                   &info->rec_buff, -1, start_recpos));
 
1152
      pos=block_info.filepos+block_info.rec_len;
 
1153
      if (block_info.rec_len < (uint) info->s->min_pack_length ||
 
1154
          block_info.rec_len > (uint) info->s->max_pack_length)
 
1155
      {
 
1156
        mi_check_print_error(param,
 
1157
                             "Found block with wrong recordlength: %d at %s",
 
1158
                             block_info.rec_len, llstr(start_recpos,llbuff));
 
1159
        got_error=1;
 
1160
        break;
 
1161
      }
 
1162
      if (_mi_read_cache(&param->read_cache,(uchar*) info->rec_buff,
 
1163
                        block_info.filepos, block_info.rec_len, READING_NEXT))
 
1164
        goto err;
 
1165
      if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
 
1166
                              info->rec_buff, block_info.rec_len))
 
1167
      {
 
1168
        mi_check_print_error(param,"Found wrong record at %s",
 
1169
                             llstr(start_recpos,llbuff));
 
1170
        got_error=1;
 
1171
      }
 
1172
      if (static_row_size)
 
1173
        param->glob_crc+= mi_static_checksum(info,record);
 
1174
      else
 
1175
        param->glob_crc+= mi_checksum(info,record);
 
1176
      link_used+= (block_info.filepos - start_recpos);
 
1177
      used+= (pos-start_recpos);
1119
1178
    case BLOCK_RECORD:
1120
1179
      assert(0);                                /* Impossible */
1121
1180
    } /* switch */
1125
1184
      records++;
1126
1185
      if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1127
1186
      {
1128
 
        printf("%s\r", llstr(records,llbuff)); fflush(stdout);
 
1187
        printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1129
1188
      }
1130
1189
 
1131
1190
      /* Check if keys match the record */
1135
1194
      {
1136
1195
        if (mi_is_key_active(info->s->state.key_map, key))
1137
1196
        {
 
1197
          if(!(keyinfo->flag & HA_FULLTEXT))
1138
1198
          {
1139
 
            uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
 
1199
            uint key_length=_mi_make_key(info,key,info->lastkey,record,
1140
1200
                                         start_recpos);
1141
1201
            if (extend)
1142
1202
            {
1156
1216
              }
1157
1217
            }
1158
1218
            else
1159
 
              key_checksum[key]+=mi_byte_checksum((unsigned char*) info->lastkey,
 
1219
              key_checksum[key]+=mi_byte_checksum((uchar*) info->lastkey,
1160
1220
                                                  key_length);
1161
1221
          }
1162
1222
        }
1172
1232
  }
1173
1233
  if (param->testflag & T_WRITE_LOOP)
1174
1234
  {
1175
 
    fputs("          \r",stdout); fflush(stdout);
 
1235
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1176
1236
  }
1177
1237
  if (records != info->state->records)
1178
1238
  {
1199
1259
  {
1200
1260
    for (key=0 ; key < info->s->base.keys;  key++)
1201
1261
    {
1202
 
      if (key_checksum[key] != param->key_crc[key])
 
1262
      if (key_checksum[key] != param->key_crc[key] &&
 
1263
          !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1203
1264
      {
1204
1265
        mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
1205
1266
                    key+1);
1249
1310
      printf("Records:%18s    M.recordlength:%9lu   Packed:%14.0f%%\n",
1250
1311
             llstr(records,llbuff), (long)((used-link_used)/records),
1251
1312
             (info->s->base.blobs ? 0.0 :
1252
 
              (uint64_t2double((uint64_t) info->s->base.reclength*records)-
 
1313
              (ulonglong2double((ulonglong) info->s->base.reclength*records)-
1253
1314
               my_off_t2double(used))/
1254
 
              uint64_t2double((uint64_t) info->s->base.reclength*records)*100.0));
 
1315
              ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1255
1316
      printf("Recordspace used:%9.0f%%   Empty space:%12d%%  Blocks/Record: %6.2f\n",
1256
 
             (uint64_t2double(used-link_used)/uint64_t2double(used-link_used+empty)*100.0),
1257
 
             (!records ? 100 : (int) (uint64_t2double(del_length+empty)/
 
1317
             (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0),
 
1318
             (!records ? 100 : (int) (ulonglong2double(del_length+empty)/
1258
1319
                                      my_off_t2double(used)*100.0)),
1259
 
             uint64_t2double(splits - del_blocks) / records);
 
1320
             ulonglong2double(splits - del_blocks) / records);
1260
1321
    }
1261
1322
    printf("Record blocks:%12s    Delete blocks:%10s\n",
1262
1323
           llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1265
1326
    printf("Lost space:   %12s    Linkdata:     %10s\n",
1266
1327
           llstr(empty,llbuff),llstr(link_used,llbuff2));
1267
1328
  }
1268
 
  free(mi_get_rec_buff_ptr(info, record));
1269
 
  return (error);
 
1329
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
1330
  DBUG_RETURN (error);
1270
1331
 err:
1271
1332
  mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1272
1333
 err2:
1273
 
  free(mi_get_rec_buff_ptr(info, record));
 
1334
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1335
  param->testflag|=T_RETRY_WITHOUT_QUICK;
1275
 
  return(1);
 
1336
  DBUG_RETURN(1);
1276
1337
} /* chk_data_link */
1277
1338
 
1278
1339
 
1329
1390
    then recrate all indexes.
1330
1391
*/
1331
1392
 
1332
 
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
 
1393
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1333
1394
{
1334
1395
  MYISAM_SHARE *share= info->s;
1335
1396
  MI_STATE_INFO *state= &share->state;
1336
 
  uint32_t i;
 
1397
  uint i;
1337
1398
  int error;
 
1399
  DBUG_ENTER("mi_drop_all_indexes");
1338
1400
 
1339
1401
  /*
1340
1402
    If any of the disabled indexes has a key block assigned, we must
1345
1407
  */
1346
1408
  if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
1347
1409
  {
 
1410
    DBUG_PRINT("repair", ("creating missing indexes"));
1348
1411
    for (i= 0; i < share->base.keys; i++)
1349
1412
    {
 
1413
      DBUG_PRINT("repair", ("index #: %u  key_root: 0x%lx  active: %d",
 
1414
                            i, (long) state->key_root[i],
 
1415
                            mi_is_key_active(state->key_map, i)));
1350
1416
      if ((state->key_root[i] != HA_OFFSET_ERROR) &&
1351
1417
          !mi_is_key_active(state->key_map, i))
1352
1418
      {
1355
1421
          We would lose its block(s) if would just recreate it.
1356
1422
          So we need to drop and recreate all indexes.
1357
1423
        */
 
1424
        DBUG_PRINT("repair", ("nonempty and disabled: recreate all"));
1358
1425
        break;
1359
1426
      }
1360
1427
    }
1365
1432
        Flush dirty blocks of this index file from key cache and remove
1366
1433
        all blocks of this index file from key cache.
1367
1434
      */
 
1435
      DBUG_PRINT("repair", ("all disabled are empty: create missing"));
1368
1436
      error= flush_key_blocks(share->key_cache, share->kfile,
1369
1437
                              FLUSH_FORCE_WRITE);
1370
1438
      goto end;
1375
1443
      disabled indexes and enable them.
1376
1444
    */
1377
1445
    mi_clear_all_keys_active(state->key_map);
 
1446
    DBUG_PRINT("repair", ("declared all indexes disabled"));
1378
1447
  }
1379
1448
 
1380
1449
  /* Remove all key blocks of this index file from key cache. */
1393
1462
  /* Reset index file length to end of index file header. */
1394
1463
  info->state->key_file_length= share->base.keystart;
1395
1464
 
 
1465
  DBUG_PRINT("repair", ("dropped all indexes"));
1396
1466
  /* error= 0; set by last (error= flush_key_bocks()). */
1397
1467
 
1398
1468
 end:
1399
 
  return(error);
 
1469
  DBUG_RETURN(error);
1400
1470
}
1401
1471
 
1402
1472
 
1414
1484
  char llbuff[22],llbuff2[22];
1415
1485
  SORT_INFO sort_info;
1416
1486
  MI_SORT_PARAM sort_param;
 
1487
  DBUG_ENTER("mi_repair");
1417
1488
 
1418
 
  memset(&sort_info, 0, sizeof(sort_info));
1419
 
  memset(&sort_param, 0, sizeof(sort_param));
 
1489
  bzero((char *)&sort_info, sizeof(sort_info));
 
1490
  bzero((char *)&sort_param, sizeof(sort_param));
1420
1491
  start_records=info->state->records;
1421
1492
  new_header_length=(param->testflag & T_UNPACK) ? 0L :
1422
1493
    share->pack.header_length;
1435
1506
    param->testflag|=T_CALC_CHECKSUM;
1436
1507
 
1437
1508
  if (!param->using_global_keycache)
1438
 
    init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
 
                   param->use_buffers, 0, 0);
 
1509
    VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
 
1510
                        param->use_buffers, 0, 0));
1440
1511
 
1441
1512
  if (init_io_cache(&param->read_cache,info->dfile,
1442
1513
                    (uint) param->read_buffer_length,
1443
1514
                    READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1444
1515
  {
1445
 
    memset(&info->rec_cache, 0, sizeof(info->rec_cache));
 
1516
    bzero(&info->rec_cache,sizeof(info->rec_cache));
1446
1517
    goto err;
1447
1518
  }
1448
1519
  if (!rep_quick)
1461
1532
  if (!rep_quick)
1462
1533
  {
1463
1534
    /* Get real path for data file */
1464
 
    if ((new_file=my_create(fn_format(param->temp_filename,
1465
 
                                      share->data_file_name, "",
1466
 
                                      DATA_TMP_EXT, 2+4),
1467
 
                            0,param->tmpfile_createflag,
1468
 
                            MYF(0))) < 0)
 
1535
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
1536
                                           share->data_file_name, "",
 
1537
                                           DATA_TMP_EXT, 2+4),
 
1538
                                 0,param->tmpfile_createflag,
 
1539
                                 share->base.raid_type,
 
1540
                                 share->base.raid_chunks,
 
1541
                                 share->base.raid_chunksize,
 
1542
                                 MYF(0))) < 0)
1469
1543
    {
1470
1544
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
 
                           param->temp_filename);
 
1545
                           param->temp_filename);
1472
1546
      goto err;
1473
1547
    }
1474
1548
    if (new_header_length &&
1475
1549
        filecopy(param,new_file,info->dfile,0L,new_header_length,
1476
 
                 "datafile-header"))
 
1550
                 "datafile-header"))
1477
1551
      goto err;
1478
1552
    info->s->state.dellink= HA_OFFSET_ERROR;
1479
1553
    info->rec_cache.file=new_file;
1491
1565
  param->read_cache.end_of_file=sort_info.filelength=
1492
1566
    my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1493
1567
  sort_info.dupp=0;
1494
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
1568
  sort_param.fix_datafile= (my_bool) (! rep_quick);
1495
1569
  sort_param.master=1;
1496
1570
  sort_info.max_records= ~(ha_rows) 0;
1497
1571
 
1508
1582
  /* This function always recreates all enabled indexes. */
1509
1583
  if (param->testflag & T_CREATE_MISSING_KEYS)
1510
1584
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
1511
 
  mi_drop_all_indexes(param, info, true);
 
1585
  mi_drop_all_indexes(param, info, TRUE);
1512
1586
 
1513
1587
  lock_memory(param);                   /* Everything is alloced */
1514
1588
 
1519
1593
    {
1520
1594
      if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1521
1595
        goto err;
 
1596
      DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
1522
1597
      mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
1523
1598
                          info->errkey+1,
1524
1599
                          llstr(sort_param.start_recpos,llbuff),
1525
1600
                          llstr(info->dupp_key_pos,llbuff2));
1526
1601
      if (param->testflag & T_VERBOSE)
1527
1602
      {
1528
 
        _mi_make_key(info,(uint) info->errkey,info->lastkey,
1529
 
                     sort_param.record,0L);
 
1603
        VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
 
1604
                          sort_param.record,0L));
 
1605
        _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
 
1606
                      USE_WHOLE_KEY);
1530
1607
      }
1531
1608
      sort_info.dupp++;
1532
1609
      if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1540
1617
    if (sort_write_record(&sort_param))
1541
1618
      goto err;
1542
1619
  }
1543
 
  if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
 
1620
  if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1544
1621
      flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1545
1622
    goto err;
1546
1623
 
1547
1624
  if (param->testflag & T_WRITE_LOOP)
1548
1625
  {
1549
 
    fputs("          \r",stdout); fflush(stdout);
 
1626
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1550
1627
  }
1551
1628
  if (ftruncate(share->kfile, info->state->key_file_length))
1552
1629
  {
1628
1705
                  llstr(sort_param.start_recpos,llbuff));
1629
1706
    if (new_file >= 0)
1630
1707
    {
1631
 
      my_close(new_file,MYF(0));
1632
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
1708
      VOID(my_close(new_file,MYF(0)));
 
1709
      VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
 
1710
                          MYF(MY_WME)));
1633
1711
      info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1634
1712
    }
1635
1713
    mi_mark_crashed_on_repair(info);
1636
1714
  }
1637
 
 
1638
 
  void * rec_buff_ptr= NULL;
1639
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1640
 
  if (rec_buff_ptr != NULL)
1641
 
    free(rec_buff_ptr);
1642
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1643
 
  if (rec_buff_ptr != NULL)
1644
 
    free(rec_buff_ptr);
1645
 
  rec_buff_ptr= NULL;
1646
 
 
1647
 
  free(sort_info.buff);
1648
 
  end_io_cache(&param->read_cache);
 
1715
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
1716
                            MYF(MY_ALLOW_ZERO_PTR));
 
1717
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
1718
          MYF(MY_ALLOW_ZERO_PTR));
 
1719
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
1720
  VOID(end_io_cache(&param->read_cache));
1649
1721
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
 
  end_io_cache(&info->rec_cache);
 
1722
  VOID(end_io_cache(&info->rec_cache));
1651
1723
  got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1724
  if (!got_error && param->testflag & T_UNPACK)
1653
1725
  {
1654
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
1726
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1727
    share->pack.header_length=0;
1656
1728
    share->data_file_type=sort_info.new_data_file_type;
1657
1729
  }
1658
1730
  share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1659
1731
                          STATE_NOT_ANALYZED);
1660
 
  return(got_error);
 
1732
  DBUG_RETURN(got_error);
1661
1733
}
1662
1734
 
1663
1735
 
1665
1737
 
1666
1738
static int writekeys(MI_SORT_PARAM *sort_param)
1667
1739
{
1668
 
  register uint32_t i;
1669
 
  unsigned char    *key;
 
1740
  register uint i;
 
1741
  uchar    *key;
1670
1742
  MI_INFO  *info=   sort_param->sort_info->info;
1671
 
  unsigned char    *buff=   sort_param->record;
 
1743
  uchar    *buff=   sort_param->record;
1672
1744
  my_off_t filepos= sort_param->filepos;
 
1745
  DBUG_ENTER("writekeys");
1673
1746
 
1674
1747
  key=info->lastkey+info->s->base.max_key_length;
1675
1748
  for (i=0 ; i < info->s->base.keys ; i++)
1677
1750
    if (mi_is_key_active(info->s->state.key_map, i))
1678
1751
    {
1679
1752
      {
1680
 
        uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1753
        uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1754
        if (_mi_ck_write(info,i,key,key_length))
1682
1755
          goto err;
1683
1756
      }
1684
1757
    }
1685
1758
  }
1686
 
  return(0);
 
1759
  DBUG_RETURN(0);
1687
1760
 
1688
1761
 err:
1689
1762
  if (my_errno == HA_ERR_FOUND_DUPP_KEY)
1694
1767
      if (mi_is_key_active(info->s->state.key_map, i))
1695
1768
      {
1696
1769
        {
1697
 
          uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1770
          uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1771
          if (_mi_ck_delete(info,i,key,key_length))
1699
1772
            break;
1700
1773
        }
1704
1777
  /* Remove checksum that was added to glob_crc in sort_get_next_record */
1705
1778
  if (sort_param->calc_checksum)
1706
1779
    sort_param->sort_info->param->glob_crc-= info->checksum;
1707
 
  return(-1);
 
1780
  DBUG_PRINT("error",("errno: %d",my_errno));
 
1781
  DBUG_RETURN(-1);
1708
1782
} /* writekeys */
1709
1783
 
1710
1784
 
1711
1785
        /* Change all key-pointers that points to a records */
1712
1786
 
1713
 
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1714
 
              my_off_t newpos, uint32_t prot_key)
 
1787
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
 
1788
              my_off_t newpos, uint prot_key)
1715
1789
{
1716
 
  register uint32_t i;
1717
 
  unsigned char *key;
1718
 
  uint32_t key_length;
 
1790
  register uint i;
 
1791
  uchar *key;
 
1792
  uint key_length;
 
1793
  DBUG_ENTER("movepoint");
1719
1794
 
1720
1795
  key=info->lastkey+info->s->base.max_key_length;
1721
1796
  for (i=0 ; i < info->s->base.keys; i++)
1725
1800
      key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1801
      if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1802
      {                                 /* Change pointer direct */
1728
 
        uint32_t nod_flag;
 
1803
        uint nod_flag;
1729
1804
        MI_KEYDEF *keyinfo;
1730
1805
        keyinfo=info->s->keyinfo+i;
1731
1806
        if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1732
1807
                       (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1733
1808
                       info->s->state.key_root[i]))
1734
 
          return(-1);
 
1809
          DBUG_RETURN(-1);
1735
1810
        nod_flag=mi_test_if_nod(info->buff);
1736
1811
        _mi_dpointer(info,info->int_keypos-nod_flag-
1737
1812
                     info->s->rec_reflength,newpos);
1738
1813
        if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1739
1814
                              DFLT_INIT_HITS,info->buff))
1740
 
          return(-1);
 
1815
          DBUG_RETURN(-1);
1741
1816
      }
1742
1817
      else
1743
1818
      {                                 /* Change old key to new */
1744
1819
        if (_mi_ck_delete(info,i,key,key_length))
1745
 
          return(-1);
 
1820
          DBUG_RETURN(-1);
1746
1821
        key_length=_mi_make_key(info,i,key,record,newpos);
1747
1822
        if (_mi_ck_write(info,i,key,key_length))
1748
 
          return(-1);
 
1823
          DBUG_RETURN(-1);
1749
1824
      }
1750
1825
    }
1751
1826
  }
1752
 
  return(0);
 
1827
  DBUG_RETURN(0);
1753
1828
} /* movepoint */
1754
1829
 
1755
1830
 
1788
1863
 
1789
1864
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1790
1865
{
1791
 
  register uint32_t key;
 
1866
  register uint key;
1792
1867
  register MI_KEYDEF *keyinfo;
1793
1868
  File new_file;
1794
1869
  my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
 
  uint32_t r_locks,w_locks;
 
1870
  uint r_locks,w_locks;
1796
1871
  int old_lock;
1797
1872
  MYISAM_SHARE *share=info->s;
1798
1873
  MI_STATE_INFO old_state;
 
1874
  DBUG_ENTER("mi_sort_index");
1799
1875
 
1800
1876
  /* cannot sort index files with R-tree indexes */
1801
1877
  for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1812
1888
  {
1813
1889
    mi_check_print_error(param,"Can't create new tempfile: '%s'",
1814
1890
                         param->temp_filename);
1815
 
    return(-1);
 
1891
    DBUG_RETURN(-1);
1816
1892
  }
1817
1893
  if (filecopy(param, new_file,share->kfile,0L,
1818
1894
               (ulong) share->base.keystart, "headerblock"))
1848
1924
        /* Put same locks as old file */
1849
1925
  share->r_locks= share->w_locks= share->tot_locks= 0;
1850
1926
  (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1851
 
  my_close(share->kfile,MYF(MY_WME));
 
1927
  VOID(my_close(share->kfile,MYF(MY_WME)));
1852
1928
  share->kfile = -1;
1853
 
  my_close(new_file,MYF(MY_WME));
 
1929
  VOID(my_close(new_file,MYF(MY_WME)));
1854
1930
  if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1855
1931
                        MYF(0)) ||
1856
1932
      mi_open_keyfile(share))
1871
1947
    info->s->state.key_del[key]=  HA_OFFSET_ERROR;
1872
1948
 
1873
1949
  info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
1874
 
  return(0);
 
1950
  DBUG_RETURN(0);
1875
1951
 
1876
1952
err:
1877
 
  my_close(new_file,MYF(MY_WME));
 
1953
  VOID(my_close(new_file,MYF(MY_WME)));
1878
1954
err2:
1879
 
  my_delete(param->temp_filename,MYF(MY_WME));
1880
 
  return(-1);
 
1955
  VOID(my_delete(param->temp_filename,MYF(MY_WME)));
 
1956
  DBUG_RETURN(-1);
1881
1957
} /* mi_sort_index */
1882
1958
 
1883
1959
 
1886
1962
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
1963
                          my_off_t pagepos, File new_file)
1888
1964
{
1889
 
  uint32_t length,nod_flag,used_length, key_length;
1890
 
  unsigned char *buff,*keypos,*endpos;
1891
 
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
 
1965
  uint length,nod_flag,used_length, key_length;
 
1966
  uchar *buff,*keypos,*endpos;
 
1967
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
1968
  my_off_t new_page_pos,next_page;
1893
1969
  char llbuff[22];
 
1970
  DBUG_ENTER("sort_one_index");
1894
1971
 
1895
1972
  new_page_pos=param->new_file_pos;
1896
1973
  param->new_file_pos+=keyinfo->block_length;
1897
1974
 
1898
 
  if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
 
1975
  if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1899
1976
  {
1900
1977
    mi_check_print_error(param,"Not enough memory for key block");
1901
 
    return(-1);
 
1978
    DBUG_RETURN(-1);
1902
1979
  }
1903
1980
  if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
1904
1981
  {
1906
1983
                llstr(pagepos,llbuff));
1907
1984
    goto err;
1908
1985
  }
1909
 
  if ((nod_flag=mi_test_if_nod(buff)))
 
1986
  if ((nod_flag=mi_test_if_nod(buff)) || keyinfo->flag & HA_FULLTEXT)
1910
1987
  {
1911
1988
    used_length=mi_getint(buff);
1912
1989
    keypos=buff+2+nod_flag;
1919
1996
        _mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */
1920
1997
        if (sort_one_index(param,info,keyinfo,next_page,new_file))
1921
1998
        {
 
1999
          DBUG_PRINT("error",
 
2000
                     ("From page: %ld, keyoffset: %lu  used_length: %d",
 
2001
                      (ulong) pagepos, (ulong) (keypos - buff),
 
2002
                      (int) used_length));
 
2003
          DBUG_DUMP("buff",(uchar*) buff,used_length);
1922
2004
          goto err;
1923
2005
        }
1924
2006
      }
1925
2007
      if (keypos >= endpos ||
1926
2008
          (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
1927
2009
        break;
1928
 
      assert(keypos <= endpos);
 
2010
      DBUG_ASSERT(keypos <= endpos);
1929
2011
    }
1930
2012
  }
1931
2013
 
1932
2014
  /* Fill block with zero and write it to the new index file */
1933
2015
  length=mi_getint(buff);
1934
 
  memset(buff+length, 0, keyinfo->block_length-length);
1935
 
  if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
 
2016
  bzero((uchar*) buff+length,keyinfo->block_length-length);
 
2017
  if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
2018
                new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1937
2019
  {
1938
2020
    mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1939
2021
    goto err;
1940
2022
  }
1941
 
  my_afree((unsigned char*) buff);
1942
 
  return(0);
 
2023
  my_afree((uchar*) buff);
 
2024
  DBUG_RETURN(0);
1943
2025
err:
1944
 
  my_afree((unsigned char*) buff);
1945
 
  return(1);
 
2026
  my_afree((uchar*) buff);
 
2027
  DBUG_RETURN(1);
1946
2028
} /* sort_one_index */
1947
2029
 
1948
2030
 
1957
2039
 
1958
2040
int change_to_newfile(const char * filename, const char * old_ext,
1959
2041
                      const char * new_ext,
1960
 
                      uint32_t raid_chunks __attribute__((unused)),
 
2042
                      uint raid_chunks __attribute__((unused)),
1961
2043
                      myf MyFlags)
1962
2044
{
1963
2045
  char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1969
2051
} /* change_to_newfile */
1970
2052
 
1971
2053
 
 
2054
        /* Locks a whole file */
 
2055
        /* Gives an error-message if file can't be locked */
 
2056
 
 
2057
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
 
2058
              const char *filetype, const char *filename)
 
2059
{
 
2060
  if (my_lock(file,lock_type,start,F_TO_EOF,
 
2061
              param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
 
2062
              MYF(MY_SEEK_NOT_DONE |  MY_DONT_WAIT)))
 
2063
  {
 
2064
    mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename);
 
2065
    param->error_printed=2;             /* Don't give that data is crashed */
 
2066
    return 1;
 
2067
  }
 
2068
  return 0;
 
2069
} /* lock_file */
 
2070
 
1972
2071
 
1973
2072
        /* Copy a block between two files */
1974
2073
 
1977
2076
{
1978
2077
  char tmp_buff[IO_SIZE],*buff;
1979
2078
  ulong buff_length;
 
2079
  DBUG_ENTER("filecopy");
1980
2080
 
1981
 
  buff_length=(ulong) cmin(param->write_buffer_length,length);
 
2081
  buff_length=(ulong) min(param->write_buffer_length,length);
1982
2082
  if (!(buff=my_malloc(buff_length,MYF(0))))
1983
2083
  {
1984
2084
    buff=tmp_buff; buff_length=IO_SIZE;
1985
2085
  }
1986
2086
 
1987
 
  my_seek(from,start,MY_SEEK_SET,MYF(0));
 
2087
  VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1988
2088
  while (length > buff_length)
1989
2089
  {
1990
 
    if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1991
 
        my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
 
2090
    if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
 
2091
        my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1992
2092
      goto err;
1993
2093
    length-= buff_length;
1994
2094
  }
1995
 
  if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1996
 
      my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
 
2095
  if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
 
2096
      my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1997
2097
    goto err;
1998
2098
  if (buff != tmp_buff)
1999
 
    free(buff);
2000
 
  return(0);
 
2099
    my_free(buff,MYF(0));
 
2100
  DBUG_RETURN(0);
2001
2101
err:
2002
2102
  if (buff != tmp_buff)
2003
 
    free(buff);
 
2103
    my_free(buff,MYF(0));
2004
2104
  mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2105
                       type,my_errno);
2006
 
  return(1);
 
2106
  DBUG_RETURN(1);
2007
2107
}
2008
2108
 
2009
2109
 
2026
2126
                      const char * name, int rep_quick)
2027
2127
{
2028
2128
  int got_error;
2029
 
  uint32_t i;
 
2129
  uint i;
2030
2130
  ulong length;
2031
2131
  ha_rows start_records;
2032
2132
  my_off_t new_header_length,del;
2037
2137
  ulong   *rec_per_key_part;
2038
2138
  char llbuff[22];
2039
2139
  SORT_INFO sort_info;
2040
 
  uint64_t key_map= 0;
 
2140
  ulonglong key_map= 0;
 
2141
  DBUG_ENTER("mi_repair_by_sort");
2041
2142
 
2042
2143
  start_records=info->state->records;
2043
2144
  got_error=1;
2054
2155
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2055
2156
    param->testflag|=T_CALC_CHECKSUM;
2056
2157
 
2057
 
  memset(&sort_info, 0, sizeof(sort_info));
2058
 
  memset(&sort_param, 0, sizeof(sort_param));
 
2158
  bzero((char*)&sort_info,sizeof(sort_info));
 
2159
  bzero((char *)&sort_param, sizeof(sort_param));
2059
2160
  if (!(sort_info.key_block=
2060
2161
        alloc_key_blocks(param,
2061
2162
                         (uint) param->sort_key_blocks,
2082
2183
  if (!rep_quick)
2083
2184
  {
2084
2185
    /* Get real path for data file */
2085
 
    if ((new_file=my_create(fn_format(param->temp_filename,
2086
 
                                      share->data_file_name, "",
2087
 
                                      DATA_TMP_EXT, 2+4),
2088
 
                            0,param->tmpfile_createflag,
2089
 
                            MYF(0))) < 0)
 
2186
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2187
                                           share->data_file_name, "",
 
2188
                                           DATA_TMP_EXT, 2+4),
 
2189
                                 0,param->tmpfile_createflag,
 
2190
                                 share->base.raid_type,
 
2191
                                 share->base.raid_chunks,
 
2192
                                 share->base.raid_chunksize,
 
2193
                                 MYF(0))) < 0)
2090
2194
    {
2091
2195
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
 
                           param->temp_filename);
 
2196
                           param->temp_filename);
2093
2197
      goto err;
2094
2198
    }
2095
2199
    if (new_header_length &&
2108
2212
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2109
2213
 
2110
2214
  /* Optionally drop indexes and optionally modify the key_map. */
2111
 
  mi_drop_all_indexes(param, info, false);
 
2215
  mi_drop_all_indexes(param, info, FALSE);
2112
2216
  key_map= share->state.key_map;
2113
2217
  if (param->testflag & T_CREATE_MISSING_KEYS)
2114
2218
  {
2129
2233
  sort_param.wordlist=NULL;
2130
2234
 
2131
2235
  if (share->data_file_type == DYNAMIC_RECORD)
2132
 
    length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
 
2236
    length=max(share->base.min_pack_length+1,share->base.min_block_length);
2133
2237
  else if (share->data_file_type == COMPRESSED_RECORD)
2134
2238
    length=share->base.min_block_length;
2135
2239
  else
2141
2245
  sort_param.lock_in_memory=lock_memory;
2142
2246
  sort_param.tmpdir=param->tmpdir;
2143
2247
  sort_param.sort_info=&sort_info;
2144
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
2248
  sort_param.fix_datafile= (my_bool) (! rep_quick);
2145
2249
  sort_param.master =1;
2146
2250
  
2147
2251
  del=info->state->del;
2163
2267
    if (! mi_is_key_active(key_map, sort_param.key))
2164
2268
    {
2165
2269
      /* Remember old statistics for key */
2166
 
      assert(rec_per_key_part >= param->rec_per_key_part);
2167
 
      memcpy(rec_per_key_part,
2168
 
             (share->state.rec_per_key_part +
2169
 
              (rec_per_key_part - param->rec_per_key_part)),
 
2270
      memcpy((char*) rec_per_key_part,
 
2271
             (char*) (share->state.rec_per_key_part +
 
2272
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2170
2273
             sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
 
2274
      DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
 
2275
                            sort_param.key));
2171
2276
      continue;
2172
2277
    }
2173
2278
 
2175
2280
      printf ("- Fixing index %d\n",sort_param.key+1);
2176
2281
    sort_param.max_pos=sort_param.pos=share->pack.header_length;
2177
2282
    keyseg=sort_param.seg;
2178
 
    memset(sort_param.unique, 0, sizeof(sort_param.unique));
 
2283
    bzero((char*) sort_param.unique,sizeof(sort_param.unique));
2179
2284
    sort_param.key_length=share->rec_reflength;
2180
2285
    for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
2181
2286
    {
2196
2301
    }
2197
2302
 
2198
2303
    if (_create_index_by_sort(&sort_param,
2199
 
                              (bool) (!(param->testflag & T_VERBOSE)),
 
2304
                              (my_bool) (!(param->testflag & T_VERBOSE)),
2200
2305
                              (uint) param->sort_buffer_length))
2201
2306
    {
2202
2307
      param->retry_repair=1;
2213
2318
      update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
2214
2319
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
2215
2320
                       sort_param.notnull: NULL,
2216
 
                       (uint64_t) info->state->records);
 
2321
                       (ulonglong) info->state->records);
2217
2322
    /* Enable this index in the permanent (not the copied) key_map. */
2218
2323
    mi_set_key_active(share->state.key_map, sort_param.key);
 
2324
    DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
2219
2325
 
2220
2326
    if (sort_param.fix_datafile)
2221
2327
    {
2251
2357
 
2252
2358
  if (param->testflag & T_WRITE_LOOP)
2253
2359
  {
2254
 
    fputs("          \r",stdout); fflush(stdout);
 
2360
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
2255
2361
  }
2256
2362
 
2257
2363
  if (rep_quick && del+sort_info.dupp != info->state->del)
2304
2410
 
2305
2411
err:
2306
2412
  got_error|= flush_blocks(param, share->key_cache, share->kfile);
2307
 
  end_io_cache(&info->rec_cache);
 
2413
  VOID(end_io_cache(&info->rec_cache));
2308
2414
  if (!got_error)
2309
2415
  {
2310
2416
    /* Replace the actual file with the temporary file */
2326
2432
      mi_check_print_error(param,"%d when fixing table",my_errno);
2327
2433
    if (new_file >= 0)
2328
2434
    {
2329
 
      my_close(new_file,MYF(0));
2330
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
2435
      VOID(my_close(new_file,MYF(0)));
 
2436
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
2437
                          MYF(MY_WME)));
2331
2438
      if (info->dfile == new_file)
2332
 
        info->dfile= -1;
 
2439
        info->dfile= -1;
2333
2440
    }
2334
2441
    mi_mark_crashed_on_repair(info);
2335
2442
  }
2337
2444
    share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2445
  share->state.changed|=STATE_NOT_SORTED_PAGES;
2339
2446
 
2340
 
  void * rec_buff_ptr= NULL;
2341
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2342
 
  if (rec_buff_ptr != NULL)
2343
 
    free(rec_buff_ptr);
2344
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2345
 
  if (rec_buff_ptr != NULL)
2346
 
    free(rec_buff_ptr);
2347
 
  rec_buff_ptr= NULL;
2348
 
 
2349
 
  free((unsigned char*) sort_info.key_block);
2350
 
  free(sort_info.buff);
2351
 
  end_io_cache(&param->read_cache);
 
2447
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
2448
                            MYF(MY_ALLOW_ZERO_PTR));
 
2449
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
2450
          MYF(MY_ALLOW_ZERO_PTR));
 
2451
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
2452
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
2453
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
2454
  VOID(end_io_cache(&param->read_cache));
2352
2455
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2456
  if (!got_error && (param->testflag & T_UNPACK))
2354
2457
  {
2355
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
2458
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2459
    share->pack.header_length=0;
2357
2460
  }
2358
 
  return(got_error);
 
2461
  DBUG_RETURN(got_error);
2359
2462
}
2360
2463
 
2361
2464
/*
2404
2507
                        const char * name, int rep_quick)
2405
2508
{
2406
2509
  int got_error;
2407
 
  uint32_t i,key, total_key_length, istep;
 
2510
  uint i,key, total_key_length, istep;
2408
2511
  ulong rec_length;
2409
2512
  ha_rows start_records;
2410
2513
  my_off_t new_header_length,del;
2417
2520
  IO_CACHE new_data_cache; /* For non-quick repair. */
2418
2521
  IO_CACHE_SHARE io_share;
2419
2522
  SORT_INFO sort_info;
2420
 
  uint64_t key_map= 0;
 
2523
  ulonglong key_map= 0;
2421
2524
  pthread_attr_t thr_attr;
2422
2525
  ulong max_pack_reclength;
 
2526
  DBUG_ENTER("mi_repair_parallel");
2423
2527
 
2424
2528
  start_records=info->state->records;
2425
2529
  got_error=1;
2464
2568
      position 'new_header_length'.
2465
2569
    }
2466
2570
  */
2467
 
  memset(&sort_info, 0, sizeof(sort_info));
 
2571
  DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
 
2572
  bzero((char*)&sort_info,sizeof(sort_info));
2468
2573
  /* Initialize pthread structures before goto err. */
2469
2574
  pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2470
2575
  pthread_cond_init(&sort_info.cond, 0);
2492
2597
  if (!rep_quick)
2493
2598
  {
2494
2599
    /* Get real path for data file */
2495
 
    if ((new_file=my_create(fn_format(param->temp_filename,
2496
 
                                      share->data_file_name, "",
2497
 
                                      DATA_TMP_EXT,
2498
 
                                      2+4),
2499
 
                            0,param->tmpfile_createflag,
2500
 
                            MYF(0))) < 0)
 
2600
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2601
                                           share->data_file_name, "",
 
2602
                                           DATA_TMP_EXT,
 
2603
                                           2+4),
 
2604
                                 0,param->tmpfile_createflag,
 
2605
                                 share->base.raid_type,
 
2606
                                 share->base.raid_chunks,
 
2607
                                 share->base.raid_chunksize,
 
2608
                                 MYF(0))) < 0)
2501
2609
    {
2502
2610
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2611
                           param->temp_filename);
2519
2627
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2520
2628
 
2521
2629
  /* Optionally drop indexes and optionally modify the key_map. */
2522
 
  mi_drop_all_indexes(param, info, false);
 
2630
  mi_drop_all_indexes(param, info, FALSE);
2523
2631
  key_map= share->state.key_map;
2524
2632
  if (param->testflag & T_CREATE_MISSING_KEYS)
2525
2633
  {
2537
2645
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2538
2646
 
2539
2647
  if (share->data_file_type == DYNAMIC_RECORD)
2540
 
    rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
 
2648
    rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2649
  else if (share->data_file_type == COMPRESSED_RECORD)
2542
2650
    rec_length=share->base.min_block_length;
2543
2651
  else
2590
2698
    if (! mi_is_key_active(key_map, key))
2591
2699
    {
2592
2700
      /* Remember old statistics for key */
2593
 
      assert(rec_per_key_part >= param->rec_per_key_part);
2594
 
      memcpy(rec_per_key_part,
2595
 
             (share->state.rec_per_key_part +
2596
 
              (rec_per_key_part - param->rec_per_key_part)),
 
2701
      memcpy((char*) rec_per_key_part,
 
2702
             (char*) (share->state.rec_per_key_part+
 
2703
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2597
2704
             sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2598
2705
      istep=0;
2599
2706
      continue;
2616
2723
    sort_param[i].filepos=new_header_length;
2617
2724
    sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2618
2725
 
2619
 
    sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
 
2726
    sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2727
                           (max_pack_reclength * i));
2621
2728
    if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2622
2729
    {
2640
2747
  }
2641
2748
  sort_info.total_keys=i;
2642
2749
  sort_param[0].master= 1;
2643
 
  sort_param[0].fix_datafile= (bool)(! rep_quick);
 
2750
  sort_param[0].fix_datafile= (my_bool)(! rep_quick);
2644
2751
  sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM);
2645
2752
 
2646
2753
  sort_info.got_error=0;
2677
2784
    */
2678
2785
    sort_param[i].read_cache= ((rep_quick || !i) ? param->read_cache :
2679
2786
                               new_data_cache);
 
2787
    DBUG_PRINT("io_cache_share", ("thread: %u  read_cache: 0x%lx",
 
2788
                                  i, (long) &sort_param[i].read_cache));
2680
2789
 
2681
2790
    /*
2682
2791
      two approaches: the same amount of memory for each thread
2698
2807
      /* Cleanup: Detach from the share. Avoid others to be blocked. */
2699
2808
      if (io_share.total_threads)
2700
2809
        remove_io_thread(&sort_param[i].read_cache);
 
2810
      DBUG_PRINT("error", ("Cannot start a repair thread"));
2701
2811
      sort_info.got_error=1;
2702
2812
    }
2703
2813
    else
2806
2916
    the share by remove_io_thread() or it was not yet started (if the
2807
2917
    error happend before creating the thread).
2808
2918
  */
2809
 
  end_io_cache(&info->rec_cache);
 
2919
  VOID(end_io_cache(&info->rec_cache));
2810
2920
  /*
2811
2921
    Destroy the new data cache in case of non-quick repair. All slave
2812
2922
    threads did either detach from the share by remove_io_thread()
2814
2924
    creating the threads).
2815
2925
  */
2816
2926
  if (!rep_quick)
2817
 
    end_io_cache(&new_data_cache);
 
2927
    VOID(end_io_cache(&new_data_cache));
2818
2928
  if (!got_error)
2819
2929
  {
2820
2930
    /* Replace the actual file with the temporary file */
2836
2946
      mi_check_print_error(param,"%d when fixing table",my_errno);
2837
2947
    if (new_file >= 0)
2838
2948
    {
2839
 
      my_close(new_file,MYF(0));
2840
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
2949
      VOID(my_close(new_file,MYF(0)));
 
2950
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
2951
                          MYF(MY_WME)));
2841
2952
      if (info->dfile == new_file)
2842
 
        info->dfile= -1;
 
2953
        info->dfile= -1;
2843
2954
    }
2844
2955
    mi_mark_crashed_on_repair(info);
2845
2956
  }
2850
2961
  pthread_cond_destroy (&sort_info.cond);
2851
2962
  pthread_mutex_destroy(&sort_info.mutex);
2852
2963
 
2853
 
  free((unsigned char*) sort_info.key_block);
2854
 
  free((unsigned char*) sort_param);
2855
 
  free(sort_info.buff);
2856
 
  end_io_cache(&param->read_cache);
 
2964
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
2965
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
2966
  my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
 
2967
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
2968
  VOID(end_io_cache(&param->read_cache));
2857
2969
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
2970
  if (!got_error && (param->testflag & T_UNPACK))
2859
2971
  {
2860
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
2972
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
2973
    share->pack.header_length=0;
2862
2974
  }
2863
 
  return(got_error);
 
2975
  DBUG_RETURN(got_error);
2864
2976
}
2865
2977
 
2866
2978
        /* Read next record and return next key */
2870
2982
  int error;
2871
2983
  SORT_INFO *sort_info=sort_param->sort_info;
2872
2984
  MI_INFO *info=sort_info->info;
 
2985
  DBUG_ENTER("sort_key_read");
2873
2986
 
2874
2987
  if ((error=sort_get_next_record(sort_param)))
2875
 
    return(error);
 
2988
    DBUG_RETURN(error);
2876
2989
  if (info->state->records == sort_info->max_records)
2877
2990
  {
2878
2991
    mi_check_print_error(sort_info->param,
2879
2992
                         "Key %d - Found too many records; Can't continue",
2880
2993
                         sort_param->key+1);
2881
 
    return(1);
 
2994
    DBUG_RETURN(1);
2882
2995
  }
2883
2996
  sort_param->real_key_length=
2884
2997
    (info->s->rec_reflength+
2885
 
     _mi_make_key(info, sort_param->key, (unsigned char*) key,
 
2998
     _mi_make_key(info, sort_param->key, (uchar*) key,
2886
2999
                  sort_param->record, sort_param->filepos));
2887
3000
#ifdef HAVE_purify
2888
 
  memset(key+sort_param->real_key_length, 0,
2889
 
         (sort_param->key_length-sort_param->real_key_length));
 
3001
  bzero(key+sort_param->real_key_length,
 
3002
        (sort_param->key_length-sort_param->real_key_length));
2890
3003
#endif
2891
 
  return(sort_write_record(sort_param));
 
3004
  DBUG_RETURN(sort_write_record(sort_param));
2892
3005
} /* sort_key_read */
2893
3006
 
2894
3007
 
2927
3040
{
2928
3041
  int searching;
2929
3042
  int parallel_flag;
2930
 
  uint32_t found_record,b_type,left_length;
 
3043
  uint found_record,b_type,left_length;
2931
3044
  my_off_t pos;
2932
 
  unsigned char *to= NULL;
 
3045
  uchar *to= NULL;
2933
3046
  MI_BLOCK_INFO block_info;
2934
3047
  SORT_INFO *sort_info=sort_param->sort_info;
2935
3048
  MI_CHECK *param=sort_info->param;
2936
3049
  MI_INFO *info=sort_info->info;
2937
3050
  MYISAM_SHARE *share=info->s;
2938
3051
  char llbuff[22],llbuff2[22];
 
3052
  DBUG_ENTER("sort_get_next_record");
2939
3053
 
2940
3054
  if (*killed_ptr(param))
2941
 
    return(1);
 
3055
    DBUG_RETURN(1);
2942
3056
 
2943
3057
  switch (share->data_file_type) {
2944
3058
  case STATIC_RECORD:
2951
3065
          param->out_flag |= O_DATA_LOST;
2952
3066
        param->retry_repair=1;
2953
3067
        param->testflag|=T_RETRY_WITHOUT_QUICK;
2954
 
        return(-1);
 
3068
        DBUG_RETURN(-1);
2955
3069
      }
2956
3070
      sort_param->start_recpos=sort_param->pos;
2957
3071
      if (!sort_param->fix_datafile)
2966
3080
        if (sort_param->calc_checksum)
2967
3081
          param->glob_crc+= (info->checksum=
2968
3082
                             mi_static_checksum(info,sort_param->record));
2969
 
        return(0);
 
3083
        DBUG_RETURN(0);
2970
3084
      }
2971
3085
      if (!sort_param->fix_datafile && sort_param->master)
2972
3086
      {
3005
3119
                     llstr(param->search_after_block,llbuff),
3006
3120
                     llstr(sort_param->start_recpos,llbuff2));
3007
3121
        if (_mi_read_cache(&sort_param->read_cache,
3008
 
                           (unsigned char*) block_info.header,pos,
 
3122
                           (uchar*) block_info.header,pos,
3009
3123
                           MI_BLOCK_INFO_HEADER_LENGTH,
3010
3124
                           (! found_record ? READING_NEXT : 0) |
3011
3125
                           parallel_flag | READING_HEADER))
3017
3131
                                llstr(sort_param->start_recpos,llbuff),errno);
3018
3132
            goto try_next;
3019
3133
          }
3020
 
          return(-1);
 
3134
          DBUG_RETURN(-1);
3021
3135
        }
3022
3136
        if (searching && ! sort_param->fix_datafile)
3023
3137
        {
3024
3138
          param->error_printed=1;
3025
3139
          param->retry_repair=1;
3026
3140
          param->testflag|=T_RETRY_WITHOUT_QUICK;
3027
 
          return(1);    /* Something wrong with data */
 
3141
          DBUG_RETURN(1);       /* Something wrong with data */
3028
3142
        }
3029
3143
        b_type=_mi_get_block_info(&block_info,-1,pos);
3030
3144
        if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3032
3146
             (block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3147
              block_info.rec_len > (uint) share->base.max_pack_length)))
3034
3148
        {
3035
 
          uint32_t i;
 
3149
          uint i;
3036
3150
          if (param->testflag & T_VERBOSE || searching == 0)
3037
3151
            mi_check_print_info(param,
3038
3152
                                "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3055
3169
        }
3056
3170
        if (b_type & BLOCK_DELETED)
3057
3171
        {
3058
 
          bool error=0;
 
3172
          my_bool error=0;
3059
3173
          if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3060
3174
              share->base.min_block_length)
3061
3175
          {
3156
3270
                mi_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
3157
3271
                                     llstr(sort_param->start_recpos,llbuff),
3158
3272
                                     (ulong) block_info.rec_len);
3159
 
                return(1);
 
3273
                DBUG_RETURN(1);
3160
3274
              }
3161
3275
              else
3162
3276
              {
3191
3305
          streched over the end of the previous buffer contents.
3192
3306
        */
3193
3307
        {
3194
 
          uint32_t header_len= (uint) (block_info.filepos - pos);
3195
 
          uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
 
3308
          uint header_len= (uint) (block_info.filepos - pos);
 
3309
          uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3196
3310
 
3197
3311
          if (prefetch_len > block_info.data_len)
3198
3312
            prefetch_len= block_info.data_len;
3238
3352
                         sort_param->find_length) != MY_FILE_ERROR)
3239
3353
      {
3240
3354
        if (sort_param->read_cache.error < 0)
3241
 
          return(1);
 
3355
          DBUG_RETURN(1);
3242
3356
        if (sort_param->calc_checksum)
3243
3357
          info->checksum= mi_checksum(info, sort_param->record);
3244
3358
        if ((param->testflag & (T_EXTEND | T_REP)) || searching)
3256
3370
        }
3257
3371
        if (sort_param->calc_checksum)
3258
3372
          param->glob_crc+= info->checksum;
3259
 
        return(0);
 
3373
        DBUG_RETURN(0);
3260
3374
      }
3261
3375
      if (!searching)
3262
3376
        mi_check_print_info(param,"Key %d - Found wrong stored record at %s",
3267
3381
      searching=1;
3268
3382
    }
3269
3383
  case COMPRESSED_RECORD:
 
3384
    for (searching=0 ;; searching=1, sort_param->pos++)
 
3385
    {
 
3386
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
 
3387
                         sort_param->pos,
 
3388
                         share->pack.ref_length,READING_NEXT))
 
3389
        DBUG_RETURN(-1);
 
3390
      if (searching && ! sort_param->fix_datafile)
 
3391
      {
 
3392
        param->error_printed=1;
 
3393
        param->retry_repair=1;
 
3394
        param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3395
        DBUG_RETURN(1);         /* Something wrong with data */
 
3396
      }
 
3397
      sort_param->start_recpos=sort_param->pos;
 
3398
      if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
 
3399
                                  &sort_param->rec_buff, -1, sort_param->pos))
 
3400
        DBUG_RETURN(-1);
 
3401
      if (!block_info.rec_len &&
 
3402
          sort_param->pos + MEMMAP_EXTRA_MARGIN ==
 
3403
          sort_param->read_cache.end_of_file)
 
3404
        DBUG_RETURN(-1);
 
3405
      if (block_info.rec_len < (uint) share->min_pack_length ||
 
3406
          block_info.rec_len > (uint) share->max_pack_length)
 
3407
      {
 
3408
        if (! searching)
 
3409
          mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
 
3410
                              block_info.rec_len,
 
3411
                              llstr(sort_param->pos,llbuff));
 
3412
        continue;
 
3413
      }
 
3414
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
 
3415
                         block_info.filepos, block_info.rec_len,
 
3416
                         READING_NEXT))
 
3417
      {
 
3418
        if (! searching)
 
3419
          mi_check_print_info(param,"Couldn't read whole record from %s",
 
3420
                              llstr(sort_param->pos,llbuff));
 
3421
        continue;
 
3422
      }
 
3423
      if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
 
3424
                              sort_param->rec_buff, block_info.rec_len))
 
3425
      {
 
3426
        if (! searching)
 
3427
          mi_check_print_info(param,"Found wrong record at %s",
 
3428
                              llstr(sort_param->pos,llbuff));
 
3429
        continue;
 
3430
      }
 
3431
      if (!sort_param->fix_datafile)
 
3432
      {
 
3433
        sort_param->filepos=sort_param->pos;
 
3434
        if (sort_param->master)
 
3435
          share->state.split++;
 
3436
      }
 
3437
      sort_param->max_pos=(sort_param->pos=block_info.filepos+
 
3438
                         block_info.rec_len);
 
3439
      info->packed_length=block_info.rec_len;
 
3440
      if (sort_param->calc_checksum)
 
3441
        param->glob_crc+= (info->checksum=
 
3442
                           mi_checksum(info, sort_param->record));
 
3443
      DBUG_RETURN(0);
 
3444
    }
3270
3445
  case BLOCK_RECORD:
3271
3446
    assert(0);                                  /* Impossible */
3272
3447
  }
3273
 
  return(1);                               /* Impossible */
 
3448
  DBUG_RETURN(1);                               /* Impossible */
3274
3449
}
3275
3450
 
3276
3451
 
3292
3467
int sort_write_record(MI_SORT_PARAM *sort_param)
3293
3468
{
3294
3469
  int flag;
 
3470
  uint length;
3295
3471
  ulong block_length,reclength;
3296
 
  unsigned char *from;
 
3472
  uchar *from;
 
3473
  uchar block_buff[8];
3297
3474
  SORT_INFO *sort_info=sort_param->sort_info;
3298
3475
  MI_CHECK *param=sort_info->param;
3299
3476
  MI_INFO *info=sort_info->info;
3300
3477
  MYISAM_SHARE *share=info->s;
 
3478
  DBUG_ENTER("sort_write_record");
3301
3479
 
3302
3480
  if (sort_param->fix_datafile)
3303
3481
  {
3307
3485
                     share->base.pack_reclength))
3308
3486
      {
3309
3487
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
3310
 
        return(1);
 
3488
        DBUG_RETURN(1);
3311
3489
      }
3312
3490
      sort_param->filepos+=share->base.pack_reclength;
3313
3491
      info->s->state.split++;
3328
3506
          if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3329
3507
                                           MYF(MY_FREE_ON_ERROR |
3330
3508
                                               MY_ALLOW_ZERO_PTR))))
3331
 
            return(1);
 
3509
            DBUG_RETURN(1);
3332
3510
          sort_info->buff_length=reclength;
3333
3511
        }
3334
3512
        from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3353
3531
                                  &from,&reclength,&flag))
3354
3532
        {
3355
3533
          mi_check_print_error(param,"%d when writing to datafile",my_errno);
3356
 
          return(1);
 
3534
          DBUG_RETURN(1);
3357
3535
        }
3358
3536
        sort_param->filepos+=block_length;
3359
3537
        info->s->state.split++;
3361
3539
      /* sort_info->param->glob_crc+=info->checksum; */
3362
3540
      break;
3363
3541
    case COMPRESSED_RECORD:
 
3542
      reclength=info->packed_length;
 
3543
      length= save_pack_length((uint) share->pack.version, block_buff,
 
3544
                               reclength);
 
3545
      if (info->s->base.blobs)
 
3546
        length+= save_pack_length((uint) share->pack.version,
 
3547
                                  block_buff + length, info->blob_length);
 
3548
      if (my_b_write(&info->rec_cache,block_buff,length) ||
 
3549
          my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
 
3550
      {
 
3551
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3552
        DBUG_RETURN(1);
 
3553
      }
 
3554
      /* sort_info->param->glob_crc+=info->checksum; */
 
3555
      sort_param->filepos+=reclength+length;
 
3556
      info->s->state.split++;
 
3557
      break;
3364
3558
    case BLOCK_RECORD:
3365
3559
      assert(0);                                  /* Impossible */
3366
3560
    }
3373
3567
    {
3374
3568
      char llbuff[22];
3375
3569
      printf("%s\r", llstr(info->state->records,llbuff));
3376
 
      fflush(stdout);
 
3570
      VOID(fflush(stdout));
3377
3571
    }
3378
3572
  }
3379
 
  return(0);
 
3573
  DBUG_RETURN(0);
3380
3574
} /* sort_write_record */
3381
3575
 
3382
3576
 
3385
3579
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3386
3580
                        const void *b)
3387
3581
{
3388
 
  uint32_t not_used[2];
3389
 
  return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
 
3582
  uint not_used[2];
 
3583
  return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3390
3584
                     USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3585
} /* sort_key_cmp */
3392
3586
 
3393
3587
 
3394
3588
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3395
3589
{
3396
 
  uint32_t diff_pos[2];
 
3590
  uint diff_pos[2];
3397
3591
  char llbuff[22],llbuff2[22];
3398
3592
  SORT_INFO *sort_info=sort_param->sort_info;
3399
3593
  MI_CHECK *param= sort_info->param;
3402
3596
  if (sort_info->key_block->inited)
3403
3597
  {
3404
3598
    cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
 
                   (unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
 
3599
                   (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3406
3600
                   diff_pos);
3407
3601
    if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3602
      ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
 
                 (unsigned char*) a, USE_WHOLE_KEY, 
 
3603
                 (uchar*) a, USE_WHOLE_KEY, 
3410
3604
                 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3605
    else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3412
3606
    {
3413
3607
      diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3608
                                                 sort_param->notnull,
3415
3609
                                                 sort_info->key_block->lastkey,
3416
 
                                                 (unsigned char*)a);
 
3610
                                                 (uchar*)a);
3417
3611
    }
3418
3612
    sort_param->unique[diff_pos[0]-1]++;
3419
3613
  }
3422
3616
    cmp= -1;
3423
3617
    if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3618
      mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3425
 
                                     (unsigned char*)a);
 
3619
                                     (uchar*)a);
3426
3620
  }
3427
3621
  if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3428
3622
  {
3429
3623
    sort_info->dupp++;
3430
3624
    sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3625
                                                sort_param->keyinfo,
3432
 
                                                (unsigned char*) a);
 
3626
                                                (uchar*) a);
3433
3627
    mi_check_print_warning(param,
3434
3628
                           "Duplicate key for record at %10s against record at %10s",
3435
3629
                           llstr(sort_info->info->lastpos,llbuff),
3439
3633
                                                    lastkey),
3440
3634
                                 llbuff2));
3441
3635
    param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3636
    if (sort_info->param->testflag & T_VERBOSE)
 
3637
      _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3442
3638
    return (sort_delete_record(sort_param));
3443
3639
  }
 
3640
#ifndef DBUG_OFF
 
3641
  if (cmp > 0)
 
3642
  {
 
3643
    mi_check_print_error(param,
 
3644
                         "Internal error: Keys are not in order from sort");
 
3645
    return(1);
 
3646
  }
 
3647
#endif
3444
3648
  return (sort_insert_key(sort_param,sort_info->key_block,
3445
 
                          (unsigned char*) a, HA_OFFSET_ERROR));
 
3649
                          (uchar*) a, HA_OFFSET_ERROR));
3446
3650
} /* sort_key_write */
3447
3651
 
3448
3652
 
3449
3653
        /* get pointer to record from a key */
3450
3654
 
3451
3655
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3452
 
                                   unsigned char *key)
 
3656
                                   uchar *key)
3453
3657
{
3454
3658
  return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3659
} /* get_record_for_key */
3458
3662
        /* Insert a key in sort-key-blocks */
3459
3663
 
3460
3664
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
 
                           register SORT_KEY_BLOCKS *key_block, unsigned char *key,
 
3665
                           register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3666
                           my_off_t prev_block)
3463
3667
{
3464
 
  uint32_t a_length,t_length,nod_flag;
 
3668
  uint a_length,t_length,nod_flag;
3465
3669
  my_off_t filepos,key_file_length;
3466
 
  unsigned char *anc_buff,*lastkey;
 
3670
  uchar *anc_buff,*lastkey;
3467
3671
  MI_KEY_PARAM s_temp;
3468
3672
  MI_INFO *info;
3469
3673
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
3470
3674
  SORT_INFO *sort_info= sort_param->sort_info;
3471
3675
  MI_CHECK *param=sort_info->param;
 
3676
  DBUG_ENTER("sort_insert_key");
3472
3677
 
3473
3678
  anc_buff=key_block->buff;
3474
3679
  info=sort_info->info;
3482
3687
    if (key_block == sort_info->key_block_end)
3483
3688
    {
3484
3689
      mi_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks");
3485
 
      return(1);
 
3690
      DBUG_RETURN(1);
3486
3691
    }
3487
3692
    a_length=2+nod_flag;
3488
3693
    key_block->end_pos=anc_buff+2;
3496
3701
    _mi_kpointer(info,key_block->end_pos,prev_block);
3497
3702
 
3498
3703
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
 
                                (unsigned char*) 0,lastkey,lastkey,key,
 
3704
                                (uchar*) 0,lastkey,lastkey,key,
3500
3705
                                 &s_temp);
3501
3706
  (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
3707
  a_length+=t_length;
3504
3709
  key_block->end_pos+=t_length;
3505
3710
  if (a_length <= keyinfo->block_length)
3506
3711
  {
3507
 
    _mi_move_key(keyinfo,key_block->lastkey,key);
 
3712
    VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
3713
    key_block->last_length=a_length-t_length;
3509
 
    return(0);
 
3714
    DBUG_RETURN(0);
3510
3715
  }
3511
3716
 
3512
3717
        /* Fill block with end-zero and write filled block */
3513
3718
  mi_putint(anc_buff,key_block->last_length,nod_flag);
3514
 
  memset(anc_buff+key_block->last_length, 0,
3515
 
         keyinfo->block_length - key_block->last_length);
 
3719
  bzero((uchar*) anc_buff+key_block->last_length,
 
3720
        keyinfo->block_length- key_block->last_length);
3516
3721
  key_file_length=info->state->key_file_length;
3517
3722
  if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3518
 
    return(1);
 
3723
    DBUG_RETURN(1);
3519
3724
 
3520
3725
  /* If we read the page from the key cache, we have to write it back to it */
3521
3726
  if (key_file_length == info->state->key_file_length)
3522
3727
  {
3523
3728
    if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3524
 
      return(1);
 
3729
      DBUG_RETURN(1);
3525
3730
  }
3526
 
  else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
 
3731
  else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
3732
                     (uint) keyinfo->block_length,filepos, param->myf_rw))
3528
 
    return(1);
 
3733
    DBUG_RETURN(1);
 
3734
  DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3529
3735
 
3530
3736
        /* Write separator-key to block in next level */
3531
3737
  if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3532
 
    return(1);
 
3738
    DBUG_RETURN(1);
3533
3739
 
3534
3740
        /* clear old block and write new key in it */
3535
3741
  key_block->inited=0;
3536
 
  return(sort_insert_key(sort_param, key_block,key,prev_block));
 
3742
  DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3537
3743
} /* sort_insert_key */
3538
3744
 
3539
3745
 
3541
3747
 
3542
3748
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3543
3749
{
3544
 
  uint32_t i;
 
3750
  uint i;
3545
3751
  int old_file,error;
3546
 
  unsigned char *key;
 
3752
  uchar *key;
3547
3753
  SORT_INFO *sort_info=sort_param->sort_info;
3548
3754
  MI_CHECK *param=sort_info->param;
3549
3755
  MI_INFO *info=sort_info->info;
 
3756
  DBUG_ENTER("sort_delete_record");
3550
3757
 
3551
3758
  if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3552
3759
  {
3553
3760
    mi_check_print_error(param,
3554
3761
                         "Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3555
 
    return(1);
 
3762
    DBUG_RETURN(1);
3556
3763
  }
3557
3764
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3558
3765
  {
3559
3766
    mi_check_print_error(param,
3560
3767
                         "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'myisamchk --safe-recover' to fix it\n",stderr);;
3561
 
    return(1);
 
3768
    DBUG_RETURN(1);
3562
3769
  }
3563
3770
 
3564
3771
  old_file=info->dfile;
3571
3778
    {
3572
3779
      mi_check_print_error(param,"Can't read record to be removed");
3573
3780
      info->dfile=old_file;
3574
 
      return(1);
 
3781
      DBUG_RETURN(1);
3575
3782
    }
3576
3783
 
3577
3784
    for (i=0 ; i < sort_info->current_key ; i++)
3578
3785
    {
3579
 
      uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
 
3786
      uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
3787
      if (_mi_ck_delete(info,i,key,key_length))
3581
3788
      {
3582
3789
        mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3583
3790
        info->dfile=old_file;
3584
 
        return(1);
 
3791
        DBUG_RETURN(1);
3585
3792
      }
3586
3793
    }
3587
3794
    if (sort_param->calc_checksum)
3590
3797
  error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3591
3798
  info->dfile=old_file;                         /* restore actual value */
3592
3799
  info->state->records--;
3593
 
  return(error);
 
3800
  DBUG_RETURN(error);
3594
3801
} /* sort_delete_record */
3595
3802
 
3596
3803
        /* Fix all pending blocks and flush everything to disk */
3597
3804
 
3598
3805
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3599
3806
{
3600
 
  uint32_t nod_flag,length;
 
3807
  uint nod_flag,length;
3601
3808
  my_off_t filepos,key_file_length;
3602
3809
  SORT_KEY_BLOCKS *key_block;
3603
3810
  SORT_INFO *sort_info= sort_param->sort_info;
3604
3811
  myf myf_rw=sort_info->param->myf_rw;
3605
3812
  MI_INFO *info=sort_info->info;
3606
3813
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
 
3814
  DBUG_ENTER("flush_pending_blocks");
3607
3815
 
3608
3816
  filepos= HA_OFFSET_ERROR;                     /* if empty file */
3609
3817
  nod_flag=0;
3614
3822
    if (nod_flag)
3615
3823
      _mi_kpointer(info,key_block->end_pos,filepos);
3616
3824
    key_file_length=info->state->key_file_length;
3617
 
    memset(key_block->buff+length, 0, keyinfo->block_length-length);
 
3825
    bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3618
3826
    if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3619
 
      return(1);
 
3827
      DBUG_RETURN(1);
3620
3828
 
3621
3829
    /* If we read the page from the key cache, we have to write it back */
3622
3830
    if (key_file_length == info->state->key_file_length)
3623
3831
    {
3624
3832
      if (_mi_write_keypage(info, keyinfo, filepos,
3625
3833
                            DFLT_INIT_HITS, key_block->buff))
3626
 
        return(1);
 
3834
        DBUG_RETURN(1);
3627
3835
    }
3628
 
    else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
 
3836
    else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
3837
                       (uint) keyinfo->block_length,filepos, myf_rw))
3630
 
      return(1);
 
3838
      DBUG_RETURN(1);
 
3839
    DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3631
3840
    nod_flag=1;
3632
3841
  }
3633
3842
  info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3634
 
  return(0);
 
3843
  DBUG_RETURN(0);
3635
3844
} /* flush_pending_blocks */
3636
3845
 
3637
3846
        /* alloc space and pointers for key_blocks */
3638
3847
 
3639
 
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3640
 
                                         uint32_t buffer_length)
 
3848
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
3849
                                         uint buffer_length)
3641
3850
{
3642
 
  register uint32_t i;
 
3851
  register uint i;
3643
3852
  SORT_KEY_BLOCKS *block;
 
3853
  DBUG_ENTER("alloc_key_blocks");
3644
3854
 
3645
3855
  if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3646
3856
                                            buffer_length+IO_SIZE)*blocks,
3652
3862
  for (i=0 ; i < blocks ; i++)
3653
3863
  {
3654
3864
    block[i].inited=0;
3655
 
    block[i].buff=(unsigned char*) (block+blocks)+(buffer_length+IO_SIZE)*i;
 
3865
    block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
3656
3866
  }
3657
 
  return(block);
 
3867
  DBUG_RETURN(block);
3658
3868
} /* alloc_key_blocks */
3659
3869
 
3660
3870
 
3682
3892
  MI_COLUMNDEF *recdef,*rec,*end;
3683
3893
  MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
3894
  MI_STATUS_INFO status_info;
3685
 
  uint32_t unpack,key_parts;
 
3895
  uint unpack,key_parts;
3686
3896
  ha_rows max_records;
3687
 
  uint64_t file_length,tmp_length;
 
3897
  ulonglong file_length,tmp_length;
3688
3898
  MI_CREATE_INFO create_info;
 
3899
  DBUG_ENTER("recreate_table");
3689
3900
 
3690
3901
  error=1;                                      /* Default error */
3691
3902
  info= **org_info;
3695
3906
  unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3696
3907
    (param->testflag & T_UNPACK);
3697
3908
  if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3698
 
    return(0);
3699
 
  memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
 
3909
    DBUG_RETURN(0);
 
3910
  memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
 
3911
         (size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3700
3912
 
3701
3913
  key_parts= share.base.all_key_parts;
3702
3914
  if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
3915
                                       (key_parts+share.base.keys))))
3704
3916
  {
3705
 
    my_afree((unsigned char*) keyinfo);
3706
 
    return(1);
 
3917
    my_afree((uchar*) keyinfo);
 
3918
    DBUG_RETURN(1);
3707
3919
  }
3708
3920
  if (!(recdef=(MI_COLUMNDEF*)
3709
3921
        my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3710
3922
  {
3711
 
    my_afree((unsigned char*) keyinfo);
3712
 
    my_afree((unsigned char*) keysegs);
3713
 
    return(1);
 
3923
    my_afree((uchar*) keyinfo);
 
3924
    my_afree((uchar*) keysegs);
 
3925
    DBUG_RETURN(1);
3714
3926
  }
3715
3927
  if (!(uniquedef=(MI_UNIQUEDEF*)
3716
3928
        my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3717
3929
  {
3718
 
    my_afree((unsigned char*) recdef);
3719
 
    my_afree((unsigned char*) keyinfo);
3720
 
    my_afree((unsigned char*) keysegs);
3721
 
    return(1);
 
3930
    my_afree((uchar*) recdef);
 
3931
    my_afree((uchar*) keyinfo);
 
3932
    my_afree((uchar*) keysegs);
 
3933
    DBUG_RETURN(1);
3722
3934
  }
3723
3935
 
3724
3936
  /* Copy the column definitions */
3725
 
  memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
 
3937
  memcpy((uchar*) recdef,(uchar*) share.rec,
 
3938
         (size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3726
3939
  for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3727
3940
  {
3728
3941
    if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3733
3946
  }
3734
3947
 
3735
3948
  /* Change the new key to point at the saved key segments */
3736
 
  memcpy(keysegs,share.keyparts,
3737
 
         sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
3738
 
                            share.state.header.uniques));
 
3949
  memcpy((uchar*) keysegs,(uchar*) share.keyparts,
 
3950
         (size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
 
3951
                                      share.state.header.uniques)));
3739
3952
  keyseg=keysegs;
3740
3953
  for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3741
3954
  {
3750
3963
 
3751
3964
  /* Copy the unique definitions and change them to point at the new key
3752
3965
     segments*/
3753
 
  memcpy(uniquedef,share.uniqueinfo,
3754
 
         sizeof(MI_UNIQUEDEF)*(share.state.header.uniques));
 
3966
  memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
 
3967
         (size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3755
3968
  for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3756
3969
       u_ptr != u_end ; u_ptr++)
3757
3970
  {
3769
3982
    (param->testflag & T_UNPACK);
3770
3983
  share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3771
3984
 
3772
 
  file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
 
3985
  file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3773
3986
  tmp_length= file_length+file_length/10;
3774
3987
  set_if_bigger(file_length,param->max_data_file_length);
3775
3988
  set_if_bigger(file_length,tmp_length);
3776
 
  set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
 
3989
  set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
3777
3990
 
3778
 
  mi_close(*org_info);
3779
 
  memset(&create_info, 0, sizeof(create_info));
3780
 
  create_info.max_rows=cmax(max_records,share.base.records);
 
3991
  VOID(mi_close(*org_info));
 
3992
  bzero((char*) &create_info,sizeof(create_info));
 
3993
  create_info.max_rows=max(max_records,share.base.records);
3781
3994
  create_info.reloc_rows=share.base.reloc;
3782
3995
  create_info.old_options=(share.options |
3783
3996
                           (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3791
4004
    Allow for creating an auto_increment key. This has an effect only if
3792
4005
    an auto_increment key exists in the original table.
3793
4006
  */
3794
 
  create_info.with_auto_increment= true;
 
4007
  create_info.with_auto_increment= TRUE;
3795
4008
  /* We don't have to handle symlinks here because we are using
3796
4009
     HA_DONT_TOUCH_DATA */
3797
4010
  if (mi_create(filename,
3816
4029
  }
3817
4030
  /* We are modifing */
3818
4031
  (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
 
  _mi_readinfo(*org_info,F_WRLCK,0);
 
4032
  VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
4033
  (*org_info)->state->records=info.state->records;
3821
4034
  if (share.state.create_time)
3822
4035
    (*org_info)->s->state.create_time=share.state.create_time;
3832
4045
    goto end;
3833
4046
  error=0;
3834
4047
end:
3835
 
  my_afree((unsigned char*) uniquedef);
3836
 
  my_afree((unsigned char*) keyinfo);
3837
 
  my_afree((unsigned char*) recdef);
3838
 
  my_afree((unsigned char*) keysegs);
3839
 
  return(error);
 
4048
  my_afree((uchar*) uniquedef);
 
4049
  my_afree((uchar*) keyinfo);
 
4050
  my_afree((uchar*) recdef);
 
4051
  my_afree((uchar*) keysegs);
 
4052
  DBUG_RETURN(error);
3840
4053
}
3841
4054
 
3842
4055
 
3843
4056
        /* write suffix to data file if neaded */
3844
4057
 
3845
 
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
 
4058
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3846
4059
{
3847
4060
  MI_INFO *info=sort_info->info;
3848
4061
 
3849
4062
  if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3850
4063
  {
3851
 
    unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
 
    memset(buff, 0, sizeof(buff));
 
4064
    uchar buff[MEMMAP_EXTRA_MARGIN];
 
4065
    bzero(buff,sizeof(buff));
3853
4066
    if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3854
4067
    {
3855
4068
      mi_check_print_error(sort_info->param,
3863
4076
 
3864
4077
        /* Update state and myisamchk_time of indexfile */
3865
4078
 
3866
 
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
 
4079
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3867
4080
{
3868
4081
  MYISAM_SHARE *share=info->s;
3869
4082
 
3874
4087
  }
3875
4088
  if (update & UPDATE_STAT)
3876
4089
  {
3877
 
    uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
 
4090
    uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
4091
    share->state.rec_per_key_rows=info->state->records;
3879
4092
    share->state.changed&= ~STATE_NOT_ANALYZED;
3880
4093
    if (info->state->records)
3908
4121
  }
3909
4122
  {                                             /* Force update of status */
3910
4123
    int error;
3911
 
    uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
 
4124
    uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
4125
    share->r_locks= share->w_locks= share->tot_locks= 0;
3913
4126
    error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
4127
    share->r_locks=r_locks;
3936
4149
        */
3937
4150
 
3938
4151
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3939
 
                               bool repair_only)
 
4152
                               my_bool repair_only)
3940
4153
{
3941
 
  unsigned char *record= 0;
 
4154
  uchar *record= 0;
 
4155
  DBUG_ENTER("update_auto_increment_key");
3942
4156
 
3943
4157
  if (!info->s->base.auto_key ||
3944
4158
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3947
4161
      mi_check_print_info(param,
3948
4162
                          "Table: %s doesn't have an auto increment key\n",
3949
4163
                          param->isam_file_name);
3950
 
    return;
 
4164
    DBUG_VOID_RETURN;
3951
4165
  }
3952
4166
  if (!(param->testflag & T_SILENT) &&
3953
4167
      !(param->testflag & T_REP))
3959
4173
  if (!mi_alloc_rec_buff(info, -1, &record))
3960
4174
  {
3961
4175
    mi_check_print_error(param,"Not enough memory for extra record");
3962
 
    return;
 
4176
    DBUG_VOID_RETURN;
3963
4177
  }
3964
4178
 
3965
4179
  mi_extra(info,HA_EXTRA_KEYREAD,0);
3968
4182
    if (my_errno != HA_ERR_END_OF_FILE)
3969
4183
    {
3970
4184
      mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
 
      free(mi_get_rec_buff_ptr(info, record));
 
4185
      my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
4186
      mi_check_print_error(param,"%d when reading last record",my_errno);
3973
 
      return;
 
4187
      DBUG_VOID_RETURN;
3974
4188
    }
3975
4189
    if (!repair_only)
3976
4190
      info->s->state.auto_increment=param->auto_increment_value;
3977
4191
  }
3978
4192
  else
3979
4193
  {
3980
 
    uint64_t auto_increment= retrieve_auto_increment(info, record);
 
4194
    ulonglong auto_increment= retrieve_auto_increment(info, record);
3981
4195
    set_if_bigger(info->s->state.auto_increment,auto_increment);
3982
4196
    if (!repair_only)
3983
4197
      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3984
4198
  }
3985
4199
  mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
 
  free(mi_get_rec_buff_ptr(info, record));
 
4200
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4201
  update_state_info(param, info, UPDATE_AUTO_INC);
3988
 
  return;
 
4202
  DBUG_VOID_RETURN;
3989
4203
}
3990
4204
 
3991
4205
 
4041
4255
*/
4042
4256
 
4043
4257
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4044
 
                      uint64_t *unique, uint64_t *notnull,
4045
 
                      uint64_t records)
 
4258
                      ulonglong *unique, ulonglong *notnull,
 
4259
                      ulonglong records)
4046
4260
{
4047
 
  uint64_t count=0,tmp, unique_tuples;
4048
 
  uint64_t tuples= records;
4049
 
  uint32_t parts;
 
4261
  ulonglong count=0,tmp, unique_tuples;
 
4262
  ulonglong tuples= records;
 
4263
  uint parts;
4050
4264
  for (parts=0 ; parts < keyinfo->keysegs  ; parts++)
4051
4265
  {
4052
4266
    count+=unique[parts];
4074
4288
      let's ensure it is not
4075
4289
    */
4076
4290
    set_if_bigger(tmp,1);
4077
 
    if (tmp >= (uint64_t) ~(ulong) 0)
4078
 
      tmp=(uint64_t) ~(ulong) 0;
 
4291
    if (tmp >= (ulonglong) ~(ulong) 0)
 
4292
      tmp=(ulonglong) ~(ulong) 0;
4079
4293
 
4080
4294
    *rec_per_key_part=(ulong) tmp;
4081
4295
    rec_per_key_part++;
4083
4297
}
4084
4298
 
4085
4299
 
4086
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
 
4300
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4087
4301
{
4088
4302
  ha_checksum crc;
4089
 
  const unsigned char *end=buf+length;
 
4303
  const uchar *end=buf+length;
4090
4304
  for (crc=0; buf != end; buf++)
4091
 
    crc=((crc << 1) + *((unsigned char*) buf)) +
 
4305
    crc=((crc << 1) + *((uchar*) buf)) +
4092
4306
      test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4093
4307
  return crc;
4094
4308
}
4095
4309
 
4096
 
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
 
4310
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4097
4311
{
4098
 
  uint32_t key_maxlength=key->maxlength;
4099
 
  return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4100
 
          ((uint64_t) rows * key_maxlength >
4101
 
           (uint64_t) myisam_max_temp_length));
 
4312
  uint key_maxlength=key->maxlength;
 
4313
  return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
 
4314
          ((ulonglong) rows * key_maxlength >
 
4315
           (ulonglong) myisam_max_temp_length));
4102
4316
}
4103
4317
 
4104
4318
/*
4114
4328
{
4115
4329
  MYISAM_SHARE *share=info->s;
4116
4330
  MI_KEYDEF    *key=share->keyinfo;
4117
 
  uint32_t          i;
 
4331
  uint          i;
4118
4332
 
4119
 
  assert(info->state->records == 0 &&
 
4333
  DBUG_ASSERT(info->state->records == 0 &&
4120
4334
              (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4121
4335
  for (i=0 ; i < share->base.keys ; i++,key++)
4122
4336
  {
4123
 
    if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
 
4337
    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4124
4338
        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4125
4339
    {
4126
4340
      mi_clear_key_active(share->state.key_map, i);
4131
4345
 
4132
4346
 
4133
4347
/*
4134
 
  Return true if we can use repair by sorting
 
4348
  Return TRUE if we can use repair by sorting
4135
4349
  One can set the force argument to force to use sorting
4136
4350
  even if the temporary file would be quite big!
4137
4351
*/
4138
4352
 
4139
 
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4140
 
                            uint64_t key_map, bool force)
 
4353
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
 
4354
                            ulonglong key_map, my_bool force)
4141
4355
{
4142
4356
  MYISAM_SHARE *share=info->s;
4143
4357
  MI_KEYDEF *key=share->keyinfo;
4144
 
  uint32_t i;
 
4358
  uint i;
4145
4359
 
4146
4360
  /*
4147
4361
    mi_repair_by_sort only works if we have at least one key. If we don't
4148
4362
    have any keys, we should use the normal repair.
4149
4363
  */
4150
4364
  if (! mi_is_any_key_active(key_map))
4151
 
    return false;                               /* Can't use sort */
 
4365
    return FALSE;                               /* Can't use sort */
4152
4366
  for (i=0 ; i < share->base.keys ; i++,key++)
4153
4367
  {
4154
4368
    if (!force && mi_too_big_key_for_sort(key,rows))
4155
 
      return false;
 
4369
      return FALSE;
4156
4370
  }
4157
 
  return true;
 
4371
  return TRUE;
4158
4372
}
4159
4373
 
4160
4374
 
4172
4386
      sort_info->new_data_file_type = STATIC_RECORD;
4173
4387
 
4174
4388
    /* Set delete_function for sort_delete_record() */
4175
 
    memcpy(&tmp, share, sizeof(*share));
 
4389
    memcpy((char*) &tmp, share, sizeof(*share));
4176
4390
    tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4177
4391
    mi_setup_functions(&tmp);
4178
4392
    share->delete_record=tmp.delete_record;