~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_create.c

Renamed more stuff to drizzle.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* Create a MyISAM table */
17
17
 
18
 
#include "myisam_priv.h"
19
 
#include "drizzled/internal/my_bit.h"
20
 
#include "drizzled/internal/my_sys.h"
21
 
 
22
 
#include "drizzled/util/test.h"
23
 
#include "drizzled/global_charset_info.h"
24
 
#include "drizzled/error.h"
25
 
 
26
 
#include <cassert>
27
 
#include <algorithm>
28
 
 
29
 
using namespace std;
30
 
using namespace drizzled;
 
18
#include "myisamdef.h"
 
19
#include <m_ctype.h>
 
20
#include <my_tree.h>
 
21
#include <queues.h>
 
22
#include <mysql/plugin.h>
 
23
#include <my_bit.h>
 
24
 
 
25
#include <m_ctype.h>
31
26
 
32
27
/*
33
28
  Old options is used when recreating database, from myisamchk
34
29
*/
35
30
 
36
 
int mi_create(const char *name,uint32_t keys,MI_KEYDEF *keydefs,
37
 
              uint32_t columns, MI_COLUMNDEF *recinfo,
38
 
              uint32_t uniques, MI_UNIQUEDEF *uniquedefs,
39
 
              MI_CREATE_INFO *ci,uint32_t flags)
 
31
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
 
32
              uint columns, MI_COLUMNDEF *recinfo,
 
33
              uint uniques, MI_UNIQUEDEF *uniquedefs,
 
34
              MI_CREATE_INFO *ci,uint flags)
40
35
{
41
 
  register uint32_t i, j;
42
 
  int dfile= 0, file= 0;
 
36
  register uint i, j;
 
37
  File dfile= 0, file;
43
38
  int errpos,save_errno, create_mode= O_RDWR | O_TRUNC;
44
39
  myf create_flag;
45
 
  uint32_t fields,length,max_key_length,packed,pointer,real_length_diff,
 
40
  uint fields,length,max_key_length,packed,pointer,real_length_diff,
46
41
       key_length,info_length,key_segs,options,min_key_length_skip,
47
42
       base_pos,long_varchar_count,varchar_length,
48
43
       max_key_block_length,unique_key_parts,fulltext_keys,offset;
49
 
  uint32_t aligned_key_start, block_length;
 
44
  uint aligned_key_start, block_length;
50
45
  ulong reclength, real_reclength,min_pack_length;
51
46
  char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
52
47
  ulong pack_reclength;
53
 
  uint64_t tot_length,max_rows, tmp;
 
48
  ulonglong tot_length,max_rows, tmp;
54
49
  enum en_fieldtype type;
55
50
  MYISAM_SHARE share;
56
51
  MI_KEYDEF *keydef,tmp_keydef;
58
53
  HA_KEYSEG *keyseg,tmp_keyseg;
59
54
  MI_COLUMNDEF *rec;
60
55
  ulong *rec_per_key_part;
61
 
  internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
 
56
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
62
57
  MI_CREATE_INFO tmp_create_info;
 
58
  DBUG_ENTER("mi_create");
 
59
  DBUG_PRINT("enter", ("keys: %u  columns: %u  uniques: %u  flags: %u",
 
60
                      keys, columns, uniques, flags));
63
61
 
64
62
  if (!ci)
65
63
  {
66
 
    memset(&tmp_create_info, 0, sizeof(tmp_create_info));
 
64
    bzero((char*) &tmp_create_info,sizeof(tmp_create_info));
67
65
    ci=&tmp_create_info;
68
66
  }
69
67
 
70
68
  if (keys + uniques > MI_MAX_KEY || columns == 0)
71
69
  {
72
 
    return(errno=HA_WRONG_CREATE_OPTION);
 
70
    DBUG_RETURN(my_errno=HA_WRONG_CREATE_OPTION);
73
71
  }
74
72
  errpos= 0;
75
73
  options= 0;
76
 
  memset(&share, 0, sizeof(share));
 
74
  bzero((uchar*) &share,sizeof(share));
77
75
 
78
76
  if (flags & HA_DONT_TOUCH_DATA)
79
77
  {
80
78
    if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
81
79
      options=ci->old_options &
82
80
        (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
83
 
         HA_OPTION_READ_ONLY_DATA |
84
 
         HA_OPTION_TMP_TABLE );
 
81
         HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
 
82
         HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
85
83
    else
86
84
      options=ci->old_options &
87
 
        (HA_OPTION_TMP_TABLE );
 
85
        (HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
88
86
  }
89
87
 
90
88
  if (ci->reloc_rows > ci->max_rows)
91
89
    ci->reloc_rows=ci->max_rows;                /* Check if wrong parameter */
92
90
 
93
91
  if (!(rec_per_key_part=
94
 
        (ulong*) malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long))))
95
 
    return(errno);
96
 
  memset(rec_per_key_part, 0, (keys + uniques)*MI_MAX_KEY_SEG*sizeof(long));
 
92
        (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long),
 
93
                           MYF(MY_WME | MY_ZEROFILL))))
 
94
    DBUG_RETURN(my_errno);
97
95
 
98
96
        /* Start by checking fields and field-types used */
99
97
 
111
109
      if (type == FIELD_BLOB)
112
110
      {
113
111
        share.base.blobs++;
114
 
        if (pack_reclength != INT32_MAX)
 
112
        if (pack_reclength != INT_MAX32)
115
113
        {
116
114
          if (rec->length == 4+portable_sizeof_char_ptr)
117
 
            pack_reclength= INT32_MAX;
 
115
            pack_reclength= INT_MAX32;
118
116
          else
119
117
            pack_reclength+=(1 << ((rec->length-portable_sizeof_char_ptr)*8)); /* Max blob length */
120
118
        }
122
120
      else if (type == FIELD_SKIP_PRESPACE ||
123
121
               type == FIELD_SKIP_ENDSPACE)
124
122
      {
125
 
        if (pack_reclength != INT32_MAX)
 
123
        if (pack_reclength != INT_MAX32)
126
124
          pack_reclength+= rec->length > 255 ? 2 : 1;
127
125
        min_pack_length++;
128
126
      }
169
167
 
170
168
  if (packed || (flags & HA_PACK_RECORD))
171
169
    options|=HA_OPTION_PACK_RECORD;     /* Must use packed records */
 
170
  /* We can't use checksum with static length rows */
 
171
  if (!(options & HA_OPTION_PACK_RECORD))
 
172
    options&= ~HA_OPTION_CHECKSUM;
172
173
  if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
173
174
    min_pack_length+= varchar_length;
174
175
  if (flags & HA_CREATE_TMP_TABLE)
175
176
  {
176
177
    options|= HA_OPTION_TMP_TABLE;
177
 
    create_mode|= O_EXCL;
178
 
  }
 
178
    create_mode|= O_EXCL | O_NOFOLLOW;
 
179
  }
 
180
  if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
 
181
  {
 
182
    options|= HA_OPTION_CHECKSUM;
 
183
    min_pack_length++;
 
184
  }
 
185
  if (flags & HA_CREATE_DELAY_KEY_WRITE)
 
186
    options|= HA_OPTION_DELAY_KEY_WRITE;
 
187
  if (flags & HA_CREATE_RELIES_ON_SQL_LAYER)
 
188
    options|= HA_OPTION_RELIES_ON_SQL_LAYER;
179
189
 
180
190
  packed=(packed+7)/8;
181
 
  if (pack_reclength != INT32_MAX)
 
191
  if (pack_reclength != INT_MAX32)
182
192
    pack_reclength+= reclength+packed +
183
 
      test(test_all_bits(options,
184
 
                         uint32_t(HA_PACK_RECORD)));
 
193
      test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
185
194
  min_pack_length+=packed;
186
195
 
187
196
  if (!ci->data_file_length && ci->max_rows)
188
197
  {
189
 
    if (pack_reclength == INT32_MAX ||
190
 
             (~(uint64_t) 0)/ci->max_rows < (uint64_t) pack_reclength)
191
 
      ci->data_file_length= ~(uint64_t) 0;
 
198
    if (pack_reclength == INT_MAX32 ||
 
199
             (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
 
200
      ci->data_file_length= ~(ulonglong) 0;
192
201
    else
193
 
      ci->data_file_length=(uint64_t) ci->max_rows*pack_reclength;
 
202
      ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength;
194
203
  }
195
204
  else if (!ci->max_rows)
196
205
    ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
198
207
                                          3 : 0)));
199
208
 
200
209
  if (options & (HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD))
201
 
    pointer=mi_get_pointer_length(ci->data_file_length, data_pointer_size);
 
210
    pointer=mi_get_pointer_length(ci->data_file_length,myisam_data_pointer_size);
202
211
  else
203
 
    pointer=mi_get_pointer_length(ci->max_rows, data_pointer_size);
204
 
  if (!(max_rows=(uint64_t) ci->max_rows))
205
 
    max_rows= ((((uint64_t) 1 << (pointer*8)) -1) / min_pack_length);
 
212
    pointer=mi_get_pointer_length(ci->max_rows,myisam_data_pointer_size);
 
213
  if (!(max_rows=(ulonglong) ci->max_rows))
 
214
    max_rows= ((((ulonglong) 1 << (pointer*8)) -1) / min_pack_length);
206
215
 
207
216
 
208
217
  real_reclength=reclength;
236
245
      /* Test if prefix compression */
237
246
      if (keydef->flag & HA_PACK_KEY)
238
247
      {
 
248
        /* Can't use space_compression on number keys */
 
249
        if ((keydef->seg[0].flag & HA_SPACE_PACK) &&
 
250
            keydef->seg[0].type == (int) HA_KEYTYPE_NUM)
 
251
          keydef->seg[0].flag&= ~HA_SPACE_PACK;
 
252
 
239
253
        /* Only use HA_PACK_KEY when first segment is a variable length key */
240
254
        if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
241
255
                                     HA_VAR_LENGTH_PART)))
260
274
      {
261
275
        /* numbers are stored with high by first to make compression easier */
262
276
        switch (keyseg->type) {
 
277
        case HA_KEYTYPE_SHORT_INT:
263
278
        case HA_KEYTYPE_LONG_INT:
 
279
        case HA_KEYTYPE_FLOAT:
264
280
        case HA_KEYTYPE_DOUBLE:
 
281
        case HA_KEYTYPE_USHORT_INT:
265
282
        case HA_KEYTYPE_ULONG_INT:
266
283
        case HA_KEYTYPE_LONGLONG:
267
284
        case HA_KEYTYPE_ULONGLONG:
 
285
        case HA_KEYTYPE_INT24:
 
286
        case HA_KEYTYPE_UINT24:
 
287
        case HA_KEYTYPE_INT8:
268
288
          keyseg->flag|= HA_SWAP_KEY;
269
289
          break;
270
290
        case HA_KEYTYPE_VARTEXT1:
286
306
        }
287
307
        if (keyseg->flag & HA_SPACE_PACK)
288
308
        {
289
 
          assert(!(keyseg->flag & HA_VAR_LENGTH_PART));
 
309
          DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
290
310
          keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
291
311
          options|=HA_OPTION_PACK_KEYS;         /* Using packed keys */
292
312
          length++;                             /* At least one length byte */
299
319
        }
300
320
        if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
301
321
        {
302
 
          assert(!test_all_bits(keyseg->flag,
 
322
          DBUG_ASSERT(!test_all_bits(keyseg->flag,
303
323
                                    (HA_VAR_LENGTH_PART | HA_BLOB_PART)));
304
324
          keydef->flag|=HA_VAR_LENGTH_KEY;
305
325
          length++;                             /* At least one length byte */
324
344
    key_segs+=keydef->keysegs;
325
345
    if (keydef->keysegs > MI_MAX_KEY_SEG)
326
346
    {
327
 
      errno=HA_WRONG_CREATE_OPTION;
 
347
      my_errno=HA_WRONG_CREATE_OPTION;
328
348
      goto err;
329
349
    }
330
350
    /*
337
357
      share.state.rec_per_key_part[key_segs-1]=1L;
338
358
    length+=key_length;
339
359
    /* Get block length for key, if defined by user */
340
 
    block_length= (keydef->block_length ?
 
360
    block_length= (keydef->block_length ? 
341
361
                   my_round_up_to_next_power(keydef->block_length) :
342
362
                   myisam_block_size);
343
 
    block_length= max(block_length, (uint32_t)MI_MIN_KEY_BLOCK_LENGTH);
344
 
    block_length= min(block_length, (uint32_t)MI_MAX_KEY_BLOCK_LENGTH);
 
363
    block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
 
364
    block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
345
365
 
346
 
    keydef->block_length= (uint16_t) MI_BLOCK_SIZE(length-real_length_diff,
 
366
    keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
347
367
                                                 pointer,MI_MAX_KEYPTR_SIZE,
348
368
                                                 block_length);
349
369
    if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
350
370
        length >= MI_MAX_KEY_BUFF)
351
371
    {
352
 
      errno=HA_WRONG_CREATE_OPTION;
 
372
      my_errno=HA_WRONG_CREATE_OPTION;
353
373
      goto err;
354
374
    }
355
 
    set_if_bigger(max_key_block_length,(uint32_t)keydef->block_length);
356
 
    keydef->keylength= (uint16_t) key_length;
357
 
    keydef->minlength= (uint16_t) (length-min_key_length_skip);
358
 
    keydef->maxlength= (uint16_t) length;
 
375
    set_if_bigger(max_key_block_length,keydef->block_length);
 
376
    keydef->keylength= (uint16) key_length;
 
377
    keydef->minlength= (uint16) (length-min_key_length_skip);
 
378
    keydef->maxlength= (uint16) length;
359
379
 
360
380
    if (length > max_key_length)
361
381
      max_key_length= length;
389
409
                               uniques * MI_UNIQUEDEF_SIZE +
390
410
                               (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+
391
411
                               columns*MI_COLUMNDEF_SIZE);
 
412
  DBUG_PRINT("info", ("info_length: %u", info_length));
392
413
  /* There are only 16 bits for the total header length. */
393
414
  if (info_length > 65535)
394
415
  {
395
416
    my_printf_error(0, "MyISAM table '%s' has too many columns and/or "
396
417
                    "indexes and/or unique constraints.",
397
 
                    MYF(0), name + internal::dirname_length(name));
398
 
    errno= HA_WRONG_CREATE_OPTION;
 
418
                    MYF(0), name + dirname_length(name));
 
419
    my_errno= HA_WRONG_CREATE_OPTION;
399
420
    goto err;
400
421
  }
401
422
 
402
 
  memmove(share.state.header.file_version,myisam_file_magic,4);
 
423
  bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
403
424
  ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
404
425
                        HA_OPTION_COMPRESS_RECORD |
405
426
                        HA_OPTION_TEMP_COMPRESS_RECORD: 0);
417
438
  share.state.unique=   (ulong) 0;
418
439
  share.state.update_count=(ulong) 0;
419
440
  share.state.version=  (ulong) time((time_t*) 0);
420
 
  share.state.sortkey=  UINT16_MAX;
 
441
  share.state.sortkey=  (ushort) ~0;
421
442
  share.state.auto_increment=ci->auto_increment;
422
443
  share.options=options;
423
444
  share.base.rec_reflength=pointer;
448
469
  share.base.records=ci->max_rows;
449
470
  share.base.reloc=  ci->reloc_rows;
450
471
  share.base.reclength=real_reclength;
451
 
  share.base.pack_reclength=reclength;
 
472
  share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);
452
473
  share.base.max_pack_length=pack_reclength;
453
474
  share.base.min_pack_length=min_pack_length;
454
475
  share.base.pack_bits=packed;
457
478
 
458
479
  /* max_data_file_length and max_key_file_length are recalculated on open */
459
480
  if (options & HA_OPTION_TMP_TABLE)
460
 
    share.base.max_data_file_length=(internal::my_off_t) ci->data_file_length;
 
481
    share.base.max_data_file_length=(my_off_t) ci->data_file_length;
461
482
 
462
483
  share.base.min_block_length=
463
484
    (share.base.pack_reclength+3 < MI_EXTEND_BLOCK_LENGTH &&
464
485
     ! share.base.blobs) ?
465
 
    max(share.base.pack_reclength,(ulong)MI_MIN_BLOCK_LENGTH) :
 
486
    max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) :
466
487
    MI_EXTEND_BLOCK_LENGTH;
467
488
  if (! (flags & HA_DONT_TOUCH_DATA))
468
489
    share.state.create_time= (long) time((time_t*) 0);
469
490
 
470
 
  THR_LOCK_myisam.lock();
 
491
  pthread_mutex_lock(&THR_LOCK_myisam);
471
492
 
472
493
  /*
473
494
    NOTE: For test_if_reopen() we need a real path name. Hence we need
474
 
    MY_RETURN_REAL_PATH for every internal::fn_format(filename, ...).
 
495
    MY_RETURN_REAL_PATH for every fn_format(filename, ...).
475
496
  */
476
497
  if (ci->index_file_name)
477
498
  {
478
 
    char *iext= strrchr((char *)ci->index_file_name, '.');
 
499
    char *iext= strrchr(ci->index_file_name, '.');
479
500
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
480
501
    if (options & HA_OPTION_TMP_TABLE)
481
502
    {
482
503
      char *path;
483
504
      /* chop off the table name, tempory tables use generated name */
484
 
      if ((path= strrchr((char *)ci->index_file_name, FN_LIBCHAR)))
 
505
      if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
485
506
        *path= '\0';
486
 
      internal::fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
 
507
      fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT,
487
508
                MY_REPLACE_DIR | MY_UNPACK_FILENAME |
488
509
                MY_RETURN_REAL_PATH | MY_APPEND_EXT);
489
510
    }
490
511
    else
491
512
    {
492
 
      internal::fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
 
513
      fn_format(filename, ci->index_file_name, "", MI_NAME_IEXT,
493
514
                MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
494
515
                (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
495
516
    }
496
 
    internal::fn_format(linkname, name, "", MI_NAME_IEXT,
 
517
    fn_format(linkname, name, "", MI_NAME_IEXT,
497
518
              MY_UNPACK_FILENAME|MY_APPEND_EXT);
498
519
    linkname_ptr=linkname;
499
520
    /*
504
525
  }
505
526
  else
506
527
  {
507
 
    char *iext= strrchr((char *)name, '.');
 
528
    char *iext= strrchr(name, '.');
508
529
    int have_iext= iext && !strcmp(iext, MI_NAME_IEXT);
509
 
    internal::fn_format(filename, name, "", MI_NAME_IEXT,
 
530
    fn_format(filename, name, "", MI_NAME_IEXT,
510
531
              MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
511
532
              (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
512
533
    linkname_ptr=0;
528
549
  {
529
550
    my_printf_error(0, "MyISAM table '%s' is in use "
530
551
                    "(most likely by a MERGE table). Try FLUSH TABLES.",
531
 
                    MYF(0), name + internal::dirname_length(name));
532
 
    errno= HA_ERR_TABLE_EXIST;
 
552
                    MYF(0), name + dirname_length(name));
 
553
    my_errno= HA_ERR_TABLE_EXIST;
533
554
    goto err;
534
555
  }
535
556
 
536
 
  if ((file= internal::my_create_with_symlink(linkname_ptr,
537
 
                                              filename,
538
 
                                              0,
539
 
                                              create_mode,
540
 
                                              MYF(MY_WME | create_flag))) < 0)
 
557
  if ((file= my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
 
558
                                    MYF(MY_WME | create_flag))) < 0)
541
559
    goto err;
542
560
  errpos=1;
543
561
 
546
564
    {
547
565
      if (ci->data_file_name)
548
566
      {
549
 
        char *dext= strrchr((char *)ci->data_file_name, '.');
 
567
        char *dext= strrchr(ci->data_file_name, '.');
550
568
        int have_dext= dext && !strcmp(dext, MI_NAME_DEXT);
551
569
 
552
570
        if (options & HA_OPTION_TMP_TABLE)
553
571
        {
554
572
          char *path;
555
573
          /* chop off the table name, tempory tables use generated name */
556
 
          if ((path= strrchr((char *)ci->data_file_name, FN_LIBCHAR)))
 
574
          if ((path= strrchr(ci->data_file_name, FN_LIBCHAR)))
557
575
            *path= '\0';
558
 
          internal::fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
 
576
          fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT,
559
577
                    MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
560
578
        }
561
579
        else
562
580
        {
563
 
          internal::fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
 
581
          fn_format(filename, ci->data_file_name, "", MI_NAME_DEXT,
564
582
                    MY_UNPACK_FILENAME |
565
583
                    (have_dext ? MY_REPLACE_EXT : MY_APPEND_EXT));
566
584
        }
567
585
 
568
 
        internal::fn_format(linkname, name, "",MI_NAME_DEXT,
 
586
        fn_format(linkname, name, "",MI_NAME_DEXT,
569
587
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
570
588
        linkname_ptr=linkname;
571
589
        create_flag=0;
572
590
      }
573
591
      else
574
592
      {
575
 
        internal::fn_format(filename,name,"", MI_NAME_DEXT,
 
593
        fn_format(filename,name,"", MI_NAME_DEXT,
576
594
                  MY_UNPACK_FILENAME | MY_APPEND_EXT);
577
595
        linkname_ptr=0;
578
596
        create_flag=(flags & HA_CREATE_KEEP_FILES) ? 0 : MY_DELETE_OLD;
579
597
      }
580
 
      if ((dfile= internal::my_create_with_symlink(linkname_ptr,
581
 
                                                   filename, 0, create_mode,
582
 
                                                   MYF(MY_WME | create_flag))) < 0)
 
598
      if ((dfile=
 
599
           my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
 
600
                                  MYF(MY_WME | create_flag))) < 0)
583
601
        goto err;
584
602
    }
585
603
    errpos=3;
586
604
  }
587
605
 
 
606
  DBUG_PRINT("info", ("write state info and base info"));
588
607
  if (mi_state_info_write(file, &share.state, 2) ||
589
608
      mi_base_info_write(file, &share.base))
590
609
    goto err;
 
610
#ifndef DBUG_OFF
 
611
  if ((uint) my_tell(file,MYF(0)) != base_pos+ MI_BASE_INFO_SIZE)
 
612
  {
 
613
    uint pos=(uint) my_tell(file,MYF(0));
 
614
    DBUG_PRINT("warning",("base_length: %d  != used_length: %d",
 
615
                          base_pos+ MI_BASE_INFO_SIZE, pos));
 
616
  }
 
617
#endif
591
618
 
592
619
  /* Write key and keyseg definitions */
 
620
  DBUG_PRINT("info", ("write key and keyseg definitions"));
593
621
  for (i=0 ; i < share.base.keys - uniques; i++)
594
622
  {
595
 
    uint32_t sp_segs= 0;
 
623
    uint sp_segs= 0;
596
624
 
597
625
    if (mi_keydef_write(file, &keydefs[i]))
598
626
      goto err;
602
630
  }
603
631
  /* Create extra keys for unique definitions */
604
632
  offset=reclength-uniques*MI_UNIQUE_HASH_LENGTH;
605
 
  memset(&tmp_keydef, 0, sizeof(tmp_keydef));
606
 
  memset(&tmp_keyseg, 0, sizeof(tmp_keyseg));
 
633
  bzero((char*) &tmp_keydef,sizeof(tmp_keydef));
 
634
  bzero((char*) &tmp_keyseg,sizeof(tmp_keyseg));
607
635
  for (i=0; i < uniques ; i++)
608
636
  {
609
637
    tmp_keydef.keysegs=1;
610
638
    tmp_keydef.flag=            HA_UNIQUE_CHECK;
611
 
    tmp_keydef.block_length=    (uint16_t)myisam_block_size;
 
639
    tmp_keydef.block_length=    (uint16)myisam_block_size;
612
640
    tmp_keydef.keylength=       MI_UNIQUE_HASH_LENGTH + pointer;
613
641
    tmp_keydef.minlength=tmp_keydef.maxlength=tmp_keydef.keylength;
614
642
    tmp_keyseg.type=            MI_UNIQUE_HASH_TYPE;
621
649
  }
622
650
 
623
651
  /* Save unique definition */
 
652
  DBUG_PRINT("info", ("write unique definitions"));
624
653
  for (i=0 ; i < share.state.header.uniques ; i++)
625
654
  {
626
655
    HA_KEYSEG *keyseg_end;
651
680
        goto err;
652
681
    }
653
682
  }
 
683
  DBUG_PRINT("info", ("write field definitions"));
654
684
  for (i=0 ; i < share.base.fields ; i++)
655
685
    if (mi_recinfo_write(file, &recinfo[i]))
656
686
      goto err;
657
687
 
 
688
#ifndef DBUG_OFF
 
689
  if ((uint) my_tell(file,MYF(0)) != info_length)
 
690
  {
 
691
    uint pos= (uint) my_tell(file,MYF(0));
 
692
    DBUG_PRINT("warning",("info_length: %d  != used_length: %d",
 
693
                          info_length, pos));
 
694
  }
 
695
#endif
 
696
 
658
697
        /* Enlarge files */
 
698
  DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart));
659
699
  if (ftruncate(file, (off_t) share.base.keystart))
660
700
    goto err;
661
701
 
666
706
      goto err;
667
707
#endif
668
708
    errpos=2;
669
 
    if (internal::my_close(dfile,MYF(0)))
 
709
    if (my_close(dfile,MYF(0)))
670
710
      goto err;
671
711
  }
672
712
  errpos=0;
673
 
  THR_LOCK_myisam.unlock();
674
 
  if (internal::my_close(file,MYF(0)))
 
713
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
714
  if (my_close(file,MYF(0)))
675
715
    goto err;
676
 
  free((char*) rec_per_key_part);
677
 
  return(0);
 
716
  my_free((char*) rec_per_key_part,MYF(0));
 
717
  DBUG_RETURN(0);
678
718
 
679
719
err:
680
 
  THR_LOCK_myisam.unlock();
681
 
  save_errno=errno;
 
720
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
721
  save_errno=my_errno;
682
722
  switch (errpos) {
683
723
  case 3:
684
 
    internal::my_close(dfile,MYF(0));
 
724
    VOID(my_close(dfile,MYF(0)));
685
725
    /* fall through */
686
726
  case 2:
 
727
    /* QQ: T�nu should add a call to my_raid_delete() here */
687
728
  if (! (flags & HA_DONT_TOUCH_DATA))
688
 
    internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_DEXT,
 
729
    my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_DEXT,
689
730
                                     MY_UNPACK_FILENAME | MY_APPEND_EXT),
690
731
                           MYF(0));
691
732
    /* fall through */
692
733
  case 1:
693
 
    internal::my_close(file,MYF(0));
 
734
    VOID(my_close(file,MYF(0)));
694
735
    if (! (flags & HA_DONT_TOUCH_DATA))
695
 
      internal::my_delete_with_symlink(internal::fn_format(filename,name,"",MI_NAME_IEXT,
 
736
      my_delete_with_symlink(fn_format(filename,name,"",MI_NAME_IEXT,
696
737
                                       MY_UNPACK_FILENAME | MY_APPEND_EXT),
697
738
                             MYF(0));
698
739
  }
699
 
  free((char*) rec_per_key_part);
700
 
  return(errno=save_errno);             /* return the fatal errno */
 
740
  my_free((char*) rec_per_key_part, MYF(0));
 
741
  DBUG_RETURN(my_errno=save_errno);             /* return the fatal errno */
701
742
}
702
743
 
703
744
 
704
 
uint32_t mi_get_pointer_length(uint64_t file_length, uint32_t def)
 
745
uint mi_get_pointer_length(ulonglong file_length, uint def)
705
746
{
706
 
  assert(def >= 2 && def <= 7);
 
747
  DBUG_ASSERT(def >= 2 && def <= 7);
707
748
  if (file_length)                              /* If not default */
708
749
  {
709
750
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS