~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_check.c

  • Committer: Stewart Smith
  • Date: 2008-07-13 06:56:15 UTC
  • mto: (210.1.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 211.
  • Revision ID: stewart@flamingspork.com-20080713065615-vzok75kgnnviokl9
Move MD5() into a UDF

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 "myisam_priv.h"
44
 
#include "drizzled/internal/m_string.h"
 
43
#include "myisamdef.h"
 
44
#include <m_ctype.h>
45
45
#include <stdarg.h>
46
 
#include "drizzled/option.h"
 
46
#include <my_getopt.h>
47
47
#ifdef HAVE_SYS_VADVISE_H
48
48
#include <sys/vadvise.h>
49
49
#endif
50
 
#ifdef HAVE_SYS_TYPES
51
 
#include <sys/types.h>
52
 
#endif
53
50
#ifdef HAVE_SYS_MMAN_H
54
51
#include <sys/mman.h>
55
52
#endif
56
 
#include <drizzled/util/test.h>
57
 
#include "drizzled/error.h"
58
 
 
59
 
#include <algorithm>
60
 
 
61
 
using namespace std;
62
 
using namespace drizzled;
63
 
using namespace drizzled::internal;
64
 
 
65
 
 
66
 
#define my_off_t2double(A)  ((double) (my_off_t) (A))
67
 
 
68
 
/* Functions defined in this file */
69
 
 
70
 
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
 
53
 
 
54
#ifndef USE_RAID
 
55
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
 
56
#define my_raid_delete(A,B,C) my_delete(A,B)
 
57
#endif
 
58
 
 
59
        /* Functions defined in this file */
 
60
 
 
61
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
71
62
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
72
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
73
 
                     ha_checksum *key_checksum, uint32_t level);
74
 
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
 
63
                     my_off_t page, uchar *buff, ha_rows *keys,
 
64
                     ha_checksum *key_checksum, uint level);
 
65
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
75
66
static ha_checksum calc_checksum(ha_rows count);
76
67
static int writekeys(MI_SORT_PARAM *sort_param);
77
68
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
78
 
                          my_off_t pagepos, int new_file);
79
 
int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
80
 
int sort_get_next_record(MI_SORT_PARAM *sort_param);
81
 
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
82
 
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
83
 
my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
84
 
                            unsigned char *key);
85
 
int sort_insert_key(MI_SORT_PARAM  *sort_param,
86
 
                    register SORT_KEY_BLOCKS *key_block,
87
 
                    unsigned char *key, my_off_t prev_block);
88
 
int sort_delete_record(MI_SORT_PARAM *sort_param);
89
 
 
 
69
                          my_off_t pagepos, File new_file);
 
70
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
 
71
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
 
72
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
 
73
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
 
74
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
 
75
                                uchar *key);
 
76
static int sort_insert_key(MI_SORT_PARAM  *sort_param,
 
77
                           register SORT_KEY_BLOCKS *key_block,
 
78
                           uchar *key, my_off_t prev_block);
 
79
static int sort_delete_record(MI_SORT_PARAM *sort_param);
90
80
/*static int flush_pending_blocks(MI_CHECK *param);*/
91
 
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
92
 
                                          uint32_t buffer_length);
93
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
 
81
static SORT_KEY_BLOCKS  *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
82
                                          uint buffer_length);
 
83
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
94
84
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
95
85
 
96
86
void myisamchk_init(MI_CHECK *param)
97
87
{
98
 
  memset(param, 0, sizeof(*param));
 
88
  bzero((uchar*) param,sizeof(*param));
99
89
  param->opt_follow_links=1;
100
 
  param->keys_in_use= ~(uint64_t) 0;
 
90
  param->keys_in_use= ~(ulonglong) 0;
101
91
  param->search_after_block=HA_OFFSET_ERROR;
102
92
  param->auto_increment_value= 0;
103
93
  param->use_buffers=USE_BUFFER_INIT;
108
98
  param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
109
99
  param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL);
110
100
  param->start_check_pos=0;
111
 
  param->max_record_length= INT64_MAX;
 
101
  param->max_record_length= LONGLONG_MAX;
112
102
  param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
113
103
  param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
114
104
}
128
118
  if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
129
119
  {
130
120
    /* Don't count this as a real warning, as check can correct this ! */
131
 
    uint32_t save=param->warning_printed;
 
121
    uint save=param->warning_printed;
132
122
    mi_check_print_warning(param,
133
 
                           share->state.open_count==1 ?
134
 
                           "%d client is using or hasn't closed the table properly" :
 
123
                           share->state.open_count==1 ? 
 
124
                           "%d client is using or hasn't closed the table properly" : 
135
125
                           "%d clients are using or haven't closed the table properly",
136
126
                           share->state.open_count);
137
127
    /* If this will be fixed by the check, forget the warning */
143
133
 
144
134
        /* Check delete links */
145
135
 
146
 
int chk_del(MI_CHECK *param, register MI_INFO *info, uint32_t test_flag)
 
136
int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
147
137
{
148
138
  register ha_rows i;
149
 
  uint32_t delete_link_length;
 
139
  uint delete_link_length;
150
140
  my_off_t empty, next_link, old_link= 0;
151
141
  char buff[22],buff2[22];
 
142
  DBUG_ENTER("chk_del");
152
143
 
153
144
  param->record_checksum=0;
154
145
  delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 :
173
164
    for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--)
174
165
    {
175
166
      if (*killed_ptr(param))
176
 
        return(1);
 
167
        DBUG_RETURN(1);
177
168
      if (test_flag & T_VERBOSE)
178
169
        printf(" %9s",llstr(next_link,buff));
179
170
      if (next_link >= info->state->data_file_length)
180
171
        goto wrong;
181
 
      if (my_pread(info->dfile, (unsigned char*) buff,delete_link_length,
 
172
      if (my_pread(info->dfile, (uchar*) buff,delete_link_length,
182
173
                   next_link,MYF(MY_NABP)))
183
174
      {
184
175
        if (test_flag & T_VERBOSE) puts("");
185
176
        mi_check_print_error(param,"Can't read delete-link at filepos: %s",
186
177
                    llstr(next_link,buff));
187
 
        return(1);
 
178
        DBUG_RETURN(1);
188
179
      }
189
180
      if (*buff != '\0')
190
181
      {
209
200
      else
210
201
      {
211
202
        param->record_checksum+=(ha_checksum) next_link;
212
 
        next_link=_mi_rec_pos(info->s,(unsigned char*) buff+1);
 
203
        next_link=_mi_rec_pos(info->s,(uchar*) buff+1);
213
204
        empty+=info->s->base.pack_reclength;
214
205
      }
215
206
    }
238
229
      goto wrong;
239
230
    }
240
231
  }
241
 
  return(0);
 
232
  DBUG_RETURN(0);
242
233
 
243
234
wrong:
244
235
  param->testflag|=T_RETRY_WITHOUT_QUICK;
245
236
  if (test_flag & T_VERBOSE) puts("");
246
237
  mi_check_print_error(param,"record delete-link-chain corrupted");
247
 
  return(1);
 
238
  DBUG_RETURN(1);
248
239
} /* chk_del */
249
240
 
250
241
 
251
242
        /* Check delete links in index file */
252
243
 
253
 
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
 
244
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
254
245
{
255
246
  my_off_t next_link;
256
 
  uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
 
247
  uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
257
248
  ha_rows records;
258
249
  char llbuff[21], llbuff2[21];
259
 
  unsigned char *buff;
 
250
  uchar *buff;
 
251
  DBUG_ENTER("check_k_link");
 
252
  DBUG_PRINT("enter", ("block_size: %u", block_size));
260
253
 
261
254
  if (param->testflag & T_VERBOSE)
262
 
    printf("block_size %4u:", block_size);
 
255
    printf("block_size %4u:", block_size); /* purecov: tested */
263
256
 
264
257
  next_link=info->s->state.key_del[nr];
265
258
  records= (ha_rows) (info->state->key_file_length / block_size);
266
259
  while (next_link != HA_OFFSET_ERROR && records > 0)
267
260
  {
268
261
    if (*killed_ptr(param))
269
 
      return(1);
 
262
      DBUG_RETURN(1);
270
263
    if (param->testflag & T_VERBOSE)
271
264
      printf("%16s",llstr(next_link,llbuff));
272
265
 
273
266
    /* Key blocks must lay within the key file length entirely. */
274
267
    if (next_link + block_size > info->state->key_file_length)
275
268
    {
 
269
      /* purecov: begin tested */
276
270
      mi_check_print_error(param, "Invalid key block position: %s  "
277
271
                           "key block size: %u  file_length: %s",
278
272
                           llstr(next_link, llbuff), block_size,
279
273
                           llstr(info->state->key_file_length, llbuff2));
280
 
      return(1);
 
274
      DBUG_RETURN(1);
 
275
      /* purecov: end */
281
276
    }
282
277
 
283
278
    /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
284
279
    if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
285
280
    {
 
281
      /* purecov: begin tested */
286
282
      mi_check_print_error(param, "Mis-aligned key block: %s  "
287
283
                           "minimum key block length: %u",
288
284
                           llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
289
 
      return(1);
 
285
      DBUG_RETURN(1);
 
286
      /* purecov: end */
290
287
    }
291
288
 
292
289
    /*
296
293
    */
297
294
    if (!(buff=key_cache_read(info->s->key_cache,
298
295
                              info->s->kfile, next_link, DFLT_INIT_HITS,
299
 
                              (unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
 
296
                              (uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
300
297
                              MI_MIN_KEY_BLOCK_LENGTH, 1)))
301
298
    {
 
299
      /* purecov: begin tested */
302
300
      mi_check_print_error(param, "key cache read error for block: %s",
303
301
                           llstr(next_link,llbuff));
304
 
      return(1);
 
302
      DBUG_RETURN(1);
 
303
      /* purecov: end */
305
304
    }
306
305
    next_link=mi_sizekorr(buff);
307
306
    records--;
314
313
    else
315
314
      puts("");
316
315
  }
317
 
  return (next_link != HA_OFFSET_ERROR);
 
316
  DBUG_RETURN (next_link != HA_OFFSET_ERROR);
318
317
} /* check_k_link */
319
318
 
320
319
 
325
324
  int error=0;
326
325
  register my_off_t skr,size;
327
326
  char buff[22],buff2[22];
 
327
  DBUG_ENTER("chk_size");
328
328
 
329
329
  if (!(param->testflag & T_SILENT)) puts("- check file-size");
330
330
 
332
332
  flush_key_blocks(info->s->key_cache,
333
333
                   info->s->kfile, FLUSH_FORCE_WRITE);
334
334
 
335
 
  size= lseek(info->s->kfile, 0, SEEK_END);
 
335
  size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
336
336
  if ((skr=(my_off_t) info->state->key_file_length) != size)
337
337
  {
338
338
    /* Don't give error if file generated by myisampack */
350
350
  }
351
351
  if (!(param->testflag & T_VERY_SILENT) &&
352
352
      ! (info->s->options & HA_OPTION_COMPRESS_RECORD) &&
353
 
      uint64_t2double(info->state->key_file_length) >
354
 
      uint64_t2double(info->s->base.margin_key_file_length)*0.9)
 
353
      ulonglong2double(info->state->key_file_length) >
 
354
      ulonglong2double(info->s->base.margin_key_file_length)*0.9)
355
355
    mi_check_print_warning(param,"Keyfile is almost full, %10s of %10s used",
356
356
                           llstr(info->state->key_file_length,buff),
357
357
                           llstr(info->s->base.max_key_file_length-1,buff));
358
358
 
359
 
  size=lseek(info->dfile,0L,SEEK_END);
 
359
  size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
360
360
  skr=(my_off_t) info->state->data_file_length;
361
361
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
362
362
    skr+= MEMMAP_EXTRA_MARGIN;
384
384
  }
385
385
  if (!(param->testflag & T_VERY_SILENT) &&
386
386
      !(info->s->options & HA_OPTION_COMPRESS_RECORD) &&
387
 
      uint64_t2double(info->state->data_file_length) >
388
 
      (uint64_t2double(info->s->base.max_data_file_length)*0.9))
 
387
      ulonglong2double(info->state->data_file_length) >
 
388
      (ulonglong2double(info->s->base.max_data_file_length)*0.9))
389
389
    mi_check_print_warning(param, "Datafile is almost full, %10s of %10s used",
390
390
                           llstr(info->state->data_file_length,buff),
391
391
                           llstr(info->s->base.max_data_file_length-1,buff2));
392
 
  return(error);
 
392
  DBUG_RETURN(error);
393
393
} /* chk_size */
394
394
 
395
395
 
397
397
 
398
398
int chk_key(MI_CHECK *param, register MI_INFO *info)
399
399
{
400
 
  uint32_t key,found_keys=0,full_text_keys=0,result=0;
 
400
  uint key,found_keys=0,full_text_keys=0,result=0;
401
401
  ha_rows keys;
402
402
  ha_checksum old_record_checksum,init_checksum;
403
403
  my_off_t all_keydata,all_totaldata,key_totlength,length;
405
405
  MYISAM_SHARE *share=info->s;
406
406
  MI_KEYDEF *keyinfo;
407
407
  char buff[22],buff2[22];
 
408
  DBUG_ENTER("chk_key");
408
409
 
409
410
  if (!(param->testflag & T_SILENT))
410
411
    puts("- check key delete-chain");
415
416
    {
416
417
      if (param->testflag & T_VERBOSE) puts("");
417
418
      mi_check_print_error(param,"key delete-link-chain corrupted");
418
 
      return(-1);
 
419
      DBUG_RETURN(-1);
419
420
    }
420
421
 
421
422
  if (!(param->testflag & T_SILENT)) puts("- check index reference");
435
436
    if (! mi_is_key_active(share->state.key_map, key))
436
437
    {
437
438
      /* Remember old statistics for key */
438
 
      assert(rec_per_key_part >= param->rec_per_key_part);
439
 
      memcpy(rec_per_key_part,
440
 
             (share->state.rec_per_key_part +
441
 
              (rec_per_key_part - param->rec_per_key_part)),
 
439
      memcpy((char*) rec_per_key_part,
 
440
             (char*) (share->state.rec_per_key_part +
 
441
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
442
442
             keyinfo->keysegs*sizeof(*rec_per_key_part));
443
443
      continue;
444
444
    }
445
445
    found_keys++;
446
446
 
447
447
    param->record_checksum=init_checksum;
448
 
 
449
 
    memset(&param->unique_count, 0, sizeof(param->unique_count));
450
 
    memset(&param->notnull_count, 0, sizeof(param->notnull_count));
 
448
    
 
449
    bzero((char*) &param->unique_count,sizeof(param->unique_count));
 
450
    bzero((char*) &param->notnull_count,sizeof(param->notnull_count));
451
451
 
452
452
    if ((!(param->testflag & T_SILENT)))
453
453
      printf ("- check data record references index: %d\n",key+1);
454
 
    if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0))
 
454
    if (share->state.key_root[key] == HA_OFFSET_ERROR &&
 
455
        (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
455
456
      goto do_stat;
456
457
    if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key],
457
458
                           DFLT_INIT_HITS,info->buff,0))
459
460
      mi_check_print_error(param,"Can't read indexpage from filepos: %s",
460
461
                  llstr(share->state.key_root[key],buff));
461
462
      if (!(param->testflag & T_INFO))
462
 
        return(-1);
 
463
        DBUG_RETURN(-1);
463
464
      result= -1;
464
465
      continue;
465
466
    }
470
471
    param->max_level=0;
471
472
    if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
472
473
                  &keys, param->key_crc+key,1))
473
 
      return(-1);
474
 
    if(!(0))
 
474
      DBUG_RETURN(-1);
 
475
    if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
475
476
    {
476
477
      if (keys != info->state->records)
477
478
      {
478
479
        mi_check_print_error(param,"Found %s keys of %s",llstr(keys,buff),
479
480
                    llstr(info->state->records,buff2));
480
481
        if (!(param->testflag & T_INFO))
481
 
        return(-1);
 
482
        DBUG_RETURN(-1);
482
483
        result= -1;
483
484
        continue;
484
485
      }
495
496
        else
496
497
          mi_check_print_error(param,"Key 1 doesn't point at all records");
497
498
        if (!(param->testflag & T_INFO))
498
 
          return(-1);
 
499
          DBUG_RETURN(-1);
499
500
        result= -1;
500
501
        continue;
501
502
      }
503
504
    if ((uint) share->base.auto_key -1 == key)
504
505
    {
505
506
      /* Check that auto_increment key is bigger than max key value */
506
 
      uint64_t auto_increment;
 
507
      ulonglong auto_increment;
507
508
      info->lastinx=key;
508
509
      _mi_read_key_record(info, 0L, info->rec_buff);
509
510
      auto_increment= retrieve_auto_increment(info, info->rec_buff);
524
525
 
525
526
      /* Check that there isn't a row with auto_increment = 0 in the table */
526
527
      mi_extra(info,HA_EXTRA_KEYREAD,0);
527
 
      memset(info->lastkey, 0, keyinfo->seg->length);
528
 
      if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
 
528
      bzero(info->lastkey,keyinfo->seg->length);
 
529
      if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
529
530
                   (key_part_map)1, HA_READ_KEY_EXACT))
530
531
      {
531
532
        /* Don't count this as a real warning, as myisamchk can't correct it */
532
 
        uint32_t save=param->warning_printed;
 
533
        uint save=param->warning_printed;
533
534
        mi_check_print_warning(param, "Found row where the auto_increment "
534
535
                               "column has the value 0");
535
536
        param->warning_printed=save;
551
552
    if (param->testflag & T_STATISTICS)
552
553
      update_key_parts(keyinfo, rec_per_key_part, param->unique_count,
553
554
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
554
 
                       param->notnull_count: NULL,
555
 
                       (uint64_t)info->state->records);
 
555
                       param->notnull_count: NULL, 
 
556
                       (ulonglong)info->state->records);
556
557
  }
557
558
  if (param->testflag & T_INFO)
558
559
  {
567
568
      puts("");
568
569
  }
569
570
  if (param->key_file_blocks != info->state->key_file_length &&
570
 
      param->keys_in_use != ~(uint64_t) 0)
 
571
      param->keys_in_use != ~(ulonglong) 0)
571
572
    mi_check_print_warning(param, "Some data are unreferenced in keyfile");
572
573
  if (found_keys != full_text_keys)
573
574
    param->record_checksum=old_record_checksum-init_checksum;   /* Remove delete links */
574
575
  else
575
576
    param->record_checksum=0;
576
 
  return(result);
 
577
  DBUG_RETURN(result);
577
578
} /* chk_key */
578
579
 
579
580
 
580
581
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
581
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
582
 
                     ha_checksum *key_checksum, uint32_t level)
 
582
                     my_off_t page, uchar *buff, ha_rows *keys,
 
583
                     ha_checksum *key_checksum, uint level)
583
584
{
584
585
  char llbuff[22],llbuff2[22];
 
586
  DBUG_ENTER("chk_index_down");
585
587
 
586
588
  /* Key blocks must lay within the key file length entirely. */
587
589
  if (page + keyinfo->block_length > info->state->key_file_length)
588
590
  {
 
591
    /* purecov: begin tested */
589
592
    /* Give it a chance to fit in the real file size. */
590
 
    my_off_t max_length= lseek(info->s->kfile, 0, SEEK_END);
 
593
    my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
 
594
                                 MYF(MY_THREADSAFE));
591
595
    mi_check_print_error(param, "Invalid key block position: %s  "
592
596
                         "key block size: %u  file_length: %s",
593
597
                         llstr(page, llbuff), keyinfo->block_length,
597
601
    /* Fix the remebered key file length. */
598
602
    info->state->key_file_length= (max_length &
599
603
                                   ~ (my_off_t) (keyinfo->block_length - 1));
 
604
    /* purecov: end */
600
605
  }
601
606
 
602
607
  /* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
603
608
  if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
604
609
  {
 
610
    /* purecov: begin tested */
605
611
    mi_check_print_error(param, "Mis-aligned key block: %s  "
606
612
                         "minimum key block length: %u",
607
613
                         llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
608
614
    goto err;
 
615
    /* purecov: end */
609
616
  }
610
617
 
611
618
  if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
618
625
  if (chk_index(param,info,keyinfo,page,buff,keys,key_checksum,level))
619
626
    goto err;
620
627
 
621
 
  return(0);
 
628
  DBUG_RETURN(0);
622
629
 
 
630
  /* purecov: begin tested */
623
631
err:
624
 
  return(1);
 
632
  DBUG_RETURN(1);
 
633
  /* purecov: end */
625
634
}
626
635
 
627
636
 
641
650
*/
642
651
 
643
652
static
644
 
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, uint64_t *notnull,
645
 
                                    unsigned char *key)
 
653
void mi_collect_stats_nonulls_first(HA_KEYSEG *keyseg, ulonglong *notnull,
 
654
                                    uchar *key)
646
655
{
647
 
  uint32_t first_null, kp;
 
656
  uint first_null, kp;
648
657
  first_null= ha_find_null(keyseg, key) - keyseg;
649
658
  /*
650
659
    All prefix tuples that don't include keypart_{first_null} are not-null
671
680
    1. Find out which prefix tuples of last_key don't contain NULLs, and
672
681
       update the array of notnull counters accordingly.
673
682
    2. Find the first keypart number where the prev_key and last_key tuples
674
 
       are different(A), or last_key has NULL value(B), and return it, so the
675
 
       caller can count number of unique tuples for each key prefix. We don't
676
 
       need (B) to be counted, and that is compensated back in
 
683
       are different(A), or last_key has NULL value(B), and return it, so the 
 
684
       caller can count number of unique tuples for each key prefix. We don't 
 
685
       need (B) to be counted, and that is compensated back in 
677
686
       update_key_parts().
678
687
 
679
688
  RETURN
681
690
*/
682
691
 
683
692
static
684
 
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, uint64_t *notnull,
685
 
                                  unsigned char *prev_key, unsigned char *last_key)
 
693
int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull,
 
694
                                  uchar *prev_key, uchar *last_key)
686
695
{
687
 
  uint32_t diffs[2];
688
 
  uint32_t first_null_seg, kp;
 
696
  uint diffs[2];
 
697
  uint first_null_seg, kp;
689
698
  HA_KEYSEG *seg;
690
699
 
691
 
  /*
 
700
  /* 
692
701
     Find the first keypart where values are different or either of them is
693
702
     NULL. We get results in diffs array:
694
703
     diffs[0]= 1 + number of first different keypart
696
705
                      last_key that is NULL or different from corresponding
697
706
                      value in prev_key.
698
707
  */
699
 
  ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY,
 
708
  ha_key_cmp(keyseg, prev_key, last_key, USE_WHOLE_KEY, 
700
709
             SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diffs);
701
710
  seg= keyseg + diffs[0] - 1;
702
711
 
705
714
  for (kp= 0; kp < first_null_seg; kp++)
706
715
    notnull[kp]++;
707
716
 
708
 
  /*
 
717
  /* 
709
718
    Return 1+ number of first key part where values differ. Don't care if
710
719
    these were NULLs and not .... We compensate for that in
711
720
    update_key_parts.
717
726
        /* Check if index is ok */
718
727
 
719
728
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
720
 
                     my_off_t page, unsigned char *buff, ha_rows *keys,
721
 
                     ha_checksum *key_checksum, uint32_t level)
 
729
                     my_off_t page, uchar *buff, ha_rows *keys,
 
730
                     ha_checksum *key_checksum, uint level)
722
731
{
723
732
  int flag;
724
 
  uint32_t used_length,comp_flag,nod_flag,key_length=0;
725
 
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
 
733
  uint used_length,comp_flag,nod_flag,key_length=0;
 
734
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
726
735
  my_off_t next_page,record;
727
736
  char llbuff[22];
728
 
  uint32_t diff_pos[2];
 
737
  uint diff_pos[2];
 
738
  DBUG_ENTER("chk_index");
 
739
  DBUG_DUMP("buff",(uchar*) buff,mi_getint(buff));
729
740
 
730
 
  if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
 
741
  if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
731
742
  {
732
743
    mi_check_print_error(param,"Not enough memory for keyblock");
733
 
    return(-1);
 
744
    DBUG_RETURN(-1);
734
745
  }
735
746
 
736
747
  if (keyinfo->flag & HA_NOSAME)
757
768
  {
758
769
    if (*killed_ptr(param))
759
770
      goto err;
760
 
    memcpy(info->lastkey,key,key_length);
 
771
    memcpy((char*) info->lastkey,(char*) key,key_length);
761
772
    info->lastkey_length=key_length;
762
773
    if (nod_flag)
763
774
    {
770
781
    if (keypos >= endpos ||
771
782
        (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
772
783
      break;
773
 
    assert(key_length <= sizeof(key));
 
784
    DBUG_ASSERT(key_length <= sizeof(key));
774
785
    if (keypos > endpos)
775
786
    {
776
787
      mi_check_print_error(param,"Wrong key block length at page: %s",llstr(page,llbuff));
780
791
        (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
781
792
                         comp_flag, diff_pos)) >=0)
782
793
    {
 
794
      DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length);
 
795
      DBUG_DUMP("new",(uchar*) key, key_length);
 
796
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
 
797
 
783
798
      if (comp_flag & SEARCH_FIND && flag == 0)
784
799
        mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff));
785
800
      else
796
811
                     diff_pos);
797
812
        else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
798
813
        {
799
 
          diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
 
814
          diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg, 
800
815
                                                  param->notnull_count,
801
816
                                                  info->lastkey, key);
802
817
        }
803
818
        param->unique_count[diff_pos[0]-1]++;
804
819
      }
805
820
      else
806
 
      {
 
821
      {  
807
822
        if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
808
823
          mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
809
824
                                         key);
810
825
      }
811
826
    }
812
 
    (*key_checksum)+= mi_byte_checksum((unsigned char*) key,
 
827
    (*key_checksum)+= mi_byte_checksum((uchar*) key,
813
828
                                       key_length- info->s->rec_reflength);
814
829
    record= _mi_dpos(info,0,key+key_length);
815
830
    if (record >= info->state->data_file_length)
816
831
    {
 
832
#ifndef DBUG_OFF
 
833
      char llbuff2[22], llbuff3[22];
 
834
#endif
817
835
      mi_check_print_error(param,"Found key at page %s that points to record outside datafile",llstr(page,llbuff));
 
836
      DBUG_PRINT("test",("page: %s  record: %s  filelength: %s",
 
837
                         llstr(page,llbuff),llstr(record,llbuff2),
 
838
                         llstr(info->state->data_file_length,llbuff3)));
 
839
      DBUG_DUMP("key",(uchar*) key,key_length);
 
840
      DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos));
818
841
      goto err;
819
842
    }
820
843
    param->record_checksum+=(ha_checksum) record;
825
848
                llstr(page,llbuff), used_length, (keypos - buff));
826
849
    goto err;
827
850
  }
828
 
  free(temp_buff);
829
 
  return(0);
 
851
  my_afree((uchar*) temp_buff);
 
852
  DBUG_RETURN(0);
830
853
 err:
831
 
  free(temp_buff);
832
 
  return(1);
 
854
  my_afree((uchar*) temp_buff);
 
855
  DBUG_RETURN(1);
833
856
} /* chk_index */
834
857
 
835
858
 
837
860
 
838
861
static ha_checksum calc_checksum(ha_rows count)
839
862
{
840
 
  uint64_t sum,a,b;
 
863
  ulonglong sum,a,b;
 
864
  DBUG_ENTER("calc_checksum");
841
865
 
842
866
  sum=0;
843
867
  a=count; b=count+1;
851
875
      sum+=a;
852
876
    a<<=1; b>>=1;
853
877
  }
854
 
  return((ha_checksum) sum);
 
878
  DBUG_PRINT("exit",("sum: %lx",(ulong) sum));
 
879
  DBUG_RETURN((ha_checksum) sum);
855
880
} /* calc_checksum */
856
881
 
857
882
 
858
883
        /* Calc length of key in normal isam */
859
884
 
860
 
static uint32_t isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
 
885
static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo)
861
886
{
862
 
  uint32_t length;
 
887
  uint length;
863
888
  HA_KEYSEG *keyseg;
 
889
  DBUG_ENTER("isam_key_length");
864
890
 
865
891
  length= info->s->rec_reflength;
866
892
  for (keyseg=keyinfo->seg ; keyseg->type ; keyseg++)
867
893
    length+= keyseg->length;
868
894
 
869
 
  return(length);
 
895
  DBUG_PRINT("exit",("length: %d",length));
 
896
  DBUG_RETURN(length);
870
897
} /* key_length */
871
898
 
872
899
 
879
906
  ha_rows records, del_blocks;
880
907
  my_off_t used, empty, pos, splits, start_recpos= 0,
881
908
           del_length, link_used, start_block;
882
 
  unsigned char *record= NULL, *to= NULL;
 
909
  uchar *record= NULL, *to= NULL;
883
910
  char llbuff[22],llbuff2[22],llbuff3[22];
884
911
  ha_checksum intern_record_checksum;
885
912
  ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
886
 
  bool static_row_size;
 
913
  my_bool static_row_size;
887
914
  MI_KEYDEF *keyinfo;
888
915
  MI_BLOCK_INFO block_info;
 
916
  DBUG_ENTER("chk_data_link");
889
917
 
890
918
  if (!(param->testflag & T_SILENT))
891
919
  {
898
926
  if (!mi_alloc_rec_buff(info, -1, &record))
899
927
  {
900
928
    mi_check_print_error(param,"Not enough memory for record");
901
 
    return(-1);
 
929
    DBUG_RETURN(-1);
902
930
  }
903
931
  records=del_blocks=0;
904
932
  used=link_used=splits=del_length=0;
922
950
  }
923
951
 
924
952
  pos=my_b_tell(&param->read_cache);
925
 
  memset(key_checksum, 0, info->s->base.keys * sizeof(key_checksum[0]));
 
953
  bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0]));
926
954
  while (pos < info->state->data_file_length)
927
955
  {
928
956
    if (*killed_ptr(param))
929
957
      goto err2;
930
958
    switch (info->s->data_file_type) {
931
959
    case STATIC_RECORD:
932
 
      if (my_b_read(&param->read_cache,(unsigned char*) record,
 
960
      if (my_b_read(&param->read_cache,(uchar*) record,
933
961
                    info->s->base.pack_reclength))
934
962
        goto err;
935
963
      start_recpos=pos;
949
977
      block_info.next_filepos=pos;
950
978
      do
951
979
      {
952
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) block_info.header,
 
980
        if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header,
953
981
                           (start_block=block_info.next_filepos),
954
982
                           sizeof(block_info.header),
955
983
                           (flag ? 0 : READING_NEXT) | READING_HEADER))
1053
1081
          got_error=1;
1054
1082
          break;
1055
1083
        }
1056
 
        if (_mi_read_cache(&param->read_cache,(unsigned char*) to,block_info.filepos,
 
1084
        if (_mi_read_cache(&param->read_cache,(uchar*) to,block_info.filepos,
1057
1085
                           (uint) block_info.data_len,
1058
1086
                           flag == 1 ? READING_NEXT : 0))
1059
1087
          goto err;
1114
1142
        pos=block_info.filepos+block_info.block_len;
1115
1143
      break;
1116
1144
    case COMPRESSED_RECORD:
 
1145
      if (_mi_read_cache(&param->read_cache,(uchar*) block_info.header, pos,
 
1146
                         info->s->pack.ref_length, READING_NEXT))
 
1147
        goto err;
 
1148
      start_recpos=pos;
 
1149
      splits++;
 
1150
      VOID(_mi_pack_get_block_info(info, &info->bit_buff, &block_info,
 
1151
                                   &info->rec_buff, -1, start_recpos));
 
1152
      pos=block_info.filepos+block_info.rec_len;
 
1153
      if (block_info.rec_len < (uint) info->s->min_pack_length ||
 
1154
          block_info.rec_len > (uint) info->s->max_pack_length)
 
1155
      {
 
1156
        mi_check_print_error(param,
 
1157
                             "Found block with wrong recordlength: %d at %s",
 
1158
                             block_info.rec_len, llstr(start_recpos,llbuff));
 
1159
        got_error=1;
 
1160
        break;
 
1161
      }
 
1162
      if (_mi_read_cache(&param->read_cache,(uchar*) info->rec_buff,
 
1163
                        block_info.filepos, block_info.rec_len, READING_NEXT))
 
1164
        goto err;
 
1165
      if (_mi_pack_rec_unpack(info, &info->bit_buff, record,
 
1166
                              info->rec_buff, block_info.rec_len))
 
1167
      {
 
1168
        mi_check_print_error(param,"Found wrong record at %s",
 
1169
                             llstr(start_recpos,llbuff));
 
1170
        got_error=1;
 
1171
      }
 
1172
      if (static_row_size)
 
1173
        param->glob_crc+= mi_static_checksum(info,record);
 
1174
      else
 
1175
        param->glob_crc+= mi_checksum(info,record);
 
1176
      link_used+= (block_info.filepos - start_recpos);
 
1177
      used+= (pos-start_recpos);
1117
1178
    case BLOCK_RECORD:
1118
1179
      assert(0);                                /* Impossible */
1119
1180
    } /* switch */
1123
1184
      records++;
1124
1185
      if (param->testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
1125
1186
      {
1126
 
        printf("%s\r", llstr(records,llbuff)); fflush(stdout);
 
1187
        printf("%s\r", llstr(records,llbuff)); VOID(fflush(stdout));
1127
1188
      }
1128
1189
 
1129
1190
      /* Check if keys match the record */
1133
1194
      {
1134
1195
        if (mi_is_key_active(info->s->state.key_map, key))
1135
1196
        {
 
1197
          if(!(keyinfo->flag & HA_FULLTEXT))
1136
1198
          {
1137
 
            uint32_t key_length=_mi_make_key(info,key,info->lastkey,record,
 
1199
            uint key_length=_mi_make_key(info,key,info->lastkey,record,
1138
1200
                                         start_recpos);
1139
1201
            if (extend)
1140
1202
            {
1154
1216
              }
1155
1217
            }
1156
1218
            else
1157
 
              key_checksum[key]+=mi_byte_checksum((unsigned char*) info->lastkey,
 
1219
              key_checksum[key]+=mi_byte_checksum((uchar*) info->lastkey,
1158
1220
                                                  key_length);
1159
1221
          }
1160
1222
        }
1170
1232
  }
1171
1233
  if (param->testflag & T_WRITE_LOOP)
1172
1234
  {
1173
 
    fputs("          \r",stdout); fflush(stdout);
 
1235
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1174
1236
  }
1175
1237
  if (records != info->state->records)
1176
1238
  {
1187
1249
  }
1188
1250
  else if (param->glob_crc != info->state->checksum &&
1189
1251
           (info->s->options &
1190
 
            (HA_OPTION_COMPRESS_RECORD)))
 
1252
            (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)))
1191
1253
  {
1192
1254
    mi_check_print_warning(param,
1193
1255
                           "Record checksum is not the same as checksum stored in the index file\n");
1197
1259
  {
1198
1260
    for (key=0 ; key < info->s->base.keys;  key++)
1199
1261
    {
1200
 
      if (key_checksum[key] != param->key_crc[key])
 
1262
      if (key_checksum[key] != param->key_crc[key] &&
 
1263
          !(info->s->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
1201
1264
      {
1202
1265
        mi_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
1203
1266
                    key+1);
1247
1310
      printf("Records:%18s    M.recordlength:%9lu   Packed:%14.0f%%\n",
1248
1311
             llstr(records,llbuff), (long)((used-link_used)/records),
1249
1312
             (info->s->base.blobs ? 0.0 :
1250
 
              (uint64_t2double((uint64_t) info->s->base.reclength*records)-
 
1313
              (ulonglong2double((ulonglong) info->s->base.reclength*records)-
1251
1314
               my_off_t2double(used))/
1252
 
              uint64_t2double((uint64_t) info->s->base.reclength*records)*100.0));
 
1315
              ulonglong2double((ulonglong) info->s->base.reclength*records)*100.0));
1253
1316
      printf("Recordspace used:%9.0f%%   Empty space:%12d%%  Blocks/Record: %6.2f\n",
1254
 
             (uint64_t2double(used-link_used)/uint64_t2double(used-link_used+empty)*100.0),
1255
 
             (!records ? 100 : (int) (uint64_t2double(del_length+empty)/
 
1317
             (ulonglong2double(used-link_used)/ulonglong2double(used-link_used+empty)*100.0),
 
1318
             (!records ? 100 : (int) (ulonglong2double(del_length+empty)/
1256
1319
                                      my_off_t2double(used)*100.0)),
1257
 
             uint64_t2double(splits - del_blocks) / records);
 
1320
             ulonglong2double(splits - del_blocks) / records);
1258
1321
    }
1259
1322
    printf("Record blocks:%12s    Delete blocks:%10s\n",
1260
1323
           llstr(splits-del_blocks,llbuff),llstr(del_blocks,llbuff2));
1263
1326
    printf("Lost space:   %12s    Linkdata:     %10s\n",
1264
1327
           llstr(empty,llbuff),llstr(link_used,llbuff2));
1265
1328
  }
1266
 
  free(mi_get_rec_buff_ptr(info, record));
1267
 
  return (error);
 
1329
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
1330
  DBUG_RETURN (error);
1268
1331
 err:
1269
 
  mi_check_print_error(param,"got error: %d when reading datafile at record: %s",errno, llstr(records,llbuff));
 
1332
  mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1270
1333
 err2:
1271
 
  free(mi_get_rec_buff_ptr(info, record));
 
1334
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1272
1335
  param->testflag|=T_RETRY_WITHOUT_QUICK;
1273
 
  return(1);
 
1336
  DBUG_RETURN(1);
1274
1337
} /* chk_data_link */
1275
1338
 
1276
1339
 
1314
1377
 
1315
1378
    However, there is an exception. Sometimes MySQL disables non-unique
1316
1379
    indexes when the table is empty (e.g. when copying a table in
1317
 
    drizzled::alter_table()). When enabling the non-unique indexes, they
 
1380
    mysql_alter_table()). When enabling the non-unique indexes, they
1318
1381
    are still empty. So there is no index block that can be lost. This
1319
1382
    optimization is implemented in this function.
1320
1383
 
1327
1390
    then recrate all indexes.
1328
1391
*/
1329
1392
 
1330
 
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, bool force)
 
1393
static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
1331
1394
{
1332
1395
  MYISAM_SHARE *share= info->s;
1333
1396
  MI_STATE_INFO *state= &share->state;
1334
 
  uint32_t i;
 
1397
  uint i;
1335
1398
  int error;
 
1399
  DBUG_ENTER("mi_drop_all_indexes");
1336
1400
 
1337
1401
  /*
1338
1402
    If any of the disabled indexes has a key block assigned, we must
1343
1407
  */
1344
1408
  if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
1345
1409
  {
 
1410
    DBUG_PRINT("repair", ("creating missing indexes"));
1346
1411
    for (i= 0; i < share->base.keys; i++)
1347
1412
    {
 
1413
      DBUG_PRINT("repair", ("index #: %u  key_root: 0x%lx  active: %d",
 
1414
                            i, (long) state->key_root[i],
 
1415
                            mi_is_key_active(state->key_map, i)));
1348
1416
      if ((state->key_root[i] != HA_OFFSET_ERROR) &&
1349
1417
          !mi_is_key_active(state->key_map, i))
1350
1418
      {
1353
1421
          We would lose its block(s) if would just recreate it.
1354
1422
          So we need to drop and recreate all indexes.
1355
1423
        */
 
1424
        DBUG_PRINT("repair", ("nonempty and disabled: recreate all"));
1356
1425
        break;
1357
1426
      }
1358
1427
    }
1363
1432
        Flush dirty blocks of this index file from key cache and remove
1364
1433
        all blocks of this index file from key cache.
1365
1434
      */
 
1435
      DBUG_PRINT("repair", ("all disabled are empty: create missing"));
1366
1436
      error= flush_key_blocks(share->key_cache, share->kfile,
1367
1437
                              FLUSH_FORCE_WRITE);
1368
1438
      goto end;
1373
1443
      disabled indexes and enable them.
1374
1444
    */
1375
1445
    mi_clear_all_keys_active(state->key_map);
 
1446
    DBUG_PRINT("repair", ("declared all indexes disabled"));
1376
1447
  }
1377
1448
 
1378
1449
  /* Remove all key blocks of this index file from key cache. */
1379
1450
  if ((error= flush_key_blocks(share->key_cache, share->kfile,
1380
1451
                               FLUSH_IGNORE_CHANGED)))
1381
 
    goto end;
 
1452
    goto end; /* purecov: inspected */
1382
1453
 
1383
1454
  /* Clear index root block pointers. */
1384
1455
  for (i= 0; i < share->base.keys; i++)
1391
1462
  /* Reset index file length to end of index file header. */
1392
1463
  info->state->key_file_length= share->base.keystart;
1393
1464
 
 
1465
  DBUG_PRINT("repair", ("dropped all indexes"));
1394
1466
  /* error= 0; set by last (error= flush_key_bocks()). */
1395
1467
 
1396
1468
 end:
1397
 
  return(error);
 
1469
  DBUG_RETURN(error);
1398
1470
}
1399
1471
 
1400
1472
 
1407
1479
  int error,got_error;
1408
1480
  ha_rows start_records,new_header_length;
1409
1481
  my_off_t del;
1410
 
  int new_file;
 
1482
  File new_file;
1411
1483
  MYISAM_SHARE *share=info->s;
1412
1484
  char llbuff[22],llbuff2[22];
1413
1485
  SORT_INFO sort_info;
1414
1486
  MI_SORT_PARAM sort_param;
 
1487
  DBUG_ENTER("mi_repair");
1415
1488
 
1416
 
  memset(&sort_info, 0, sizeof(sort_info));
1417
 
  memset(&sort_param, 0, sizeof(sort_param));
 
1489
  bzero((char *)&sort_info, sizeof(sort_info));
 
1490
  bzero((char *)&sort_param, sizeof(sort_param));
1418
1491
  start_records=info->state->records;
1419
1492
  new_header_length=(param->testflag & T_UNPACK) ? 0L :
1420
1493
    share->pack.header_length;
1429
1502
  }
1430
1503
  param->testflag|=T_REP; /* for easy checking */
1431
1504
 
1432
 
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
 
1505
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1433
1506
    param->testflag|=T_CALC_CHECKSUM;
1434
1507
 
1435
1508
  if (!param->using_global_keycache)
1436
 
    init_key_cache(dflt_key_cache, param->key_cache_block_size,
1437
 
                   (size_t)param->use_buffers, 0, 0);
 
1509
    VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
 
1510
                        param->use_buffers, 0, 0));
1438
1511
 
1439
1512
  if (init_io_cache(&param->read_cache,info->dfile,
1440
1513
                    (uint) param->read_buffer_length,
1441
1514
                    READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
1442
1515
  {
1443
 
    memset(&info->rec_cache, 0, sizeof(info->rec_cache));
 
1516
    bzero(&info->rec_cache,sizeof(info->rec_cache));
1444
1517
    goto err;
1445
1518
  }
1446
1519
  if (!rep_quick)
1459
1532
  if (!rep_quick)
1460
1533
  {
1461
1534
    /* Get real path for data file */
1462
 
    if ((new_file=my_create(internal::fn_format(param->temp_filename,
1463
 
                                      share->data_file_name, "",
1464
 
                                      DATA_TMP_EXT, 2+4),
1465
 
                            0,param->tmpfile_createflag,
1466
 
                            MYF(0))) < 0)
 
1535
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
1536
                                           share->data_file_name, "",
 
1537
                                           DATA_TMP_EXT, 2+4),
 
1538
                                 0,param->tmpfile_createflag,
 
1539
                                 share->base.raid_type,
 
1540
                                 share->base.raid_chunks,
 
1541
                                 share->base.raid_chunksize,
 
1542
                                 MYF(0))) < 0)
1467
1543
    {
1468
1544
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
1469
 
                           param->temp_filename);
 
1545
                           param->temp_filename);
1470
1546
      goto err;
1471
1547
    }
1472
1548
    if (new_header_length &&
1473
1549
        filecopy(param,new_file,info->dfile,0L,new_header_length,
1474
 
                 "datafile-header"))
 
1550
                 "datafile-header"))
1475
1551
      goto err;
1476
1552
    info->s->state.dellink= HA_OFFSET_ERROR;
1477
1553
    info->rec_cache.file=new_file;
1487
1563
  sort_param.pos=sort_param.max_pos=share->pack.header_length;
1488
1564
  sort_param.filepos=new_header_length;
1489
1565
  param->read_cache.end_of_file=sort_info.filelength=
1490
 
    lseek(info->dfile,0L,SEEK_END);
 
1566
    my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
1491
1567
  sort_info.dupp=0;
1492
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
1568
  sort_param.fix_datafile= (my_bool) (! rep_quick);
1493
1569
  sort_param.master=1;
1494
1570
  sort_info.max_records= ~(ha_rows) 0;
1495
1571
 
1506
1582
  /* This function always recreates all enabled indexes. */
1507
1583
  if (param->testflag & T_CREATE_MISSING_KEYS)
1508
1584
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
1509
 
  mi_drop_all_indexes(param, info, true);
 
1585
  mi_drop_all_indexes(param, info, TRUE);
1510
1586
 
1511
1587
  lock_memory(param);                   /* Everything is alloced */
1512
1588
 
1515
1591
  {
1516
1592
    if (writekeys(&sort_param))
1517
1593
    {
1518
 
      if (errno != HA_ERR_FOUND_DUPP_KEY)
 
1594
      if (my_errno != HA_ERR_FOUND_DUPP_KEY)
1519
1595
        goto err;
 
1596
      DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
1520
1597
      mi_check_print_info(param,"Duplicate key %2d for record at %10s against new record at %10s",
1521
1598
                          info->errkey+1,
1522
1599
                          llstr(sort_param.start_recpos,llbuff),
1523
1600
                          llstr(info->dupp_key_pos,llbuff2));
1524
1601
      if (param->testflag & T_VERBOSE)
1525
1602
      {
1526
 
        _mi_make_key(info,(uint) info->errkey,info->lastkey,
1527
 
                     sort_param.record,0L);
 
1603
        VOID(_mi_make_key(info,(uint) info->errkey,info->lastkey,
 
1604
                          sort_param.record,0L));
 
1605
        _mi_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
 
1606
                      USE_WHOLE_KEY);
1528
1607
      }
1529
1608
      sort_info.dupp++;
1530
1609
      if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
1538
1617
    if (sort_write_record(&sort_param))
1539
1618
      goto err;
1540
1619
  }
1541
 
  if (error > 0 || write_data_suffix(&sort_info, (bool)!rep_quick) ||
 
1620
  if (error > 0 || write_data_suffix(&sort_info, (my_bool)!rep_quick) ||
1542
1621
      flush_io_cache(&info->rec_cache) || param->read_cache.error < 0)
1543
1622
    goto err;
1544
1623
 
1545
1624
  if (param->testflag & T_WRITE_LOOP)
1546
1625
  {
1547
 
    fputs("          \r",stdout); fflush(stdout);
 
1626
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
1548
1627
  }
1549
1628
  if (ftruncate(share->kfile, info->state->key_file_length))
1550
1629
  {
1551
1630
    mi_check_print_warning(param,
1552
1631
                           "Can't change size of indexfile, error: %d",
1553
 
                           errno);
 
1632
                           my_errno);
1554
1633
    goto err;
1555
1634
  }
1556
1635
 
1576
1655
 
1577
1656
  if (!rep_quick)
1578
1657
  {
1579
 
    internal::my_close(info->dfile,MYF(0));
 
1658
    my_close(info->dfile,MYF(0));
1580
1659
    info->dfile=new_file;
1581
1660
    info->state->data_file_length=sort_param.filepos;
1582
1661
    share->state.version=(ulong) time((time_t*) 0);     /* Force reopen */
1609
1688
    /* Replace the actual file with the temporary file */
1610
1689
    if (new_file >= 0)
1611
1690
    {
1612
 
      internal::my_close(new_file,MYF(0));
 
1691
      my_close(new_file,MYF(0));
1613
1692
      info->dfile=new_file= -1;
1614
1693
      if (change_to_newfile(share->data_file_name,MI_NAME_DEXT,
1615
1694
                            DATA_TMP_EXT, share->base.raid_chunks,
1622
1701
  if (got_error)
1623
1702
  {
1624
1703
    if (! param->error_printed)
1625
 
      mi_check_print_error(param,"%d for record at pos %s",errno,
 
1704
      mi_check_print_error(param,"%d for record at pos %s",my_errno,
1626
1705
                  llstr(sort_param.start_recpos,llbuff));
1627
1706
    if (new_file >= 0)
1628
1707
    {
1629
 
      internal::my_close(new_file,MYF(0));
1630
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
1708
      VOID(my_close(new_file,MYF(0)));
 
1709
      VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
 
1710
                          MYF(MY_WME)));
1631
1711
      info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1632
1712
    }
1633
1713
    mi_mark_crashed_on_repair(info);
1634
1714
  }
1635
 
 
1636
 
  void * rec_buff_ptr= NULL;
1637
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1638
 
  if (rec_buff_ptr != NULL)
1639
 
    free(rec_buff_ptr);
1640
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1641
 
  if (rec_buff_ptr != NULL)
1642
 
    free(rec_buff_ptr);
1643
 
  rec_buff_ptr= NULL;
1644
 
 
1645
 
  free(sort_info.buff);
1646
 
  end_io_cache(&param->read_cache);
 
1715
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
1716
                            MYF(MY_ALLOW_ZERO_PTR));
 
1717
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
1718
          MYF(MY_ALLOW_ZERO_PTR));
 
1719
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
1720
  VOID(end_io_cache(&param->read_cache));
1647
1721
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1648
 
  end_io_cache(&info->rec_cache);
 
1722
  VOID(end_io_cache(&info->rec_cache));
1649
1723
  got_error|=flush_blocks(param, share->key_cache, share->kfile);
1650
1724
  if (!got_error && param->testflag & T_UNPACK)
1651
1725
  {
1652
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
1726
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1653
1727
    share->pack.header_length=0;
1654
1728
    share->data_file_type=sort_info.new_data_file_type;
1655
1729
  }
1656
1730
  share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
1657
1731
                          STATE_NOT_ANALYZED);
1658
 
  return(got_error);
 
1732
  DBUG_RETURN(got_error);
1659
1733
}
1660
1734
 
1661
1735
 
1663
1737
 
1664
1738
static int writekeys(MI_SORT_PARAM *sort_param)
1665
1739
{
1666
 
  register uint32_t i;
1667
 
  unsigned char    *key;
 
1740
  register uint i;
 
1741
  uchar    *key;
1668
1742
  MI_INFO  *info=   sort_param->sort_info->info;
1669
 
  unsigned char    *buff=   sort_param->record;
 
1743
  uchar    *buff=   sort_param->record;
1670
1744
  my_off_t filepos= sort_param->filepos;
 
1745
  DBUG_ENTER("writekeys");
1671
1746
 
1672
1747
  key=info->lastkey+info->s->base.max_key_length;
1673
1748
  for (i=0 ; i < info->s->base.keys ; i++)
1675
1750
    if (mi_is_key_active(info->s->state.key_map, i))
1676
1751
    {
1677
1752
      {
1678
 
        uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1753
        uint key_length=_mi_make_key(info,i,key,buff,filepos);
1679
1754
        if (_mi_ck_write(info,i,key,key_length))
1680
1755
          goto err;
1681
1756
      }
1682
1757
    }
1683
1758
  }
1684
 
  return(0);
 
1759
  DBUG_RETURN(0);
1685
1760
 
1686
1761
 err:
1687
 
  if (errno == HA_ERR_FOUND_DUPP_KEY)
 
1762
  if (my_errno == HA_ERR_FOUND_DUPP_KEY)
1688
1763
  {
1689
1764
    info->errkey=(int) i;                       /* This key was found */
1690
1765
    while ( i-- > 0 )
1692
1767
      if (mi_is_key_active(info->s->state.key_map, i))
1693
1768
      {
1694
1769
        {
1695
 
          uint32_t key_length=_mi_make_key(info,i,key,buff,filepos);
 
1770
          uint key_length=_mi_make_key(info,i,key,buff,filepos);
1696
1771
          if (_mi_ck_delete(info,i,key,key_length))
1697
1772
            break;
1698
1773
        }
1702
1777
  /* Remove checksum that was added to glob_crc in sort_get_next_record */
1703
1778
  if (sort_param->calc_checksum)
1704
1779
    sort_param->sort_info->param->glob_crc-= info->checksum;
1705
 
  return(-1);
 
1780
  DBUG_PRINT("error",("errno: %d",my_errno));
 
1781
  DBUG_RETURN(-1);
1706
1782
} /* writekeys */
1707
1783
 
1708
1784
 
1709
1785
        /* Change all key-pointers that points to a records */
1710
1786
 
1711
 
int movepoint(register MI_INFO *info, unsigned char *record, my_off_t oldpos,
1712
 
              my_off_t newpos, uint32_t prot_key)
 
1787
int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos,
 
1788
              my_off_t newpos, uint prot_key)
1713
1789
{
1714
 
  register uint32_t i;
1715
 
  unsigned char *key;
1716
 
  uint32_t key_length;
 
1790
  register uint i;
 
1791
  uchar *key;
 
1792
  uint key_length;
 
1793
  DBUG_ENTER("movepoint");
1717
1794
 
1718
1795
  key=info->lastkey+info->s->base.max_key_length;
1719
1796
  for (i=0 ; i < info->s->base.keys; i++)
1723
1800
      key_length=_mi_make_key(info,i,key,record,oldpos);
1724
1801
      if (info->s->keyinfo[i].flag & HA_NOSAME)
1725
1802
      {                                 /* Change pointer direct */
1726
 
        uint32_t nod_flag;
 
1803
        uint nod_flag;
1727
1804
        MI_KEYDEF *keyinfo;
1728
1805
        keyinfo=info->s->keyinfo+i;
1729
1806
        if (_mi_search(info,keyinfo,key,USE_WHOLE_KEY,
1730
1807
                       (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
1731
1808
                       info->s->state.key_root[i]))
1732
 
          return(-1);
 
1809
          DBUG_RETURN(-1);
1733
1810
        nod_flag=mi_test_if_nod(info->buff);
1734
1811
        _mi_dpointer(info,info->int_keypos-nod_flag-
1735
1812
                     info->s->rec_reflength,newpos);
1736
1813
        if (_mi_write_keypage(info,keyinfo,info->last_keypage,
1737
1814
                              DFLT_INIT_HITS,info->buff))
1738
 
          return(-1);
 
1815
          DBUG_RETURN(-1);
1739
1816
      }
1740
1817
      else
1741
1818
      {                                 /* Change old key to new */
1742
1819
        if (_mi_ck_delete(info,i,key,key_length))
1743
 
          return(-1);
 
1820
          DBUG_RETURN(-1);
1744
1821
        key_length=_mi_make_key(info,i,key,record,newpos);
1745
1822
        if (_mi_ck_write(info,i,key,key_length))
1746
 
          return(-1);
 
1823
          DBUG_RETURN(-1);
1747
1824
      }
1748
1825
    }
1749
1826
  }
1750
 
  return(0);
 
1827
  DBUG_RETURN(0);
1751
1828
} /* movepoint */
1752
1829
 
1753
1830
 
1754
1831
        /* Tell system that we want all memory for our cache */
1755
1832
 
1756
 
void lock_memory(MI_CHECK *)
 
1833
void lock_memory(MI_CHECK *param __attribute__((unused)))
1757
1834
{
 
1835
#ifdef SUN_OS                           /* Key-cacheing thrases on sun 4.1 */
 
1836
  if (param->opt_lock_memory)
 
1837
  {
 
1838
    int success = mlockall(MCL_CURRENT);        /* or plock(DATLOCK); */
 
1839
    if (geteuid() == 0 && success != 0)
 
1840
      mi_check_print_warning(param,
 
1841
                             "Failed to lock memory. errno %d",my_errno);
 
1842
  }
 
1843
#endif
1758
1844
} /* lock_memory */
1759
1845
 
1760
1846
 
1761
1847
        /* Flush all changed blocks to disk */
1762
1848
 
1763
 
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, int file)
 
1849
int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file)
1764
1850
{
1765
1851
  if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
1766
1852
  {
1767
 
    mi_check_print_error(param,"%d when trying to write bufferts",errno);
 
1853
    mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
1768
1854
    return(1);
1769
1855
  }
1770
1856
  if (!param->using_global_keycache)
1777
1863
 
1778
1864
int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name)
1779
1865
{
1780
 
  register uint32_t key;
 
1866
  register uint key;
1781
1867
  register MI_KEYDEF *keyinfo;
1782
 
  int new_file;
 
1868
  File new_file;
1783
1869
  my_off_t index_pos[HA_MAX_POSSIBLE_KEY];
1784
 
  uint32_t r_locks,w_locks;
 
1870
  uint r_locks,w_locks;
1785
1871
  int old_lock;
1786
1872
  MYISAM_SHARE *share=info->s;
1787
1873
  MI_STATE_INFO old_state;
 
1874
  DBUG_ENTER("mi_sort_index");
1788
1875
 
1789
1876
  /* cannot sort index files with R-tree indexes */
1790
1877
  for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
1794
1881
    printf("- Sorting index for MyISAM-table '%s'\n",name);
1795
1882
 
1796
1883
  /* Get real path for index file */
1797
 
  internal::fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
1798
 
  if ((new_file=my_create(internal::fn_format(param->temp_filename,param->temp_filename,
 
1884
  fn_format(param->temp_filename,name,"", MI_NAME_IEXT,2+4+32);
 
1885
  if ((new_file=my_create(fn_format(param->temp_filename,param->temp_filename,
1799
1886
                                    "", INDEX_TMP_EXT,2+4),
1800
1887
                          0,param->tmpfile_createflag,MYF(0))) <= 0)
1801
1888
  {
1802
1889
    mi_check_print_error(param,"Can't create new tempfile: '%s'",
1803
1890
                         param->temp_filename);
1804
 
    return(-1);
 
1891
    DBUG_RETURN(-1);
1805
1892
  }
1806
1893
  if (filecopy(param, new_file,share->kfile,0L,
1807
1894
               (ulong) share->base.keystart, "headerblock"))
1837
1924
        /* Put same locks as old file */
1838
1925
  share->r_locks= share->w_locks= share->tot_locks= 0;
1839
1926
  (void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1840
 
  internal::my_close(share->kfile,MYF(MY_WME));
 
1927
  VOID(my_close(share->kfile,MYF(MY_WME)));
1841
1928
  share->kfile = -1;
1842
 
  internal::my_close(new_file,MYF(MY_WME));
 
1929
  VOID(my_close(new_file,MYF(MY_WME)));
1843
1930
  if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1844
1931
                        MYF(0)) ||
1845
1932
      mi_open_keyfile(share))
1860
1947
    info->s->state.key_del[key]=  HA_OFFSET_ERROR;
1861
1948
 
1862
1949
  info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
1863
 
  return(0);
 
1950
  DBUG_RETURN(0);
1864
1951
 
1865
1952
err:
1866
 
  internal::my_close(new_file,MYF(MY_WME));
 
1953
  VOID(my_close(new_file,MYF(MY_WME)));
1867
1954
err2:
1868
 
  my_delete(param->temp_filename,MYF(MY_WME));
1869
 
  return(-1);
 
1955
  VOID(my_delete(param->temp_filename,MYF(MY_WME)));
 
1956
  DBUG_RETURN(-1);
1870
1957
} /* mi_sort_index */
1871
1958
 
1872
1959
 
1873
1960
         /* Sort records recursive using one index */
1874
1961
 
1875
1962
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1876
 
                          my_off_t pagepos, int new_file)
 
1963
                          my_off_t pagepos, File new_file)
1877
1964
{
1878
 
  uint32_t length,nod_flag,used_length, key_length;
1879
 
  unsigned char *buff,*keypos,*endpos;
1880
 
  unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
 
1965
  uint length,nod_flag,used_length, key_length;
 
1966
  uchar *buff,*keypos,*endpos;
 
1967
  uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1881
1968
  my_off_t new_page_pos,next_page;
1882
1969
  char llbuff[22];
 
1970
  DBUG_ENTER("sort_one_index");
1883
1971
 
1884
1972
  new_page_pos=param->new_file_pos;
1885
1973
  param->new_file_pos+=keyinfo->block_length;
1886
1974
 
1887
 
  if (!(buff=(unsigned char*) malloc(keyinfo->block_length)))
 
1975
  if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1888
1976
  {
1889
1977
    mi_check_print_error(param,"Not enough memory for key block");
1890
 
    return(-1);
 
1978
    DBUG_RETURN(-1);
1891
1979
  }
1892
1980
  if (!_mi_fetch_keypage(info,keyinfo,pagepos,DFLT_INIT_HITS,buff,0))
1893
1981
  {
1895
1983
                llstr(pagepos,llbuff));
1896
1984
    goto err;
1897
1985
  }
1898
 
  if ((nod_flag=mi_test_if_nod(buff)))
 
1986
  if ((nod_flag=mi_test_if_nod(buff)) || keyinfo->flag & HA_FULLTEXT)
1899
1987
  {
1900
1988
    used_length=mi_getint(buff);
1901
1989
    keypos=buff+2+nod_flag;
1908
1996
        _mi_kpointer(info,keypos-nod_flag,param->new_file_pos); /* Save new pos */
1909
1997
        if (sort_one_index(param,info,keyinfo,next_page,new_file))
1910
1998
        {
 
1999
          DBUG_PRINT("error",
 
2000
                     ("From page: %ld, keyoffset: %lu  used_length: %d",
 
2001
                      (ulong) pagepos, (ulong) (keypos - buff),
 
2002
                      (int) used_length));
 
2003
          DBUG_DUMP("buff",(uchar*) buff,used_length);
1911
2004
          goto err;
1912
2005
        }
1913
2006
      }
1914
2007
      if (keypos >= endpos ||
1915
2008
          (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
1916
2009
        break;
1917
 
      assert(keypos <= endpos);
 
2010
      DBUG_ASSERT(keypos <= endpos);
1918
2011
    }
1919
2012
  }
1920
2013
 
1921
2014
  /* Fill block with zero and write it to the new index file */
1922
2015
  length=mi_getint(buff);
1923
 
  memset(buff+length, 0, keyinfo->block_length-length);
1924
 
  if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
 
2016
  bzero((uchar*) buff+length,keyinfo->block_length-length);
 
2017
  if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1925
2018
                new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1926
2019
  {
1927
 
    mi_check_print_error(param,"Can't write indexblock, error: %d",errno);
 
2020
    mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1928
2021
    goto err;
1929
2022
  }
1930
 
  free(buff);
1931
 
  return(0);
 
2023
  my_afree((uchar*) buff);
 
2024
  DBUG_RETURN(0);
1932
2025
err:
1933
 
  free(buff);
1934
 
  return(1);
 
2026
  my_afree((uchar*) buff);
 
2027
  DBUG_RETURN(1);
1935
2028
} /* sort_one_index */
1936
2029
 
1937
2030
 
1946
2039
 
1947
2040
int change_to_newfile(const char * filename, const char * old_ext,
1948
2041
                      const char * new_ext,
1949
 
                      uint32_t raid_chunks,
 
2042
                      uint raid_chunks __attribute__((unused)),
1950
2043
                      myf MyFlags)
1951
2044
{
1952
 
  (void)raid_chunks;
1953
2045
  char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
1954
2046
  /* Get real path to filename */
1955
 
  (void) internal::fn_format(old_filename,filename,"",old_ext,2+4+32);
 
2047
  (void) fn_format(old_filename,filename,"",old_ext,2+4+32);
1956
2048
  return my_redel(old_filename,
1957
 
                  internal::fn_format(new_filename,old_filename,"",new_ext,2+4),
 
2049
                  fn_format(new_filename,old_filename,"",new_ext,2+4),
1958
2050
                  MYF(MY_WME | MY_LINK_WARNING | MyFlags));
1959
2051
} /* change_to_newfile */
1960
2052
 
1961
2053
 
 
2054
        /* Locks a whole file */
 
2055
        /* Gives an error-message if file can't be locked */
 
2056
 
 
2057
int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
 
2058
              const char *filetype, const char *filename)
 
2059
{
 
2060
  if (my_lock(file,lock_type,start,F_TO_EOF,
 
2061
              param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
 
2062
              MYF(MY_SEEK_NOT_DONE |  MY_DONT_WAIT)))
 
2063
  {
 
2064
    mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename);
 
2065
    param->error_printed=2;             /* Don't give that data is crashed */
 
2066
    return 1;
 
2067
  }
 
2068
  return 0;
 
2069
} /* lock_file */
 
2070
 
1962
2071
 
1963
2072
        /* Copy a block between two files */
1964
2073
 
1965
 
int filecopy(MI_CHECK *param, int to,int from,my_off_t start,
 
2074
int filecopy(MI_CHECK *param, File to,File from,my_off_t start,
1966
2075
             my_off_t length, const char *type)
1967
2076
{
1968
2077
  char tmp_buff[IO_SIZE],*buff;
1969
2078
  ulong buff_length;
 
2079
  DBUG_ENTER("filecopy");
1970
2080
 
1971
 
  buff_length=(ulong) min(param->write_buffer_length, (size_t)length);
1972
 
  if (!(buff=(char *)malloc(buff_length)))
 
2081
  buff_length=(ulong) min(param->write_buffer_length,length);
 
2082
  if (!(buff=my_malloc(buff_length,MYF(0))))
1973
2083
  {
1974
2084
    buff=tmp_buff; buff_length=IO_SIZE;
1975
2085
  }
1976
2086
 
1977
 
  lseek(from,start,SEEK_SET);
 
2087
  VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1978
2088
  while (length > buff_length)
1979
2089
  {
1980
 
    if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1981
 
        my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
 
2090
    if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
 
2091
        my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1982
2092
      goto err;
1983
2093
    length-= buff_length;
1984
2094
  }
1985
 
  if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1986
 
      my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
 
2095
  if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
 
2096
      my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1987
2097
    goto err;
1988
2098
  if (buff != tmp_buff)
1989
 
    free(buff);
1990
 
  return(0);
 
2099
    my_free(buff,MYF(0));
 
2100
  DBUG_RETURN(0);
1991
2101
err:
1992
2102
  if (buff != tmp_buff)
1993
 
    free(buff);
 
2103
    my_free(buff,MYF(0));
1994
2104
  mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
1995
 
                       type,errno);
1996
 
  return(1);
 
2105
                       type,my_errno);
 
2106
  DBUG_RETURN(1);
1997
2107
}
1998
2108
 
1999
2109
 
2016
2126
                      const char * name, int rep_quick)
2017
2127
{
2018
2128
  int got_error;
2019
 
  uint32_t i;
 
2129
  uint i;
2020
2130
  ulong length;
2021
2131
  ha_rows start_records;
2022
2132
  my_off_t new_header_length,del;
2023
 
  int new_file;
 
2133
  File new_file;
2024
2134
  MI_SORT_PARAM sort_param;
2025
2135
  MYISAM_SHARE *share=info->s;
2026
2136
  HA_KEYSEG *keyseg;
2027
2137
  ulong   *rec_per_key_part;
2028
2138
  char llbuff[22];
2029
2139
  SORT_INFO sort_info;
2030
 
  uint64_t key_map= 0;
 
2140
  ulonglong key_map= 0;
 
2141
  DBUG_ENTER("mi_repair_by_sort");
2031
2142
 
2032
2143
  start_records=info->state->records;
2033
2144
  got_error=1;
2041
2152
  }
2042
2153
  param->testflag|=T_REP; /* for easy checking */
2043
2154
 
2044
 
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
 
2155
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2045
2156
    param->testflag|=T_CALC_CHECKSUM;
2046
2157
 
2047
 
  memset(&sort_info, 0, sizeof(sort_info));
2048
 
  memset(&sort_param, 0, sizeof(sort_param));
 
2158
  bzero((char*)&sort_info,sizeof(sort_info));
 
2159
  bzero((char *)&sort_param, sizeof(sort_param));
2049
2160
  if (!(sort_info.key_block=
2050
2161
        alloc_key_blocks(param,
2051
2162
                         (uint) param->sort_key_blocks,
2072
2183
  if (!rep_quick)
2073
2184
  {
2074
2185
    /* Get real path for data file */
2075
 
    if ((new_file=my_create(internal::fn_format(param->temp_filename,
2076
 
                                      share->data_file_name, "",
2077
 
                                      DATA_TMP_EXT, 2+4),
2078
 
                            0,param->tmpfile_createflag,
2079
 
                            MYF(0))) < 0)
 
2186
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2187
                                           share->data_file_name, "",
 
2188
                                           DATA_TMP_EXT, 2+4),
 
2189
                                 0,param->tmpfile_createflag,
 
2190
                                 share->base.raid_type,
 
2191
                                 share->base.raid_chunks,
 
2192
                                 share->base.raid_chunksize,
 
2193
                                 MYF(0))) < 0)
2080
2194
    {
2081
2195
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2082
 
                           param->temp_filename);
 
2196
                           param->temp_filename);
2083
2197
      goto err;
2084
2198
    }
2085
2199
    if (new_header_length &&
2098
2212
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2099
2213
 
2100
2214
  /* Optionally drop indexes and optionally modify the key_map. */
2101
 
  mi_drop_all_indexes(param, info, false);
 
2215
  mi_drop_all_indexes(param, info, FALSE);
2102
2216
  key_map= share->state.key_map;
2103
2217
  if (param->testflag & T_CREATE_MISSING_KEYS)
2104
2218
  {
2114
2228
  sort_info.dupp=0;
2115
2229
  sort_info.buff=0;
2116
2230
  param->read_cache.end_of_file=sort_info.filelength=
2117
 
    lseek(param->read_cache.file,0L,SEEK_END);
 
2231
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2118
2232
 
2119
2233
  sort_param.wordlist=NULL;
2120
2234
 
2129
2243
     (ha_rows) (sort_info.filelength/length+1));
2130
2244
  sort_param.key_cmp=sort_key_cmp;
2131
2245
  sort_param.lock_in_memory=lock_memory;
 
2246
  sort_param.tmpdir=param->tmpdir;
2132
2247
  sort_param.sort_info=&sort_info;
2133
 
  sort_param.fix_datafile= (bool) (! rep_quick);
 
2248
  sort_param.fix_datafile= (my_bool) (! rep_quick);
2134
2249
  sort_param.master =1;
2135
 
 
 
2250
  
2136
2251
  del=info->state->del;
2137
2252
  param->glob_crc=0;
2138
2253
  if (param->testflag & T_CALC_CHECKSUM)
2152
2267
    if (! mi_is_key_active(key_map, sort_param.key))
2153
2268
    {
2154
2269
      /* Remember old statistics for key */
2155
 
      assert(rec_per_key_part >= param->rec_per_key_part);
2156
 
      memcpy(rec_per_key_part,
2157
 
             (share->state.rec_per_key_part +
2158
 
              (rec_per_key_part - param->rec_per_key_part)),
 
2270
      memcpy((char*) rec_per_key_part,
 
2271
             (char*) (share->state.rec_per_key_part +
 
2272
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2159
2273
             sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
 
2274
      DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
 
2275
                            sort_param.key));
2160
2276
      continue;
2161
2277
    }
2162
2278
 
2164
2280
      printf ("- Fixing index %d\n",sort_param.key+1);
2165
2281
    sort_param.max_pos=sort_param.pos=share->pack.header_length;
2166
2282
    keyseg=sort_param.seg;
2167
 
    memset(sort_param.unique, 0, sizeof(sort_param.unique));
 
2283
    bzero((char*) sort_param.unique,sizeof(sort_param.unique));
2168
2284
    sort_param.key_length=share->rec_reflength;
2169
2285
    for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
2170
2286
    {
2185
2301
    }
2186
2302
 
2187
2303
    if (_create_index_by_sort(&sort_param,
2188
 
                              (bool) (!(param->testflag & T_VERBOSE)),
 
2304
                              (my_bool) (!(param->testflag & T_VERBOSE)),
2189
2305
                              (uint) param->sort_buffer_length))
2190
2306
    {
2191
2307
      param->retry_repair=1;
2202
2318
      update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
2203
2319
                       param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
2204
2320
                       sort_param.notnull: NULL,
2205
 
                       (uint64_t) info->state->records);
 
2321
                       (ulonglong) info->state->records);
2206
2322
    /* Enable this index in the permanent (not the copied) key_map. */
2207
2323
    mi_set_key_active(share->state.key_map, sort_param.key);
 
2324
    DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
2208
2325
 
2209
2326
    if (sort_param.fix_datafile)
2210
2327
    {
2224
2341
        sort_param.filepos;
2225
2342
      /* Only whole records */
2226
2343
      share->state.version=(ulong) time((time_t*) 0);
2227
 
      internal::my_close(info->dfile,MYF(0));
 
2344
      my_close(info->dfile,MYF(0));
2228
2345
      info->dfile=new_file;
2229
2346
      share->data_file_type=sort_info.new_data_file_type;
2230
2347
      share->pack.header_length=(ulong) new_header_length;
2240
2357
 
2241
2358
  if (param->testflag & T_WRITE_LOOP)
2242
2359
  {
2243
 
    fputs("          \r",stdout); fflush(stdout);
 
2360
    VOID(fputs("          \r",stdout)); VOID(fflush(stdout));
2244
2361
  }
2245
2362
 
2246
2363
  if (rep_quick && del+sort_info.dupp != info->state->del)
2267
2384
      if (ftruncate(info->dfile, skr))
2268
2385
        mi_check_print_warning(param,
2269
2386
                               "Can't change size of datafile,  error: %d",
2270
 
                               errno);
 
2387
                               my_errno);
2271
2388
  }
2272
2389
  if (param->testflag & T_CALC_CHECKSUM)
2273
2390
    info->state->checksum=param->glob_crc;
2275
2392
  if (ftruncate(share->kfile, info->state->key_file_length))
2276
2393
    mi_check_print_warning(param,
2277
2394
                           "Can't change size of indexfile, error: %d",
2278
 
                           errno);
 
2395
                           my_errno);
2279
2396
 
2280
2397
  if (!(param->testflag & T_SILENT))
2281
2398
  {
2293
2410
 
2294
2411
err:
2295
2412
  got_error|= flush_blocks(param, share->key_cache, share->kfile);
2296
 
  end_io_cache(&info->rec_cache);
 
2413
  VOID(end_io_cache(&info->rec_cache));
2297
2414
  if (!got_error)
2298
2415
  {
2299
2416
    /* Replace the actual file with the temporary file */
2300
2417
    if (new_file >= 0)
2301
2418
    {
2302
 
      internal::my_close(new_file,MYF(0));
 
2419
      my_close(new_file,MYF(0));
2303
2420
      info->dfile=new_file= -1;
2304
2421
      if (change_to_newfile(share->data_file_name,MI_NAME_DEXT,
2305
2422
                            DATA_TMP_EXT, share->base.raid_chunks,
2312
2429
  if (got_error)
2313
2430
  {
2314
2431
    if (! param->error_printed)
2315
 
      mi_check_print_error(param,"%d when fixing table",errno);
 
2432
      mi_check_print_error(param,"%d when fixing table",my_errno);
2316
2433
    if (new_file >= 0)
2317
2434
    {
2318
 
      internal::my_close(new_file,MYF(0));
2319
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
2435
      VOID(my_close(new_file,MYF(0)));
 
2436
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
2437
                          MYF(MY_WME)));
2320
2438
      if (info->dfile == new_file)
2321
 
        info->dfile= -1;
 
2439
        info->dfile= -1;
2322
2440
    }
2323
2441
    mi_mark_crashed_on_repair(info);
2324
2442
  }
2326
2444
    share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2327
2445
  share->state.changed|=STATE_NOT_SORTED_PAGES;
2328
2446
 
2329
 
  void * rec_buff_ptr= NULL;
2330
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2331
 
  if (rec_buff_ptr != NULL)
2332
 
    free(rec_buff_ptr);
2333
 
  rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2334
 
  if (rec_buff_ptr != NULL)
2335
 
    free(rec_buff_ptr);
2336
 
  rec_buff_ptr= NULL;
2337
 
 
2338
 
  free((unsigned char*) sort_info.key_block);
2339
 
  free(sort_info.buff);
2340
 
  end_io_cache(&param->read_cache);
 
2447
  my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
 
2448
                            MYF(MY_ALLOW_ZERO_PTR));
 
2449
  my_free(mi_get_rec_buff_ptr(info, sort_param.record),
 
2450
          MYF(MY_ALLOW_ZERO_PTR));
 
2451
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
2452
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
2453
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
2454
  VOID(end_io_cache(&param->read_cache));
2341
2455
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2342
2456
  if (!got_error && (param->testflag & T_UNPACK))
2343
2457
  {
2344
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
2458
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2345
2459
    share->pack.header_length=0;
2346
2460
  }
2347
 
  return(got_error);
 
2461
  DBUG_RETURN(got_error);
2348
2462
}
2349
2463
 
2350
2464
/*
2393
2507
                        const char * name, int rep_quick)
2394
2508
{
2395
2509
  int got_error;
2396
 
  uint32_t i,key, total_key_length, istep;
 
2510
  uint i,key, total_key_length, istep;
2397
2511
  ulong rec_length;
2398
2512
  ha_rows start_records;
2399
2513
  my_off_t new_header_length,del;
2400
 
  int new_file;
 
2514
  File new_file;
2401
2515
  MI_SORT_PARAM *sort_param=0;
2402
2516
  MYISAM_SHARE *share=info->s;
2403
2517
  ulong   *rec_per_key_part;
2406
2520
  IO_CACHE new_data_cache; /* For non-quick repair. */
2407
2521
  IO_CACHE_SHARE io_share;
2408
2522
  SORT_INFO sort_info;
2409
 
  uint64_t key_map= 0;
 
2523
  ulonglong key_map= 0;
2410
2524
  pthread_attr_t thr_attr;
2411
2525
  ulong max_pack_reclength;
 
2526
  DBUG_ENTER("mi_repair_parallel");
2412
2527
 
2413
2528
  start_records=info->state->records;
2414
2529
  got_error=1;
2422
2537
  }
2423
2538
  param->testflag|=T_REP; /* for easy checking */
2424
2539
 
2425
 
  if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
 
2540
  if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
2426
2541
    param->testflag|=T_CALC_CHECKSUM;
2427
2542
 
2428
2543
  /*
2453
2568
      position 'new_header_length'.
2454
2569
    }
2455
2570
  */
2456
 
  memset(&sort_info, 0, sizeof(sort_info));
 
2571
  DBUG_PRINT("info", ("is quick repair: %d", rep_quick));
 
2572
  bzero((char*)&sort_info,sizeof(sort_info));
2457
2573
  /* Initialize pthread structures before goto err. */
2458
2574
  pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST);
2459
2575
  pthread_cond_init(&sort_info.cond, 0);
2481
2597
  if (!rep_quick)
2482
2598
  {
2483
2599
    /* Get real path for data file */
2484
 
    if ((new_file=my_create(internal::fn_format(param->temp_filename,
2485
 
                                      share->data_file_name, "",
2486
 
                                      DATA_TMP_EXT,
2487
 
                                      2+4),
2488
 
                            0,param->tmpfile_createflag,
2489
 
                            MYF(0))) < 0)
 
2600
    if ((new_file=my_raid_create(fn_format(param->temp_filename,
 
2601
                                           share->data_file_name, "",
 
2602
                                           DATA_TMP_EXT,
 
2603
                                           2+4),
 
2604
                                 0,param->tmpfile_createflag,
 
2605
                                 share->base.raid_type,
 
2606
                                 share->base.raid_chunks,
 
2607
                                 share->base.raid_chunksize,
 
2608
                                 MYF(0))) < 0)
2490
2609
    {
2491
2610
      mi_check_print_error(param,"Can't create new tempfile: '%s'",
2492
2611
                           param->temp_filename);
2508
2627
  info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
2509
2628
 
2510
2629
  /* Optionally drop indexes and optionally modify the key_map. */
2511
 
  mi_drop_all_indexes(param, info, false);
 
2630
  mi_drop_all_indexes(param, info, FALSE);
2512
2631
  key_map= share->state.key_map;
2513
2632
  if (param->testflag & T_CREATE_MISSING_KEYS)
2514
2633
  {
2523
2642
  sort_info.dupp=0;
2524
2643
  sort_info.buff=0;
2525
2644
  param->read_cache.end_of_file=sort_info.filelength=
2526
 
    lseek(param->read_cache.file,0L,SEEK_END);
 
2645
    my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
2527
2646
 
2528
2647
  if (share->data_file_type == DYNAMIC_RECORD)
2529
2648
    rec_length=max(share->base.min_pack_length+1,share->base.min_block_length);
2554
2673
  if (share->options & HA_OPTION_COMPRESS_RECORD)
2555
2674
    set_if_bigger(max_pack_reclength, share->max_pack_length);
2556
2675
  if (!(sort_param=(MI_SORT_PARAM *)
2557
 
        malloc(share->base.keys *
2558
 
               (sizeof(MI_SORT_PARAM) + max_pack_reclength))))
 
2676
        my_malloc((uint) share->base.keys *
 
2677
                  (sizeof(MI_SORT_PARAM) + max_pack_reclength),
 
2678
                  MYF(MY_ZEROFILL))))
2559
2679
  {
2560
2680
    mi_check_print_error(param,"Not enough memory for key!");
2561
2681
    goto err;
2562
2682
  }
2563
 
  memset(sort_param, 0, share->base.keys *
2564
 
                        (sizeof(MI_SORT_PARAM) + max_pack_reclength));
2565
2683
  total_key_length=0;
2566
2684
  rec_per_key_part= param->rec_per_key_part;
2567
2685
  info->state->records=info->state->del=share->state.split=0;
2580
2698
    if (! mi_is_key_active(key_map, key))
2581
2699
    {
2582
2700
      /* Remember old statistics for key */
2583
 
      assert(rec_per_key_part >= param->rec_per_key_part);
2584
 
      memcpy(rec_per_key_part,
2585
 
             (share->state.rec_per_key_part +
2586
 
              (rec_per_key_part - param->rec_per_key_part)),
 
2701
      memcpy((char*) rec_per_key_part,
 
2702
             (char*) (share->state.rec_per_key_part+
 
2703
                      (uint) (rec_per_key_part - param->rec_per_key_part)),
2587
2704
             sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
2588
2705
      istep=0;
2589
2706
      continue;
2597
2714
    }
2598
2715
    sort_param[i].key_cmp=sort_key_cmp;
2599
2716
    sort_param[i].lock_in_memory=lock_memory;
 
2717
    sort_param[i].tmpdir=param->tmpdir;
2600
2718
    sort_param[i].sort_info=&sort_info;
2601
2719
    sort_param[i].master=0;
2602
2720
    sort_param[i].fix_datafile=0;
2605
2723
    sort_param[i].filepos=new_header_length;
2606
2724
    sort_param[i].max_pos=sort_param[i].pos=share->pack.header_length;
2607
2725
 
2608
 
    sort_param[i].record= (((unsigned char *)(sort_param+share->base.keys))+
 
2726
    sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+
2609
2727
                           (max_pack_reclength * i));
2610
2728
    if (!mi_alloc_rec_buff(info, -1, &sort_param[i].rec_buff))
2611
2729
    {
2629
2747
  }
2630
2748
  sort_info.total_keys=i;
2631
2749
  sort_param[0].master= 1;
2632
 
  sort_param[0].fix_datafile= (bool)(! rep_quick);
 
2750
  sort_param[0].fix_datafile= (my_bool)(! rep_quick);
2633
2751
  sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM);
2634
2752
 
2635
2753
  sort_info.got_error=0;
2666
2784
    */
2667
2785
    sort_param[i].read_cache= ((rep_quick || !i) ? param->read_cache :
2668
2786
                               new_data_cache);
 
2787
    DBUG_PRINT("io_cache_share", ("thread: %u  read_cache: 0x%lx",
 
2788
                                  i, (long) &sort_param[i].read_cache));
2669
2789
 
2670
2790
    /*
2671
2791
      two approaches: the same amount of memory for each thread
2687
2807
      /* Cleanup: Detach from the share. Avoid others to be blocked. */
2688
2808
      if (io_share.total_threads)
2689
2809
        remove_io_thread(&sort_param[i].read_cache);
 
2810
      DBUG_PRINT("error", ("Cannot start a repair thread"));
2690
2811
      sort_info.got_error=1;
2691
2812
    }
2692
2813
    else
2733
2854
      Exchange the data file descriptor of the table, so that we use the
2734
2855
      new file from now on.
2735
2856
     */
2736
 
    internal::my_close(info->dfile,MYF(0));
 
2857
    my_close(info->dfile,MYF(0));
2737
2858
    info->dfile=new_file;
2738
2859
 
2739
2860
    share->data_file_type=sort_info.new_data_file_type;
2765
2886
      if (ftruncate(info->dfile, skr))
2766
2887
        mi_check_print_warning(param,
2767
2888
                               "Can't change size of datafile,  error: %d",
2768
 
                               errno);
 
2889
                               my_errno);
2769
2890
  }
2770
2891
  if (param->testflag & T_CALC_CHECKSUM)
2771
2892
    info->state->checksum=param->glob_crc;
2772
2893
 
2773
2894
  if (ftruncate(share->kfile, info->state->key_file_length))
2774
2895
    mi_check_print_warning(param,
2775
 
                           "Can't change size of indexfile, error: %d", errno);
 
2896
                           "Can't change size of indexfile, error: %d", my_errno);
2776
2897
 
2777
2898
  if (!(param->testflag & T_SILENT))
2778
2899
  {
2795
2916
    the share by remove_io_thread() or it was not yet started (if the
2796
2917
    error happend before creating the thread).
2797
2918
  */
2798
 
  end_io_cache(&info->rec_cache);
 
2919
  VOID(end_io_cache(&info->rec_cache));
2799
2920
  /*
2800
2921
    Destroy the new data cache in case of non-quick repair. All slave
2801
2922
    threads did either detach from the share by remove_io_thread()
2803
2924
    creating the threads).
2804
2925
  */
2805
2926
  if (!rep_quick)
2806
 
    end_io_cache(&new_data_cache);
 
2927
    VOID(end_io_cache(&new_data_cache));
2807
2928
  if (!got_error)
2808
2929
  {
2809
2930
    /* Replace the actual file with the temporary file */
2810
2931
    if (new_file >= 0)
2811
2932
    {
2812
 
      internal::my_close(new_file,MYF(0));
 
2933
      my_close(new_file,MYF(0));
2813
2934
      info->dfile=new_file= -1;
2814
2935
      if (change_to_newfile(share->data_file_name,MI_NAME_DEXT,
2815
2936
                            DATA_TMP_EXT, share->base.raid_chunks,
2822
2943
  if (got_error)
2823
2944
  {
2824
2945
    if (! param->error_printed)
2825
 
      mi_check_print_error(param,"%d when fixing table",errno);
 
2946
      mi_check_print_error(param,"%d when fixing table",my_errno);
2826
2947
    if (new_file >= 0)
2827
2948
    {
2828
 
      internal::my_close(new_file,MYF(0));
2829
 
      my_delete(param->temp_filename, MYF(MY_WME));
 
2949
      VOID(my_close(new_file,MYF(0)));
 
2950
      VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
 
2951
                          MYF(MY_WME)));
2830
2952
      if (info->dfile == new_file)
2831
 
        info->dfile= -1;
 
2953
        info->dfile= -1;
2832
2954
    }
2833
2955
    mi_mark_crashed_on_repair(info);
2834
2956
  }
2839
2961
  pthread_cond_destroy (&sort_info.cond);
2840
2962
  pthread_mutex_destroy(&sort_info.mutex);
2841
2963
 
2842
 
  free((unsigned char*) sort_info.key_block);
2843
 
  free((unsigned char*) sort_param);
2844
 
  free(sort_info.buff);
2845
 
  end_io_cache(&param->read_cache);
 
2964
  my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR));
 
2965
  my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
 
2966
  my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
 
2967
  my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
 
2968
  VOID(end_io_cache(&param->read_cache));
2846
2969
  info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2847
2970
  if (!got_error && (param->testflag & T_UNPACK))
2848
2971
  {
2849
 
    share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
 
2972
    share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2850
2973
    share->pack.header_length=0;
2851
2974
  }
2852
 
  return(got_error);
 
2975
  DBUG_RETURN(got_error);
2853
2976
}
2854
2977
 
2855
2978
        /* Read next record and return next key */
2856
2979
 
2857
 
int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
 
2980
static int sort_key_read(MI_SORT_PARAM *sort_param, void *key)
2858
2981
{
2859
2982
  int error;
2860
2983
  SORT_INFO *sort_info=sort_param->sort_info;
2861
2984
  MI_INFO *info=sort_info->info;
 
2985
  DBUG_ENTER("sort_key_read");
2862
2986
 
2863
2987
  if ((error=sort_get_next_record(sort_param)))
2864
 
    return(error);
 
2988
    DBUG_RETURN(error);
2865
2989
  if (info->state->records == sort_info->max_records)
2866
2990
  {
2867
2991
    mi_check_print_error(sort_info->param,
2868
2992
                         "Key %d - Found too many records; Can't continue",
2869
2993
                         sort_param->key+1);
2870
 
    return(1);
 
2994
    DBUG_RETURN(1);
2871
2995
  }
2872
2996
  sort_param->real_key_length=
2873
2997
    (info->s->rec_reflength+
2874
 
     _mi_make_key(info, sort_param->key, (unsigned char*) key,
 
2998
     _mi_make_key(info, sort_param->key, (uchar*) key,
2875
2999
                  sort_param->record, sort_param->filepos));
2876
3000
#ifdef HAVE_purify
2877
 
  memset((unsigned char *)key+sort_param->real_key_length, 0,
2878
 
         (sort_param->key_length-sort_param->real_key_length));
 
3001
  bzero(key+sort_param->real_key_length,
 
3002
        (sort_param->key_length-sort_param->real_key_length));
2879
3003
#endif
2880
 
  return(sort_write_record(sort_param));
 
3004
  DBUG_RETURN(sort_write_record(sort_param));
2881
3005
} /* sort_key_read */
2882
3006
 
2883
3007
 
2912
3036
    > 0         error
2913
3037
*/
2914
3038
 
2915
 
int sort_get_next_record(MI_SORT_PARAM *sort_param)
 
3039
static int sort_get_next_record(MI_SORT_PARAM *sort_param)
2916
3040
{
2917
3041
  int searching;
2918
3042
  int parallel_flag;
2919
 
  uint32_t found_record,b_type,left_length;
 
3043
  uint found_record,b_type,left_length;
2920
3044
  my_off_t pos;
2921
 
  unsigned char *to= NULL;
 
3045
  uchar *to= NULL;
2922
3046
  MI_BLOCK_INFO block_info;
2923
3047
  SORT_INFO *sort_info=sort_param->sort_info;
2924
3048
  MI_CHECK *param=sort_info->param;
2925
3049
  MI_INFO *info=sort_info->info;
2926
3050
  MYISAM_SHARE *share=info->s;
2927
3051
  char llbuff[22],llbuff2[22];
 
3052
  DBUG_ENTER("sort_get_next_record");
2928
3053
 
2929
3054
  if (*killed_ptr(param))
2930
 
    return(1);
 
3055
    DBUG_RETURN(1);
2931
3056
 
2932
3057
  switch (share->data_file_type) {
2933
3058
  case STATIC_RECORD:
2940
3065
          param->out_flag |= O_DATA_LOST;
2941
3066
        param->retry_repair=1;
2942
3067
        param->testflag|=T_RETRY_WITHOUT_QUICK;
2943
 
        return(-1);
 
3068
        DBUG_RETURN(-1);
2944
3069
      }
2945
3070
      sort_param->start_recpos=sort_param->pos;
2946
3071
      if (!sort_param->fix_datafile)
2955
3080
        if (sort_param->calc_checksum)
2956
3081
          param->glob_crc+= (info->checksum=
2957
3082
                             mi_static_checksum(info,sort_param->record));
2958
 
        return(0);
 
3083
        DBUG_RETURN(0);
2959
3084
      }
2960
3085
      if (!sort_param->fix_datafile && sort_param->master)
2961
3086
      {
2994
3119
                     llstr(param->search_after_block,llbuff),
2995
3120
                     llstr(sort_param->start_recpos,llbuff2));
2996
3121
        if (_mi_read_cache(&sort_param->read_cache,
2997
 
                           (unsigned char*) block_info.header,pos,
 
3122
                           (uchar*) block_info.header,pos,
2998
3123
                           MI_BLOCK_INFO_HEADER_LENGTH,
2999
3124
                           (! found_record ? READING_NEXT : 0) |
3000
3125
                           parallel_flag | READING_HEADER))
3006
3131
                                llstr(sort_param->start_recpos,llbuff),errno);
3007
3132
            goto try_next;
3008
3133
          }
3009
 
          return(-1);
 
3134
          DBUG_RETURN(-1);
3010
3135
        }
3011
3136
        if (searching && ! sort_param->fix_datafile)
3012
3137
        {
3013
3138
          param->error_printed=1;
3014
3139
          param->retry_repair=1;
3015
3140
          param->testflag|=T_RETRY_WITHOUT_QUICK;
3016
 
          return(1);    /* Something wrong with data */
 
3141
          DBUG_RETURN(1);       /* Something wrong with data */
3017
3142
        }
3018
3143
        b_type=_mi_get_block_info(&block_info,-1,pos);
3019
3144
        if ((b_type & (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
3021
3146
             (block_info.rec_len < (uint) share->base.min_pack_length ||
3022
3147
              block_info.rec_len > (uint) share->base.max_pack_length)))
3023
3148
        {
3024
 
          uint32_t i;
 
3149
          uint i;
3025
3150
          if (param->testflag & T_VERBOSE || searching == 0)
3026
3151
            mi_check_print_info(param,
3027
3152
                                "Wrong bytesec: %3d-%3d-%3d at %10s; Skipped",
3044
3169
        }
3045
3170
        if (b_type & BLOCK_DELETED)
3046
3171
        {
3047
 
          bool error=0;
 
3172
          my_bool error=0;
3048
3173
          if (block_info.block_len+ (uint) (block_info.filepos-pos) <
3049
3174
              share->base.min_block_length)
3050
3175
          {
3145
3270
                mi_check_print_error(param,"Not enough memory for blob at %s (need %lu)",
3146
3271
                                     llstr(sort_param->start_recpos,llbuff),
3147
3272
                                     (ulong) block_info.rec_len);
3148
 
                return(1);
 
3273
                DBUG_RETURN(1);
3149
3274
              }
3150
3275
              else
3151
3276
              {
3180
3305
          streched over the end of the previous buffer contents.
3181
3306
        */
3182
3307
        {
3183
 
          uint32_t header_len= (uint) (block_info.filepos - pos);
3184
 
          uint32_t prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
 
3308
          uint header_len= (uint) (block_info.filepos - pos);
 
3309
          uint prefetch_len= (MI_BLOCK_INFO_HEADER_LENGTH - header_len);
3185
3310
 
3186
3311
          if (prefetch_len > block_info.data_len)
3187
3312
            prefetch_len= block_info.data_len;
3202
3327
        {
3203
3328
          mi_check_print_info(param,
3204
3329
                              "Read error for block at: %s (error: %d); Skipped",
3205
 
                              llstr(block_info.filepos,llbuff),errno);
 
3330
                              llstr(block_info.filepos,llbuff),my_errno);
3206
3331
          goto try_next;
3207
3332
        }
3208
3333
        left_length-=block_info.data_len;
3227
3352
                         sort_param->find_length) != MY_FILE_ERROR)
3228
3353
      {
3229
3354
        if (sort_param->read_cache.error < 0)
3230
 
          return(1);
 
3355
          DBUG_RETURN(1);
3231
3356
        if (sort_param->calc_checksum)
3232
3357
          info->checksum= mi_checksum(info, sort_param->record);
3233
3358
        if ((param->testflag & (T_EXTEND | T_REP)) || searching)
3245
3370
        }
3246
3371
        if (sort_param->calc_checksum)
3247
3372
          param->glob_crc+= info->checksum;
3248
 
        return(0);
 
3373
        DBUG_RETURN(0);
3249
3374
      }
3250
3375
      if (!searching)
3251
3376
        mi_check_print_info(param,"Key %d - Found wrong stored record at %s",
3256
3381
      searching=1;
3257
3382
    }
3258
3383
  case COMPRESSED_RECORD:
 
3384
    for (searching=0 ;; searching=1, sort_param->pos++)
 
3385
    {
 
3386
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) block_info.header,
 
3387
                         sort_param->pos,
 
3388
                         share->pack.ref_length,READING_NEXT))
 
3389
        DBUG_RETURN(-1);
 
3390
      if (searching && ! sort_param->fix_datafile)
 
3391
      {
 
3392
        param->error_printed=1;
 
3393
        param->retry_repair=1;
 
3394
        param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3395
        DBUG_RETURN(1);         /* Something wrong with data */
 
3396
      }
 
3397
      sort_param->start_recpos=sort_param->pos;
 
3398
      if (_mi_pack_get_block_info(info, &sort_param->bit_buff, &block_info,
 
3399
                                  &sort_param->rec_buff, -1, sort_param->pos))
 
3400
        DBUG_RETURN(-1);
 
3401
      if (!block_info.rec_len &&
 
3402
          sort_param->pos + MEMMAP_EXTRA_MARGIN ==
 
3403
          sort_param->read_cache.end_of_file)
 
3404
        DBUG_RETURN(-1);
 
3405
      if (block_info.rec_len < (uint) share->min_pack_length ||
 
3406
          block_info.rec_len > (uint) share->max_pack_length)
 
3407
      {
 
3408
        if (! searching)
 
3409
          mi_check_print_info(param,"Found block with wrong recordlength: %d at %s\n",
 
3410
                              block_info.rec_len,
 
3411
                              llstr(sort_param->pos,llbuff));
 
3412
        continue;
 
3413
      }
 
3414
      if (_mi_read_cache(&sort_param->read_cache,(uchar*) sort_param->rec_buff,
 
3415
                         block_info.filepos, block_info.rec_len,
 
3416
                         READING_NEXT))
 
3417
      {
 
3418
        if (! searching)
 
3419
          mi_check_print_info(param,"Couldn't read whole record from %s",
 
3420
                              llstr(sort_param->pos,llbuff));
 
3421
        continue;
 
3422
      }
 
3423
      if (_mi_pack_rec_unpack(info, &sort_param->bit_buff, sort_param->record,
 
3424
                              sort_param->rec_buff, block_info.rec_len))
 
3425
      {
 
3426
        if (! searching)
 
3427
          mi_check_print_info(param,"Found wrong record at %s",
 
3428
                              llstr(sort_param->pos,llbuff));
 
3429
        continue;
 
3430
      }
 
3431
      if (!sort_param->fix_datafile)
 
3432
      {
 
3433
        sort_param->filepos=sort_param->pos;
 
3434
        if (sort_param->master)
 
3435
          share->state.split++;
 
3436
      }
 
3437
      sort_param->max_pos=(sort_param->pos=block_info.filepos+
 
3438
                         block_info.rec_len);
 
3439
      info->packed_length=block_info.rec_len;
 
3440
      if (sort_param->calc_checksum)
 
3441
        param->glob_crc+= (info->checksum=
 
3442
                           mi_checksum(info, sort_param->record));
 
3443
      DBUG_RETURN(0);
 
3444
    }
3259
3445
  case BLOCK_RECORD:
3260
3446
    assert(0);                                  /* Impossible */
3261
3447
  }
3262
 
  return(1);                               /* Impossible */
 
3448
  DBUG_RETURN(1);                               /* Impossible */
3263
3449
}
3264
3450
 
3265
3451
 
3281
3467
int sort_write_record(MI_SORT_PARAM *sort_param)
3282
3468
{
3283
3469
  int flag;
 
3470
  uint length;
3284
3471
  ulong block_length,reclength;
3285
 
  unsigned char *from;
 
3472
  uchar *from;
 
3473
  uchar block_buff[8];
3286
3474
  SORT_INFO *sort_info=sort_param->sort_info;
3287
3475
  MI_CHECK *param=sort_info->param;
3288
3476
  MI_INFO *info=sort_info->info;
3289
3477
  MYISAM_SHARE *share=info->s;
 
3478
  DBUG_ENTER("sort_write_record");
3290
3479
 
3291
3480
  if (sort_param->fix_datafile)
3292
3481
  {
3295
3484
      if (my_b_write(&info->rec_cache,sort_param->record,
3296
3485
                     share->base.pack_reclength))
3297
3486
      {
3298
 
        mi_check_print_error(param,"%d when writing to datafile",errno);
3299
 
        return(1);
 
3487
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3488
        DBUG_RETURN(1);
3300
3489
      }
3301
3490
      sort_param->filepos+=share->base.pack_reclength;
3302
3491
      info->s->state.split++;
3314
3503
          MI_DYN_DELETE_BLOCK_HEADER;
3315
3504
        if (sort_info->buff_length < reclength)
3316
3505
        {
3317
 
          void *tmpptr= NULL;
3318
 
          tmpptr= realloc(sort_info->buff, reclength);
3319
 
          if(tmpptr)
3320
 
          {
3321
 
            sort_info->buff_length=reclength;
3322
 
            sort_info->buff= (unsigned char *)tmpptr;
3323
 
          }
3324
 
          else
3325
 
          {
3326
 
            mi_check_print_error(param,"Could not realloc() sort_info->buff "
3327
 
                                 " to %ul bytes", reclength);
3328
 
            return(1);
3329
 
          }
 
3506
          if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
 
3507
                                           MYF(MY_FREE_ON_ERROR |
 
3508
                                               MY_ALLOW_ZERO_PTR))))
 
3509
            DBUG_RETURN(1);
 
3510
          sort_info->buff_length=reclength;
3330
3511
        }
3331
3512
        from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3332
3513
      }
3349
3530
                                  sort_param->filepos+block_length,
3350
3531
                                  &from,&reclength,&flag))
3351
3532
        {
3352
 
          mi_check_print_error(param,"%d when writing to datafile",errno);
3353
 
          return(1);
 
3533
          mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3534
          DBUG_RETURN(1);
3354
3535
        }
3355
3536
        sort_param->filepos+=block_length;
3356
3537
        info->s->state.split++;
3358
3539
      /* sort_info->param->glob_crc+=info->checksum; */
3359
3540
      break;
3360
3541
    case COMPRESSED_RECORD:
 
3542
      reclength=info->packed_length;
 
3543
      length= save_pack_length((uint) share->pack.version, block_buff,
 
3544
                               reclength);
 
3545
      if (info->s->base.blobs)
 
3546
        length+= save_pack_length((uint) share->pack.version,
 
3547
                                  block_buff + length, info->blob_length);
 
3548
      if (my_b_write(&info->rec_cache,block_buff,length) ||
 
3549
          my_b_write(&info->rec_cache,(uchar*) sort_param->rec_buff,reclength))
 
3550
      {
 
3551
        mi_check_print_error(param,"%d when writing to datafile",my_errno);
 
3552
        DBUG_RETURN(1);
 
3553
      }
 
3554
      /* sort_info->param->glob_crc+=info->checksum; */
 
3555
      sort_param->filepos+=reclength+length;
 
3556
      info->s->state.split++;
 
3557
      break;
3361
3558
    case BLOCK_RECORD:
3362
3559
      assert(0);                                  /* Impossible */
3363
3560
    }
3370
3567
    {
3371
3568
      char llbuff[22];
3372
3569
      printf("%s\r", llstr(info->state->records,llbuff));
3373
 
      fflush(stdout);
 
3570
      VOID(fflush(stdout));
3374
3571
    }
3375
3572
  }
3376
 
  return(0);
 
3573
  DBUG_RETURN(0);
3377
3574
} /* sort_write_record */
3378
3575
 
3379
3576
 
3380
3577
        /* Compare two keys from _create_index_by_sort */
3381
3578
 
3382
 
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b)
 
3579
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
 
3580
                        const void *b)
3383
3581
{
3384
 
  uint32_t not_used[2];
3385
 
  return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
 
3582
  uint not_used[2];
 
3583
  return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
3386
3584
                     USE_WHOLE_KEY, SEARCH_SAME, not_used));
3387
3585
} /* sort_key_cmp */
3388
3586
 
3389
3587
 
3390
 
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
 
3588
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3391
3589
{
3392
 
  uint32_t diff_pos[2];
 
3590
  uint diff_pos[2];
3393
3591
  char llbuff[22],llbuff2[22];
3394
3592
  SORT_INFO *sort_info=sort_param->sort_info;
3395
3593
  MI_CHECK *param= sort_info->param;
3398
3596
  if (sort_info->key_block->inited)
3399
3597
  {
3400
3598
    cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3401
 
                   (unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
 
3599
                   (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3402
3600
                   diff_pos);
3403
3601
    if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3404
3602
      ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3405
 
                 (unsigned char*) a, USE_WHOLE_KEY,
 
3603
                 (uchar*) a, USE_WHOLE_KEY, 
3406
3604
                 SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3407
3605
    else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3408
3606
    {
3409
3607
      diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3410
3608
                                                 sort_param->notnull,
3411
3609
                                                 sort_info->key_block->lastkey,
3412
 
                                                 (unsigned char*)a);
 
3610
                                                 (uchar*)a);
3413
3611
    }
3414
3612
    sort_param->unique[diff_pos[0]-1]++;
3415
3613
  }
3418
3616
    cmp= -1;
3419
3617
    if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3420
3618
      mi_collect_stats_nonulls_first(sort_param->seg, sort_param->notnull,
3421
 
                                     (unsigned char*)a);
 
3619
                                     (uchar*)a);
3422
3620
  }
3423
3621
  if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
3424
3622
  {
3425
3623
    sort_info->dupp++;
3426
3624
    sort_info->info->lastpos=get_record_for_key(sort_info->info,
3427
3625
                                                sort_param->keyinfo,
3428
 
                                                (unsigned char*) a);
 
3626
                                                (uchar*) a);
3429
3627
    mi_check_print_warning(param,
3430
3628
                           "Duplicate key for record at %10s against record at %10s",
3431
3629
                           llstr(sort_info->info->lastpos,llbuff),
3435
3633
                                                    lastkey),
3436
3634
                                 llbuff2));
3437
3635
    param->testflag|=T_RETRY_WITHOUT_QUICK;
 
3636
    if (sort_info->param->testflag & T_VERBOSE)
 
3637
      _mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
3438
3638
    return (sort_delete_record(sort_param));
3439
3639
  }
 
3640
#ifndef DBUG_OFF
 
3641
  if (cmp > 0)
 
3642
  {
 
3643
    mi_check_print_error(param,
 
3644
                         "Internal error: Keys are not in order from sort");
 
3645
    return(1);
 
3646
  }
 
3647
#endif
3440
3648
  return (sort_insert_key(sort_param,sort_info->key_block,
3441
 
                          (unsigned char*) a, HA_OFFSET_ERROR));
 
3649
                          (uchar*) a, HA_OFFSET_ERROR));
3442
3650
} /* sort_key_write */
3443
3651
 
3444
3652
 
3445
3653
        /* get pointer to record from a key */
3446
3654
 
3447
 
my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3448
 
                            unsigned char *key) {
 
3655
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
 
3656
                                   uchar *key)
 
3657
{
3449
3658
  return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3450
3659
} /* get_record_for_key */
3451
3660
 
3452
3661
 
3453
3662
        /* Insert a key in sort-key-blocks */
3454
3663
 
3455
 
int sort_insert_key(MI_SORT_PARAM *sort_param,
3456
 
                    register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3457
 
                    my_off_t prev_block)
 
3664
static int sort_insert_key(MI_SORT_PARAM *sort_param,
 
3665
                           register SORT_KEY_BLOCKS *key_block, uchar *key,
 
3666
                           my_off_t prev_block)
3458
3667
{
3459
 
  uint32_t a_length,t_length,nod_flag;
 
3668
  uint a_length,t_length,nod_flag;
3460
3669
  my_off_t filepos,key_file_length;
3461
 
  unsigned char *anc_buff,*lastkey;
 
3670
  uchar *anc_buff,*lastkey;
3462
3671
  MI_KEY_PARAM s_temp;
3463
3672
  MI_INFO *info;
3464
3673
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
3465
3674
  SORT_INFO *sort_info= sort_param->sort_info;
3466
3675
  MI_CHECK *param=sort_info->param;
 
3676
  DBUG_ENTER("sort_insert_key");
3467
3677
 
3468
3678
  anc_buff=key_block->buff;
3469
3679
  info=sort_info->info;
3477
3687
    if (key_block == sort_info->key_block_end)
3478
3688
    {
3479
3689
      mi_check_print_error(param,"To many key-block-levels; Try increasing sort_key_blocks");
3480
 
      return(1);
 
3690
      DBUG_RETURN(1);
3481
3691
    }
3482
3692
    a_length=2+nod_flag;
3483
3693
    key_block->end_pos=anc_buff+2;
3491
3701
    _mi_kpointer(info,key_block->end_pos,prev_block);
3492
3702
 
3493
3703
  t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
3494
 
                                (unsigned char*) 0,lastkey,lastkey,key,
 
3704
                                (uchar*) 0,lastkey,lastkey,key,
3495
3705
                                 &s_temp);
3496
3706
  (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
3497
3707
  a_length+=t_length;
3499
3709
  key_block->end_pos+=t_length;
3500
3710
  if (a_length <= keyinfo->block_length)
3501
3711
  {
3502
 
    _mi_move_key(keyinfo,key_block->lastkey,key);
 
3712
    VOID(_mi_move_key(keyinfo,key_block->lastkey,key));
3503
3713
    key_block->last_length=a_length-t_length;
3504
 
    return(0);
 
3714
    DBUG_RETURN(0);
3505
3715
  }
3506
3716
 
3507
3717
        /* Fill block with end-zero and write filled block */
3508
3718
  mi_putint(anc_buff,key_block->last_length,nod_flag);
3509
 
  memset(anc_buff+key_block->last_length, 0,
3510
 
         keyinfo->block_length - key_block->last_length);
 
3719
  bzero((uchar*) anc_buff+key_block->last_length,
 
3720
        keyinfo->block_length- key_block->last_length);
3511
3721
  key_file_length=info->state->key_file_length;
3512
3722
  if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3513
 
    return(1);
 
3723
    DBUG_RETURN(1);
3514
3724
 
3515
3725
  /* If we read the page from the key cache, we have to write it back to it */
3516
3726
  if (key_file_length == info->state->key_file_length)
3517
3727
  {
3518
3728
    if (_mi_write_keypage(info, keyinfo, filepos, DFLT_INIT_HITS, anc_buff))
3519
 
      return(1);
 
3729
      DBUG_RETURN(1);
3520
3730
  }
3521
 
  else if (my_pwrite(info->s->kfile,(unsigned char*) anc_buff,
 
3731
  else if (my_pwrite(info->s->kfile,(uchar*) anc_buff,
3522
3732
                     (uint) keyinfo->block_length,filepos, param->myf_rw))
3523
 
    return(1);
 
3733
    DBUG_RETURN(1);
 
3734
  DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff));
3524
3735
 
3525
3736
        /* Write separator-key to block in next level */
3526
3737
  if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos))
3527
 
    return(1);
 
3738
    DBUG_RETURN(1);
3528
3739
 
3529
3740
        /* clear old block and write new key in it */
3530
3741
  key_block->inited=0;
3531
 
  return(sort_insert_key(sort_param, key_block,key,prev_block));
 
3742
  DBUG_RETURN(sort_insert_key(sort_param, key_block,key,prev_block));
3532
3743
} /* sort_insert_key */
3533
3744
 
3534
3745
 
3535
3746
        /* Delete record when we found a duplicated key */
3536
3747
 
3537
 
int sort_delete_record(MI_SORT_PARAM *sort_param)
 
3748
static int sort_delete_record(MI_SORT_PARAM *sort_param)
3538
3749
{
3539
 
  uint32_t i;
 
3750
  uint i;
3540
3751
  int old_file,error;
3541
 
  unsigned char *key;
 
3752
  uchar *key;
3542
3753
  SORT_INFO *sort_info=sort_param->sort_info;
3543
3754
  MI_CHECK *param=sort_info->param;
3544
3755
  MI_INFO *info=sort_info->info;
 
3756
  DBUG_ENTER("sort_delete_record");
3545
3757
 
3546
3758
  if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
3547
3759
  {
3548
3760
    mi_check_print_error(param,
3549
3761
                         "Quick-recover aborted; Run recovery without switch -q or with switch -qq");
3550
 
    return(1);
 
3762
    DBUG_RETURN(1);
3551
3763
  }
3552
3764
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3553
3765
  {
3554
3766
    mi_check_print_error(param,
3555
3767
                         "Recover aborted; Can't run standard recovery on compressed tables with errors in data-file. Use switch 'myisamchk --safe-recover' to fix it\n",stderr);;
3556
 
    return(1);
 
3768
    DBUG_RETURN(1);
3557
3769
  }
3558
3770
 
3559
3771
  old_file=info->dfile;
3566
3778
    {
3567
3779
      mi_check_print_error(param,"Can't read record to be removed");
3568
3780
      info->dfile=old_file;
3569
 
      return(1);
 
3781
      DBUG_RETURN(1);
3570
3782
    }
3571
3783
 
3572
3784
    for (i=0 ; i < sort_info->current_key ; i++)
3573
3785
    {
3574
 
      uint32_t key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
 
3786
      uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos);
3575
3787
      if (_mi_ck_delete(info,i,key,key_length))
3576
3788
      {
3577
3789
        mi_check_print_error(param,"Can't delete key %d from record to be removed",i+1);
3578
3790
        info->dfile=old_file;
3579
 
        return(1);
 
3791
        DBUG_RETURN(1);
3580
3792
      }
3581
3793
    }
3582
3794
    if (sort_param->calc_checksum)
3585
3797
  error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
3586
3798
  info->dfile=old_file;                         /* restore actual value */
3587
3799
  info->state->records--;
3588
 
  return(error);
 
3800
  DBUG_RETURN(error);
3589
3801
} /* sort_delete_record */
3590
3802
 
3591
3803
        /* Fix all pending blocks and flush everything to disk */
3592
3804
 
3593
3805
int flush_pending_blocks(MI_SORT_PARAM *sort_param)
3594
3806
{
3595
 
  uint32_t nod_flag,length;
 
3807
  uint nod_flag,length;
3596
3808
  my_off_t filepos,key_file_length;
3597
3809
  SORT_KEY_BLOCKS *key_block;
3598
3810
  SORT_INFO *sort_info= sort_param->sort_info;
3599
3811
  myf myf_rw=sort_info->param->myf_rw;
3600
3812
  MI_INFO *info=sort_info->info;
3601
3813
  MI_KEYDEF *keyinfo=sort_param->keyinfo;
 
3814
  DBUG_ENTER("flush_pending_blocks");
3602
3815
 
3603
3816
  filepos= HA_OFFSET_ERROR;                     /* if empty file */
3604
3817
  nod_flag=0;
3609
3822
    if (nod_flag)
3610
3823
      _mi_kpointer(info,key_block->end_pos,filepos);
3611
3824
    key_file_length=info->state->key_file_length;
3612
 
    memset(key_block->buff+length, 0, keyinfo->block_length-length);
 
3825
    bzero((uchar*) key_block->buff+length, keyinfo->block_length-length);
3613
3826
    if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
3614
 
      return(1);
 
3827
      DBUG_RETURN(1);
3615
3828
 
3616
3829
    /* If we read the page from the key cache, we have to write it back */
3617
3830
    if (key_file_length == info->state->key_file_length)
3618
3831
    {
3619
3832
      if (_mi_write_keypage(info, keyinfo, filepos,
3620
3833
                            DFLT_INIT_HITS, key_block->buff))
3621
 
        return(1);
 
3834
        DBUG_RETURN(1);
3622
3835
    }
3623
 
    else if (my_pwrite(info->s->kfile,(unsigned char*) key_block->buff,
 
3836
    else if (my_pwrite(info->s->kfile,(uchar*) key_block->buff,
3624
3837
                       (uint) keyinfo->block_length,filepos, myf_rw))
3625
 
      return(1);
 
3838
      DBUG_RETURN(1);
 
3839
    DBUG_DUMP("buff",(uchar*) key_block->buff,length);
3626
3840
    nod_flag=1;
3627
3841
  }
3628
3842
  info->s->state.key_root[sort_param->key]=filepos; /* Last is root for tree */
3629
 
  return(0);
 
3843
  DBUG_RETURN(0);
3630
3844
} /* flush_pending_blocks */
3631
3845
 
3632
3846
        /* alloc space and pointers for key_blocks */
3633
3847
 
3634
 
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
3635
 
                                         uint32_t buffer_length)
 
3848
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
 
3849
                                         uint buffer_length)
3636
3850
{
3637
 
  register uint32_t i;
 
3851
  register uint i;
3638
3852
  SORT_KEY_BLOCKS *block;
 
3853
  DBUG_ENTER("alloc_key_blocks");
3639
3854
 
3640
 
  if (!(block=(SORT_KEY_BLOCKS*) malloc((sizeof(SORT_KEY_BLOCKS)+
3641
 
                                        buffer_length+IO_SIZE)*blocks)))
 
3855
  if (!(block=(SORT_KEY_BLOCKS*) my_malloc((sizeof(SORT_KEY_BLOCKS)+
 
3856
                                            buffer_length+IO_SIZE)*blocks,
 
3857
                                           MYF(0))))
3642
3858
  {
3643
3859
    mi_check_print_error(param,"Not enough memory for sort-key-blocks");
3644
3860
    return(0);
3646
3862
  for (i=0 ; i < blocks ; i++)
3647
3863
  {
3648
3864
    block[i].inited=0;
3649
 
    block[i].buff=(unsigned char*) (block+blocks)+(buffer_length+IO_SIZE)*i;
 
3865
    block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
3650
3866
  }
3651
 
  return(block);
 
3867
  DBUG_RETURN(block);
3652
3868
} /* alloc_key_blocks */
3653
3869
 
3654
3870
 
3658
3874
{
3659
3875
  if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3660
3876
    return 0;
3661
 
  return (my_off_t)(lseek(info->s->kfile, 0L, SEEK_END) / 10 * 9) >
 
3877
  return my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)) / 10 * 9 >
3662
3878
         (my_off_t) info->s->base.max_key_file_length ||
3663
 
         (my_off_t)(lseek(info->dfile, 0L, SEEK_END) / 10 * 9) >
 
3879
         my_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
3664
3880
         (my_off_t) info->s->base.max_data_file_length;
3665
3881
}
3666
3882
 
3676
3892
  MI_COLUMNDEF *recdef,*rec,*end;
3677
3893
  MI_UNIQUEDEF *uniquedef,*u_ptr,*u_end;
3678
3894
  MI_STATUS_INFO status_info;
3679
 
  uint32_t unpack,key_parts;
 
3895
  uint unpack,key_parts;
3680
3896
  ha_rows max_records;
3681
 
  uint64_t file_length,tmp_length;
 
3897
  ulonglong file_length,tmp_length;
3682
3898
  MI_CREATE_INFO create_info;
 
3899
  DBUG_ENTER("recreate_table");
3683
3900
 
3684
3901
  error=1;                                      /* Default error */
3685
3902
  info= **org_info;
3688
3905
  share= *(*org_info)->s;
3689
3906
  unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3690
3907
    (param->testflag & T_UNPACK);
3691
 
  if (!(keyinfo=(MI_KEYDEF*) malloc(sizeof(MI_KEYDEF)*share.base.keys)))
3692
 
    return(0);
3693
 
  memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
 
3908
  if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
 
3909
    DBUG_RETURN(0);
 
3910
  memcpy((uchar*) keyinfo,(uchar*) share.keyinfo,
 
3911
         (size_t) (sizeof(MI_KEYDEF)*share.base.keys));
3694
3912
 
3695
3913
  key_parts= share.base.all_key_parts;
3696
 
  if (!(keysegs=(HA_KEYSEG*) malloc(sizeof(HA_KEYSEG)*
3697
 
                                    (key_parts+share.base.keys))))
 
3914
  if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
 
3915
                                       (key_parts+share.base.keys))))
3698
3916
  {
3699
 
    free(keyinfo);
3700
 
    return(1);
 
3917
    my_afree((uchar*) keyinfo);
 
3918
    DBUG_RETURN(1);
3701
3919
  }
3702
3920
  if (!(recdef=(MI_COLUMNDEF*)
3703
 
        malloc(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
 
3921
        my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3704
3922
  {
3705
 
    free(keyinfo);
3706
 
    free(keysegs);
3707
 
    return(1);
 
3923
    my_afree((uchar*) keyinfo);
 
3924
    my_afree((uchar*) keysegs);
 
3925
    DBUG_RETURN(1);
3708
3926
  }
3709
3927
  if (!(uniquedef=(MI_UNIQUEDEF*)
3710
 
        malloc(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
 
3928
        my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3711
3929
  {
3712
 
    free(recdef);
3713
 
    free(keyinfo);
3714
 
    free(keysegs);
3715
 
    return(1);
 
3930
    my_afree((uchar*) recdef);
 
3931
    my_afree((uchar*) keyinfo);
 
3932
    my_afree((uchar*) keysegs);
 
3933
    DBUG_RETURN(1);
3716
3934
  }
3717
3935
 
3718
3936
  /* Copy the column definitions */
3719
 
  memcpy(recdef, share.rec, sizeof(MI_COLUMNDEF)*(share.base.fields+1));
 
3937
  memcpy((uchar*) recdef,(uchar*) share.rec,
 
3938
         (size_t) (sizeof(MI_COLUMNDEF)*(share.base.fields+1)));
3720
3939
  for (rec=recdef,end=recdef+share.base.fields; rec != end ; rec++)
3721
3940
  {
3722
3941
    if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
3727
3946
  }
3728
3947
 
3729
3948
  /* Change the new key to point at the saved key segments */
3730
 
  memcpy(keysegs,share.keyparts,
3731
 
         sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
3732
 
                            share.state.header.uniques));
 
3949
  memcpy((uchar*) keysegs,(uchar*) share.keyparts,
 
3950
         (size_t) (sizeof(HA_KEYSEG)*(key_parts+share.base.keys+
 
3951
                                      share.state.header.uniques)));
3733
3952
  keyseg=keysegs;
3734
3953
  for (key=keyinfo,key_end=keyinfo+share.base.keys; key != key_end ; key++)
3735
3954
  {
3744
3963
 
3745
3964
  /* Copy the unique definitions and change them to point at the new key
3746
3965
     segments*/
3747
 
  memcpy(uniquedef,share.uniqueinfo,
3748
 
         sizeof(MI_UNIQUEDEF)*(share.state.header.uniques));
 
3966
  memcpy((uchar*) uniquedef,(uchar*) share.uniqueinfo,
 
3967
         (size_t) (sizeof(MI_UNIQUEDEF)*(share.state.header.uniques)));
3749
3968
  for (u_ptr=uniquedef,u_end=uniquedef+share.state.header.uniques;
3750
3969
       u_ptr != u_end ; u_ptr++)
3751
3970
  {
3755
3974
  if (share.options & HA_OPTION_COMPRESS_RECORD)
3756
3975
    share.base.records=max_records=info.state->records;
3757
3976
  else if (share.base.min_pack_length)
3758
 
    max_records=(ha_rows) (lseek(info.dfile,0L,SEEK_END) /
 
3977
    max_records=(ha_rows) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) /
3759
3978
                           (ulong) share.base.min_pack_length);
3760
3979
  else
3761
3980
    max_records=0;
3763
3982
    (param->testflag & T_UNPACK);
3764
3983
  share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3765
3984
 
3766
 
  file_length=(uint64_t) lseek(info.dfile,0L,SEEK_END);
 
3985
  file_length=(ulonglong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3767
3986
  tmp_length= file_length+file_length/10;
3768
3987
  set_if_bigger(file_length,param->max_data_file_length);
3769
3988
  set_if_bigger(file_length,tmp_length);
3770
 
  set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
 
3989
  set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
3771
3990
 
3772
 
  mi_close(*org_info);
3773
 
  memset(&create_info, 0, sizeof(create_info));
 
3991
  VOID(mi_close(*org_info));
 
3992
  bzero((char*) &create_info,sizeof(create_info));
3774
3993
  create_info.max_rows=max(max_records,share.base.records);
3775
3994
  create_info.reloc_rows=share.base.reloc;
3776
3995
  create_info.old_options=(share.options |
3785
4004
    Allow for creating an auto_increment key. This has an effect only if
3786
4005
    an auto_increment key exists in the original table.
3787
4006
  */
3788
 
  create_info.with_auto_increment= true;
 
4007
  create_info.with_auto_increment= TRUE;
3789
4008
  /* We don't have to handle symlinks here because we are using
3790
4009
     HA_DONT_TOUCH_DATA */
3791
4010
  if (mi_create(filename,
3795
4014
                &create_info,
3796
4015
                HA_DONT_TOUCH_DATA))
3797
4016
  {
3798
 
    mi_check_print_error(param,"Got error %d when trying to recreate indexfile",errno);
 
4017
    mi_check_print_error(param,"Got error %d when trying to recreate indexfile",my_errno);
3799
4018
    goto end;
3800
4019
  }
3801
4020
  *org_info=mi_open(filename,O_RDWR,
3805
4024
  if (!*org_info)
3806
4025
  {
3807
4026
    mi_check_print_error(param,"Got error %d when trying to open re-created indexfile",
3808
 
                errno);
 
4027
                my_errno);
3809
4028
    goto end;
3810
4029
  }
3811
4030
  /* We are modifing */
3812
4031
  (*org_info)->s->options&= ~HA_OPTION_READ_ONLY_DATA;
3813
 
  _mi_readinfo(*org_info,F_WRLCK,0);
 
4032
  VOID(_mi_readinfo(*org_info,F_WRLCK,0));
3814
4033
  (*org_info)->state->records=info.state->records;
3815
4034
  if (share.state.create_time)
3816
4035
    (*org_info)->s->state.create_time=share.state.create_time;
3826
4045
    goto end;
3827
4046
  error=0;
3828
4047
end:
3829
 
  free(uniquedef);
3830
 
  free(keyinfo);
3831
 
  free(recdef);
3832
 
  free(keysegs);
3833
 
  return(error);
 
4048
  my_afree((uchar*) uniquedef);
 
4049
  my_afree((uchar*) keyinfo);
 
4050
  my_afree((uchar*) recdef);
 
4051
  my_afree((uchar*) keysegs);
 
4052
  DBUG_RETURN(error);
3834
4053
}
3835
4054
 
3836
4055
 
3837
4056
        /* write suffix to data file if neaded */
3838
4057
 
3839
 
int write_data_suffix(SORT_INFO *sort_info, bool fix_datafile)
 
4058
int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile)
3840
4059
{
3841
4060
  MI_INFO *info=sort_info->info;
3842
4061
 
3843
4062
  if (info->s->options & HA_OPTION_COMPRESS_RECORD && fix_datafile)
3844
4063
  {
3845
 
    unsigned char buff[MEMMAP_EXTRA_MARGIN];
3846
 
    memset(buff, 0, sizeof(buff));
 
4064
    uchar buff[MEMMAP_EXTRA_MARGIN];
 
4065
    bzero(buff,sizeof(buff));
3847
4066
    if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
3848
4067
    {
3849
4068
      mi_check_print_error(sort_info->param,
3850
 
                           "%d when writing to datafile",errno);
 
4069
                           "%d when writing to datafile",my_errno);
3851
4070
      return 1;
3852
4071
    }
3853
4072
    sort_info->param->read_cache.end_of_file+=sizeof(buff);
3857
4076
 
3858
4077
        /* Update state and myisamchk_time of indexfile */
3859
4078
 
3860
 
int update_state_info(MI_CHECK *param, MI_INFO *info,uint32_t update)
 
4079
int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
3861
4080
{
3862
4081
  MYISAM_SHARE *share=info->s;
3863
4082
 
3868
4087
  }
3869
4088
  if (update & UPDATE_STAT)
3870
4089
  {
3871
 
    uint32_t i, key_parts= mi_uint2korr(share->state.header.key_parts);
 
4090
    uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
3872
4091
    share->state.rec_per_key_rows=info->state->records;
3873
4092
    share->state.changed&= ~STATE_NOT_ANALYZED;
3874
4093
    if (info->state->records)
3902
4121
  }
3903
4122
  {                                             /* Force update of status */
3904
4123
    int error;
3905
 
    uint32_t r_locks=share->r_locks,w_locks=share->w_locks;
 
4124
    uint r_locks=share->r_locks,w_locks=share->w_locks;
3906
4125
    share->r_locks= share->w_locks= share->tot_locks= 0;
3907
4126
    error=_mi_writeinfo(info,WRITEINFO_NO_UNLOCK);
3908
4127
    share->r_locks=r_locks;
3912
4131
      return 0;
3913
4132
  }
3914
4133
err:
3915
 
  mi_check_print_error(param,"%d when updating keyfile",errno);
 
4134
  mi_check_print_error(param,"%d when updating keyfile",my_errno);
3916
4135
  return 1;
3917
4136
}
3918
4137
 
3930
4149
        */
3931
4150
 
3932
4151
void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
3933
 
                               bool repair_only)
 
4152
                               my_bool repair_only)
3934
4153
{
3935
 
  unsigned char *record= 0;
 
4154
  uchar *record= 0;
 
4155
  DBUG_ENTER("update_auto_increment_key");
3936
4156
 
3937
4157
  if (!info->s->base.auto_key ||
3938
4158
      ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
3941
4161
      mi_check_print_info(param,
3942
4162
                          "Table: %s doesn't have an auto increment key\n",
3943
4163
                          param->isam_file_name);
3944
 
    return;
 
4164
    DBUG_VOID_RETURN;
3945
4165
  }
3946
4166
  if (!(param->testflag & T_SILENT) &&
3947
4167
      !(param->testflag & T_REP))
3948
4168
    printf("Updating MyISAM file: %s\n", param->isam_file_name);
3949
4169
  /*
3950
 
    We have to use an allocated buffer instead of info->rec_buff as
 
4170
    We have to use an allocated buffer instead of info->rec_buff as 
3951
4171
    _mi_put_key_in_record() may use info->rec_buff
3952
4172
  */
3953
4173
  if (!mi_alloc_rec_buff(info, -1, &record))
3954
4174
  {
3955
4175
    mi_check_print_error(param,"Not enough memory for extra record");
3956
 
    return;
 
4176
    DBUG_VOID_RETURN;
3957
4177
  }
3958
4178
 
3959
4179
  mi_extra(info,HA_EXTRA_KEYREAD,0);
3960
4180
  if (mi_rlast(info, record, info->s->base.auto_key-1))
3961
4181
  {
3962
 
    if (errno != HA_ERR_END_OF_FILE)
 
4182
    if (my_errno != HA_ERR_END_OF_FILE)
3963
4183
    {
3964
4184
      mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3965
 
      free(mi_get_rec_buff_ptr(info, record));
3966
 
      mi_check_print_error(param,"%d when reading last record",errno);
3967
 
      return;
 
4185
      my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
 
4186
      mi_check_print_error(param,"%d when reading last record",my_errno);
 
4187
      DBUG_VOID_RETURN;
3968
4188
    }
3969
4189
    if (!repair_only)
3970
4190
      info->s->state.auto_increment=param->auto_increment_value;
3971
4191
  }
3972
4192
  else
3973
4193
  {
3974
 
    uint64_t auto_increment= retrieve_auto_increment(info, record);
 
4194
    ulonglong auto_increment= retrieve_auto_increment(info, record);
3975
4195
    set_if_bigger(info->s->state.auto_increment,auto_increment);
3976
4196
    if (!repair_only)
3977
4197
      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
3978
4198
  }
3979
4199
  mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
3980
 
  free(mi_get_rec_buff_ptr(info, record));
 
4200
  my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
3981
4201
  update_state_info(param, info, UPDATE_AUTO_INC);
3982
 
  return;
 
4202
  DBUG_VOID_RETURN;
3983
4203
}
3984
4204
 
3985
4205
 
3995
4215
      records               Number of records in the table
3996
4216
 
3997
4217
  DESCRIPTION
3998
 
    This function is called produce index statistics values from unique and
 
4218
    This function is called produce index statistics values from unique and 
3999
4219
    notnull_tuples arrays after these arrays were produced with sequential
4000
4220
    index scan (the scan is done in two places: chk_index() and
4001
4221
    sort_key_write()).
4009
4229
 
4010
4230
    For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too:
4011
4231
      notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL)
4012
 
      notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
 
4232
      notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all 
4013
4233
                          keypart{i} are not NULL)
4014
4234
      ...
4015
4235
    For all other statistics collection methods notnull_tuples==NULL.
4016
4236
 
4017
4237
    Output is an array:
4018
 
    rec_per_key_part[k] =
4019
 
     = E(#records in the table such that keypart_1=c_1 AND ... AND
4020
 
         keypart_k=c_k for arbitrary constants c_1 ... c_k)
4021
 
 
 
4238
    rec_per_key_part[k] = 
 
4239
     = E(#records in the table such that keypart_1=c_1 AND ... AND 
 
4240
         keypart_k=c_k for arbitrary constants c_1 ... c_k) 
 
4241
     
4022
4242
     = {assuming that values have uniform distribution and index contains all
4023
4243
        tuples from the domain (or that {c_1, ..., c_k} tuple is choosen from
4024
4244
        index tuples}
4025
 
 
 
4245
     
4026
4246
     = #tuples-in-the-index / #distinct-tuples-in-the-index.
4027
 
 
4028
 
    The #tuples-in-the-index and #distinct-tuples-in-the-index have different
 
4247
    
 
4248
    The #tuples-in-the-index and #distinct-tuples-in-the-index have different 
4029
4249
    meaning depending on which statistics collection method is used:
4030
 
 
 
4250
    
4031
4251
    MI_STATS_METHOD_*  how are nulls compared?  which tuples are counted?
4032
4252
     NULLS_EQUAL            NULL == NULL           all tuples in table
4033
4253
     NULLS_NOT_EQUAL        NULL != NULL           all tuples in table
4035
4255
*/
4036
4256
 
4037
4257
void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
4038
 
                      uint64_t *unique, uint64_t *notnull,
4039
 
                      uint64_t records)
 
4258
                      ulonglong *unique, ulonglong *notnull,
 
4259
                      ulonglong records)
4040
4260
{
4041
 
  uint64_t count=0,tmp, unique_tuples;
4042
 
  uint64_t tuples= records;
4043
 
  uint32_t parts;
 
4261
  ulonglong count=0,tmp, unique_tuples;
 
4262
  ulonglong tuples= records;
 
4263
  uint parts;
4044
4264
  for (parts=0 ; parts < keyinfo->keysegs  ; parts++)
4045
4265
  {
4046
4266
    count+=unique[parts];
4047
 
    unique_tuples= count + 1;
 
4267
    unique_tuples= count + 1;    
4048
4268
    if (notnull)
4049
4269
    {
4050
4270
      tuples= notnull[parts];
4051
 
      /*
4052
 
        #(unique_tuples not counting tuples with NULLs) =
4053
 
          #(unique_tuples counting tuples with NULLs as different) -
 
4271
      /* 
 
4272
        #(unique_tuples not counting tuples with NULLs) = 
 
4273
          #(unique_tuples counting tuples with NULLs as different) - 
4054
4274
          #(tuples with NULLs)
4055
4275
      */
4056
4276
      unique_tuples -= (records - notnull[parts]);
4057
4277
    }
4058
 
 
 
4278
    
4059
4279
    if (unique_tuples == 0)
4060
4280
      tmp= 1;
4061
4281
    else if (count == 0)
4063
4283
    else
4064
4284
      tmp= (tuples + unique_tuples/2) / unique_tuples;
4065
4285
 
4066
 
    /*
4067
 
      for some weird keys (e.g. FULLTEXT) tmp can be <1 here.
 
4286
    /* 
 
4287
      for some weird keys (e.g. FULLTEXT) tmp can be <1 here. 
4068
4288
      let's ensure it is not
4069
4289
    */
4070
 
    if (tmp < 1)
4071
 
      tmp= 1;
4072
 
    if (tmp >= (uint64_t) ~(ulong) 0)
4073
 
      tmp=(uint64_t) ~(ulong) 0;
 
4290
    set_if_bigger(tmp,1);
 
4291
    if (tmp >= (ulonglong) ~(ulong) 0)
 
4292
      tmp=(ulonglong) ~(ulong) 0;
4074
4293
 
4075
4294
    *rec_per_key_part=(ulong) tmp;
4076
4295
    rec_per_key_part++;
4078
4297
}
4079
4298
 
4080
4299
 
4081
 
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
 
4300
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4082
4301
{
4083
4302
  ha_checksum crc;
4084
 
  const unsigned char *end=buf+length;
 
4303
  const uchar *end=buf+length;
4085
4304
  for (crc=0; buf != end; buf++)
4086
 
    crc=((crc << 1) + *((unsigned char*) buf)) +
 
4305
    crc=((crc << 1) + *((uchar*) buf)) +
4087
4306
      test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4088
4307
  return crc;
4089
4308
}
4090
4309
 
4091
 
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
 
4310
static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4092
4311
{
4093
 
  uint32_t key_maxlength=key->maxlength;
4094
 
  return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4095
 
          ((uint64_t) rows * key_maxlength >
4096
 
           (uint64_t) MAX_FILE_SIZE));
 
4312
  uint key_maxlength=key->maxlength;
 
4313
  return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY | HA_FULLTEXT) &&
 
4314
          ((ulonglong) rows * key_maxlength >
 
4315
           (ulonglong) myisam_max_temp_length));
4097
4316
}
4098
4317
 
4099
4318
/*
4109
4328
{
4110
4329
  MYISAM_SHARE *share=info->s;
4111
4330
  MI_KEYDEF    *key=share->keyinfo;
4112
 
  uint32_t          i;
 
4331
  uint          i;
4113
4332
 
4114
 
  assert(info->state->records == 0 &&
 
4333
  DBUG_ASSERT(info->state->records == 0 &&
4115
4334
              (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
4116
4335
  for (i=0 ; i < share->base.keys ; i++,key++)
4117
4336
  {
4118
 
    if (!(key->flag & (HA_NOSAME | HA_AUTO_KEY)) &&
 
4337
    if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
4119
4338
        ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1)
4120
4339
    {
4121
4340
      mi_clear_key_active(share->state.key_map, i);
4126
4345
 
4127
4346
 
4128
4347
/*
4129
 
  Return true if we can use repair by sorting
 
4348
  Return TRUE if we can use repair by sorting
4130
4349
  One can set the force argument to force to use sorting
4131
4350
  even if the temporary file would be quite big!
4132
4351
*/
4133
4352
 
4134
 
bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
4135
 
                            uint64_t key_map, bool force)
 
4353
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
 
4354
                            ulonglong key_map, my_bool force)
4136
4355
{
4137
4356
  MYISAM_SHARE *share=info->s;
4138
4357
  MI_KEYDEF *key=share->keyinfo;
4139
 
  uint32_t i;
 
4358
  uint i;
4140
4359
 
4141
4360
  /*
4142
4361
    mi_repair_by_sort only works if we have at least one key. If we don't
4143
4362
    have any keys, we should use the normal repair.
4144
4363
  */
4145
4364
  if (! mi_is_any_key_active(key_map))
4146
 
    return false;                               /* Can't use sort */
 
4365
    return FALSE;                               /* Can't use sort */
4147
4366
  for (i=0 ; i < share->base.keys ; i++,key++)
4148
4367
  {
4149
4368
    if (!force && mi_too_big_key_for_sort(key,rows))
4150
 
      return false;
 
4369
      return FALSE;
4151
4370
  }
4152
 
  return true;
 
4371
  return TRUE;
4153
4372
}
4154
4373
 
4155
4374
 
4167
4386
      sort_info->new_data_file_type = STATIC_RECORD;
4168
4387
 
4169
4388
    /* Set delete_function for sort_delete_record() */
4170
 
    memcpy(&tmp, share, sizeof(*share));
 
4389
    memcpy((char*) &tmp, share, sizeof(*share));
4171
4390
    tmp.options= ~HA_OPTION_COMPRESS_RECORD;
4172
4391
    mi_setup_functions(&tmp);
4173
4392
    share->delete_record=tmp.delete_record;