~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_check.c

Removed SCCS references.

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
 
  if (ftruncate(share->kfile, info->state->key_file_length))
 
1668
  if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0)))
1552
1669
  {
1553
1670
    mi_check_print_warning(param,
1554
1671
                           "Can't change size of indexfile, error: %d",
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)
2275
2505
      skr=share->base.reloc*share->base.min_pack_length;
2276
2506
#endif
2277
2507
    if (skr != sort_info.filelength && !info->s->base.raid_type)
2278
 
      if (ftruncate(info->dfile, skr))
 
2508
      if (my_chsize(info->dfile,skr,0,MYF(0)))
2279
2509
        mi_check_print_warning(param,
2280
2510
                               "Can't change size of datafile,  error: %d",
2281
2511
                               my_errno);
2283
2513
  if (param->testflag & T_CALC_CHECKSUM)
2284
2514
    info->state->checksum=param->glob_crc;
2285
2515
 
2286
 
  if (ftruncate(share->kfile, info->state->key_file_length))
 
2516
  if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0)))
2287
2517
    mi_check_print_warning(param,
2288
2518
                           "Can't change size of indexfile, error: %d",
2289
2519
                           my_errno);
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
/*
2403
2630
int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
2404
2631
                        const char * name, int rep_quick)
2405
2632
{
 
2633
#ifndef THREAD
 
2634
  return mi_repair_by_sort(param, info, name, rep_quick);
 
2635
#else
2406
2636
  int got_error;
2407
 
  uint32_t i,key, total_key_length, istep;
 
2637
  uint i,key, total_key_length, istep;
2408
2638
  ulong rec_length;
2409
2639
  ha_rows start_records;
2410
2640
  my_off_t new_header_length,del;
2417
2647
  IO_CACHE new_data_cache; /* For non-quick repair. */
2418
2648
  IO_CACHE_SHARE io_share;
2419
2649
  SORT_INFO sort_info;
2420
 
  uint64_t key_map= 0;
 
2650
  ulonglong key_map= 0;
2421
2651
  pthread_attr_t thr_attr;
2422
2652
  ulong max_pack_reclength;
 
2653
  DBUG_ENTER("mi_repair_parallel");
2423
2654
 
2424
2655
  start_records=info->state->records;
2425
2656
  got_error=1;
2464
2695
      position 'new_header_length'.
2465
2696
    }
2466
2697
  */
2467
 
  memset(&sort_info, 0, sizeof(sort_info));
 
2698
  DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
 
2699
  bzero((char*)&sort_info,sizeof(sort_info));
2468
2700
  /* Initialize pthread structures before goto err. */
2469
2701
  pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2470
2702
  pthread_cond_init(&sort_info.cond, 0);
2492
2724
  if (!rep_quick)
2493
2725
  {
2494
2726
    /* 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)
 
2727
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2728
                                           share->data_file_name, "",
 
2729
                                           DATA_TMP_EXT,
 
2730
                                           2+4),
 
2731
                                 0,param->tmpfile_createflag,
 
2732
                                 share->base.raid_type,
 
2733
                                 share->base.raid_chunks,
 
2734
                                 share->base.raid_chunksize,
 
2735
                                 MYF(0))) < 0)
2501
2736
    {
2502
2737
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2738
                           param->temp_filename);
2519
2754
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2520
2755
 
2521
2756
  /* Optionally drop indexes and optionally modify the key_map. */
2522
 
  mi_drop_all_indexes(param, info, false);
 
2757
  mi_drop_all_indexes(param, info, FALSE);
2523
2758
  key_map= share->state.key_map;
2524
2759
  if (param->testflag & T_CREATE_MISSING_KEYS)
2525
2760
  {
2537
2772
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2538
2773
 
2539
2774
  if (share->data_file_type == DYNAMIC_RECORD)
2540
 
    rec_length=cmax(share->base.min_pack_length+1,share->base.min_block_length);
 
2775
    rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2541
2776
  else if (share->data_file_type == COMPRESSED_RECORD)
2542
2777
    rec_length=share->base.min_block_length;
2543
2778
  else
2590
2825
    if (! mi_is_key_active(key_map, key))
2591
2826
    {
2592
2827
      /* 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)),
 
2828
      memcpy((char*) rec_per_key_part,
 
2829
             (char*) (share->state.rec_per_key_part+
 
2830
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2597
2831
             sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2598
2832
      istep=0;
2599
2833
      continue;
2601
2835
    istep=1;
2602
2836
    if ((!(param->testflag & T_SILENT)))
2603
2837
      printf ("- Fixing index %d\n",key+1);
 
2838
    if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
 
2839
    {
 
2840
      sort_param[i].key_read=sort_ft_key_read;
 
2841
      sort_param[i].key_write=sort_ft_key_write;
 
2842
    }
 
2843
    else
2604
2844
    {
2605
2845
      sort_param[i].key_read=sort_key_read;
2606
2846
      sort_param[i].key_write=sort_key_write;
2616
2856
    sort_param[i].filepos=new_header_length;
2617
2857
    sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2618
2858
 
2619
 
    sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
 
2859
    sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2620
2860
                           (max_pack_reclength * i));
2621
2861
    if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2622
2862
    {
2637
2877
        sort_param[i].key_length++;
2638
2878
    }
2639
2879
    total_key_length+=sort_param[i].key_length;
 
2880
 
 
2881
    if (sort_param[i].keyinfo->flag & HA_FULLTEXT)
 
2882
    {
 
2883
      uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
 
2884
                                    sort_param[i].keyinfo->seg->charset->mbmaxlen;
 
2885
      sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
 
2886
      init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
 
2887
    }
2640
2888
  }
2641
2889
  sort_info.total_keys=i;
2642
2890
  sort_param[0].master= 1;
2643
 
  sort_param[0].fix_datafile= (bool)(! rep_quick);
 
2891
  sort_param[0].fix_datafile= (my_bool)(! rep_quick);
2644
2892
  sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM);
2645
2893
 
2646
2894
  sort_info.got_error=0;
2677
2925
    */
2678
2926
    sort_param[i].read_cache= ((rep_quick || !i) ? param->read_cache :
2679
2927
                               new_data_cache);
 
2928
    DBUG_PRINT("io_cache_share", ("thread: %u  read_cache: 0x%lx",
 
2929
                                  i, (long) &sort_param[i].read_cache));
2680
2930
 
2681
2931
    /*
2682
2932
      two approaches: the same amount of memory for each thread
2698
2948
      /* Cleanup: Detach from the share. Avoid others to be blocked. */
2699
2949
      if (io_share.total_threads)
2700
2950
        remove_io_thread(&sort_param[i].read_cache);
 
2951
      DBUG_PRINT("error", ("Cannot start a repair thread"));
2701
2952
      sort_info.got_error=1;
2702
2953
    }
2703
2954
    else
2773
3024
      skr=share->base.reloc*share->base.min_pack_length;
2774
3025
#endif
2775
3026
    if (skr != sort_info.filelength && !info->s->base.raid_type)
2776
 
      if (ftruncate(info->dfile, skr))
 
3027
      if (my_chsize(info->dfile,skr,0,MYF(0)))
2777
3028
        mi_check_print_warning(param,
2778
3029
                               "Can't change size of datafile,  error: %d",
2779
3030
                               my_errno);
2781
3032
  if (param->testflag & T_CALC_CHECKSUM)
2782
3033
    info->state->checksum=param->glob_crc;
2783
3034
 
2784
 
  if (ftruncate(share->kfile, info->state->key_file_length))
 
3035
  if (my_chsize(share->kfile,info->state->key_file_length,0,MYF(0)))
2785
3036
    mi_check_print_warning(param,
2786
3037
                           "Can't change size of indexfile, error: %d", my_errno);
2787
3038
 
2806
3057
    the share by remove_io_thread() or it was not yet started (if the
2807
3058
    error happend before creating the thread).
2808
3059
  */
2809
 
  end_io_cache(&info->rec_cache);
 
3060
  VOID(end_io_cache(&info->rec_cache));
2810
3061
  /*
2811
3062
    Destroy the new data cache in case of non-quick repair. All slave
2812
3063
    threads did either detach from the share by remove_io_thread()
2814
3065
    creating the threads).
2815
3066
  */
2816
3067
  if (!rep_quick)
2817
 
    end_io_cache(&new_data_cache);
 
3068
    VOID(end_io_cache(&new_data_cache));
2818
3069
  if (!got_error)
2819
3070
  {
2820
3071
    /* Replace the actual file with the temporary file */
2836
3087
      mi_check_print_error(param,"%d when fixing table",my_errno);
2837
3088
    if (new_file >= 0)
2838
3089
    {
2839
 
      my_close(new_file,MYF(0));
2840
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
3090
      VOID(my_close(new_file,MYF(0)));
 
3091
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
3092
                          MYF(MY_WME)));
2841
3093
      if (info->dfile == new_file)
2842
 
        info->dfile= -1;
 
3094
        info->dfile= -1;
2843
3095
    }
2844
3096
    mi_mark_crashed_on_repair(info);
2845
3097
  }
2850
3102
  pthread_cond_destroy (&sort_info.cond);
2851
3103
  pthread_mutex_destroy(&sort_info.mutex);
2852
3104
 
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);
 
3105
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
3106
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
3107
  my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
 
3108
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
3109
  VOID(end_io_cache(&param->read_cache));
2857
3110
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2858
3111
  if (!got_error && (param->testflag & T_UNPACK))
2859
3112
  {
2860
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
3113
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2861
3114
    share->pack.header_length=0;
2862
3115
  }
2863
 
  return(got_error);
 
3116
  DBUG_RETURN(got_error);
 
3117
#endif /* THREAD */
2864
3118
}
2865
3119
 
2866
3120
        /* Read next record and return next key */
2870
3124
  int error;
2871
3125
  SORT_INFO *sort_info=sort_param->sort_info;
2872
3126
  MI_INFO *info=sort_info->info;
 
3127
  DBUG_ENTER("sort_key_read");
2873
3128
 
2874
3129
  if ((error=sort_get_next_record(sort_param)))
2875
 
    return(error);
 
3130
    DBUG_RETURN(error);
2876
3131
  if (info->state->records == sort_info->max_records)
2877
3132
  {
2878
3133
    mi_check_print_error(sort_info->param,
2879
3134
                         "Key %d - Found too many records; Can't continue",
2880
3135
                         sort_param->key+1);
2881
 
    return(1);
 
3136
    DBUG_RETURN(1);
2882
3137
  }
2883
3138
  sort_param->real_key_length=
2884
3139
    (info->s->rec_reflength+
2885
 
     _mi_make_key(info, sort_param->key, (unsigned char*) key,
 
3140
     _mi_make_key(info, sort_param->key, (uchar*) key,
2886
3141
                  sort_param->record, sort_param->filepos));
2887
3142
#ifdef HAVE_purify
2888
 
  memset(key+sort_param->real_key_length, 0,
2889
 
         (sort_param->key_length-sort_param->real_key_length));
 
3143
  bzero(key+sort_param->real_key_length,
 
3144
        (sort_param->key_length-sort_param->real_key_length));
2890
3145
#endif
2891
 
  return(sort_write_record(sort_param));
 
3146
  DBUG_RETURN(sort_write_record(sort_param));
2892
3147
} /* sort_key_read */
2893
3148
 
 
3149
static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
 
3150
{
 
3151
  int error;
 
3152
  SORT_INFO *sort_info=sort_param->sort_info;
 
3153
  MI_INFO *info=sort_info->info;
 
3154
  FT_WORD *wptr=0;
 
3155
  DBUG_ENTER("sort_ft_key_read");
 
3156
 
 
3157
  if (!sort_param->wordlist)
 
3158
  {
 
3159
    for (;;)
 
3160
    {
 
3161
      free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
 
3162
      if ((error=sort_get_next_record(sort_param)))
 
3163
        DBUG_RETURN(error);
 
3164
      if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record,
 
3165
                                    &sort_param->wordroot)))
 
3166
        DBUG_RETURN(1);
 
3167
      if (wptr->pos)
 
3168
        break;
 
3169
      error=sort_write_record(sort_param);
 
3170
    }
 
3171
    sort_param->wordptr=sort_param->wordlist=wptr;
 
3172
  }
 
3173
  else
 
3174
  {
 
3175
    error=0;
 
3176
    wptr=(FT_WORD*)(sort_param->wordptr);
 
3177
  }
 
3178
 
 
3179
  sort_param->real_key_length=(info->s->rec_reflength+
 
3180
                               _ft_make_key(info, sort_param->key,
 
3181
                                            key, wptr++, sort_param->filepos));
 
3182
#ifdef HAVE_purify
 
3183
  if (sort_param->key_length > sort_param->real_key_length)
 
3184
    bzero(key+sort_param->real_key_length,
 
3185
          (sort_param->key_length-sort_param->real_key_length));
 
3186
#endif
 
3187
  if (!wptr->pos)
 
3188
  {
 
3189
    free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
 
3190
    sort_param->wordlist=0;
 
3191
    error=sort_write_record(sort_param);
 
3192
  }
 
3193
  else
 
3194
    sort_param->wordptr=(void*)wptr;
 
3195
 
 
3196
  DBUG_RETURN(error);
 
3197
} /* sort_ft_key_read */
 
3198
 
2894
3199
 
2895
3200
/*
2896
3201
  Read next record from file using parameters in sort_info.
2927
3232
{
2928
3233
  int searching;
2929
3234
  int parallel_flag;
2930
 
  uint32_t found_record,b_type,left_length;
 
3235
  uint found_record,b_type,left_length;
2931
3236
  my_off_t pos;
2932
 
  unsigned char *to= NULL;
 
3237
  uchar *to= NULL;
2933
3238
  MI_BLOCK_INFO block_info;
2934
3239
  SORT_INFO *sort_info=sort_param->sort_info;
2935
3240
  MI_CHECK *param=sort_info->param;
2936
3241
  MI_INFO *info=sort_info->info;
2937
3242
  MYISAM_SHARE *share=info->s;
2938
3243
  char llbuff[22],llbuff2[22];
 
3244
  DBUG_ENTER("sort_get_next_record");
2939
3245
 
2940
3246
  if (*killed_ptr(param))
2941
 
    return(1);
 
3247
    DBUG_RETURN(1);
2942
3248
 
2943
3249
  switch (share->data_file_type) {
2944
3250
  case STATIC_RECORD:
2951
3257
          param->out_flag |= O_DATA_LOST;
2952
3258
        param->retry_repair=1;
2953
3259
        param->testflag|=T_RETRY_WITHOUT_QUICK;
2954
 
        return(-1);
 
3260
        DBUG_RETURN(-1);
2955
3261
      }
2956
3262
      sort_param->start_recpos=sort_param->pos;
2957
3263
      if (!sort_param->fix_datafile)
2966
3272
        if (sort_param->calc_checksum)
2967
3273
          param->glob_crc+= (info->checksum=
2968
3274
                             mi_static_checksum(info,sort_param->record));
2969
 
        return(0);
 
3275
        DBUG_RETURN(0);
2970
3276
      }
2971
3277
      if (!sort_param->fix_datafile && sort_param->master)
2972
3278
      {
3005
3311
                     llstr(param->search_after_block,llbuff),
3006
3312
                     llstr(sort_param->start_recpos,llbuff2));
3007
3313
        if (_mi_read_cache(&sort_param->read_cache,
3008
 
                           (unsigned char*) block_info.header,pos,
 
3314
                           (uchar*) block_info.header,pos,
3009
3315
                           MI_BLOCK_INFO_HEADER_LENGTH,
3010
3316
                           (! found_record ? READING_NEXT : 0) |
3011
3317
                           parallel_flag | READING_HEADER))
3017
3323
                                llstr(sort_param->start_recpos,llbuff),errno);
3018
3324
            goto try_next;
3019
3325
          }
3020
 
          return(-1);
 
3326
          DBUG_RETURN(-1);
3021
3327
        }
3022
3328
        if (searching && ! sort_param->fix_datafile)
3023
3329
        {
3024
3330
          param->error_printed=1;
3025
3331
          param->retry_repair=1;
3026
3332
          param->testflag|=T_RETRY_WITHOUT_QUICK;
3027
 
          return(1);    /* Something wrong with data */
 
3333
          DBUG_RETURN(1);       /* Something wrong with data */
3028
3334
        }
3029
3335
        b_type=_mi_get_block_info(&block_info,-1,pos);
3030
3336
        if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3032
3338
             (block_info.rec_len < (uint) share->base.min_pack_length ||
3033
3339
              block_info.rec_len > (uint) share->base.max_pack_length)))
3034
3340
        {
3035
 
          uint32_t i;
 
3341
          uint i;
3036
3342
          if (param->testflag & T_VERBOSE || searching == 0)
3037
3343
            mi_check_print_info(param,
3038
3344
                                "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3055
3361
        }
3056
3362
        if (b_type & BLOCK_DELETED)
3057
3363
        {
3058
 
          bool error=0;
 
3364
          my_bool error=0;
3059
3365
          if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3060
3366
              share->base.min_block_length)
3061
3367
          {
3156
3462
                mi_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
3157
3463
                                     llstr(sort_param->start_recpos,llbuff),
3158
3464
                                     (ulong) block_info.rec_len);
3159
 
                return(1);
 
3465
                DBUG_RETURN(1);
3160
3466
              }
3161
3467
              else
3162
3468
              {
3191
3497
          streched over the end of the previous buffer contents.
3192
3498
        */
3193
3499
        {
3194
 
          uint32_t header_len= (uint) (block_info.filepos - pos);
3195
 
          uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
 
3500
          uint header_len= (uint) (block_info.filepos - pos);
 
3501
          uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3196
3502
 
3197
3503
          if (prefetch_len > block_info.data_len)
3198
3504
            prefetch_len= block_info.data_len;
3238
3544
                         sort_param->find_length) != MY_FILE_ERROR)
3239
3545
      {
3240
3546
        if (sort_param->read_cache.error < 0)
3241
 
          return(1);
 
3547
          DBUG_RETURN(1);
3242
3548
        if (sort_param->calc_checksum)
3243
3549
          info->checksum= mi_checksum(info, sort_param->record);
3244
3550
        if ((param->testflag & (T_EXTEND | T_REP)) || searching)
3256
3562
        }
3257
3563
        if (sort_param->calc_checksum)
3258
3564
          param->glob_crc+= info->checksum;
3259
 
        return(0);
 
3565
        DBUG_RETURN(0);
3260
3566
      }
3261
3567
      if (!searching)
3262
3568
        mi_check_print_info(param,"Key %d - Found wrong stored record at %s",
3267
3573
      searching=1;
3268
3574
    }
3269
3575
  case COMPRESSED_RECORD:
 
3576
    for (searching=0 ;; searching=1, sort_param->pos++)
 
3577
    {
 
3578
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
 
3579
                         sort_param->pos,
 
3580
                         share->pack.ref_length,READING_NEXT))
 
3581
        DBUG_RETURN(-1);
 
3582
      if (searching && ! sort_param->fix_datafile)
 
3583
      {
 
3584
        param->error_printed=1;
 
3585
        param->retry_repair=1;
 
3586
        param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3587
        DBUG_RETURN(1);         /* Something wrong with data */
 
3588
      }
 
3589
      sort_param->start_recpos=sort_param->pos;
 
3590
      if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
 
3591
                                  &sort_param->rec_buff, -1, sort_param->pos))
 
3592
        DBUG_RETURN(-1);
 
3593
      if (!block_info.rec_len &&
 
3594
          sort_param->pos + MEMMAP_EXTRA_MARGIN ==
 
3595
          sort_param->read_cache.end_of_file)
 
3596
        DBUG_RETURN(-1);
 
3597
      if (block_info.rec_len < (uint) share->min_pack_length ||
 
3598
          block_info.rec_len > (uint) share->max_pack_length)
 
3599
      {
 
3600
        if (! searching)
 
3601
          mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
 
3602
                              block_info.rec_len,
 
3603
                              llstr(sort_param->pos,llbuff));
 
3604
        continue;
 
3605
      }
 
3606
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
 
3607
                         block_info.filepos, block_info.rec_len,
 
3608
                         READING_NEXT))
 
3609
      {
 
3610
        if (! searching)
 
3611
          mi_check_print_info(param,"Couldn't read whole record from %s",
 
3612
                              llstr(sort_param->pos,llbuff));
 
3613
        continue;
 
3614
      }
 
3615
      if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
 
3616
                              sort_param->rec_buff, block_info.rec_len))
 
3617
      {
 
3618
        if (! searching)
 
3619
          mi_check_print_info(param,"Found wrong record at %s",
 
3620
                              llstr(sort_param->pos,llbuff));
 
3621
        continue;
 
3622
      }
 
3623
      if (!sort_param->fix_datafile)
 
3624
      {
 
3625
        sort_param->filepos=sort_param->pos;
 
3626
        if (sort_param->master)
 
3627
          share->state.split++;
 
3628
      }
 
3629
      sort_param->max_pos=(sort_param->pos=block_info.filepos+
 
3630
                         block_info.rec_len);
 
3631
      info->packed_length=block_info.rec_len;
 
3632
      if (sort_param->calc_checksum)
 
3633
        param->glob_crc+= (info->checksum=
 
3634
                           mi_checksum(info, sort_param->record));
 
3635
      DBUG_RETURN(0);
 
3636
    }
3270
3637
  case BLOCK_RECORD:
3271
3638
    assert(0);                                  /* Impossible */
3272
3639
  }
3273
 
  return(1);                               /* Impossible */
 
3640
  DBUG_RETURN(1);                               /* Impossible */
3274
3641
}
3275
3642
 
3276
3643
 
3292
3659
int sort_write_record(MI_SORT_PARAM *sort_param)
3293
3660
{
3294
3661
  int flag;
 
3662
  uint length;
3295
3663
  ulong block_length,reclength;
3296
 
  unsigned char *from;
 
3664
  uchar *from;
 
3665
  uchar block_buff[8];
3297
3666
  SORT_INFO *sort_info=sort_param->sort_info;
3298
3667
  MI_CHECK *param=sort_info->param;
3299
3668
  MI_INFO *info=sort_info->info;
3300
3669
  MYISAM_SHARE *share=info->s;
 
3670
  DBUG_ENTER("sort_write_record");
3301
3671
 
3302
3672
  if (sort_param->fix_datafile)
3303
3673
  {
3307
3677
                     share->base.pack_reclength))
3308
3678
      {
3309
3679
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
3310
 
        return(1);
 
3680
        DBUG_RETURN(1);
3311
3681
      }
3312
3682
      sort_param->filepos+=share->base.pack_reclength;
3313
3683
      info->s->state.split++;
3328
3698
          if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3329
3699
                                           MYF(MY_FREE_ON_ERROR |
3330
3700
                                               MY_ALLOW_ZERO_PTR))))
3331
 
            return(1);
 
3701
            DBUG_RETURN(1);
3332
3702
          sort_info->buff_length=reclength;
3333
3703
        }
3334
3704
        from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3353
3723
                                  &from,&reclength,&flag))
3354
3724
        {
3355
3725
          mi_check_print_error(param,"%d when writing to datafile",my_errno);
3356
 
          return(1);
 
3726
          DBUG_RETURN(1);
3357
3727
        }
3358
3728
        sort_param->filepos+=block_length;
3359
3729
        info->s->state.split++;
3361
3731
      /* sort_info->param->glob_crc+=info->checksum; */
3362
3732
      break;
3363
3733
    case COMPRESSED_RECORD:
 
3734
      reclength=info->packed_length;
 
3735
      length= save_pack_length((uint) share->pack.version, block_buff,
 
3736
                               reclength);
 
3737
      if (info->s->base.blobs)
 
3738
        length+= save_pack_length((uint) share->pack.version,
 
3739
                                  block_buff + length, info->blob_length);
 
3740
      if (my_b_write(&info->rec_cache,block_buff,length) ||
 
3741
          my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
 
3742
      {
 
3743
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3744
        DBUG_RETURN(1);
 
3745
      }
 
3746
      /* sort_info->param->glob_crc+=info->checksum; */
 
3747
      sort_param->filepos+=reclength+length;
 
3748
      info->s->state.split++;
 
3749
      break;
3364
3750
    case BLOCK_RECORD:
3365
3751
      assert(0);                                  /* Impossible */
3366
3752
    }
3373
3759
    {
3374
3760
      char llbuff[22];
3375
3761
      printf("%s\r", llstr(info->state->records,llbuff));
3376
 
      fflush(stdout);
 
3762
      VOID(fflush(stdout));
3377
3763
    }
3378
3764
  }
3379
 
  return(0);
 
3765
  DBUG_RETURN(0);
3380
3766
} /* sort_write_record */
3381
3767
 
3382
3768
 
3385
3771
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3386
3772
                        const void *b)
3387
3773
{
3388
 
  uint32_t not_used[2];
3389
 
  return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
 
3774
  uint not_used[2];
 
3775
  return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3390
3776
                     USE_WHOLE_KEY, SEARCH_SAME, not_used));
3391
3777
} /* sort_key_cmp */
3392
3778
 
3393
3779
 
3394
3780
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3395
3781
{
3396
 
  uint32_t diff_pos[2];
 
3782
  uint diff_pos[2];
3397
3783
  char llbuff[22],llbuff2[22];
3398
3784
  SORT_INFO *sort_info=sort_param->sort_info;
3399
3785
  MI_CHECK *param= sort_info->param;
3402
3788
  if (sort_info->key_block->inited)
3403
3789
  {
3404
3790
    cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
 
                   (unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
 
3791
                   (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3406
3792
                   diff_pos);
3407
3793
    if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3408
3794
      ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3409
 
                 (unsigned char*) a, USE_WHOLE_KEY, 
 
3795
                 (uchar*) a, USE_WHOLE_KEY, 
3410
3796
                 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3411
3797
    else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3412
3798
    {
3413
3799
      diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3414
3800
                                                 sort_param->notnull,
3415
3801
                                                 sort_info->key_block->lastkey,
3416
 
                                                 (unsigned char*)a);
 
3802
                                                 (uchar*)a);
3417
3803
    }
3418
3804
    sort_param->unique[diff_pos[0]-1]++;
3419
3805
  }
3422
3808
    cmp= -1;
3423
3809
    if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3424
3810
      mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3425
 
                                     (unsigned char*)a);
 
3811
                                     (uchar*)a);
3426
3812
  }
3427
3813
  if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3428
3814
  {
3429
3815
    sort_info->dupp++;
3430
3816
    sort_info->info->lastpos=get_record_for_key(sort_info->info,
3431
3817
                                                sort_param->keyinfo,
3432
 
                                                (unsigned char*) a);
 
3818
                                                (uchar*) a);
3433
3819
    mi_check_print_warning(param,
3434
3820
                           "Duplicate key for record at %10s against record at %10s",
3435
3821
                           llstr(sort_info->info->lastpos,llbuff),
3439
3825
                                                    lastkey),
3440
3826
                                 llbuff2));
3441
3827
    param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3828
    if (sort_info->param->testflag & T_VERBOSE)
 
3829
      _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3442
3830
    return (sort_delete_record(sort_param));
3443
3831
  }
 
3832
#ifndef DBUG_OFF
 
3833
  if (cmp > 0)
 
3834
  {
 
3835
    mi_check_print_error(param,
 
3836
                         "Internal error: Keys are not in order from sort");
 
3837
    return(1);
 
3838
  }
 
3839
#endif
3444
3840
  return (sort_insert_key(sort_param,sort_info->key_block,
3445
 
                          (unsigned char*) a, HA_OFFSET_ERROR));
 
3841
                          (uchar*) a, HA_OFFSET_ERROR));
3446
3842
} /* sort_key_write */
3447
3843
 
 
3844
int sort_ft_buf_flush(MI_SORT_PARAM *sort_param)
 
3845
{
 
3846
  SORT_INFO *sort_info=sort_param->sort_info;
 
3847
  SORT_KEY_BLOCKS *key_block=sort_info->key_block;
 
3848
  MYISAM_SHARE *share=sort_info->info->s;
 
3849
  uint val_off, val_len;
 
3850
  int error;
 
3851
  SORT_FT_BUF *ft_buf=sort_info->ft_buf;
 
3852
  uchar *from, *to;
 
3853
 
 
3854
  val_len=share->ft2_keyinfo.keylength;
 
3855
  get_key_full_length_rdonly(val_off, ft_buf->lastkey);
 
3856
  to=ft_buf->lastkey+val_off;
 
3857
 
 
3858
  if (ft_buf->buf)
 
3859
  {
 
3860
    /* flushing first-level tree */
 
3861
    error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
 
3862
                          HA_OFFSET_ERROR);
 
3863
    for (from=to+val_len;
 
3864
         !error && from < ft_buf->buf;
 
3865
         from+= val_len)
 
3866
    {
 
3867
      memcpy(to, from, val_len);
 
3868
      error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
 
3869
                            HA_OFFSET_ERROR);
 
3870
    }
 
3871
    return error;
 
3872
  }
 
3873
  /* flushing second-level tree keyblocks */
 
3874
  error=flush_pending_blocks(sort_param);
 
3875
  /* updating lastkey with second-level tree info */
 
3876
  ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count);
 
3877
  _mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN,
 
3878
      share->state.key_root[sort_param->key]);
 
3879
  /* restoring first level tree data in sort_info/sort_param */
 
3880
  sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
 
3881
  sort_param->keyinfo=share->keyinfo+sort_param->key;
 
3882
  share->state.key_root[sort_param->key]=HA_OFFSET_ERROR;
 
3883
  /* writing lastkey in first-level tree */
 
3884
  return error ? error :
 
3885
                 sort_insert_key(sort_param,sort_info->key_block,
 
3886
                                 ft_buf->lastkey,HA_OFFSET_ERROR);
 
3887
}
 
3888
 
 
3889
static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
 
3890
{
 
3891
  uint a_len, val_off, val_len, error;
 
3892
  uchar *p;
 
3893
  SORT_INFO *sort_info=sort_param->sort_info;
 
3894
  SORT_FT_BUF *ft_buf=sort_info->ft_buf;
 
3895
  SORT_KEY_BLOCKS *key_block=sort_info->key_block;
 
3896
 
 
3897
  val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
 
3898
  get_key_full_length_rdonly(a_len, (uchar *)a);
 
3899
 
 
3900
  if (!ft_buf)
 
3901
  {
 
3902
    /*
 
3903
      use two-level tree only if key_reflength fits in rec_reflength place
 
3904
      and row format is NOT static - for _mi_dpointer not to garble offsets
 
3905
     */
 
3906
    if ((sort_info->info->s->base.key_reflength <=
 
3907
         sort_info->info->s->base.rec_reflength) &&
 
3908
        (sort_info->info->s->options &
 
3909
          (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
 
3910
      ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
 
3911
                                      sizeof(SORT_FT_BUF), MYF(MY_WME));
 
3912
 
 
3913
    if (!ft_buf)
 
3914
    {
 
3915
      sort_param->key_write=sort_key_write;
 
3916
      return sort_key_write(sort_param, a);
 
3917
    }
 
3918
    sort_info->ft_buf=ft_buf;
 
3919
    goto word_init_ft_buf; /* no need to duplicate the code */
 
3920
  }
 
3921
  get_key_full_length_rdonly(val_off, ft_buf->lastkey);
 
3922
 
 
3923
  if (ha_compare_text(sort_param->seg->charset,
 
3924
                      ((uchar *)a)+1,a_len-1,
 
3925
                      ft_buf->lastkey+1,val_off-1, 0, 0)==0)
 
3926
  {
 
3927
    if (!ft_buf->buf) /* store in second-level tree */
 
3928
    {
 
3929
      ft_buf->count++;
 
3930
      return sort_insert_key(sort_param,key_block,
 
3931
                             ((uchar *)a)+a_len, HA_OFFSET_ERROR);
 
3932
    }
 
3933
 
 
3934
    /* storing the key in the buffer. */
 
3935
    memcpy (ft_buf->buf, (char *)a+a_len, val_len);
 
3936
    ft_buf->buf+=val_len;
 
3937
    if (ft_buf->buf < ft_buf->end)
 
3938
      return 0;
 
3939
 
 
3940
    /* converting to two-level tree */
 
3941
    p=ft_buf->lastkey+val_off;
 
3942
 
 
3943
    while (key_block->inited)
 
3944
      key_block++;
 
3945
    sort_info->key_block=key_block;
 
3946
    sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo;
 
3947
    ft_buf->count=(ft_buf->buf - p)/val_len;
 
3948
 
 
3949
    /* flushing buffer to second-level tree */
 
3950
    for (error=0; !error && p < ft_buf->buf; p+= val_len)
 
3951
      error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR);
 
3952
    ft_buf->buf=0;
 
3953
    return error;
 
3954
  }
 
3955
 
 
3956
  /* flushing buffer */
 
3957
  if ((error=sort_ft_buf_flush(sort_param)))
 
3958
    return error;
 
3959
 
 
3960
word_init_ft_buf:
 
3961
  a_len+=val_len;
 
3962
  memcpy(ft_buf->lastkey, a, a_len);
 
3963
  ft_buf->buf=ft_buf->lastkey+a_len;
 
3964
  /*
 
3965
    32 is just a safety margin here
 
3966
    (at least max(val_len, sizeof(nod_flag)) should be there).
 
3967
    May be better performance could be achieved if we'd put
 
3968
      (sort_info->keyinfo->block_length-32)/XXX
 
3969
      instead.
 
3970
        TODO: benchmark the best value for XXX.
 
3971
  */
 
3972
  ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
 
3973
  return 0;
 
3974
} /* sort_ft_key_write */
 
3975
 
3448
3976
 
3449
3977
        /* get pointer to record from a key */
3450
3978
 
3451
3979
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3452
 
                                   unsigned char *key)
 
3980
                                   uchar *key)
3453
3981
{
3454
3982
  return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3455
3983
} /* get_record_for_key */
3458
3986
        /* Insert a key in sort-key-blocks */
3459
3987
 
3460
3988
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3461
 
                           register SORT_KEY_BLOCKS *key_block, unsigned char *key,
 
3989
                           register SORT_KEY_BLOCKS *key_block, uchar *key,
3462
3990
                           my_off_t prev_block)
3463
3991
{
3464
 
  uint32_t a_length,t_length,nod_flag;
 
3992
  uint a_length,t_length,nod_flag;
3465
3993
  my_off_t filepos,key_file_length;
3466
 
  unsigned char *anc_buff,*lastkey;
 
3994
  uchar *anc_buff,*lastkey;
3467
3995
  MI_KEY_PARAM s_temp;
3468
3996
  MI_INFO *info;
3469
3997
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
3470
3998
  SORT_INFO *sort_info= sort_param->sort_info;
3471
3999
  MI_CHECK *param=sort_info->param;
 
4000
  DBUG_ENTER("sort_insert_key");
3472
4001
 
3473
4002
  anc_buff=key_block->buff;
3474
4003
  info=sort_info->info;
3482
4011
    if (key_block == sort_info->key_block_end)
3483
4012
    {
3484
4013
      mi_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks");
3485
 
      return(1);
 
4014
      DBUG_RETURN(1);
3486
4015
    }
3487
4016
    a_length=2+nod_flag;
3488
4017
    key_block->end_pos=anc_buff+2;
3496
4025
    _mi_kpointer(info,key_block->end_pos,prev_block);
3497
4026
 
3498
4027
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3499
 
                                (unsigned char*) 0,lastkey,lastkey,key,
 
4028
                                (uchar*) 0,lastkey,lastkey,key,
3500
4029
                                 &s_temp);
3501
4030
  (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3502
4031
  a_length+=t_length;
3504
4033
  key_block->end_pos+=t_length;
3505
4034
  if (a_length <= keyinfo->block_length)
3506
4035
  {
3507
 
    _mi_move_key(keyinfo,key_block->lastkey,key);
 
4036
    VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3508
4037
    key_block->last_length=a_length-t_length;
3509
 
    return(0);
 
4038
    DBUG_RETURN(0);
3510
4039
  }
3511
4040
 
3512
4041
        /* Fill block with end-zero and write filled block */
3513
4042
  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);
 
4043
  bzero((uchar*) anc_buff+key_block->last_length,
 
4044
        keyinfo->block_length- key_block->last_length);
3516
4045
  key_file_length=info->state->key_file_length;
3517
4046
  if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3518
 
    return(1);
 
4047
    DBUG_RETURN(1);
3519
4048
 
3520
4049
  /* If we read the page from the key cache, we have to write it back to it */
3521
4050
  if (key_file_length == info->state->key_file_length)
3522
4051
  {
3523
4052
    if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3524
 
      return(1);
 
4053
      DBUG_RETURN(1);
3525
4054
  }
3526
 
  else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
 
4055
  else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3527
4056
                     (uint) keyinfo->block_length,filepos, param->myf_rw))
3528
 
    return(1);
 
4057
    DBUG_RETURN(1);
 
4058
  DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3529
4059
 
3530
4060
        /* Write separator-key to block in next level */
3531
4061
  if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3532
 
    return(1);
 
4062
    DBUG_RETURN(1);
3533
4063
 
3534
4064
        /* clear old block and write new key in it */
3535
4065
  key_block->inited=0;
3536
 
  return(sort_insert_key(sort_param, key_block,key,prev_block));
 
4066
  DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3537
4067
} /* sort_insert_key */
3538
4068
 
3539
4069
 
3541
4071
 
3542
4072
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3543
4073
{
3544
 
  uint32_t i;
 
4074
  uint i;
3545
4075
  int old_file,error;
3546
 
  unsigned char *key;
 
4076
  uchar *key;
3547
4077
  SORT_INFO *sort_info=sort_param->sort_info;
3548
4078
  MI_CHECK *param=sort_info->param;
3549
4079
  MI_INFO *info=sort_info->info;
 
4080
  DBUG_ENTER("sort_delete_record");
3550
4081
 
3551
4082
  if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3552
4083
  {
3553
4084
    mi_check_print_error(param,
3554
4085
                         "Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3555
 
    return(1);
 
4086
    DBUG_RETURN(1);
3556
4087
  }
3557
4088
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3558
4089
  {
3559
4090
    mi_check_print_error(param,
3560
4091
                         "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);
 
4092
    DBUG_RETURN(1);
3562
4093
  }
3563
4094
 
3564
4095
  old_file=info->dfile;
3571
4102
    {
3572
4103
      mi_check_print_error(param,"Can't read record to be removed");
3573
4104
      info->dfile=old_file;
3574
 
      return(1);
 
4105
      DBUG_RETURN(1);
3575
4106
    }
3576
4107
 
3577
4108
    for (i=0 ; i < sort_info->current_key ; i++)
3578
4109
    {
3579
 
      uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
 
4110
      uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3580
4111
      if (_mi_ck_delete(info,i,key,key_length))
3581
4112
      {
3582
4113
        mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3583
4114
        info->dfile=old_file;
3584
 
        return(1);
 
4115
        DBUG_RETURN(1);
3585
4116
      }
3586
4117
    }
3587
4118
    if (sort_param->calc_checksum)
3590
4121
  error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3591
4122
  info->dfile=old_file;                         /* restore actual value */
3592
4123
  info->state->records--;
3593
 
  return(error);
 
4124
  DBUG_RETURN(error);
3594
4125
} /* sort_delete_record */
3595
4126
 
3596
4127
        /* Fix all pending blocks and flush everything to disk */
3597
4128
 
3598
4129
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3599
4130
{
3600
 
  uint32_t nod_flag,length;
 
4131
  uint nod_flag,length;
3601
4132
  my_off_t filepos,key_file_length;
3602
4133
  SORT_KEY_BLOCKS *key_block;
3603
4134
  SORT_INFO *sort_info= sort_param->sort_info;
3604
4135
  myf myf_rw=sort_info->param->myf_rw;
3605
4136
  MI_INFO *info=sort_info->info;
3606
4137
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
 
4138
  DBUG_ENTER("flush_pending_blocks");
3607
4139
 
3608
4140
  filepos= HA_OFFSET_ERROR;                     /* if empty file */
3609
4141
  nod_flag=0;
3614
4146
    if (nod_flag)
3615
4147
      _mi_kpointer(info,key_block->end_pos,filepos);
3616
4148
    key_file_length=info->state->key_file_length;
3617
 
    memset(key_block->buff+length, 0, keyinfo->block_length-length);
 
4149
    bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3618
4150
    if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3619
 
      return(1);
 
4151
      DBUG_RETURN(1);
3620
4152
 
3621
4153
    /* If we read the page from the key cache, we have to write it back */
3622
4154
    if (key_file_length == info->state->key_file_length)
3623
4155
    {
3624
4156
      if (_mi_write_keypage(info, keyinfo, filepos,
3625
4157
                            DFLT_INIT_HITS, key_block->buff))
3626
 
        return(1);
 
4158
        DBUG_RETURN(1);
3627
4159
    }
3628
 
    else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
 
4160
    else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3629
4161
                       (uint) keyinfo->block_length,filepos, myf_rw))
3630
 
      return(1);
 
4162
      DBUG_RETURN(1);
 
4163
    DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3631
4164
    nod_flag=1;
3632
4165
  }
3633
4166
  info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3634
 
  return(0);
 
4167
  DBUG_RETURN(0);
3635
4168
} /* flush_pending_blocks */
3636
4169
 
3637
4170
        /* alloc space and pointers for key_blocks */
3638
4171
 
3639
 
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3640
 
                                         uint32_t buffer_length)
 
4172
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
4173
                                         uint buffer_length)
3641
4174
{
3642
 
  register uint32_t i;
 
4175
  register uint i;
3643
4176
  SORT_KEY_BLOCKS *block;
 
4177
  DBUG_ENTER("alloc_key_blocks");
3644
4178
 
3645
4179
  if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
3646
4180
                                            buffer_length+IO_SIZE)*blocks,
3652
4186
  for (i=0 ; i < blocks ; i++)
3653
4187
  {
3654
4188
    block[i].inited=0;
3655
 
    block[i].buff=(unsigned char*) (block+blocks)+(buffer_length+IO_SIZE)*i;
 
4189
    block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
3656
4190
  }
3657
 
  return(block);
 
4191
  DBUG_RETURN(block);
3658
4192
} /* alloc_key_blocks */
3659
4193
 
3660
4194
 
3682
4216
  MI_COLUMNDEF *recdef,*rec,*end;
3683
4217
  MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3684
4218
  MI_STATUS_INFO status_info;
3685
 
  uint32_t unpack,key_parts;
 
4219
  uint unpack,key_parts;
3686
4220
  ha_rows max_records;
3687
 
  uint64_t file_length,tmp_length;
 
4221
  ulonglong file_length,tmp_length;
3688
4222
  MI_CREATE_INFO create_info;
 
4223
  DBUG_ENTER("recreate_table");
3689
4224
 
3690
4225
  error=1;                                      /* Default error */
3691
4226
  info= **org_info;
3695
4230
  unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3696
4231
    (param->testflag & T_UNPACK);
3697
4232
  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);
 
4233
    DBUG_RETURN(0);
 
4234
  memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
 
4235
         (size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3700
4236
 
3701
4237
  key_parts= share.base.all_key_parts;
3702
4238
  if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3703
4239
                                       (key_parts+share.base.keys))))
3704
4240
  {
3705
 
    my_afree((unsigned char*) keyinfo);
3706
 
    return(1);
 
4241
    my_afree((uchar*) keyinfo);
 
4242
    DBUG_RETURN(1);
3707
4243
  }
3708
4244
  if (!(recdef=(MI_COLUMNDEF*)
3709
4245
        my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3710
4246
  {
3711
 
    my_afree((unsigned char*) keyinfo);
3712
 
    my_afree((unsigned char*) keysegs);
3713
 
    return(1);
 
4247
    my_afree((uchar*) keyinfo);
 
4248
    my_afree((uchar*) keysegs);
 
4249
    DBUG_RETURN(1);
3714
4250
  }
3715
4251
  if (!(uniquedef=(MI_UNIQUEDEF*)
3716
4252
        my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3717
4253
  {
3718
 
    my_afree((unsigned char*) recdef);
3719
 
    my_afree((unsigned char*) keyinfo);
3720
 
    my_afree((unsigned char*) keysegs);
3721
 
    return(1);
 
4254
    my_afree((uchar*) recdef);
 
4255
    my_afree((uchar*) keyinfo);
 
4256
    my_afree((uchar*) keysegs);
 
4257
    DBUG_RETURN(1);
3722
4258
  }
3723
4259
 
3724
4260
  /* Copy the column definitions */
3725
 
  memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
 
4261
  memcpy((uchar*) recdef,(uchar*) share.rec,
 
4262
         (size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3726
4263
  for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3727
4264
  {
3728
4265
    if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3733
4270
  }
3734
4271
 
3735
4272
  /* 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));
 
4273
  memcpy((uchar*) keysegs,(uchar*) share.keyparts,
 
4274
         (size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
 
4275
                                      share.state.header.uniques)));
3739
4276
  keyseg=keysegs;
3740
4277
  for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3741
4278
  {
3750
4287
 
3751
4288
  /* Copy the unique definitions and change them to point at the new key
3752
4289
     segments*/
3753
 
  memcpy(uniquedef,share.uniqueinfo,
3754
 
         sizeof(MI_UNIQUEDEF)*(share.state.header.uniques));
 
4290
  memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
 
4291
         (size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3755
4292
  for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3756
4293
       u_ptr != u_end ; u_ptr++)
3757
4294
  {
3769
4306
    (param->testflag & T_UNPACK);
3770
4307
  share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3771
4308
 
3772
 
  file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
 
4309
  file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3773
4310
  tmp_length= file_length+file_length/10;
3774
4311
  set_if_bigger(file_length,param->max_data_file_length);
3775
4312
  set_if_bigger(file_length,tmp_length);
3776
 
  set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
 
4313
  set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
3777
4314
 
3778
 
  mi_close(*org_info);
3779
 
  memset(&create_info, 0, sizeof(create_info));
3780
 
  create_info.max_rows=cmax(max_records,share.base.records);
 
4315
  VOID(mi_close(*org_info));
 
4316
  bzero((char*) &create_info,sizeof(create_info));
 
4317
  create_info.max_rows=max(max_records,share.base.records);
3781
4318
  create_info.reloc_rows=share.base.reloc;
3782
4319
  create_info.old_options=(share.options |
3783
4320
                           (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0));
3791
4328
    Allow for creating an auto_increment key. This has an effect only if
3792
4329
    an auto_increment key exists in the original table.
3793
4330
  */
3794
 
  create_info.with_auto_increment= true;
 
4331
  create_info.with_auto_increment= TRUE;
3795
4332
  /* We don't have to handle symlinks here because we are using
3796
4333
     HA_DONT_TOUCH_DATA */
3797
4334
  if (mi_create(filename,
3816
4353
  }
3817
4354
  /* We are modifing */
3818
4355
  (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3819
 
  _mi_readinfo(*org_info,F_WRLCK,0);
 
4356
  VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3820
4357
  (*org_info)->state->records=info.state->records;
3821
4358
  if (share.state.create_time)
3822
4359
    (*org_info)->s->state.create_time=share.state.create_time;
3832
4369
    goto end;
3833
4370
  error=0;
3834
4371
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);
 
4372
  my_afree((uchar*) uniquedef);
 
4373
  my_afree((uchar*) keyinfo);
 
4374
  my_afree((uchar*) recdef);
 
4375
  my_afree((uchar*) keysegs);
 
4376
  DBUG_RETURN(error);
3840
4377
}
3841
4378
 
3842
4379
 
3843
4380
        /* write suffix to data file if neaded */
3844
4381
 
3845
 
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
 
4382
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3846
4383
{
3847
4384
  MI_INFO *info=sort_info->info;
3848
4385
 
3849
4386
  if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3850
4387
  {
3851
 
    unsigned char buff[MEMMAP_EXTRA_MARGIN];
3852
 
    memset(buff, 0, sizeof(buff));
 
4388
    uchar buff[MEMMAP_EXTRA_MARGIN];
 
4389
    bzero(buff,sizeof(buff));
3853
4390
    if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3854
4391
    {
3855
4392
      mi_check_print_error(sort_info->param,
3863
4400
 
3864
4401
        /* Update state and myisamchk_time of indexfile */
3865
4402
 
3866
 
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
 
4403
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3867
4404
{
3868
4405
  MYISAM_SHARE *share=info->s;
3869
4406
 
3874
4411
  }
3875
4412
  if (update & UPDATE_STAT)
3876
4413
  {
3877
 
    uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
 
4414
    uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3878
4415
    share->state.rec_per_key_rows=info->state->records;
3879
4416
    share->state.changed&= ~STATE_NOT_ANALYZED;
3880
4417
    if (info->state->records)
3908
4445
  }
3909
4446
  {                                             /* Force update of status */
3910
4447
    int error;
3911
 
    uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
 
4448
    uint r_locks=share->r_locks,w_locks=share->w_locks;
3912
4449
    share->r_locks= share->w_locks= share->tot_locks= 0;
3913
4450
    error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3914
4451
    share->r_locks=r_locks;
3936
4473
        */
3937
4474
 
3938
4475
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3939
 
                               bool repair_only)
 
4476
                               my_bool repair_only)
3940
4477
{
3941
 
  unsigned char *record= 0;
 
4478
  uchar *record= 0;
 
4479
  DBUG_ENTER("update_auto_increment_key");
3942
4480
 
3943
4481
  if (!info->s->base.auto_key ||
3944
4482
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3947
4485
      mi_check_print_info(param,
3948
4486
                          "Table: %s doesn't have an auto increment key\n",
3949
4487
                          param->isam_file_name);
3950
 
    return;
 
4488
    DBUG_VOID_RETURN;
3951
4489
  }
3952
4490
  if (!(param->testflag & T_SILENT) &&
3953
4491
      !(param->testflag & T_REP))
3959
4497
  if (!mi_alloc_rec_buff(info, -1, &record))
3960
4498
  {
3961
4499
    mi_check_print_error(param,"Not enough memory for extra record");
3962
 
    return;
 
4500
    DBUG_VOID_RETURN;
3963
4501
  }
3964
4502
 
3965
4503
  mi_extra(info,HA_EXTRA_KEYREAD,0);
3968
4506
    if (my_errno != HA_ERR_END_OF_FILE)
3969
4507
    {
3970
4508
      mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3971
 
      free(mi_get_rec_buff_ptr(info, record));
 
4509
      my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3972
4510
      mi_check_print_error(param,"%d when reading last record",my_errno);
3973
 
      return;
 
4511
      DBUG_VOID_RETURN;
3974
4512
    }
3975
4513
    if (!repair_only)
3976
4514
      info->s->state.auto_increment=param->auto_increment_value;
3977
4515
  }
3978
4516
  else
3979
4517
  {
3980
 
    uint64_t auto_increment= retrieve_auto_increment(info, record);
 
4518
    ulonglong auto_increment= retrieve_auto_increment(info, record);
3981
4519
    set_if_bigger(info->s->state.auto_increment,auto_increment);
3982
4520
    if (!repair_only)
3983
4521
      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3984
4522
  }
3985
4523
  mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3986
 
  free(mi_get_rec_buff_ptr(info, record));
 
4524
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3987
4525
  update_state_info(param, info, UPDATE_AUTO_INC);
3988
 
  return;
 
4526
  DBUG_VOID_RETURN;
3989
4527
}
3990
4528
 
3991
4529
 
4041
4579
*/
4042
4580
 
4043
4581
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4044
 
                      uint64_t *unique, uint64_t *notnull,
4045
 
                      uint64_t records)
 
4582
                      ulonglong *unique, ulonglong *notnull,
 
4583
                      ulonglong records)
4046
4584
{
4047
 
  uint64_t count=0,tmp, unique_tuples;
4048
 
  uint64_t tuples= records;
4049
 
  uint32_t parts;
 
4585
  ulonglong count=0,tmp, unique_tuples;
 
4586
  ulonglong tuples= records;
 
4587
  uint parts;
4050
4588
  for (parts=0 ; parts < keyinfo->keysegs  ; parts++)
4051
4589
  {
4052
4590
    count+=unique[parts];
4074
4612
      let's ensure it is not
4075
4613
    */
4076
4614
    set_if_bigger(tmp,1);
4077
 
    if (tmp >= (uint64_t) ~(ulong) 0)
4078
 
      tmp=(uint64_t) ~(ulong) 0;
 
4615
    if (tmp >= (ulonglong) ~(ulong) 0)
 
4616
      tmp=(ulonglong) ~(ulong) 0;
4079
4617
 
4080
4618
    *rec_per_key_part=(ulong) tmp;
4081
4619
    rec_per_key_part++;
4083
4621
}
4084
4622
 
4085
4623
 
4086
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
 
4624
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4087
4625
{
4088
4626
  ha_checksum crc;
4089
 
  const unsigned char *end=buf+length;
 
4627
  const uchar *end=buf+length;
4090
4628
  for (crc=0; buf != end; buf++)
4091
 
    crc=((crc << 1) + *((unsigned char*) buf)) +
 
4629
    crc=((crc << 1) + *((uchar*) buf)) +
4092
4630
      test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4093
4631
  return crc;
4094
4632
}
4095
4633
 
4096
 
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
 
4634
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4097
4635
{
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));
 
4636
  uint key_maxlength=key->maxlength;
 
4637
  if (key->flag & HA_FULLTEXT)
 
4638
  {
 
4639
    uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
 
4640
                                  key->seg->charset->mbmaxlen;
 
4641
    key_maxlength+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
 
4642
  }
 
4643
  return (key->flag & HA_SPATIAL) ||
 
4644
          (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
 
4645
          ((ulonglong) rows * key_maxlength >
 
4646
           (ulonglong) myisam_max_temp_length));
4102
4647
}
4103
4648
 
4104
4649
/*
4114
4659
{
4115
4660
  MYISAM_SHARE *share=info->s;
4116
4661
  MI_KEYDEF    *key=share->keyinfo;
4117
 
  uint32_t          i;
 
4662
  uint          i;
4118
4663
 
4119
 
  assert(info->state->records == 0 &&
 
4664
  DBUG_ASSERT(info->state->records == 0 &&
4120
4665
              (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4121
4666
  for (i=0 ; i < share->base.keys ; i++,key++)
4122
4667
  {
4123
 
    if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
 
4668
    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4124
4669
        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4125
4670
    {
4126
4671
      mi_clear_key_active(share->state.key_map, i);
4131
4676
 
4132
4677
 
4133
4678
/*
4134
 
  Return true if we can use repair by sorting
 
4679
  Return TRUE if we can use repair by sorting
4135
4680
  One can set the force argument to force to use sorting
4136
4681
  even if the temporary file would be quite big!
4137
4682
*/
4138
4683
 
4139
 
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4140
 
                            uint64_t key_map, bool force)
 
4684
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
 
4685
                            ulonglong key_map, my_bool force)
4141
4686
{
4142
4687
  MYISAM_SHARE *share=info->s;
4143
4688
  MI_KEYDEF *key=share->keyinfo;
4144
 
  uint32_t i;
 
4689
  uint i;
4145
4690
 
4146
4691
  /*
4147
4692
    mi_repair_by_sort only works if we have at least one key. If we don't
4148
4693
    have any keys, we should use the normal repair.
4149
4694
  */
4150
4695
  if (! mi_is_any_key_active(key_map))
4151
 
    return false;                               /* Can't use sort */
 
4696
    return FALSE;                               /* Can't use sort */
4152
4697
  for (i=0 ; i < share->base.keys ; i++,key++)
4153
4698
  {
4154
4699
    if (!force && mi_too_big_key_for_sort(key,rows))
4155
 
      return false;
 
4700
      return FALSE;
4156
4701
  }
4157
 
  return true;
 
4702
  return TRUE;
4158
4703
}
4159
4704
 
4160
4705
 
4172
4717
      sort_info->new_data_file_type = STATIC_RECORD;
4173
4718
 
4174
4719
    /* Set delete_function for sort_delete_record() */
4175
 
    memcpy(&tmp, share, sizeof(*share));
 
4720
    memcpy((char*) &tmp, share, sizeof(*share));
4176
4721
    tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4177
4722
    mi_setup_functions(&tmp);
4178
4723
    share->delete_record=tmp.delete_record;