~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_check.c

  • Committer: Monty Taylor
  • Date: 2008-07-05 17:07:46 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705170746-8aq11u9fuwtfwy85
Removed my_alarm. Made my_lock only do the non-alarm version. Moved my_lock to MyISAM where it belongs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
  only. And it is sufficient to calculate the checksum once only.
41
41
*/
42
42
 
43
 
#include "myisamdef.h"
 
43
#include "ftdefs.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
#include "rt_index.h"
 
54
 
 
55
#ifndef USE_RAID
 
56
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
 
57
#define my_raid_delete(A,B,C) my_delete(A,B)
 
58
#endif
 
59
 
 
60
        /* Functions defined in this file */
 
61
 
 
62
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
61
63
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);
 
64
                     my_off_t page, uchar *buff, ha_rows *keys,
 
65
                     ha_checksum *key_checksum, uint level);
 
66
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
67
static ha_checksum calc_checksum(ha_rows count);
66
68
static int writekeys(MI_SORT_PARAM *sort_param);
67
69
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
68
70
                          my_off_t pagepos, File new_file);
69
71
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
 
72
static int sort_ft_key_read(MI_SORT_PARAM *sort_param,void *key);
70
73
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
71
74
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
 
75
static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a);
72
76
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
77
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
74
 
                                unsigned char *key);
 
78
                                uchar *key);
75
79
static int sort_insert_key(MI_SORT_PARAM  *sort_param,
76
80
                           register SORT_KEY_BLOCKS *key_block,
77
 
                           unsigned char *key, my_off_t prev_block);
 
81
                           uchar *key, my_off_t prev_block);
78
82
static int sort_delete_record(MI_SORT_PARAM *sort_param);
79
83
/*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);
 
84
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
85
                                          uint buffer_length);
 
86
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
83
87
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
84
88
 
85
89
void myisamchk_init(MI_CHECK *param)
86
90
{
87
 
  memset(param, 0, sizeof(*param));
 
91
  bzero((uchar*) param,sizeof(*param));
88
92
  param->opt_follow_links=1;
89
 
  param->keys_in_use= ~(uint64_t) 0;
 
93
  param->keys_in_use= ~(ulonglong) 0;
90
94
  param->search_after_block=HA_OFFSET_ERROR;
91
95
  param->auto_increment_value= 0;
92
96
  param->use_buffers=USE_BUFFER_INIT;
97
101
  param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
98
102
  param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
99
103
  param->start_check_pos=0;
100
 
  param->max_record_length= INT64_MAX;
 
104
  param->max_record_length= LONGLONG_MAX;
101
105
  param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
102
106
  param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
103
107
}
117
121
  if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
118
122
  {
119
123
    /* Don't count this as a real warning, as check can correct this ! */
120
 
    uint32_t save=param->warning_printed;
 
124
    uint save=param->warning_printed;
121
125
    mi_check_print_warning(param,
122
126
                           share->state.open_count==1 ? 
123
127
                           "%d client is using or hasn't closed the table properly" : 
132
136
 
133
137
        /* Check delete links */
134
138
 
135
 
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
 
139
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
136
140
{
137
141
  register ha_rows i;
138
 
  uint32_t delete_link_length;
 
142
  uint delete_link_length;
139
143
  my_off_t empty, next_link, old_link= 0;
140
144
  char buff[22],buff2[22];
 
145
  DBUG_ENTER("chk_del");
141
146
 
142
147
  param->record_checksum=0;
143
148
  delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
162
167
    for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
163
168
    {
164
169
      if (*killed_ptr(param))
165
 
        return(1);
 
170
        DBUG_RETURN(1);
166
171
      if (test_flag & T_VERBOSE)
167
172
        printf(" %9s",llstr(next_link,buff));
168
173
      if (next_link >= info->state->data_file_length)
169
174
        goto wrong;
170
 
      if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
 
175
      if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
171
176
                   next_link,MYF(MY_NABP)))
172
177
      {
173
178
        if (test_flag & T_VERBOSE) puts("");
174
179
        mi_check_print_error(param,"Can't read delete-link at filepos: %s",
175
180
                    llstr(next_link,buff));
176
 
        return(1);
 
181
        DBUG_RETURN(1);
177
182
      }
178
183
      if (*buff != '\0')
179
184
      {
198
203
      else
199
204
      {
200
205
        param->record_checksum+=(ha_checksum) next_link;
201
 
        next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
 
206
        next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
202
207
        empty+=info->s->base.pack_reclength;
203
208
      }
204
209
    }
227
232
      goto wrong;
228
233
    }
229
234
  }
230
 
  return(0);
 
235
  DBUG_RETURN(0);
231
236
 
232
237
wrong:
233
238
  param->testflag|=T_RETRY_WITHOUT_QUICK;
234
239
  if (test_flag & T_VERBOSE) puts("");
235
240
  mi_check_print_error(param,"record delete-link-chain corrupted");
236
 
  return(1);
 
241
  DBUG_RETURN(1);
237
242
} /* chk_del */
238
243
 
239
244
 
240
245
        /* Check delete links in index file */
241
246
 
242
 
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
 
247
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
243
248
{
244
249
  my_off_t next_link;
245
 
  uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
 
250
  uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
246
251
  ha_rows records;
247
252
  char llbuff[21], llbuff2[21];
248
 
  unsigned char *buff;
 
253
  uchar *buff;
 
254
  DBUG_ENTER("check_k_link");
 
255
  DBUG_PRINT("enter", ("block_size: %u", block_size));
249
256
 
250
257
  if (param->testflag & T_VERBOSE)
251
258
    printf("block_size %4u:", block_size); /* purecov: tested */
255
262
  while (next_link != HA_OFFSET_ERROR && records > 0)
256
263
  {
257
264
    if (*killed_ptr(param))
258
 
      return(1);
 
265
      DBUG_RETURN(1);
259
266
    if (param->testflag & T_VERBOSE)
260
267
      printf("%16s",llstr(next_link,llbuff));
261
268
 
267
274
                           "key block size: %u  file_length: %s",
268
275
                           llstr(next_link, llbuff), block_size,
269
276
                           llstr(info->state->key_file_length, llbuff2));
270
 
      return(1);
 
277
      DBUG_RETURN(1);
271
278
      /* purecov: end */
272
279
    }
273
280
 
278
285
      mi_check_print_error(param, "Mis-aligned key block: %s  "
279
286
                           "minimum key block length: %u",
280
287
                           llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
281
 
      return(1);
 
288
      DBUG_RETURN(1);
282
289
      /* purecov: end */
283
290
    }
284
291
 
289
296
    */
290
297
    if (!(buff=key_cache_read(info->s->key_cache,
291
298
                              info->s->kfile, next_link, DFLT_INIT_HITS,
292
 
                              (unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
 
299
                              (uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
300
                              MI_MIN_KEY_BLOCK_LENGTH, 1)))
294
301
    {
295
302
      /* purecov: begin tested */
296
303
      mi_check_print_error(param, "key cache read error for block: %s",
297
304
                           llstr(next_link,llbuff));
298
 
      return(1);
 
305
      DBUG_RETURN(1);
299
306
      /* purecov: end */
300
307
    }
301
308
    next_link=mi_sizekorr(buff);
309
316
    else
310
317
      puts("");
311
318
  }
312
 
  return (next_link != HA_OFFSET_ERROR);
 
319
  DBUG_RETURN (next_link != HA_OFFSET_ERROR);
313
320
} /* check_k_link */
314
321
 
315
322
 
320
327
  int error=0;
321
328
  register my_off_t skr,size;
322
329
  char buff[22],buff2[22];
 
330
  DBUG_ENTER("chk_size");
323
331
 
324
332
  if (!(param->testflag & T_SILENT)) puts("- check file-size");
325
333
 
345
353
  }
346
354
  if (!(param->testflag & T_VERY_SILENT) &&
347
355
      ! (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)
 
356
      ulonglong2double(info->state->key_file_length) >
 
357
      ulonglong2double(info->s->base.margin_key_file_length)*0.9)
350
358
    mi_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
351
359
                           llstr(info->state->key_file_length,buff),
352
360
                           llstr(info->s->base.max_key_file_length-1,buff));
379
387
  }
380
388
  if (!(param->testflag & T_VERY_SILENT) &&
381
389
      !(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))
 
390
      ulonglong2double(info->state->data_file_length) >
 
391
      (ulonglong2double(info->s->base.max_data_file_length)*0.9))
384
392
    mi_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
385
393
                           llstr(info->state->data_file_length,buff),
386
394
                           llstr(info->s->base.max_data_file_length-1,buff2));
387
 
  return(error);
 
395
  DBUG_RETURN(error);
388
396
} /* chk_size */
389
397
 
390
398
 
392
400
 
393
401
int chk_key(MI_CHECK *param, register MI_INFO *info)
394
402
{
395
 
  uint32_t key,found_keys=0,full_text_keys=0,result=0;
 
403
  uint key,found_keys=0,full_text_keys=0,result=0;
396
404
  ha_rows keys;
397
405
  ha_checksum old_record_checksum,init_checksum;
398
406
  my_off_t all_keydata,all_totaldata,key_totlength,length;
400
408
  MYISAM_SHARE *share=info->s;
401
409
  MI_KEYDEF *keyinfo;
402
410
  char buff[22],buff2[22];
 
411
  DBUG_ENTER("chk_key");
403
412
 
404
413
  if (!(param->testflag & T_SILENT))
405
414
    puts("- check key delete-chain");
410
419
    {
411
420
      if (param->testflag & T_VERBOSE) puts("");
412
421
      mi_check_print_error(param,"key delete-link-chain corrupted");
413
 
      return(-1);
 
422
      DBUG_RETURN(-1);
414
423
    }
415
424
 
416
425
  if (!(param->testflag & T_SILENT)) puts("- check index reference");
430
439
    if (! mi_is_key_active(share->state.key_map, key))
431
440
    {
432
441
      /* 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)),
 
442
      memcpy((char*) rec_per_key_part,
 
443
             (char*) (share->state.rec_per_key_part +
 
444
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
437
445
             keyinfo->keysegs*sizeof(*rec_per_key_part));
438
446
      continue;
439
447
    }
441
449
 
442
450
    param->record_checksum=init_checksum;
443
451
    
444
 
    memset(&param->unique_count, 0, sizeof(param->unique_count));
445
 
    memset(&param->notnull_count, 0, sizeof(param->notnull_count));
 
452
    bzero((char*) &param->unique_count,sizeof(param->unique_count));
 
453
    bzero((char*) &param->notnull_count,sizeof(param->notnull_count));
446
454
 
447
455
    if ((!(param->testflag & T_SILENT)))
448
456
      printf ("- check data record references index: %d\n",key+1);
449
 
    if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0))
 
457
    if (keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL))
 
458
      full_text_keys++;
 
459
    if (share->state.key_root[key] == HA_OFFSET_ERROR &&
 
460
        (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
450
461
      goto do_stat;
451
462
    if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
452
463
                           DFLT_INIT_HITS,info->buff,0))
454
465
      mi_check_print_error(param,"Can't read indexpage from filepos: %s",
455
466
                  llstr(share->state.key_root[key],buff));
456
467
      if (!(param->testflag & T_INFO))
457
 
        return(-1);
 
468
        DBUG_RETURN(-1);
458
469
      result= -1;
459
470
      continue;
460
471
    }
465
476
    param->max_level=0;
466
477
    if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
467
478
                  &keys, param->key_crc+key,1))
468
 
      return(-1);
469
 
    if(!(0))
 
479
      DBUG_RETURN(-1);
 
480
    if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
470
481
    {
471
482
      if (keys != info->state->records)
472
483
      {
473
484
        mi_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
474
485
                    llstr(info->state->records,buff2));
475
486
        if (!(param->testflag & T_INFO))
476
 
        return(-1);
 
487
        DBUG_RETURN(-1);
477
488
        result= -1;
478
489
        continue;
479
490
      }
490
501
        else
491
502
          mi_check_print_error(param,"Key 1 doesn't point at all records");
492
503
        if (!(param->testflag & T_INFO))
493
 
          return(-1);
 
504
          DBUG_RETURN(-1);
494
505
        result= -1;
495
506
        continue;
496
507
      }
498
509
    if ((uint) share->base.auto_key -1 == key)
499
510
    {
500
511
      /* Check that auto_increment key is bigger than max key value */
501
 
      uint64_t auto_increment;
 
512
      ulonglong auto_increment;
502
513
      info->lastinx=key;
503
514
      _mi_read_key_record(info, 0L, info->rec_buff);
504
515
      auto_increment= retrieve_auto_increment(info, info->rec_buff);
519
530
 
520
531
      /* Check that there isn't a row with auto_increment = 0 in the table */
521
532
      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,
 
533
      bzero(info->lastkey,keyinfo->seg->length);
 
534
      if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
524
535
                   (key_part_map)1, HA_READ_KEY_EXACT))
525
536
      {
526
537
        /* Don't count this as a real warning, as myisamchk can't correct it */
527
 
        uint32_t save=param->warning_printed;
 
538
        uint save=param->warning_printed;
528
539
        mi_check_print_warning(param, "Found row where the auto_increment "
529
540
                               "column has the value 0");
530
541
        param->warning_printed=save;
547
558
      update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
548
559
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
549
560
                       param->notnull_count: NULL, 
550
 
                       (uint64_t)info->state->records);
 
561
                       (ulonglong)info->state->records);
551
562
  }
552
563
  if (param->testflag & T_INFO)
553
564
  {
562
573
      puts("");
563
574
  }
564
575
  if (param->key_file_blocks != info->state->key_file_length &&
565
 
      param->keys_in_use != ~(uint64_t) 0)
 
576
      param->keys_in_use != ~(ulonglong) 0)
566
577
    mi_check_print_warning(param, "Some data are unreferenced in keyfile");
567
578
  if (found_keys != full_text_keys)
568
579
    param->record_checksum=old_record_checksum-init_checksum;   /* Remove delete links */
569
580
  else
570
581
    param->record_checksum=0;
571
 
  return(result);
 
582
  DBUG_RETURN(result);
572
583
} /* chk_key */
573
584
 
574
585
 
575
586
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)
 
587
                     my_off_t page, uchar *buff, ha_rows *keys,
 
588
                     ha_checksum *key_checksum, uint level)
578
589
{
579
590
  char llbuff[22],llbuff2[22];
 
591
  DBUG_ENTER("chk_index_down");
580
592
 
581
593
  /* Key blocks must lay within the key file length entirely. */
582
594
  if (page + keyinfo->block_length > info->state->key_file_length)
618
630
  if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
619
631
    goto err;
620
632
 
621
 
  return(0);
 
633
  DBUG_RETURN(0);
622
634
 
623
635
  /* purecov: begin tested */
624
636
err:
625
 
  return(1);
 
637
  DBUG_RETURN(1);
626
638
  /* purecov: end */
627
639
}
628
640
 
643
655
*/
644
656
 
645
657
static
646
 
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
647
 
                                    unsigned char *key)
 
658
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull,
 
659
                                    uchar *key)
648
660
{
649
 
  uint32_t first_null, kp;
 
661
  uint first_null, kp;
650
662
  first_null= ha_find_null(keyseg, key) - keyseg;
651
663
  /*
652
664
    All prefix tuples that don't include keypart_{first_null} are not-null
683
695
*/
684
696
 
685
697
static
686
 
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
687
 
                                  unsigned char *prev_key, unsigned char *last_key)
 
698
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull,
 
699
                                  uchar *prev_key, uchar *last_key)
688
700
{
689
 
  uint32_t diffs[2];
690
 
  uint32_t first_null_seg, kp;
 
701
  uint diffs[2];
 
702
  uint first_null_seg, kp;
691
703
  HA_KEYSEG *seg;
692
704
 
693
705
  /* 
719
731
        /* Check if index is ok */
720
732
 
721
733
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)
 
734
                     my_off_t page, uchar *buff, ha_rows *keys,
 
735
                     ha_checksum *key_checksum, uint level)
724
736
{
725
737
  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;
 
738
  uint used_length,comp_flag,nod_flag,key_length=0;
 
739
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
740
  my_off_t next_page,record;
729
741
  char llbuff[22];
730
 
  uint32_t diff_pos[2];
731
 
 
732
 
  if (!(temp_buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
 
742
  uint diff_pos[2];
 
743
  DBUG_ENTER("chk_index");
 
744
  DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
 
745
 
 
746
  /* TODO: implement appropriate check for RTree keys */
 
747
  if (keyinfo->flag & HA_SPATIAL)
 
748
    DBUG_RETURN(0);
 
749
 
 
750
  if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
733
751
  {
734
752
    mi_check_print_error(param,"Not enough memory for keyblock");
735
 
    return(-1);
 
753
    DBUG_RETURN(-1);
736
754
  }
737
755
 
738
756
  if (keyinfo->flag & HA_NOSAME)
759
777
  {
760
778
    if (*killed_ptr(param))
761
779
      goto err;
762
 
    memcpy(info->lastkey,key,key_length);
 
780
    memcpy((char*) info->lastkey,(char*) key,key_length);
763
781
    info->lastkey_length=key_length;
764
782
    if (nod_flag)
765
783
    {
772
790
    if (keypos >= endpos ||
773
791
        (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
774
792
      break;
775
 
    assert(key_length <= sizeof(key));
 
793
    DBUG_ASSERT(key_length <= sizeof(key));
776
794
    if (keypos > endpos)
777
795
    {
778
796
      mi_check_print_error(param,"Wrong key block length at page: %s",llstr(page,llbuff));
782
800
        (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
783
801
                         comp_flag, diff_pos)) >=0)
784
802
    {
 
803
      DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length);
 
804
      DBUG_DUMP("new",(uchar*) key, key_length);
 
805
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
 
806
 
785
807
      if (comp_flag & SEARCH_FIND && flag == 0)
786
808
        mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff));
787
809
      else
811
833
                                         key);
812
834
      }
813
835
    }
814
 
    (*key_checksum)+= mi_byte_checksum((unsigned char*) key,
 
836
    (*key_checksum)+= mi_byte_checksum((uchar*) key,
815
837
                                       key_length- info->s->rec_reflength);
816
838
    record= _mi_dpos(info,0,key+key_length);
 
839
    if (keyinfo->flag & HA_FULLTEXT) /* special handling for ft2 */
 
840
    {
 
841
      uint off;
 
842
      int  subkeys;
 
843
      get_key_full_length_rdonly(off, key);
 
844
      subkeys=ft_sintXkorr(key+off);
 
845
      if (subkeys < 0)
 
846
      {
 
847
        ha_rows tmp_keys=0;
 
848
        if (chk_index_down(param,info,&info->s->ft2_keyinfo,record,
 
849
                           temp_buff,&tmp_keys,key_checksum,1))
 
850
          goto err;
 
851
        if (tmp_keys + subkeys)
 
852
        {
 
853
          mi_check_print_error(param,
 
854
                               "Number of words in the 2nd level tree "
 
855
                               "does not match the number in the header. "
 
856
                               "Parent word in on the page %s, offset %u",
 
857
                               llstr(page,llbuff), (uint) (old_keypos-buff));
 
858
          goto err;
 
859
        }
 
860
        (*keys)+=tmp_keys-1;
 
861
        continue;
 
862
      }
 
863
      /* fall through */
 
864
    }
817
865
    if (record >= info->state->data_file_length)
818
866
    {
 
867
#ifndef DBUG_OFF
 
868
      char llbuff2[22], llbuff3[22];
 
869
#endif
819
870
      mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
 
871
      DBUG_PRINT("test",("page: %s  record: %s  filelength: %s",
 
872
                         llstr(page,llbuff),llstr(record,llbuff2),
 
873
                         llstr(info->state->data_file_length,llbuff3)));
 
874
      DBUG_DUMP("key",(uchar*) key,key_length);
 
875
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
820
876
      goto err;
821
877
    }
822
878
    param->record_checksum+=(ha_checksum) record;
827
883
                llstr(page,llbuff), used_length, (keypos - buff));
828
884
    goto err;
829
885
  }
830
 
  my_afree((unsigned char*) temp_buff);
831
 
  return(0);
 
886
  my_afree((uchar*) temp_buff);
 
887
  DBUG_RETURN(0);
832
888
 err:
833
 
  my_afree((unsigned char*) temp_buff);
834
 
  return(1);
 
889
  my_afree((uchar*) temp_buff);
 
890
  DBUG_RETURN(1);
835
891
} /* chk_index */
836
892
 
837
893
 
839
895
 
840
896
static ha_checksum calc_checksum(ha_rows count)
841
897
{
842
 
  uint64_t sum,a,b;
 
898
  ulonglong sum,a,b;
 
899
  DBUG_ENTER("calc_checksum");
843
900
 
844
901
  sum=0;
845
902
  a=count; b=count+1;
853
910
      sum+=a;
854
911
    a<<=1; b>>=1;
855
912
  }
856
 
  return((ha_checksum) sum);
 
913
  DBUG_PRINT("exit",("sum: %lx",(ulong) sum));
 
914
  DBUG_RETURN((ha_checksum) sum);
857
915
} /* calc_checksum */
858
916
 
859
917
 
860
918
        /* Calc length of key in normal isam */
861
919
 
862
 
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
 
920
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
863
921
{
864
 
  uint32_t length;
 
922
  uint length;
865
923
  HA_KEYSEG *keyseg;
 
924
  DBUG_ENTER("isam_key_length");
866
925
 
867
926
  length= info->s->rec_reflength;
868
927
  for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++)
869
928
    length+= keyseg->length;
870
929
 
871
 
  return(length);
 
930
  DBUG_PRINT("exit",("length: %d",length));
 
931
  DBUG_RETURN(length);
872
932
} /* key_length */
873
933
 
874
934
 
881
941
  ha_rows records, del_blocks;
882
942
  my_off_t used, empty, pos, splits, start_recpos= 0,
883
943
           del_length, link_used, start_block;
884
 
  unsigned char *record= NULL, *to= NULL;
 
944
  uchar *record= NULL, *to= NULL;
885
945
  char llbuff[22],llbuff2[22],llbuff3[22];
886
946
  ha_checksum intern_record_checksum;
887
947
  ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
888
 
  bool static_row_size;
 
948
  my_bool static_row_size;
889
949
  MI_KEYDEF *keyinfo;
890
950
  MI_BLOCK_INFO block_info;
 
951
  DBUG_ENTER("chk_data_link");
891
952
 
892
953
  if (!(param->testflag & T_SILENT))
893
954
  {
900
961
  if (!mi_alloc_rec_buff(info, -1, &record))
901
962
  {
902
963
    mi_check_print_error(param,"Not enough memory for record");
903
 
    return(-1);
 
964
    DBUG_RETURN(-1);
904
965
  }
905
966
  records=del_blocks=0;
906
967
  used=link_used=splits=del_length=0;
924
985
  }
925
986
 
926
987
  pos=my_b_tell(&param->read_cache);
927
 
  memset(key_checksum, 0, info->s->base.keys * sizeof(key_checksum[0]));
 
988
  bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
928
989
  while (pos < info->state->data_file_length)
929
990
  {
930
991
    if (*killed_ptr(param))
931
992
      goto err2;
932
993
    switch (info->s->data_file_type) {
933
994
    case STATIC_RECORD:
934
 
      if (my_b_read(&param->read_cache,(unsigned char*) record,
 
995
      if (my_b_read(&param->read_cache,(uchar*) record,
935
996
                    info->s->base.pack_reclength))
936
997
        goto err;
937
998
      start_recpos=pos;
951
1012
      block_info.next_filepos=pos;
952
1013
      do
953
1014
      {
954
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) block_info.header,
 
1015
        if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header,
955
1016
                           (start_block=block_info.next_filepos),
956
1017
                           sizeof(block_info.header),
957
1018
                           (flag ? 0 : READING_NEXT) | READING_HEADER))
1055
1116
          got_error=1;
1056
1117
          break;
1057
1118
        }
1058
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) to,block_info.filepos,
 
1119
        if (_mi_read_cache(&param->read_cache,(uchar*) to,block_info.filepos,
1059
1120
                           (uint) block_info.data_len,
1060
1121
                           flag == 1 ? READING_NEXT : 0))
1061
1122
          goto err;
1116
1177
        pos=block_info.filepos+block_info.block_len;
1117
1178
      break;
1118
1179
    case COMPRESSED_RECORD:
 
1180
      if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header, pos,
 
1181
                         info->s->pack.ref_length, READING_NEXT))
 
1182
        goto err;
 
1183
      start_recpos=pos;
 
1184
      splits++;
 
1185
      VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
 
1186
                                   &info->rec_buff, -1, start_recpos));
 
1187
      pos=block_info.filepos+block_info.rec_len;
 
1188
      if (block_info.rec_len < (uint) info->s->min_pack_length ||
 
1189
          block_info.rec_len > (uint) info->s->max_pack_length)
 
1190
      {
 
1191
        mi_check_print_error(param,
 
1192
                             "Found block with wrong recordlength: %d at %s",
 
1193
                             block_info.rec_len, llstr(start_recpos,llbuff));
 
1194
        got_error=1;
 
1195
        break;
 
1196
      }
 
1197
      if (_mi_read_cache(&param->read_cache,(uchar*) info->rec_buff,
 
1198
                        block_info.filepos, block_info.rec_len, READING_NEXT))
 
1199
        goto err;
 
1200
      if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
 
1201
                              info->rec_buff, block_info.rec_len))
 
1202
      {
 
1203
        mi_check_print_error(param,"Found wrong record at %s",
 
1204
                             llstr(start_recpos,llbuff));
 
1205
        got_error=1;
 
1206
      }
 
1207
      if (static_row_size)
 
1208
        param->glob_crc+= mi_static_checksum(info,record);
 
1209
      else
 
1210
        param->glob_crc+= mi_checksum(info,record);
 
1211
      link_used+= (block_info.filepos - start_recpos);
 
1212
      used+= (pos-start_recpos);
1119
1213
    case BLOCK_RECORD:
1120
1214
      assert(0);                                /* Impossible */
1121
1215
    } /* switch */
1125
1219
      records++;
1126
1220
      if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1127
1221
      {
1128
 
        printf("%s\r", llstr(records,llbuff)); fflush(stdout);
 
1222
        printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1129
1223
      }
1130
1224
 
1131
1225
      /* Check if keys match the record */
1135
1229
      {
1136
1230
        if (mi_is_key_active(info->s->state.key_map, key))
1137
1231
        {
 
1232
          if(!(keyinfo->flag & HA_FULLTEXT))
1138
1233
          {
1139
 
            uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
 
1234
            uint key_length=_mi_make_key(info,key,info->lastkey,record,
1140
1235
                                         start_recpos);
1141
1236
            if (extend)
1142
1237
            {
1144
1239
                 concurrent threads when running myisamchk
1145
1240
              */
1146
1241
              int search_result=
 
1242
#ifdef HAVE_RTREE_KEYS
 
1243
                (keyinfo->flag & HA_SPATIAL) ?
 
1244
                rtree_find_first(info, key, info->lastkey, key_length,
 
1245
                                 MBR_EQUAL | MBR_DATA) : 
 
1246
#endif
1147
1247
                _mi_search(info,keyinfo,info->lastkey,key_length,
1148
1248
                           SEARCH_SAME, info->s->state.key_root[key]);
1149
1249
              if (search_result)
1156
1256
              }
1157
1257
            }
1158
1258
            else
1159
 
              key_checksum[key]+=mi_byte_checksum((unsigned char*) info->lastkey,
 
1259
              key_checksum[key]+=mi_byte_checksum((uchar*) info->lastkey,
1160
1260
                                                  key_length);
1161
1261
          }
1162
1262
        }
1172
1272
  }
1173
1273
  if (param->testflag & T_WRITE_LOOP)
1174
1274
  {
1175
 
    fputs("          \r",stdout); fflush(stdout);
 
1275
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1176
1276
  }
1177
1277
  if (records != info->state->records)
1178
1278
  {
1199
1299
  {
1200
1300
    for (key=0 ; key < info->s->base.keys;  key++)
1201
1301
    {
1202
 
      if (key_checksum[key] != param->key_crc[key])
 
1302
      if (key_checksum[key] != param->key_crc[key] &&
 
1303
          !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1203
1304
      {
1204
1305
        mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
1205
1306
                    key+1);
1249
1350
      printf("Records:%18s    M.recordlength:%9lu   Packed:%14.0f%%\n",
1250
1351
             llstr(records,llbuff), (long)((used-link_used)/records),
1251
1352
             (info->s->base.blobs ? 0.0 :
1252
 
              (uint64_t2double((uint64_t) info->s->base.reclength*records)-
 
1353
              (ulonglong2double((ulonglong) info->s->base.reclength*records)-
1253
1354
               my_off_t2double(used))/
1254
 
              uint64_t2double((uint64_t) info->s->base.reclength*records)*100.0));
 
1355
              ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1255
1356
      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)/
 
1357
             (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0),
 
1358
             (!records ? 100 : (int) (ulonglong2double(del_length+empty)/
1258
1359
                                      my_off_t2double(used)*100.0)),
1259
 
             uint64_t2double(splits - del_blocks) / records);
 
1360
             ulonglong2double(splits - del_blocks) / records);
1260
1361
    }
1261
1362
    printf("Record blocks:%12s    Delete blocks:%10s\n",
1262
1363
           llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1265
1366
    printf("Lost space:   %12s    Linkdata:     %10s\n",
1266
1367
           llstr(empty,llbuff),llstr(link_used,llbuff2));
1267
1368
  }
1268
 
  free(mi_get_rec_buff_ptr(info, record));
1269
 
  return (error);
 
1369
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
1370
  DBUG_RETURN (error);
1270
1371
 err:
1271
1372
  mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1272
1373
 err2:
1273
 
  free(mi_get_rec_buff_ptr(info, record));
 
1374
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1274
1375
  param->testflag|=T_RETRY_WITHOUT_QUICK;
1275
 
  return(1);
 
1376
  DBUG_RETURN(1);
1276
1377
} /* chk_data_link */
1277
1378
 
1278
1379
 
1329
1430
    then recrate all indexes.
1330
1431
*/
1331
1432
 
1332
 
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
 
1433
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1333
1434
{
1334
1435
  MYISAM_SHARE *share= info->s;
1335
1436
  MI_STATE_INFO *state= &share->state;
1336
 
  uint32_t i;
 
1437
  uint i;
1337
1438
  int error;
 
1439
  DBUG_ENTER("mi_drop_all_indexes");
1338
1440
 
1339
1441
  /*
1340
1442
    If any of the disabled indexes has a key block assigned, we must
1345
1447
  */
1346
1448
  if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
1347
1449
  {
 
1450
    DBUG_PRINT("repair", ("creating missing indexes"));
1348
1451
    for (i= 0; i < share->base.keys; i++)
1349
1452
    {
 
1453
      DBUG_PRINT("repair", ("index #: %u  key_root: 0x%lx  active: %d",
 
1454
                            i, (long) state->key_root[i],
 
1455
                            mi_is_key_active(state->key_map, i)));
1350
1456
      if ((state->key_root[i] != HA_OFFSET_ERROR) &&
1351
1457
          !mi_is_key_active(state->key_map, i))
1352
1458
      {
1355
1461
          We would lose its block(s) if would just recreate it.
1356
1462
          So we need to drop and recreate all indexes.
1357
1463
        */
 
1464
        DBUG_PRINT("repair", ("nonempty and disabled: recreate all"));
1358
1465
        break;
1359
1466
      }
1360
1467
    }
1365
1472
        Flush dirty blocks of this index file from key cache and remove
1366
1473
        all blocks of this index file from key cache.
1367
1474
      */
 
1475
      DBUG_PRINT("repair", ("all disabled are empty: create missing"));
1368
1476
      error= flush_key_blocks(share->key_cache, share->kfile,
1369
1477
                              FLUSH_FORCE_WRITE);
1370
1478
      goto end;
1375
1483
      disabled indexes and enable them.
1376
1484
    */
1377
1485
    mi_clear_all_keys_active(state->key_map);
 
1486
    DBUG_PRINT("repair", ("declared all indexes disabled"));
1378
1487
  }
1379
1488
 
1380
1489
  /* Remove all key blocks of this index file from key cache. */
1393
1502
  /* Reset index file length to end of index file header. */
1394
1503
  info->state->key_file_length= share->base.keystart;
1395
1504
 
 
1505
  DBUG_PRINT("repair", ("dropped all indexes"));
1396
1506
  /* error= 0; set by last (error= flush_key_bocks()). */
1397
1507
 
1398
1508
 end:
1399
 
  return(error);
 
1509
  DBUG_RETURN(error);
1400
1510
}
1401
1511
 
1402
1512
 
1414
1524
  char llbuff[22],llbuff2[22];
1415
1525
  SORT_INFO sort_info;
1416
1526
  MI_SORT_PARAM sort_param;
 
1527
  DBUG_ENTER("mi_repair");
1417
1528
 
1418
 
  memset(&sort_info, 0, sizeof(sort_info));
1419
 
  memset(&sort_param, 0, sizeof(sort_param));
 
1529
  bzero((char *)&sort_info, sizeof(sort_info));
 
1530
  bzero((char *)&sort_param, sizeof(sort_param));
1420
1531
  start_records=info->state->records;
1421
1532
  new_header_length=(param->testflag & T_UNPACK) ? 0L :
1422
1533
    share->pack.header_length;
1435
1546
    param->testflag|=T_CALC_CHECKSUM;
1436
1547
 
1437
1548
  if (!param->using_global_keycache)
1438
 
    init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
 
                   param->use_buffers, 0, 0);
 
1549
    VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
 
1550
                        param->use_buffers, 0, 0));
1440
1551
 
1441
1552
  if (init_io_cache(&param->read_cache,info->dfile,
1442
1553
                    (uint) param->read_buffer_length,
1443
1554
                    READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1444
1555
  {
1445
 
    memset(&info->rec_cache, 0, sizeof(info->rec_cache));
 
1556
    bzero(&info->rec_cache,sizeof(info->rec_cache));
1446
1557
    goto err;
1447
1558
  }
1448
1559
  if (!rep_quick)
1461
1572
  if (!rep_quick)
1462
1573
  {
1463
1574
    /* 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)
 
1575
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
1576
                                           share->data_file_name, "",
 
1577
                                           DATA_TMP_EXT, 2+4),
 
1578
                                 0,param->tmpfile_createflag,
 
1579
                                 share->base.raid_type,
 
1580
                                 share->base.raid_chunks,
 
1581
                                 share->base.raid_chunksize,
 
1582
                                 MYF(0))) < 0)
1469
1583
    {
1470
1584
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
1471
 
                           param->temp_filename);
 
1585
                           param->temp_filename);
1472
1586
      goto err;
1473
1587
    }
1474
1588
    if (new_header_length &&
1475
1589
        filecopy(param,new_file,info->dfile,0L,new_header_length,
1476
 
                 "datafile-header"))
 
1590
                 "datafile-header"))
1477
1591
      goto err;
1478
1592
    info->s->state.dellink= HA_OFFSET_ERROR;
1479
1593
    info->rec_cache.file=new_file;
1491
1605
  param->read_cache.end_of_file=sort_info.filelength=
1492
1606
    my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1493
1607
  sort_info.dupp=0;
1494
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
1608
  sort_param.fix_datafile= (my_bool) (! rep_quick);
1495
1609
  sort_param.master=1;
1496
1610
  sort_info.max_records= ~(ha_rows) 0;
1497
1611
 
1508
1622
  /* This function always recreates all enabled indexes. */
1509
1623
  if (param->testflag & T_CREATE_MISSING_KEYS)
1510
1624
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
1511
 
  mi_drop_all_indexes(param, info, true);
 
1625
  mi_drop_all_indexes(param, info, TRUE);
1512
1626
 
1513
1627
  lock_memory(param);                   /* Everything is alloced */
1514
1628
 
1519
1633
    {
1520
1634
      if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1521
1635
        goto err;
 
1636
      DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
1522
1637
      mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
1523
1638
                          info->errkey+1,
1524
1639
                          llstr(sort_param.start_recpos,llbuff),
1525
1640
                          llstr(info->dupp_key_pos,llbuff2));
1526
1641
      if (param->testflag & T_VERBOSE)
1527
1642
      {
1528
 
        _mi_make_key(info,(uint) info->errkey,info->lastkey,
1529
 
                     sort_param.record,0L);
 
1643
        VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
 
1644
                          sort_param.record,0L));
 
1645
        _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
 
1646
                      USE_WHOLE_KEY);
1530
1647
      }
1531
1648
      sort_info.dupp++;
1532
1649
      if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1540
1657
    if (sort_write_record(&sort_param))
1541
1658
      goto err;
1542
1659
  }
1543
 
  if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
 
1660
  if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1544
1661
      flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1545
1662
    goto err;
1546
1663
 
1547
1664
  if (param->testflag & T_WRITE_LOOP)
1548
1665
  {
1549
 
    fputs("          \r",stdout); fflush(stdout);
 
1666
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1550
1667
  }
1551
1668
  if (ftruncate(share->kfile, info->state->key_file_length))
1552
1669
  {
1628
1745
                  llstr(sort_param.start_recpos,llbuff));
1629
1746
    if (new_file >= 0)
1630
1747
    {
1631
 
      my_close(new_file,MYF(0));
1632
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
1748
      VOID(my_close(new_file,MYF(0)));
 
1749
      VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
 
1750
                          MYF(MY_WME)));
1633
1751
      info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1634
1752
    }
1635
1753
    mi_mark_crashed_on_repair(info);
1636
1754
  }
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);
 
1755
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
1756
                            MYF(MY_ALLOW_ZERO_PTR));
 
1757
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
1758
          MYF(MY_ALLOW_ZERO_PTR));
 
1759
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
1760
  VOID(end_io_cache(&param->read_cache));
1649
1761
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1650
 
  end_io_cache(&info->rec_cache);
 
1762
  VOID(end_io_cache(&info->rec_cache));
1651
1763
  got_error|=flush_blocks(param, share->key_cache, share->kfile);
1652
1764
  if (!got_error && param->testflag & T_UNPACK)
1653
1765
  {
1654
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
1766
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1655
1767
    share->pack.header_length=0;
1656
1768
    share->data_file_type=sort_info.new_data_file_type;
1657
1769
  }
1658
1770
  share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1659
1771
                          STATE_NOT_ANALYZED);
1660
 
  return(got_error);
 
1772
  DBUG_RETURN(got_error);
1661
1773
}
1662
1774
 
1663
1775
 
1665
1777
 
1666
1778
static int writekeys(MI_SORT_PARAM *sort_param)
1667
1779
{
1668
 
  register uint32_t i;
1669
 
  unsigned char    *key;
 
1780
  register uint i;
 
1781
  uchar    *key;
1670
1782
  MI_INFO  *info=   sort_param->sort_info->info;
1671
 
  unsigned char    *buff=   sort_param->record;
 
1783
  uchar    *buff=   sort_param->record;
1672
1784
  my_off_t filepos= sort_param->filepos;
 
1785
  DBUG_ENTER("writekeys");
1673
1786
 
1674
1787
  key=info->lastkey+info->s->base.max_key_length;
1675
1788
  for (i=0 ; i < info->s->base.keys ; i++)
1676
1789
  {
1677
1790
    if (mi_is_key_active(info->s->state.key_map, i))
1678
1791
    {
1679
 
      {
1680
 
        uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1792
      if (info->s->keyinfo[i].flag & HA_FULLTEXT )
 
1793
      {
 
1794
        if (_mi_ft_add(info, i, key, buff, filepos))
 
1795
          goto err;
 
1796
      }
 
1797
#ifdef HAVE_SPATIAL
 
1798
      else if (info->s->keyinfo[i].flag & HA_SPATIAL)
 
1799
      {
 
1800
        uint key_length=_mi_make_key(info,i,key,buff,filepos);
 
1801
        if (rtree_insert(info, i, key, key_length))
 
1802
          goto err;
 
1803
      }
 
1804
#endif /*HAVE_SPATIAL*/
 
1805
      else
 
1806
      {
 
1807
        uint key_length=_mi_make_key(info,i,key,buff,filepos);
1681
1808
        if (_mi_ck_write(info,i,key,key_length))
1682
1809
          goto err;
1683
1810
      }
1684
1811
    }
1685
1812
  }
1686
 
  return(0);
 
1813
  DBUG_RETURN(0);
1687
1814
 
1688
1815
 err:
1689
1816
  if (my_errno == HA_ERR_FOUND_DUPP_KEY)
1693
1820
    {
1694
1821
      if (mi_is_key_active(info->s->state.key_map, i))
1695
1822
      {
 
1823
        if (info->s->keyinfo[i].flag & HA_FULLTEXT)
 
1824
        {
 
1825
          if (_mi_ft_del(info,i, key,buff,filepos))
 
1826
            break;
 
1827
        }
 
1828
        else
1696
1829
        {
1697
 
          uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1830
          uint key_length=_mi_make_key(info,i,key,buff,filepos);
1698
1831
          if (_mi_ck_delete(info,i,key,key_length))
1699
1832
            break;
1700
1833
        }
1704
1837
  /* Remove checksum that was added to glob_crc in sort_get_next_record */
1705
1838
  if (sort_param->calc_checksum)
1706
1839
    sort_param->sort_info->param->glob_crc-= info->checksum;
1707
 
  return(-1);
 
1840
  DBUG_PRINT("error",("errno: %d",my_errno));
 
1841
  DBUG_RETURN(-1);
1708
1842
} /* writekeys */
1709
1843
 
1710
1844
 
1711
1845
        /* Change all key-pointers that points to a records */
1712
1846
 
1713
 
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1714
 
              my_off_t newpos, uint32_t prot_key)
 
1847
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
 
1848
              my_off_t newpos, uint prot_key)
1715
1849
{
1716
 
  register uint32_t i;
1717
 
  unsigned char *key;
1718
 
  uint32_t key_length;
 
1850
  register uint i;
 
1851
  uchar *key;
 
1852
  uint key_length;
 
1853
  DBUG_ENTER("movepoint");
1719
1854
 
1720
1855
  key=info->lastkey+info->s->base.max_key_length;
1721
1856
  for (i=0 ; i < info->s->base.keys; i++)
1725
1860
      key_length=_mi_make_key(info,i,key,record,oldpos);
1726
1861
      if (info->s->keyinfo[i].flag & HA_NOSAME)
1727
1862
      {                                 /* Change pointer direct */
1728
 
        uint32_t nod_flag;
 
1863
        uint nod_flag;
1729
1864
        MI_KEYDEF *keyinfo;
1730
1865
        keyinfo=info->s->keyinfo+i;
1731
1866
        if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1732
1867
                       (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1733
1868
                       info->s->state.key_root[i]))
1734
 
          return(-1);
 
1869
          DBUG_RETURN(-1);
1735
1870
        nod_flag=mi_test_if_nod(info->buff);
1736
1871
        _mi_dpointer(info,info->int_keypos-nod_flag-
1737
1872
                     info->s->rec_reflength,newpos);
1738
1873
        if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1739
1874
                              DFLT_INIT_HITS,info->buff))
1740
 
          return(-1);
 
1875
          DBUG_RETURN(-1);
1741
1876
      }
1742
1877
      else
1743
1878
      {                                 /* Change old key to new */
1744
1879
        if (_mi_ck_delete(info,i,key,key_length))
1745
 
          return(-1);
 
1880
          DBUG_RETURN(-1);
1746
1881
        key_length=_mi_make_key(info,i,key,record,newpos);
1747
1882
        if (_mi_ck_write(info,i,key,key_length))
1748
 
          return(-1);
 
1883
          DBUG_RETURN(-1);
1749
1884
      }
1750
1885
    }
1751
1886
  }
1752
 
  return(0);
 
1887
  DBUG_RETURN(0);
1753
1888
} /* movepoint */
1754
1889
 
1755
1890
 
1788
1923
 
1789
1924
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1790
1925
{
1791
 
  register uint32_t key;
 
1926
  register uint key;
1792
1927
  register MI_KEYDEF *keyinfo;
1793
1928
  File new_file;
1794
1929
  my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1795
 
  uint32_t r_locks,w_locks;
 
1930
  uint r_locks,w_locks;
1796
1931
  int old_lock;
1797
1932
  MYISAM_SHARE *share=info->s;
1798
1933
  MI_STATE_INFO old_state;
 
1934
  DBUG_ENTER("mi_sort_index");
1799
1935
 
1800
1936
  /* cannot sort index files with R-tree indexes */
1801
1937
  for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1802
1938
       key++,keyinfo++)
 
1939
    if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
 
1940
      DBUG_RETURN(0);
1803
1941
 
1804
1942
  if (!(param->testflag & T_SILENT))
1805
1943
    printf("- Sorting index for MyISAM-table '%s'\n",name);
1812
1950
  {
1813
1951
    mi_check_print_error(param,"Can't create new tempfile: '%s'",
1814
1952
                         param->temp_filename);
1815
 
    return(-1);
 
1953
    DBUG_RETURN(-1);
1816
1954
  }
1817
1955
  if (filecopy(param, new_file,share->kfile,0L,
1818
1956
               (ulong) share->base.keystart, "headerblock"))
1848
1986
        /* Put same locks as old file */
1849
1987
  share->r_locks= share->w_locks= share->tot_locks= 0;
1850
1988
  (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1851
 
  my_close(share->kfile,MYF(MY_WME));
 
1989
  VOID(my_close(share->kfile,MYF(MY_WME)));
1852
1990
  share->kfile = -1;
1853
 
  my_close(new_file,MYF(MY_WME));
 
1991
  VOID(my_close(new_file,MYF(MY_WME)));
1854
1992
  if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1855
1993
                        MYF(0)) ||
1856
1994
      mi_open_keyfile(share))
1871
2009
    info->s->state.key_del[key]=  HA_OFFSET_ERROR;
1872
2010
 
1873
2011
  info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
1874
 
  return(0);
 
2012
  DBUG_RETURN(0);
1875
2013
 
1876
2014
err:
1877
 
  my_close(new_file,MYF(MY_WME));
 
2015
  VOID(my_close(new_file,MYF(MY_WME)));
1878
2016
err2:
1879
 
  my_delete(param->temp_filename,MYF(MY_WME));
1880
 
  return(-1);
 
2017
  VOID(my_delete(param->temp_filename,MYF(MY_WME)));
 
2018
  DBUG_RETURN(-1);
1881
2019
} /* mi_sort_index */
1882
2020
 
1883
2021
 
1886
2024
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1887
2025
                          my_off_t pagepos, File new_file)
1888
2026
{
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];
 
2027
  uint length,nod_flag,used_length, key_length;
 
2028
  uchar *buff,*keypos,*endpos;
 
2029
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1892
2030
  my_off_t new_page_pos,next_page;
1893
2031
  char llbuff[22];
 
2032
  DBUG_ENTER("sort_one_index");
1894
2033
 
 
2034
  /* cannot walk over R-tree indices */
 
2035
  DBUG_ASSERT(keyinfo->key_alg != HA_KEY_ALG_RTREE);
1895
2036
  new_page_pos=param->new_file_pos;
1896
2037
  param->new_file_pos+=keyinfo->block_length;
1897
2038
 
1898
 
  if (!(buff=(unsigned char*) my_alloca((uint) keyinfo->block_length)))
 
2039
  if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1899
2040
  {
1900
2041
    mi_check_print_error(param,"Not enough memory for key block");
1901
 
    return(-1);
 
2042
    DBUG_RETURN(-1);
1902
2043
  }
1903
2044
  if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
1904
2045
  {
1906
2047
                llstr(pagepos,llbuff));
1907
2048
    goto err;
1908
2049
  }
1909
 
  if ((nod_flag=mi_test_if_nod(buff)))
 
2050
  if ((nod_flag=mi_test_if_nod(buff)) || keyinfo->flag & HA_FULLTEXT)
1910
2051
  {
1911
2052
    used_length=mi_getint(buff);
1912
2053
    keypos=buff+2+nod_flag;
1919
2060
        _mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */
1920
2061
        if (sort_one_index(param,info,keyinfo,next_page,new_file))
1921
2062
        {
 
2063
          DBUG_PRINT("error",
 
2064
                     ("From page: %ld, keyoffset: %lu  used_length: %d",
 
2065
                      (ulong) pagepos, (ulong) (keypos - buff),
 
2066
                      (int) used_length));
 
2067
          DBUG_DUMP("buff",(uchar*) buff,used_length);
1922
2068
          goto err;
1923
2069
        }
1924
2070
      }
1925
2071
      if (keypos >= endpos ||
1926
2072
          (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
1927
2073
        break;
1928
 
      assert(keypos <= endpos);
 
2074
      DBUG_ASSERT(keypos <= endpos);
 
2075
      if (keyinfo->flag & HA_FULLTEXT)
 
2076
      {
 
2077
        uint off;
 
2078
        int  subkeys;
 
2079
        get_key_full_length_rdonly(off, key);
 
2080
        subkeys=ft_sintXkorr(key+off);
 
2081
        if (subkeys < 0)
 
2082
        {
 
2083
          next_page= _mi_dpos(info,0,key+key_length);
 
2084
          _mi_dpointer(info,keypos-nod_flag-info->s->rec_reflength,
 
2085
                       param->new_file_pos); /* Save new pos */
 
2086
          if (sort_one_index(param,info,&info->s->ft2_keyinfo,
 
2087
                             next_page,new_file))
 
2088
            goto err;
 
2089
        }
 
2090
      }
1929
2091
    }
1930
2092
  }
1931
2093
 
1932
2094
  /* Fill block with zero and write it to the new index file */
1933
2095
  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,
 
2096
  bzero((uchar*) buff+length,keyinfo->block_length-length);
 
2097
  if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1936
2098
                new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1937
2099
  {
1938
2100
    mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1939
2101
    goto err;
1940
2102
  }
1941
 
  my_afree((unsigned char*) buff);
1942
 
  return(0);
 
2103
  my_afree((uchar*) buff);
 
2104
  DBUG_RETURN(0);
1943
2105
err:
1944
 
  my_afree((unsigned char*) buff);
1945
 
  return(1);
 
2106
  my_afree((uchar*) buff);
 
2107
  DBUG_RETURN(1);
1946
2108
} /* sort_one_index */
1947
2109
 
1948
2110
 
1957
2119
 
1958
2120
int change_to_newfile(const char * filename, const char * old_ext,
1959
2121
                      const char * new_ext,
1960
 
                      uint32_t raid_chunks __attribute__((unused)),
 
2122
                      uint raid_chunks __attribute__((unused)),
1961
2123
                      myf MyFlags)
1962
2124
{
1963
2125
  char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
 
2126
#ifdef USE_RAID
 
2127
  if (raid_chunks)
 
2128
    return my_raid_redel(fn_format(old_filename,filename,"",old_ext,2+4),
 
2129
                         fn_format(new_filename,filename,"",new_ext,2+4),
 
2130
                         raid_chunks,
 
2131
                         MYF(MY_WME | MY_LINK_WARNING | MyFlags));
 
2132
#endif
1964
2133
  /* Get real path to filename */
1965
2134
  (void) fn_format(old_filename,filename,"",old_ext,2+4+32);
1966
2135
  return my_redel(old_filename,
1969
2138
} /* change_to_newfile */
1970
2139
 
1971
2140
 
 
2141
        /* Locks a whole file */
 
2142
        /* Gives an error-message if file can't be locked */
 
2143
 
 
2144
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
 
2145
              const char *filetype, const char *filename)
 
2146
{
 
2147
  if (my_lock(file,lock_type,start,F_TO_EOF,
 
2148
              param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
 
2149
              MYF(MY_SEEK_NOT_DONE |  MY_DONT_WAIT)))
 
2150
  {
 
2151
    mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename);
 
2152
    param->error_printed=2;             /* Don't give that data is crashed */
 
2153
    return 1;
 
2154
  }
 
2155
  return 0;
 
2156
} /* lock_file */
 
2157
 
1972
2158
 
1973
2159
        /* Copy a block between two files */
1974
2160
 
1977
2163
{
1978
2164
  char tmp_buff[IO_SIZE],*buff;
1979
2165
  ulong buff_length;
 
2166
  DBUG_ENTER("filecopy");
1980
2167
 
1981
 
  buff_length=(ulong) cmin(param->write_buffer_length,length);
 
2168
  buff_length=(ulong) min(param->write_buffer_length,length);
1982
2169
  if (!(buff=my_malloc(buff_length,MYF(0))))
1983
2170
  {
1984
2171
    buff=tmp_buff; buff_length=IO_SIZE;
1985
2172
  }
1986
2173
 
1987
 
  my_seek(from,start,MY_SEEK_SET,MYF(0));
 
2174
  VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1988
2175
  while (length > buff_length)
1989
2176
  {
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))
 
2177
    if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
 
2178
        my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1992
2179
      goto err;
1993
2180
    length-= buff_length;
1994
2181
  }
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))
 
2182
  if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
 
2183
      my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1997
2184
    goto err;
1998
2185
  if (buff != tmp_buff)
1999
 
    free(buff);
2000
 
  return(0);
 
2186
    my_free(buff,MYF(0));
 
2187
  DBUG_RETURN(0);
2001
2188
err:
2002
2189
  if (buff != tmp_buff)
2003
 
    free(buff);
 
2190
    my_free(buff,MYF(0));
2004
2191
  mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2005
2192
                       type,my_errno);
2006
 
  return(1);
 
2193
  DBUG_RETURN(1);
2007
2194
}
2008
2195
 
2009
2196
 
2026
2213
                      const char * name, int rep_quick)
2027
2214
{
2028
2215
  int got_error;
2029
 
  uint32_t i;
 
2216
  uint i;
2030
2217
  ulong length;
2031
2218
  ha_rows start_records;
2032
2219
  my_off_t new_header_length,del;
2037
2224
  ulong   *rec_per_key_part;
2038
2225
  char llbuff[22];
2039
2226
  SORT_INFO sort_info;
2040
 
  uint64_t key_map= 0;
 
2227
  ulonglong key_map= 0;
 
2228
  DBUG_ENTER("mi_repair_by_sort");
2041
2229
 
2042
2230
  start_records=info->state->records;
2043
2231
  got_error=1;
2054
2242
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2055
2243
    param->testflag|=T_CALC_CHECKSUM;
2056
2244
 
2057
 
  memset(&sort_info, 0, sizeof(sort_info));
2058
 
  memset(&sort_param, 0, sizeof(sort_param));
 
2245
  bzero((char*)&sort_info,sizeof(sort_info));
 
2246
  bzero((char *)&sort_param, sizeof(sort_param));
2059
2247
  if (!(sort_info.key_block=
2060
2248
        alloc_key_blocks(param,
2061
2249
                         (uint) param->sort_key_blocks,
2082
2270
  if (!rep_quick)
2083
2271
  {
2084
2272
    /* 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)
 
2273
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2274
                                           share->data_file_name, "",
 
2275
                                           DATA_TMP_EXT, 2+4),
 
2276
                                 0,param->tmpfile_createflag,
 
2277
                                 share->base.raid_type,
 
2278
                                 share->base.raid_chunks,
 
2279
                                 share->base.raid_chunksize,
 
2280
                                 MYF(0))) < 0)
2090
2281
    {
2091
2282
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2092
 
                           param->temp_filename);
 
2283
                           param->temp_filename);
2093
2284
      goto err;
2094
2285
    }
2095
2286
    if (new_header_length &&
2108
2299
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2109
2300
 
2110
2301
  /* Optionally drop indexes and optionally modify the key_map. */
2111
 
  mi_drop_all_indexes(param, info, false);
 
2302
  mi_drop_all_indexes(param, info, FALSE);
2112
2303
  key_map= share->state.key_map;
2113
2304
  if (param->testflag & T_CREATE_MISSING_KEYS)
2114
2305
  {
2127
2318
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2128
2319
 
2129
2320
  sort_param.wordlist=NULL;
 
2321
  init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
2130
2322
 
2131
2323
  if (share->data_file_type == DYNAMIC_RECORD)
2132
 
    length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
 
2324
    length=max(share->base.min_pack_length+1,share->base.min_block_length);
2133
2325
  else if (share->data_file_type == COMPRESSED_RECORD)
2134
2326
    length=share->base.min_block_length;
2135
2327
  else
2141
2333
  sort_param.lock_in_memory=lock_memory;
2142
2334
  sort_param.tmpdir=param->tmpdir;
2143
2335
  sort_param.sort_info=&sort_info;
2144
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
2336
  sort_param.fix_datafile= (my_bool) (! rep_quick);
2145
2337
  sort_param.master =1;
2146
2338
  
2147
2339
  del=info->state->del;
2163
2355
    if (! mi_is_key_active(key_map, sort_param.key))
2164
2356
    {
2165
2357
      /* 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)),
 
2358
      memcpy((char*) rec_per_key_part,
 
2359
             (char*) (share->state.rec_per_key_part +
 
2360
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2170
2361
             sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
 
2362
      DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
 
2363
                            sort_param.key));
2171
2364
      continue;
2172
2365
    }
2173
2366
 
2175
2368
      printf ("- Fixing index %d\n",sort_param.key+1);
2176
2369
    sort_param.max_pos=sort_param.pos=share->pack.header_length;
2177
2370
    keyseg=sort_param.seg;
2178
 
    memset(sort_param.unique, 0, sizeof(sort_param.unique));
 
2371
    bzero((char*) sort_param.unique,sizeof(sort_param.unique));
2179
2372
    sort_param.key_length=share->rec_reflength;
2180
2373
    for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
2181
2374
    {
2190
2383
    info->state->records=info->state->del=share->state.split=0;
2191
2384
    info->state->empty=0;
2192
2385
 
 
2386
    if (sort_param.keyinfo->flag & HA_FULLTEXT)
 
2387
    {
 
2388
      uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
 
2389
                                    sort_param.keyinfo->seg->charset->mbmaxlen;
 
2390
      sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
 
2391
      /*
 
2392
        fulltext indexes may have much more entries than the
 
2393
        number of rows in the table. We estimate the number here.
 
2394
 
 
2395
        Note, built-in parser is always nr. 0 - see ftparser_call_initializer()
 
2396
      */
 
2397
      if (sort_param.keyinfo->ftparser_nr == 0)
 
2398
      {
 
2399
        /*
 
2400
          for built-in parser the number of generated index entries
 
2401
          cannot be larger than the size of the data file divided
 
2402
          by the minimal word's length
 
2403
        */
 
2404
        sort_info.max_records=
 
2405
          (ha_rows) (sort_info.filelength/ft_min_word_len+1);
 
2406
      }
 
2407
      else
 
2408
      {
 
2409
        /*
 
2410
          for external plugin parser we cannot tell anything at all :(
 
2411
          so, we'll use all the sort memory and start from ~10 buffpeks.
 
2412
          (see _create_index_by_sort)
 
2413
        */
 
2414
        sort_info.max_records=
 
2415
          10*param->sort_buffer_length/sort_param.key_length;
 
2416
      }
 
2417
 
 
2418
      sort_param.key_read=sort_ft_key_read;
 
2419
      sort_param.key_write=sort_ft_key_write;
 
2420
    }
 
2421
    else
2193
2422
    {
2194
2423
      sort_param.key_read=sort_key_read;
2195
2424
      sort_param.key_write=sort_key_write;
2196
2425
    }
2197
2426
 
2198
2427
    if (_create_index_by_sort(&sort_param,
2199
 
                              (bool) (!(param->testflag & T_VERBOSE)),
 
2428
                              (my_bool) (!(param->testflag & T_VERBOSE)),
2200
2429
                              (uint) param->sort_buffer_length))
2201
2430
    {
2202
2431
      param->retry_repair=1;
2213
2442
      update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
2214
2443
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
2215
2444
                       sort_param.notnull: NULL,
2216
 
                       (uint64_t) info->state->records);
 
2445
                       (ulonglong) info->state->records);
2217
2446
    /* Enable this index in the permanent (not the copied) key_map. */
2218
2447
    mi_set_key_active(share->state.key_map, sort_param.key);
 
2448
    DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
2219
2449
 
2220
2450
    if (sort_param.fix_datafile)
2221
2451
    {
2251
2481
 
2252
2482
  if (param->testflag & T_WRITE_LOOP)
2253
2483
  {
2254
 
    fputs("          \r",stdout); fflush(stdout);
 
2484
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
2255
2485
  }
2256
2486
 
2257
2487
  if (rep_quick && del+sort_info.dupp != info->state->del)
2304
2534
 
2305
2535
err:
2306
2536
  got_error|= flush_blocks(param, share->key_cache, share->kfile);
2307
 
  end_io_cache(&info->rec_cache);
 
2537
  VOID(end_io_cache(&info->rec_cache));
2308
2538
  if (!got_error)
2309
2539
  {
2310
2540
    /* Replace the actual file with the temporary file */
2326
2556
      mi_check_print_error(param,"%d when fixing table",my_errno);
2327
2557
    if (new_file >= 0)
2328
2558
    {
2329
 
      my_close(new_file,MYF(0));
2330
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
2559
      VOID(my_close(new_file,MYF(0)));
 
2560
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
2561
                          MYF(MY_WME)));
2331
2562
      if (info->dfile == new_file)
2332
 
        info->dfile= -1;
 
2563
        info->dfile= -1;
2333
2564
    }
2334
2565
    mi_mark_crashed_on_repair(info);
2335
2566
  }
2337
2568
    share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2338
2569
  share->state.changed|=STATE_NOT_SORTED_PAGES;
2339
2570
 
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);
 
2571
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
2572
                            MYF(MY_ALLOW_ZERO_PTR));
 
2573
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
2574
          MYF(MY_ALLOW_ZERO_PTR));
 
2575
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
2576
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
2577
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
2578
  VOID(end_io_cache(&param->read_cache));
2352
2579
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2353
2580
  if (!got_error && (param->testflag & T_UNPACK))
2354
2581
  {
2355
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
2582
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2356
2583
    share->pack.header_length=0;
2357
2584
  }
2358
 
  return(got_error);
 
2585
  DBUG_RETURN(got_error);
2359
2586
}
2360
2587
 
2361
2588
/*
2404
2631
                        const char * name, int rep_quick)
2405
2632
{
2406
2633
  int got_error;
2407
 
  uint32_t i,key, total_key_length, istep;
 
2634
  uint i,key, total_key_length, istep;
2408
2635
  ulong rec_length;
2409
2636
  ha_rows start_records;
2410
2637
  my_off_t new_header_length,del;
2417
2644
  IO_CACHE new_data_cache; /* For non-quick repair. */
2418
2645
  IO_CACHE_SHARE io_share;
2419
2646
  SORT_INFO sort_info;
2420
 
  uint64_t key_map= 0;
 
2647
  ulonglong key_map= 0;
2421
2648
  pthread_attr_t thr_attr;
2422
2649
  ulong max_pack_reclength;
 
2650
  DBUG_ENTER("mi_repair_parallel");
2423
2651
 
2424
2652
  start_records=info->state->records;
2425
2653
  got_error=1;
2464
2692
      position 'new_header_length'.
2465
2693
    }
2466
2694
  */
2467
 
  memset(&sort_info, 0, sizeof(sort_info));
 
2695
  DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
 
2696
  bzero((char*)&sort_info,sizeof(sort_info));
2468
2697
  /* Initialize pthread structures before goto err. */
2469
2698
  pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2470
2699
  pthread_cond_init(&sort_info.cond, 0);
2492
2721
  if (!rep_quick)
2493
2722
  {
2494
2723
    /* 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)
 
2724
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2725
                                           share->data_file_name, "",
 
2726
                                           DATA_TMP_EXT,
 
2727
                                           2+4),
 
2728
                                 0,param->tmpfile_createflag,
 
2729
                                 share->base.raid_type,
 
2730
                                 share->base.raid_chunks,
 
2731
                                 share->base.raid_chunksize,
 
2732
                                 MYF(0))) < 0)
2501
2733
    {
2502
2734
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2735
                           param->temp_filename);
2519
2751
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2520
2752
 
2521
2753
  /* Optionally drop indexes and optionally modify the key_map. */
2522
 
  mi_drop_all_indexes(param, info, false);
 
2754
  mi_drop_all_indexes(param, info, FALSE);
2523
2755
  key_map= share->state.key_map;
2524
2756
  if (param->testflag & T_CREATE_MISSING_KEYS)
2525
2757
  {
2537
2769
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2538
2770
 
2539
2771
  if (share->data_file_type == DYNAMIC_RECORD)
2540
 
    rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
 
2772
    rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2773
  else if (share->data_file_type == COMPRESSED_RECORD)
2542
2774
    rec_length=share->base.min_block_length;
2543
2775
  else
2590
2822
    if (! mi_is_key_active(key_map, key))
2591
2823
    {
2592
2824
      /* 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)),
 
2825
      memcpy((char*) rec_per_key_part,
 
2826
             (char*) (share->state.rec_per_key_part+
 
2827
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2597
2828
             sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2598
2829
      istep=0;
2599
2830
      continue;
2601
2832
    istep=1;
2602
2833
    if ((!(param->testflag & T_SILENT)))
2603
2834
      printf ("- Fixing index %d\n",key+1);
 
2835
    if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
 
2836
    {
 
2837
      sort_param[i].key_read=sort_ft_key_read;
 
2838
      sort_param[i].key_write=sort_ft_key_write;
 
2839
    }
 
2840
    else
2604
2841
    {
2605
2842
      sort_param[i].key_read=sort_key_read;
2606
2843
      sort_param[i].key_write=sort_key_write;
2616
2853
    sort_param[i].filepos=new_header_length;
2617
2854
    sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2618
2855
 
2619
 
    sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
 
2856
    sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2857
                           (max_pack_reclength * i));
2621
2858
    if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2622
2859
    {
2637
2874
        sort_param[i].key_length++;
2638
2875
    }
2639
2876
    total_key_length+=sort_param[i].key_length;
 
2877
 
 
2878
    if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
 
2879
    {
 
2880
      uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
 
2881
                                    sort_param[i].keyinfo->seg->charset->mbmaxlen;
 
2882
      sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
 
2883
      init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
 
2884
    }
2640
2885
  }
2641
2886
  sort_info.total_keys=i;
2642
2887
  sort_param[0].master= 1;
2643
 
  sort_param[0].fix_datafile= (bool)(! rep_quick);
 
2888
  sort_param[0].fix_datafile= (my_bool)(! rep_quick);
2644
2889
  sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM);
2645
2890
 
2646
2891
  sort_info.got_error=0;
2677
2922
    */
2678
2923
    sort_param[i].read_cache= ((rep_quick || !i) ? param->read_cache :
2679
2924
                               new_data_cache);
 
2925
    DBUG_PRINT("io_cache_share", ("thread: %u  read_cache: 0x%lx",
 
2926
                                  i, (long) &sort_param[i].read_cache));
2680
2927
 
2681
2928
    /*
2682
2929
      two approaches: the same amount of memory for each thread
2698
2945
      /* Cleanup: Detach from the share. Avoid others to be blocked. */
2699
2946
      if (io_share.total_threads)
2700
2947
        remove_io_thread(&sort_param[i].read_cache);
 
2948
      DBUG_PRINT("error", ("Cannot start a repair thread"));
2701
2949
      sort_info.got_error=1;
2702
2950
    }
2703
2951
    else
2806
3054
    the share by remove_io_thread() or it was not yet started (if the
2807
3055
    error happend before creating the thread).
2808
3056
  */
2809
 
  end_io_cache(&info->rec_cache);
 
3057
  VOID(end_io_cache(&info->rec_cache));
2810
3058
  /*
2811
3059
    Destroy the new data cache in case of non-quick repair. All slave
2812
3060
    threads did either detach from the share by remove_io_thread()
2814
3062
    creating the threads).
2815
3063
  */
2816
3064
  if (!rep_quick)
2817
 
    end_io_cache(&new_data_cache);
 
3065
    VOID(end_io_cache(&new_data_cache));
2818
3066
  if (!got_error)
2819
3067
  {
2820
3068
    /* Replace the actual file with the temporary file */
2836
3084
      mi_check_print_error(param,"%d when fixing table",my_errno);
2837
3085
    if (new_file >= 0)
2838
3086
    {
2839
 
      my_close(new_file,MYF(0));
2840
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
3087
      VOID(my_close(new_file,MYF(0)));
 
3088
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
3089
                          MYF(MY_WME)));
2841
3090
      if (info->dfile == new_file)
2842
 
        info->dfile= -1;
 
3091
        info->dfile= -1;
2843
3092
    }
2844
3093
    mi_mark_crashed_on_repair(info);
2845
3094
  }
2850
3099
  pthread_cond_destroy (&sort_info.cond);
2851
3100
  pthread_mutex_destroy(&sort_info.mutex);
2852
3101
 
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);
 
3102
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
3103
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
3104
  my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
 
3105
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
3106
  VOID(end_io_cache(&param->read_cache));
2857
3107
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
3108
  if (!got_error && (param->testflag & T_UNPACK))
2859
3109
  {
2860
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
3110
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
3111
    share->pack.header_length=0;
2862
3112
  }
2863
 
  return(got_error);
 
3113
  DBUG_RETURN(got_error);
2864
3114
}
2865
3115
 
2866
3116
        /* Read next record and return next key */
2870
3120
  int error;
2871
3121
  SORT_INFO *sort_info=sort_param->sort_info;
2872
3122
  MI_INFO *info=sort_info->info;
 
3123
  DBUG_ENTER("sort_key_read");
2873
3124
 
2874
3125
  if ((error=sort_get_next_record(sort_param)))
2875
 
    return(error);
 
3126
    DBUG_RETURN(error);
2876
3127
  if (info->state->records == sort_info->max_records)
2877
3128
  {
2878
3129
    mi_check_print_error(sort_info->param,
2879
3130
                         "Key %d - Found too many records; Can't continue",
2880
3131
                         sort_param->key+1);
2881
 
    return(1);
 
3132
    DBUG_RETURN(1);
2882
3133
  }
2883
3134
  sort_param->real_key_length=
2884
3135
    (info->s->rec_reflength+
2885
 
     _mi_make_key(info, sort_param->key, (unsigned char*) key,
 
3136
     _mi_make_key(info, sort_param->key, (uchar*) key,
2886
3137
                  sort_param->record, sort_param->filepos));
2887
3138
#ifdef HAVE_purify
2888
 
  memset(key+sort_param->real_key_length, 0,
2889
 
         (sort_param->key_length-sort_param->real_key_length));
 
3139
  bzero(key+sort_param->real_key_length,
 
3140
        (sort_param->key_length-sort_param->real_key_length));
2890
3141
#endif
2891
 
  return(sort_write_record(sort_param));
 
3142
  DBUG_RETURN(sort_write_record(sort_param));
2892
3143
} /* sort_key_read */
2893
3144
 
 
3145
static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
 
3146
{
 
3147
  int error;
 
3148
  SORT_INFO *sort_info=sort_param->sort_info;
 
3149
  MI_INFO *info=sort_info->info;
 
3150
  FT_WORD *wptr=0;
 
3151
  DBUG_ENTER("sort_ft_key_read");
 
3152
 
 
3153
  if (!sort_param->wordlist)
 
3154
  {
 
3155
    for (;;)
 
3156
    {
 
3157
      free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
 
3158
      if ((error=sort_get_next_record(sort_param)))
 
3159
        DBUG_RETURN(error);
 
3160
      if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record,
 
3161
                                    &sort_param->wordroot)))
 
3162
        DBUG_RETURN(1);
 
3163
      if (wptr->pos)
 
3164
        break;
 
3165
      error=sort_write_record(sort_param);
 
3166
    }
 
3167
    sort_param->wordptr=sort_param->wordlist=wptr;
 
3168
  }
 
3169
  else
 
3170
  {
 
3171
    error=0;
 
3172
    wptr=(FT_WORD*)(sort_param->wordptr);
 
3173
  }
 
3174
 
 
3175
  sort_param->real_key_length=(info->s->rec_reflength+
 
3176
                               _ft_make_key(info, sort_param->key,
 
3177
                                            key, wptr++, sort_param->filepos));
 
3178
#ifdef HAVE_purify
 
3179
  if (sort_param->key_length > sort_param->real_key_length)
 
3180
    bzero(key+sort_param->real_key_length,
 
3181
          (sort_param->key_length-sort_param->real_key_length));
 
3182
#endif
 
3183
  if (!wptr->pos)
 
3184
  {
 
3185
    free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
 
3186
    sort_param->wordlist=0;
 
3187
    error=sort_write_record(sort_param);
 
3188
  }
 
3189
  else
 
3190
    sort_param->wordptr=(void*)wptr;
 
3191
 
 
3192
  DBUG_RETURN(error);
 
3193
} /* sort_ft_key_read */
 
3194
 
2894
3195
 
2895
3196
/*
2896
3197
  Read next record from file using parameters in sort_info.
2927
3228
{
2928
3229
  int searching;
2929
3230
  int parallel_flag;
2930
 
  uint32_t found_record,b_type,left_length;
 
3231
  uint found_record,b_type,left_length;
2931
3232
  my_off_t pos;
2932
 
  unsigned char *to= NULL;
 
3233
  uchar *to= NULL;
2933
3234
  MI_BLOCK_INFO block_info;
2934
3235
  SORT_INFO *sort_info=sort_param->sort_info;
2935
3236
  MI_CHECK *param=sort_info->param;
2936
3237
  MI_INFO *info=sort_info->info;
2937
3238
  MYISAM_SHARE *share=info->s;
2938
3239
  char llbuff[22],llbuff2[22];
 
3240
  DBUG_ENTER("sort_get_next_record");
2939
3241
 
2940
3242
  if (*killed_ptr(param))
2941
 
    return(1);
 
3243
    DBUG_RETURN(1);
2942
3244
 
2943
3245
  switch (share->data_file_type) {
2944
3246
  case STATIC_RECORD:
2951
3253
          param->out_flag |= O_DATA_LOST;
2952
3254
        param->retry_repair=1;
2953
3255
        param->testflag|=T_RETRY_WITHOUT_QUICK;
2954
 
        return(-1);
 
3256
        DBUG_RETURN(-1);
2955
3257
      }
2956
3258
      sort_param->start_recpos=sort_param->pos;
2957
3259
      if (!sort_param->fix_datafile)
2966
3268
        if (sort_param->calc_checksum)
2967
3269
          param->glob_crc+= (info->checksum=
2968
3270
                             mi_static_checksum(info,sort_param->record));
2969
 
        return(0);
 
3271
        DBUG_RETURN(0);
2970
3272
      }
2971
3273
      if (!sort_param->fix_datafile && sort_param->master)
2972
3274
      {
3005
3307
                     llstr(param->search_after_block,llbuff),
3006
3308
                     llstr(sort_param->start_recpos,llbuff2));
3007
3309
        if (_mi_read_cache(&sort_param->read_cache,
3008
 
                           (unsigned char*) block_info.header,pos,
 
3310
                           (uchar*) block_info.header,pos,
3009
3311
                           MI_BLOCK_INFO_HEADER_LENGTH,
3010
3312
                           (! found_record ? READING_NEXT : 0) |
3011
3313
                           parallel_flag | READING_HEADER))
3017
3319
                                llstr(sort_param->start_recpos,llbuff),errno);
3018
3320
            goto try_next;
3019
3321
          }
3020
 
          return(-1);
 
3322
          DBUG_RETURN(-1);
3021
3323
        }
3022
3324
        if (searching && ! sort_param->fix_datafile)
3023
3325
        {
3024
3326
          param->error_printed=1;
3025
3327
          param->retry_repair=1;
3026
3328
          param->testflag|=T_RETRY_WITHOUT_QUICK;
3027
 
          return(1);    /* Something wrong with data */
 
3329
          DBUG_RETURN(1);       /* Something wrong with data */
3028
3330
        }
3029
3331
        b_type=_mi_get_block_info(&block_info,-1,pos);
3030
3332
        if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3032
3334
             (block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3335
              block_info.rec_len > (uint) share->base.max_pack_length)))
3034
3336
        {
3035
 
          uint32_t i;
 
3337
          uint i;
3036
3338
          if (param->testflag & T_VERBOSE || searching == 0)
3037
3339
            mi_check_print_info(param,
3038
3340
                                "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3055
3357
        }
3056
3358
        if (b_type & BLOCK_DELETED)
3057
3359
        {
3058
 
          bool error=0;
 
3360
          my_bool error=0;
3059
3361
          if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3060
3362
              share->base.min_block_length)
3061
3363
          {
3156
3458
                mi_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
3157
3459
                                     llstr(sort_param->start_recpos,llbuff),
3158
3460
                                     (ulong) block_info.rec_len);
3159
 
                return(1);
 
3461
                DBUG_RETURN(1);
3160
3462
              }
3161
3463
              else
3162
3464
              {
3191
3493
          streched over the end of the previous buffer contents.
3192
3494
        */
3193
3495
        {
3194
 
          uint32_t header_len= (uint) (block_info.filepos - pos);
3195
 
          uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
 
3496
          uint header_len= (uint) (block_info.filepos - pos);
 
3497
          uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3196
3498
 
3197
3499
          if (prefetch_len > block_info.data_len)
3198
3500
            prefetch_len= block_info.data_len;
3238
3540
                         sort_param->find_length) != MY_FILE_ERROR)
3239
3541
      {
3240
3542
        if (sort_param->read_cache.error < 0)
3241
 
          return(1);
 
3543
          DBUG_RETURN(1);
3242
3544
        if (sort_param->calc_checksum)
3243
3545
          info->checksum= mi_checksum(info, sort_param->record);
3244
3546
        if ((param->testflag & (T_EXTEND | T_REP)) || searching)
3256
3558
        }
3257
3559
        if (sort_param->calc_checksum)
3258
3560
          param->glob_crc+= info->checksum;
3259
 
        return(0);
 
3561
        DBUG_RETURN(0);
3260
3562
      }
3261
3563
      if (!searching)
3262
3564
        mi_check_print_info(param,"Key %d - Found wrong stored record at %s",
3267
3569
      searching=1;
3268
3570
    }
3269
3571
  case COMPRESSED_RECORD:
 
3572
    for (searching=0 ;; searching=1, sort_param->pos++)
 
3573
    {
 
3574
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
 
3575
                         sort_param->pos,
 
3576
                         share->pack.ref_length,READING_NEXT))
 
3577
        DBUG_RETURN(-1);
 
3578
      if (searching && ! sort_param->fix_datafile)
 
3579
      {
 
3580
        param->error_printed=1;
 
3581
        param->retry_repair=1;
 
3582
        param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3583
        DBUG_RETURN(1);         /* Something wrong with data */
 
3584
      }
 
3585
      sort_param->start_recpos=sort_param->pos;
 
3586
      if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
 
3587
                                  &sort_param->rec_buff, -1, sort_param->pos))
 
3588
        DBUG_RETURN(-1);
 
3589
      if (!block_info.rec_len &&
 
3590
          sort_param->pos + MEMMAP_EXTRA_MARGIN ==
 
3591
          sort_param->read_cache.end_of_file)
 
3592
        DBUG_RETURN(-1);
 
3593
      if (block_info.rec_len < (uint) share->min_pack_length ||
 
3594
          block_info.rec_len > (uint) share->max_pack_length)
 
3595
      {
 
3596
        if (! searching)
 
3597
          mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
 
3598
                              block_info.rec_len,
 
3599
                              llstr(sort_param->pos,llbuff));
 
3600
        continue;
 
3601
      }
 
3602
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
 
3603
                         block_info.filepos, block_info.rec_len,
 
3604
                         READING_NEXT))
 
3605
      {
 
3606
        if (! searching)
 
3607
          mi_check_print_info(param,"Couldn't read whole record from %s",
 
3608
                              llstr(sort_param->pos,llbuff));
 
3609
        continue;
 
3610
      }
 
3611
      if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
 
3612
                              sort_param->rec_buff, block_info.rec_len))
 
3613
      {
 
3614
        if (! searching)
 
3615
          mi_check_print_info(param,"Found wrong record at %s",
 
3616
                              llstr(sort_param->pos,llbuff));
 
3617
        continue;
 
3618
      }
 
3619
      if (!sort_param->fix_datafile)
 
3620
      {
 
3621
        sort_param->filepos=sort_param->pos;
 
3622
        if (sort_param->master)
 
3623
          share->state.split++;
 
3624
      }
 
3625
      sort_param->max_pos=(sort_param->pos=block_info.filepos+
 
3626
                         block_info.rec_len);
 
3627
      info->packed_length=block_info.rec_len;
 
3628
      if (sort_param->calc_checksum)
 
3629
        param->glob_crc+= (info->checksum=
 
3630
                           mi_checksum(info, sort_param->record));
 
3631
      DBUG_RETURN(0);
 
3632
    }
3270
3633
  case BLOCK_RECORD:
3271
3634
    assert(0);                                  /* Impossible */
3272
3635
  }
3273
 
  return(1);                               /* Impossible */
 
3636
  DBUG_RETURN(1);                               /* Impossible */
3274
3637
}
3275
3638
 
3276
3639
 
3292
3655
int sort_write_record(MI_SORT_PARAM *sort_param)
3293
3656
{
3294
3657
  int flag;
 
3658
  uint length;
3295
3659
  ulong block_length,reclength;
3296
 
  unsigned char *from;
 
3660
  uchar *from;
 
3661
  uchar block_buff[8];
3297
3662
  SORT_INFO *sort_info=sort_param->sort_info;
3298
3663
  MI_CHECK *param=sort_info->param;
3299
3664
  MI_INFO *info=sort_info->info;
3300
3665
  MYISAM_SHARE *share=info->s;
 
3666
  DBUG_ENTER("sort_write_record");
3301
3667
 
3302
3668
  if (sort_param->fix_datafile)
3303
3669
  {
3307
3673
                     share->base.pack_reclength))
3308
3674
      {
3309
3675
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
3310
 
        return(1);
 
3676
        DBUG_RETURN(1);
3311
3677
      }
3312
3678
      sort_param->filepos+=share->base.pack_reclength;
3313
3679
      info->s->state.split++;
3328
3694
          if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3329
3695
                                           MYF(MY_FREE_ON_ERROR |
3330
3696
                                               MY_ALLOW_ZERO_PTR))))
3331
 
            return(1);
 
3697
            DBUG_RETURN(1);
3332
3698
          sort_info->buff_length=reclength;
3333
3699
        }
3334
3700
        from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3353
3719
                                  &from,&reclength,&flag))
3354
3720
        {
3355
3721
          mi_check_print_error(param,"%d when writing to datafile",my_errno);
3356
 
          return(1);
 
3722
          DBUG_RETURN(1);
3357
3723
        }
3358
3724
        sort_param->filepos+=block_length;
3359
3725
        info->s->state.split++;
3361
3727
      /* sort_info->param->glob_crc+=info->checksum; */
3362
3728
      break;
3363
3729
    case COMPRESSED_RECORD:
 
3730
      reclength=info->packed_length;
 
3731
      length= save_pack_length((uint) share->pack.version, block_buff,
 
3732
                               reclength);
 
3733
      if (info->s->base.blobs)
 
3734
        length+= save_pack_length((uint) share->pack.version,
 
3735
                                  block_buff + length, info->blob_length);
 
3736
      if (my_b_write(&info->rec_cache,block_buff,length) ||
 
3737
          my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
 
3738
      {
 
3739
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3740
        DBUG_RETURN(1);
 
3741
      }
 
3742
      /* sort_info->param->glob_crc+=info->checksum; */
 
3743
      sort_param->filepos+=reclength+length;
 
3744
      info->s->state.split++;
 
3745
      break;
3364
3746
    case BLOCK_RECORD:
3365
3747
      assert(0);                                  /* Impossible */
3366
3748
    }
3373
3755
    {
3374
3756
      char llbuff[22];
3375
3757
      printf("%s\r", llstr(info->state->records,llbuff));
3376
 
      fflush(stdout);
 
3758
      VOID(fflush(stdout));
3377
3759
    }
3378
3760
  }
3379
 
  return(0);
 
3761
  DBUG_RETURN(0);
3380
3762
} /* sort_write_record */
3381
3763
 
3382
3764
 
3385
3767
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3386
3768
                        const void *b)
3387
3769
{
3388
 
  uint32_t not_used[2];
3389
 
  return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
 
3770
  uint not_used[2];
 
3771
  return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3390
3772
                     USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3773
} /* sort_key_cmp */
3392
3774
 
3393
3775
 
3394
3776
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3395
3777
{
3396
 
  uint32_t diff_pos[2];
 
3778
  uint diff_pos[2];
3397
3779
  char llbuff[22],llbuff2[22];
3398
3780
  SORT_INFO *sort_info=sort_param->sort_info;
3399
3781
  MI_CHECK *param= sort_info->param;
3402
3784
  if (sort_info->key_block->inited)
3403
3785
  {
3404
3786
    cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
 
                   (unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
 
3787
                   (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3406
3788
                   diff_pos);
3407
3789
    if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3790
      ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
 
                 (unsigned char*) a, USE_WHOLE_KEY, 
 
3791
                 (uchar*) a, USE_WHOLE_KEY, 
3410
3792
                 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3793
    else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3412
3794
    {
3413
3795
      diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3796
                                                 sort_param->notnull,
3415
3797
                                                 sort_info->key_block->lastkey,
3416
 
                                                 (unsigned char*)a);
 
3798
                                                 (uchar*)a);
3417
3799
    }
3418
3800
    sort_param->unique[diff_pos[0]-1]++;
3419
3801
  }
3422
3804
    cmp= -1;
3423
3805
    if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3806
      mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3425
 
                                     (unsigned char*)a);
 
3807
                                     (uchar*)a);
3426
3808
  }
3427
3809
  if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3428
3810
  {
3429
3811
    sort_info->dupp++;
3430
3812
    sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3813
                                                sort_param->keyinfo,
3432
 
                                                (unsigned char*) a);
 
3814
                                                (uchar*) a);
3433
3815
    mi_check_print_warning(param,
3434
3816
                           "Duplicate key for record at %10s against record at %10s",
3435
3817
                           llstr(sort_info->info->lastpos,llbuff),
3439
3821
                                                    lastkey),
3440
3822
                                 llbuff2));
3441
3823
    param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3824
    if (sort_info->param->testflag & T_VERBOSE)
 
3825
      _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3442
3826
    return (sort_delete_record(sort_param));
3443
3827
  }
 
3828
#ifndef DBUG_OFF
 
3829
  if (cmp > 0)
 
3830
  {
 
3831
    mi_check_print_error(param,
 
3832
                         "Internal error: Keys are not in order from sort");
 
3833
    return(1);
 
3834
  }
 
3835
#endif
3444
3836
  return (sort_insert_key(sort_param,sort_info->key_block,
3445
 
                          (unsigned char*) a, HA_OFFSET_ERROR));
 
3837
                          (uchar*) a, HA_OFFSET_ERROR));
3446
3838
} /* sort_key_write */
3447
3839
 
 
3840
int sort_ft_buf_flush(MI_SORT_PARAM *sort_param)
 
3841
{
 
3842
  SORT_INFO *sort_info=sort_param->sort_info;
 
3843
  SORT_KEY_BLOCKS *key_block=sort_info->key_block;
 
3844
  MYISAM_SHARE *share=sort_info->info->s;
 
3845
  uint val_off, val_len;
 
3846
  int error;
 
3847
  SORT_FT_BUF *ft_buf=sort_info->ft_buf;
 
3848
  uchar *from, *to;
 
3849
 
 
3850
  val_len=share->ft2_keyinfo.keylength;
 
3851
  get_key_full_length_rdonly(val_off, ft_buf->lastkey);
 
3852
  to=ft_buf->lastkey+val_off;
 
3853
 
 
3854
  if (ft_buf->buf)
 
3855
  {
 
3856
    /* flushing first-level tree */
 
3857
    error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
 
3858
                          HA_OFFSET_ERROR);
 
3859
    for (from=to+val_len;
 
3860
         !error && from < ft_buf->buf;
 
3861
         from+= val_len)
 
3862
    {
 
3863
      memcpy(to, from, val_len);
 
3864
      error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
 
3865
                            HA_OFFSET_ERROR);
 
3866
    }
 
3867
    return error;
 
3868
  }
 
3869
  /* flushing second-level tree keyblocks */
 
3870
  error=flush_pending_blocks(sort_param);
 
3871
  /* updating lastkey with second-level tree info */
 
3872
  ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count);
 
3873
  _mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN,
 
3874
      share->state.key_root[sort_param->key]);
 
3875
  /* restoring first level tree data in sort_info/sort_param */
 
3876
  sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
 
3877
  sort_param->keyinfo=share->keyinfo+sort_param->key;
 
3878
  share->state.key_root[sort_param->key]=HA_OFFSET_ERROR;
 
3879
  /* writing lastkey in first-level tree */
 
3880
  return error ? error :
 
3881
                 sort_insert_key(sort_param,sort_info->key_block,
 
3882
                                 ft_buf->lastkey,HA_OFFSET_ERROR);
 
3883
}
 
3884
 
 
3885
static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
 
3886
{
 
3887
  uint a_len, val_off, val_len, error;
 
3888
  uchar *p;
 
3889
  SORT_INFO *sort_info=sort_param->sort_info;
 
3890
  SORT_FT_BUF *ft_buf=sort_info->ft_buf;
 
3891
  SORT_KEY_BLOCKS *key_block=sort_info->key_block;
 
3892
 
 
3893
  val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
 
3894
  get_key_full_length_rdonly(a_len, (uchar *)a);
 
3895
 
 
3896
  if (!ft_buf)
 
3897
  {
 
3898
    /*
 
3899
      use two-level tree only if key_reflength fits in rec_reflength place
 
3900
      and row format is NOT static - for _mi_dpointer not to garble offsets
 
3901
     */
 
3902
    if ((sort_info->info->s->base.key_reflength <=
 
3903
         sort_info->info->s->base.rec_reflength) &&
 
3904
        (sort_info->info->s->options &
 
3905
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
 
3906
      ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
 
3907
                                      sizeof(SORT_FT_BUF), MYF(MY_WME));
 
3908
 
 
3909
    if (!ft_buf)
 
3910
    {
 
3911
      sort_param->key_write=sort_key_write;
 
3912
      return sort_key_write(sort_param, a);
 
3913
    }
 
3914
    sort_info->ft_buf=ft_buf;
 
3915
    goto word_init_ft_buf; /* no need to duplicate the code */
 
3916
  }
 
3917
  get_key_full_length_rdonly(val_off, ft_buf->lastkey);
 
3918
 
 
3919
  if (ha_compare_text(sort_param->seg->charset,
 
3920
                      ((uchar *)a)+1,a_len-1,
 
3921
                      ft_buf->lastkey+1,val_off-1, 0, 0)==0)
 
3922
  {
 
3923
    if (!ft_buf->buf) /* store in second-level tree */
 
3924
    {
 
3925
      ft_buf->count++;
 
3926
      return sort_insert_key(sort_param,key_block,
 
3927
                             ((uchar *)a)+a_len, HA_OFFSET_ERROR);
 
3928
    }
 
3929
 
 
3930
    /* storing the key in the buffer. */
 
3931
    memcpy (ft_buf->buf, (char *)a+a_len, val_len);
 
3932
    ft_buf->buf+=val_len;
 
3933
    if (ft_buf->buf < ft_buf->end)
 
3934
      return 0;
 
3935
 
 
3936
    /* converting to two-level tree */
 
3937
    p=ft_buf->lastkey+val_off;
 
3938
 
 
3939
    while (key_block->inited)
 
3940
      key_block++;
 
3941
    sort_info->key_block=key_block;
 
3942
    sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo;
 
3943
    ft_buf->count=(ft_buf->buf - p)/val_len;
 
3944
 
 
3945
    /* flushing buffer to second-level tree */
 
3946
    for (error=0; !error && p < ft_buf->buf; p+= val_len)
 
3947
      error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR);
 
3948
    ft_buf->buf=0;
 
3949
    return error;
 
3950
  }
 
3951
 
 
3952
  /* flushing buffer */
 
3953
  if ((error=sort_ft_buf_flush(sort_param)))
 
3954
    return error;
 
3955
 
 
3956
word_init_ft_buf:
 
3957
  a_len+=val_len;
 
3958
  memcpy(ft_buf->lastkey, a, a_len);
 
3959
  ft_buf->buf=ft_buf->lastkey+a_len;
 
3960
  /*
 
3961
    32 is just a safety margin here
 
3962
    (at least max(val_len, sizeof(nod_flag)) should be there).
 
3963
    May be better performance could be achieved if we'd put
 
3964
      (sort_info->keyinfo->block_length-32)/XXX
 
3965
      instead.
 
3966
        TODO: benchmark the best value for XXX.
 
3967
  */
 
3968
  ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
 
3969
  return 0;
 
3970
} /* sort_ft_key_write */
 
3971
 
3448
3972
 
3449
3973
        /* get pointer to record from a key */
3450
3974
 
3451
3975
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3452
 
                                   unsigned char *key)
 
3976
                                   uchar *key)
3453
3977
{
3454
3978
  return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3979
} /* get_record_for_key */
3458
3982
        /* Insert a key in sort-key-blocks */
3459
3983
 
3460
3984
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
 
                           register SORT_KEY_BLOCKS *key_block, unsigned char *key,
 
3985
                           register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3986
                           my_off_t prev_block)
3463
3987
{
3464
 
  uint32_t a_length,t_length,nod_flag;
 
3988
  uint a_length,t_length,nod_flag;
3465
3989
  my_off_t filepos,key_file_length;
3466
 
  unsigned char *anc_buff,*lastkey;
 
3990
  uchar *anc_buff,*lastkey;
3467
3991
  MI_KEY_PARAM s_temp;
3468
3992
  MI_INFO *info;
3469
3993
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
3470
3994
  SORT_INFO *sort_info= sort_param->sort_info;
3471
3995
  MI_CHECK *param=sort_info->param;
 
3996
  DBUG_ENTER("sort_insert_key");
3472
3997
 
3473
3998
  anc_buff=key_block->buff;
3474
3999
  info=sort_info->info;
3482
4007
    if (key_block == sort_info->key_block_end)
3483
4008
    {
3484
4009
      mi_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks");
3485
 
      return(1);
 
4010
      DBUG_RETURN(1);
3486
4011
    }
3487
4012
    a_length=2+nod_flag;
3488
4013
    key_block->end_pos=anc_buff+2;
3496
4021
    _mi_kpointer(info,key_block->end_pos,prev_block);
3497
4022
 
3498
4023
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
 
                                (unsigned char*) 0,lastkey,lastkey,key,
 
4024
                                (uchar*) 0,lastkey,lastkey,key,
3500
4025
                                 &s_temp);
3501
4026
  (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
4027
  a_length+=t_length;
3504
4029
  key_block->end_pos+=t_length;
3505
4030
  if (a_length <= keyinfo->block_length)
3506
4031
  {
3507
 
    _mi_move_key(keyinfo,key_block->lastkey,key);
 
4032
    VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
4033
    key_block->last_length=a_length-t_length;
3509
 
    return(0);
 
4034
    DBUG_RETURN(0);
3510
4035
  }
3511
4036
 
3512
4037
        /* Fill block with end-zero and write filled block */
3513
4038
  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);
 
4039
  bzero((uchar*) anc_buff+key_block->last_length,
 
4040
        keyinfo->block_length- key_block->last_length);
3516
4041
  key_file_length=info->state->key_file_length;
3517
4042
  if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3518
 
    return(1);
 
4043
    DBUG_RETURN(1);
3519
4044
 
3520
4045
  /* If we read the page from the key cache, we have to write it back to it */
3521
4046
  if (key_file_length == info->state->key_file_length)
3522
4047
  {
3523
4048
    if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3524
 
      return(1);
 
4049
      DBUG_RETURN(1);
3525
4050
  }
3526
 
  else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
 
4051
  else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
4052
                     (uint) keyinfo->block_length,filepos, param->myf_rw))
3528
 
    return(1);
 
4053
    DBUG_RETURN(1);
 
4054
  DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3529
4055
 
3530
4056
        /* Write separator-key to block in next level */
3531
4057
  if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3532
 
    return(1);
 
4058
    DBUG_RETURN(1);
3533
4059
 
3534
4060
        /* clear old block and write new key in it */
3535
4061
  key_block->inited=0;
3536
 
  return(sort_insert_key(sort_param, key_block,key,prev_block));
 
4062
  DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3537
4063
} /* sort_insert_key */
3538
4064
 
3539
4065
 
3541
4067
 
3542
4068
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3543
4069
{
3544
 
  uint32_t i;
 
4070
  uint i;
3545
4071
  int old_file,error;
3546
 
  unsigned char *key;
 
4072
  uchar *key;
3547
4073
  SORT_INFO *sort_info=sort_param->sort_info;
3548
4074
  MI_CHECK *param=sort_info->param;
3549
4075
  MI_INFO *info=sort_info->info;
 
4076
  DBUG_ENTER("sort_delete_record");
3550
4077
 
3551
4078
  if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3552
4079
  {
3553
4080
    mi_check_print_error(param,
3554
4081
                         "Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3555
 
    return(1);
 
4082
    DBUG_RETURN(1);
3556
4083
  }
3557
4084
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3558
4085
  {
3559
4086
    mi_check_print_error(param,
3560
4087
                         "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);
 
4088
    DBUG_RETURN(1);
3562
4089
  }
3563
4090
 
3564
4091
  old_file=info->dfile;
3571
4098
    {
3572
4099
      mi_check_print_error(param,"Can't read record to be removed");
3573
4100
      info->dfile=old_file;
3574
 
      return(1);
 
4101
      DBUG_RETURN(1);
3575
4102
    }
3576
4103
 
3577
4104
    for (i=0 ; i < sort_info->current_key ; i++)
3578
4105
    {
3579
 
      uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
 
4106
      uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
4107
      if (_mi_ck_delete(info,i,key,key_length))
3581
4108
      {
3582
4109
        mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3583
4110
        info->dfile=old_file;
3584
 
        return(1);
 
4111
        DBUG_RETURN(1);
3585
4112
      }
3586
4113
    }
3587
4114
    if (sort_param->calc_checksum)
3590
4117
  error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3591
4118
  info->dfile=old_file;                         /* restore actual value */
3592
4119
  info->state->records--;
3593
 
  return(error);
 
4120
  DBUG_RETURN(error);
3594
4121
} /* sort_delete_record */
3595
4122
 
3596
4123
        /* Fix all pending blocks and flush everything to disk */
3597
4124
 
3598
4125
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3599
4126
{
3600
 
  uint32_t nod_flag,length;
 
4127
  uint nod_flag,length;
3601
4128
  my_off_t filepos,key_file_length;
3602
4129
  SORT_KEY_BLOCKS *key_block;
3603
4130
  SORT_INFO *sort_info= sort_param->sort_info;
3604
4131
  myf myf_rw=sort_info->param->myf_rw;
3605
4132
  MI_INFO *info=sort_info->info;
3606
4133
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
 
4134
  DBUG_ENTER("flush_pending_blocks");
3607
4135
 
3608
4136
  filepos= HA_OFFSET_ERROR;                     /* if empty file */
3609
4137
  nod_flag=0;
3614
4142
    if (nod_flag)
3615
4143
      _mi_kpointer(info,key_block->end_pos,filepos);
3616
4144
    key_file_length=info->state->key_file_length;
3617
 
    memset(key_block->buff+length, 0, keyinfo->block_length-length);
 
4145
    bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3618
4146
    if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3619
 
      return(1);
 
4147
      DBUG_RETURN(1);
3620
4148
 
3621
4149
    /* If we read the page from the key cache, we have to write it back */
3622
4150
    if (key_file_length == info->state->key_file_length)
3623
4151
    {
3624
4152
      if (_mi_write_keypage(info, keyinfo, filepos,
3625
4153
                            DFLT_INIT_HITS, key_block->buff))
3626
 
        return(1);
 
4154
        DBUG_RETURN(1);
3627
4155
    }
3628
 
    else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
 
4156
    else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
4157
                       (uint) keyinfo->block_length,filepos, myf_rw))
3630
 
      return(1);
 
4158
      DBUG_RETURN(1);
 
4159
    DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3631
4160
    nod_flag=1;
3632
4161
  }
3633
4162
  info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3634
 
  return(0);
 
4163
  DBUG_RETURN(0);
3635
4164
} /* flush_pending_blocks */
3636
4165
 
3637
4166
        /* alloc space and pointers for key_blocks */
3638
4167
 
3639
 
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3640
 
                                         uint32_t buffer_length)
 
4168
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
4169
                                         uint buffer_length)
3641
4170
{
3642
 
  register uint32_t i;
 
4171
  register uint i;
3643
4172
  SORT_KEY_BLOCKS *block;
 
4173
  DBUG_ENTER("alloc_key_blocks");
3644
4174
 
3645
4175
  if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3646
4176
                                            buffer_length+IO_SIZE)*blocks,
3652
4182
  for (i=0 ; i < blocks ; i++)
3653
4183
  {
3654
4184
    block[i].inited=0;
3655
 
    block[i].buff=(unsigned char*) (block+blocks)+(buffer_length+IO_SIZE)*i;
 
4185
    block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
3656
4186
  }
3657
 
  return(block);
 
4187
  DBUG_RETURN(block);
3658
4188
} /* alloc_key_blocks */
3659
4189
 
3660
4190
 
3682
4212
  MI_COLUMNDEF *recdef,*rec,*end;
3683
4213
  MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
4214
  MI_STATUS_INFO status_info;
3685
 
  uint32_t unpack,key_parts;
 
4215
  uint unpack,key_parts;
3686
4216
  ha_rows max_records;
3687
 
  uint64_t file_length,tmp_length;
 
4217
  ulonglong file_length,tmp_length;
3688
4218
  MI_CREATE_INFO create_info;
 
4219
  DBUG_ENTER("recreate_table");
3689
4220
 
3690
4221
  error=1;                                      /* Default error */
3691
4222
  info= **org_info;
3695
4226
  unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3696
4227
    (param->testflag & T_UNPACK);
3697
4228
  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);
 
4229
    DBUG_RETURN(0);
 
4230
  memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
 
4231
         (size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3700
4232
 
3701
4233
  key_parts= share.base.all_key_parts;
3702
4234
  if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
4235
                                       (key_parts+share.base.keys))))
3704
4236
  {
3705
 
    my_afree((unsigned char*) keyinfo);
3706
 
    return(1);
 
4237
    my_afree((uchar*) keyinfo);
 
4238
    DBUG_RETURN(1);
3707
4239
  }
3708
4240
  if (!(recdef=(MI_COLUMNDEF*)
3709
4241
        my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3710
4242
  {
3711
 
    my_afree((unsigned char*) keyinfo);
3712
 
    my_afree((unsigned char*) keysegs);
3713
 
    return(1);
 
4243
    my_afree((uchar*) keyinfo);
 
4244
    my_afree((uchar*) keysegs);
 
4245
    DBUG_RETURN(1);
3714
4246
  }
3715
4247
  if (!(uniquedef=(MI_UNIQUEDEF*)
3716
4248
        my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3717
4249
  {
3718
 
    my_afree((unsigned char*) recdef);
3719
 
    my_afree((unsigned char*) keyinfo);
3720
 
    my_afree((unsigned char*) keysegs);
3721
 
    return(1);
 
4250
    my_afree((uchar*) recdef);
 
4251
    my_afree((uchar*) keyinfo);
 
4252
    my_afree((uchar*) keysegs);
 
4253
    DBUG_RETURN(1);
3722
4254
  }
3723
4255
 
3724
4256
  /* Copy the column definitions */
3725
 
  memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
 
4257
  memcpy((uchar*) recdef,(uchar*) share.rec,
 
4258
         (size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3726
4259
  for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3727
4260
  {
3728
4261
    if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3733
4266
  }
3734
4267
 
3735
4268
  /* 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));
 
4269
  memcpy((uchar*) keysegs,(uchar*) share.keyparts,
 
4270
         (size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
 
4271
                                      share.state.header.uniques)));
3739
4272
  keyseg=keysegs;
3740
4273
  for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3741
4274
  {
3750
4283
 
3751
4284
  /* Copy the unique definitions and change them to point at the new key
3752
4285
     segments*/
3753
 
  memcpy(uniquedef,share.uniqueinfo,
3754
 
         sizeof(MI_UNIQUEDEF)*(share.state.header.uniques));
 
4286
  memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
 
4287
         (size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3755
4288
  for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3756
4289
       u_ptr != u_end ; u_ptr++)
3757
4290
  {
3769
4302
    (param->testflag & T_UNPACK);
3770
4303
  share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3771
4304
 
3772
 
  file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
 
4305
  file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3773
4306
  tmp_length= file_length+file_length/10;
3774
4307
  set_if_bigger(file_length,param->max_data_file_length);
3775
4308
  set_if_bigger(file_length,tmp_length);
3776
 
  set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
 
4309
  set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
3777
4310
 
3778
 
  mi_close(*org_info);
3779
 
  memset(&create_info, 0, sizeof(create_info));
3780
 
  create_info.max_rows=cmax(max_records,share.base.records);
 
4311
  VOID(mi_close(*org_info));
 
4312
  bzero((char*) &create_info,sizeof(create_info));
 
4313
  create_info.max_rows=max(max_records,share.base.records);
3781
4314
  create_info.reloc_rows=share.base.reloc;
3782
4315
  create_info.old_options=(share.options |
3783
4316
                           (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3791
4324
    Allow for creating an auto_increment key. This has an effect only if
3792
4325
    an auto_increment key exists in the original table.
3793
4326
  */
3794
 
  create_info.with_auto_increment= true;
 
4327
  create_info.with_auto_increment= TRUE;
3795
4328
  /* We don't have to handle symlinks here because we are using
3796
4329
     HA_DONT_TOUCH_DATA */
3797
4330
  if (mi_create(filename,
3816
4349
  }
3817
4350
  /* We are modifing */
3818
4351
  (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
 
  _mi_readinfo(*org_info,F_WRLCK,0);
 
4352
  VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
4353
  (*org_info)->state->records=info.state->records;
3821
4354
  if (share.state.create_time)
3822
4355
    (*org_info)->s->state.create_time=share.state.create_time;
3832
4365
    goto end;
3833
4366
  error=0;
3834
4367
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);
 
4368
  my_afree((uchar*) uniquedef);
 
4369
  my_afree((uchar*) keyinfo);
 
4370
  my_afree((uchar*) recdef);
 
4371
  my_afree((uchar*) keysegs);
 
4372
  DBUG_RETURN(error);
3840
4373
}
3841
4374
 
3842
4375
 
3843
4376
        /* write suffix to data file if neaded */
3844
4377
 
3845
 
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
 
4378
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3846
4379
{
3847
4380
  MI_INFO *info=sort_info->info;
3848
4381
 
3849
4382
  if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3850
4383
  {
3851
 
    unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
 
    memset(buff, 0, sizeof(buff));
 
4384
    uchar buff[MEMMAP_EXTRA_MARGIN];
 
4385
    bzero(buff,sizeof(buff));
3853
4386
    if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3854
4387
    {
3855
4388
      mi_check_print_error(sort_info->param,
3863
4396
 
3864
4397
        /* Update state and myisamchk_time of indexfile */
3865
4398
 
3866
 
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
 
4399
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3867
4400
{
3868
4401
  MYISAM_SHARE *share=info->s;
3869
4402
 
3874
4407
  }
3875
4408
  if (update & UPDATE_STAT)
3876
4409
  {
3877
 
    uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
 
4410
    uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
4411
    share->state.rec_per_key_rows=info->state->records;
3879
4412
    share->state.changed&= ~STATE_NOT_ANALYZED;
3880
4413
    if (info->state->records)
3908
4441
  }
3909
4442
  {                                             /* Force update of status */
3910
4443
    int error;
3911
 
    uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
 
4444
    uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
4445
    share->r_locks= share->w_locks= share->tot_locks= 0;
3913
4446
    error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
4447
    share->r_locks=r_locks;
3936
4469
        */
3937
4470
 
3938
4471
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3939
 
                               bool repair_only)
 
4472
                               my_bool repair_only)
3940
4473
{
3941
 
  unsigned char *record= 0;
 
4474
  uchar *record= 0;
 
4475
  DBUG_ENTER("update_auto_increment_key");
3942
4476
 
3943
4477
  if (!info->s->base.auto_key ||
3944
4478
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3947
4481
      mi_check_print_info(param,
3948
4482
                          "Table: %s doesn't have an auto increment key\n",
3949
4483
                          param->isam_file_name);
3950
 
    return;
 
4484
    DBUG_VOID_RETURN;
3951
4485
  }
3952
4486
  if (!(param->testflag & T_SILENT) &&
3953
4487
      !(param->testflag & T_REP))
3959
4493
  if (!mi_alloc_rec_buff(info, -1, &record))
3960
4494
  {
3961
4495
    mi_check_print_error(param,"Not enough memory for extra record");
3962
 
    return;
 
4496
    DBUG_VOID_RETURN;
3963
4497
  }
3964
4498
 
3965
4499
  mi_extra(info,HA_EXTRA_KEYREAD,0);
3968
4502
    if (my_errno != HA_ERR_END_OF_FILE)
3969
4503
    {
3970
4504
      mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
 
      free(mi_get_rec_buff_ptr(info, record));
 
4505
      my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
4506
      mi_check_print_error(param,"%d when reading last record",my_errno);
3973
 
      return;
 
4507
      DBUG_VOID_RETURN;
3974
4508
    }
3975
4509
    if (!repair_only)
3976
4510
      info->s->state.auto_increment=param->auto_increment_value;
3977
4511
  }
3978
4512
  else
3979
4513
  {
3980
 
    uint64_t auto_increment= retrieve_auto_increment(info, record);
 
4514
    ulonglong auto_increment= retrieve_auto_increment(info, record);
3981
4515
    set_if_bigger(info->s->state.auto_increment,auto_increment);
3982
4516
    if (!repair_only)
3983
4517
      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3984
4518
  }
3985
4519
  mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
 
  free(mi_get_rec_buff_ptr(info, record));
 
4520
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4521
  update_state_info(param, info, UPDATE_AUTO_INC);
3988
 
  return;
 
4522
  DBUG_VOID_RETURN;
3989
4523
}
3990
4524
 
3991
4525
 
4041
4575
*/
4042
4576
 
4043
4577
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4044
 
                      uint64_t *unique, uint64_t *notnull,
4045
 
                      uint64_t records)
 
4578
                      ulonglong *unique, ulonglong *notnull,
 
4579
                      ulonglong records)
4046
4580
{
4047
 
  uint64_t count=0,tmp, unique_tuples;
4048
 
  uint64_t tuples= records;
4049
 
  uint32_t parts;
 
4581
  ulonglong count=0,tmp, unique_tuples;
 
4582
  ulonglong tuples= records;
 
4583
  uint parts;
4050
4584
  for (parts=0 ; parts < keyinfo->keysegs  ; parts++)
4051
4585
  {
4052
4586
    count+=unique[parts];
4074
4608
      let's ensure it is not
4075
4609
    */
4076
4610
    set_if_bigger(tmp,1);
4077
 
    if (tmp >= (uint64_t) ~(ulong) 0)
4078
 
      tmp=(uint64_t) ~(ulong) 0;
 
4611
    if (tmp >= (ulonglong) ~(ulong) 0)
 
4612
      tmp=(ulonglong) ~(ulong) 0;
4079
4613
 
4080
4614
    *rec_per_key_part=(ulong) tmp;
4081
4615
    rec_per_key_part++;
4083
4617
}
4084
4618
 
4085
4619
 
4086
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
 
4620
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4087
4621
{
4088
4622
  ha_checksum crc;
4089
 
  const unsigned char *end=buf+length;
 
4623
  const uchar *end=buf+length;
4090
4624
  for (crc=0; buf != end; buf++)
4091
 
    crc=((crc << 1) + *((unsigned char*) buf)) +
 
4625
    crc=((crc << 1) + *((uchar*) buf)) +
4092
4626
      test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4093
4627
  return crc;
4094
4628
}
4095
4629
 
4096
 
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
 
4630
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4097
4631
{
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));
 
4632
  uint key_maxlength=key->maxlength;
 
4633
  if (key->flag & HA_FULLTEXT)
 
4634
  {
 
4635
    uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
 
4636
                                  key->seg->charset->mbmaxlen;
 
4637
    key_maxlength+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
 
4638
  }
 
4639
  return (key->flag & HA_SPATIAL) ||
 
4640
          (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
 
4641
          ((ulonglong) rows * key_maxlength >
 
4642
           (ulonglong) myisam_max_temp_length));
4102
4643
}
4103
4644
 
4104
4645
/*
4114
4655
{
4115
4656
  MYISAM_SHARE *share=info->s;
4116
4657
  MI_KEYDEF    *key=share->keyinfo;
4117
 
  uint32_t          i;
 
4658
  uint          i;
4118
4659
 
4119
 
  assert(info->state->records == 0 &&
 
4660
  DBUG_ASSERT(info->state->records == 0 &&
4120
4661
              (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4121
4662
  for (i=0 ; i < share->base.keys ; i++,key++)
4122
4663
  {
4123
 
    if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
 
4664
    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4124
4665
        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4125
4666
    {
4126
4667
      mi_clear_key_active(share->state.key_map, i);
4131
4672
 
4132
4673
 
4133
4674
/*
4134
 
  Return true if we can use repair by sorting
 
4675
  Return TRUE if we can use repair by sorting
4135
4676
  One can set the force argument to force to use sorting
4136
4677
  even if the temporary file would be quite big!
4137
4678
*/
4138
4679
 
4139
 
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4140
 
                            uint64_t key_map, bool force)
 
4680
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
 
4681
                            ulonglong key_map, my_bool force)
4141
4682
{
4142
4683
  MYISAM_SHARE *share=info->s;
4143
4684
  MI_KEYDEF *key=share->keyinfo;
4144
 
  uint32_t i;
 
4685
  uint i;
4145
4686
 
4146
4687
  /*
4147
4688
    mi_repair_by_sort only works if we have at least one key. If we don't
4148
4689
    have any keys, we should use the normal repair.
4149
4690
  */
4150
4691
  if (! mi_is_any_key_active(key_map))
4151
 
    return false;                               /* Can't use sort */
 
4692
    return FALSE;                               /* Can't use sort */
4152
4693
  for (i=0 ; i < share->base.keys ; i++,key++)
4153
4694
  {
4154
4695
    if (!force && mi_too_big_key_for_sort(key,rows))
4155
 
      return false;
 
4696
      return FALSE;
4156
4697
  }
4157
 
  return true;
 
4698
  return TRUE;
4158
4699
}
4159
4700
 
4160
4701
 
4172
4713
      sort_info->new_data_file_type = STATIC_RECORD;
4173
4714
 
4174
4715
    /* Set delete_function for sort_delete_record() */
4175
 
    memcpy(&tmp, share, sizeof(*share));
 
4716
    memcpy((char*) &tmp, share, sizeof(*share));
4176
4717
    tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4177
4718
    mi_setup_functions(&tmp);
4178
4719
    share->delete_record=tmp.delete_record;