~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to .pc/enable-hurd.patch/plugin/myisam/mi_open.cc

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-10-29 15:43:40 UTC
  • mfrom: (1.2.12) (2.1.19 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029154340-2gp39el6cv8bwf2o
Tags: 1:7.2.3-2ubuntu1
* Merge from debian, remaining changes:
  - Link against boost_system because of boost_thread.
  - Add required libs to message/include.am
  - Add upstart job and adjust init script to be upstart compatible.
  - Disable -floop-parallelize-all due to gcc-4.8/4.9 compiler ICE
    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57732

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
 
 
16
/* open a isam-database */
 
17
 
 
18
#include "myisam_priv.h"
 
19
 
 
20
#include <string.h>
 
21
#include <algorithm>
 
22
#include <memory>
 
23
#include <boost/scoped_ptr.hpp>
 
24
#include <boost/scoped_array.hpp>
 
25
 
 
26
#include <drizzled/internal/m_string.h>
 
27
#include <drizzled/util/test.h>
 
28
#include <drizzled/charset.h>
 
29
#include <drizzled/memory/multi_malloc.h>
 
30
#include <drizzled/identifier.h>
 
31
 
 
32
 
 
33
using namespace std;
 
34
using namespace drizzled;
 
35
 
 
36
static void setup_key_functions(MI_KEYDEF *keyinfo);
 
37
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef);
 
38
static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg);
 
39
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo);
 
40
static uint64_t mi_safe_mul(uint64_t a, uint64_t b);
 
41
static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state);
 
42
static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def);
 
43
static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base);
 
44
 
 
45
#define disk_pos_assert(pos, end_pos) \
 
46
if (pos > end_pos)             \
 
47
{                              \
 
48
  errno=HA_ERR_CRASHED;     \
 
49
  goto err;                    \
 
50
}
 
51
 
 
52
 
 
53
/******************************************************************************
 
54
** Return the shared struct if the table is already open.
 
55
** In MySQL the server will handle version issues.
 
56
******************************************************************************/
 
57
 
 
58
MI_INFO *test_if_reopen(char *filename)
 
59
{
 
60
  list<MI_INFO *>::iterator it= myisam_open_list.begin();
 
61
  while (it != myisam_open_list.end())
 
62
  {
 
63
    MI_INFO *info= *it;
 
64
    MYISAM_SHARE *share=info->s;
 
65
    if (!strcmp(share->unique_file_name,filename) && share->last_version)
 
66
      return info;
 
67
    ++it;
 
68
  }
 
69
  return 0;
 
70
}
 
71
 
 
72
 
 
73
/******************************************************************************
 
74
  open a MyISAM database.
 
75
  See my_base.h for the handle_locking argument
 
76
  if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
 
77
  is marked crashed or if we are not using locking and the table doesn't
 
78
  have an open count of 0.
 
79
******************************************************************************/
 
80
 
 
81
MI_INFO *mi_open(const drizzled::identifier::Table &identifier, int mode, uint32_t open_flags)
 
82
{
 
83
  int lock_error,kfile,open_mode,save_errno,have_rtree=0;
 
84
  uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
 
85
    key_parts,unique_key_parts,uniques;
 
86
  char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
 
87
       data_name[FN_REFLEN], rp_buff[PATH_MAX];
 
88
  unsigned char *disk_cache= NULL;
 
89
  unsigned char *disk_pos, *end_pos;
 
90
  MI_INFO info,*m_info,*old_info;
 
91
  boost::scoped_ptr<MYISAM_SHARE> share_buff_ap(new MYISAM_SHARE);
 
92
  MYISAM_SHARE &share_buff= *share_buff_ap.get();
 
93
  MYISAM_SHARE *share;
 
94
  boost::scoped_array<ulong> rec_per_key_part_ap(new ulong[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]);
 
95
  ulong *rec_per_key_part= rec_per_key_part_ap.get();
 
96
  internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
 
97
  uint64_t max_key_file_length, max_data_file_length;
 
98
 
 
99
  kfile= -1;
 
100
  lock_error=1;
 
101
  errpos=0;
 
102
  head_length=sizeof(share_buff.state.header);
 
103
  memset(&info, 0, sizeof(info));
 
104
 
 
105
  (void)internal::fn_format(org_name,
 
106
                            identifier.getPath().c_str(), 
 
107
                            "",
 
108
                            MI_NAME_IEXT,
 
109
                            MY_UNPACK_FILENAME);
 
110
  if (!realpath(org_name,rp_buff))
 
111
    internal::my_load_path(rp_buff,org_name, NULL);
 
112
  rp_buff[FN_REFLEN-1]= '\0';
 
113
  strcpy(name_buff,rp_buff);
 
114
  THR_LOCK_myisam.lock();
 
115
  if (!(old_info=test_if_reopen(name_buff)))
 
116
  {
 
117
    share= &share_buff;
 
118
    memset(&share_buff, 0, sizeof(share_buff));
 
119
    share_buff.state.rec_per_key_part=rec_per_key_part;
 
120
    share_buff.state.key_root=key_root;
 
121
    share_buff.state.key_del=key_del;
 
122
 
 
123
    if ((kfile=internal::my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
 
124
    {
 
125
      if ((errno != EROFS && errno != EACCES) ||
 
126
          mode != O_RDONLY ||
 
127
          (kfile=internal::my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
 
128
        goto err;
 
129
    }
 
130
    share->mode=open_mode;
 
131
    errpos=1;
 
132
    if (internal::my_read(kfile, share->state.header.file_version, head_length,
 
133
                MYF(MY_NABP)))
 
134
    {
 
135
      errno= HA_ERR_NOT_A_TABLE;
 
136
      goto err;
 
137
    }
 
138
    if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
 
139
    {
 
140
      errno=HA_ERR_NOT_A_TABLE;
 
141
      goto err;
 
142
    }
 
143
    share->options= mi_uint2korr(share->state.header.options);
 
144
    static const uint64_t OLD_FILE_OPTIONS= HA_OPTION_PACK_RECORD |
 
145
            HA_OPTION_PACK_KEYS |
 
146
            HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
 
147
            HA_OPTION_TEMP_COMPRESS_RECORD |
 
148
            HA_OPTION_TMP_TABLE;
 
149
    if (share->options & ~OLD_FILE_OPTIONS)
 
150
    {
 
151
      errno=HA_ERR_OLD_FILE;
 
152
      goto err;
 
153
    }
 
154
 
 
155
    /* Don't call realpath() if the name can't be a link */
 
156
    ssize_t sym_link_size= readlink(org_name,index_name,FN_REFLEN-1);
 
157
    if (sym_link_size >= 0 )
 
158
      index_name[sym_link_size]= '\0';
 
159
    if (!strcmp(name_buff, org_name) || sym_link_size == -1)
 
160
      (void) strcpy(index_name, org_name);
 
161
    *strrchr(org_name, '.')= '\0';
 
162
    (void) internal::fn_format(data_name,org_name,"",MI_NAME_DEXT,
 
163
                     MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
 
164
 
 
165
    info_length=mi_uint2korr(share->state.header.header_length);
 
166
    base_pos=mi_uint2korr(share->state.header.base_pos);
 
167
    if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
 
168
    {
 
169
      errno=ENOMEM;
 
170
      goto err;
 
171
    }
 
172
    end_pos=disk_cache+info_length;
 
173
    errpos=2;
 
174
 
 
175
    lseek(kfile,0,SEEK_SET);
 
176
    errpos=3;
 
177
    if (internal::my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
 
178
    {
 
179
      errno=HA_ERR_CRASHED;
 
180
      goto err;
 
181
    }
 
182
    len=mi_uint2korr(share->state.header.state_info_length);
 
183
    keys=    (uint) share->state.header.keys;
 
184
    uniques= (uint) share->state.header.uniques;
 
185
    key_parts= mi_uint2korr(share->state.header.key_parts);
 
186
    unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
 
187
    share->state_diff_length=len-MI_STATE_INFO_SIZE;
 
188
 
 
189
    mi_state_info_read(disk_cache, &share->state);
 
190
    len= mi_uint2korr(share->state.header.base_info_length);
 
191
    disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
 
192
    share->state.state_length=base_pos;
 
193
 
 
194
    if (share->state.changed & STATE_CRASHED)
 
195
    {
 
196
      errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
 
197
                HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
 
198
      goto err;
 
199
    }
 
200
 
 
201
    /* sanity check */
 
202
    if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
 
203
    {
 
204
      errno=HA_ERR_CRASHED;
 
205
      goto err;
 
206
    }
 
207
 
 
208
    if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
 
209
        key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
 
210
    {
 
211
      errno=HA_ERR_UNSUPPORTED;
 
212
      goto err;
 
213
    }
 
214
 
 
215
    /* Correct max_file_length based on length of sizeof(off_t) */
 
216
    max_data_file_length=
 
217
      (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
 
218
      (((uint64_t) 1 << (share->base.rec_reflength*8))-1) :
 
219
      (mi_safe_mul(share->base.pack_reclength,
 
220
                   (uint64_t) 1 << (share->base.rec_reflength*8))-1);
 
221
    max_key_file_length=
 
222
      mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
 
223
                  ((uint64_t) 1 << (share->base.key_reflength*8))-1);
 
224
#if SIZEOF_OFF_T == 4
 
225
    set_if_smaller(max_data_file_length, INT32_MAX);
 
226
    set_if_smaller(max_key_file_length, INT32_MAX);
 
227
#endif
 
228
    if (share->base.raid_type)
 
229
    {
 
230
      errno=HA_ERR_UNSUPPORTED;
 
231
      goto err;
 
232
    }
 
233
    share->base.max_data_file_length=(internal::my_off_t) max_data_file_length;
 
234
    share->base.max_key_file_length=(internal::my_off_t) max_key_file_length;
 
235
 
 
236
    if (share->options & HA_OPTION_COMPRESS_RECORD)
 
237
      share->base.max_key_length+=2;    /* For safety */
 
238
 
 
239
    /* Add space for node pointer */
 
240
    share->base.max_key_length+= share->base.key_reflength;
 
241
 
 
242
    if (!drizzled::memory::multi_malloc(false,
 
243
           &share,sizeof(*share),
 
244
           &share->state.rec_per_key_part,sizeof(long)*key_parts,
 
245
           &share->keyinfo,keys*sizeof(MI_KEYDEF),
 
246
           &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
 
247
           &share->keyparts,
 
248
           (key_parts+unique_key_parts+keys+uniques) * sizeof(HA_KEYSEG),
 
249
           &share->rec, (share->base.fields+1)*sizeof(MI_COLUMNDEF),
 
250
           &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
 
251
           &share->unique_file_name,strlen(name_buff)+1,
 
252
           &share->index_file_name,strlen(index_name)+1,
 
253
           &share->data_file_name,strlen(data_name)+1,
 
254
           &share->state.key_root,keys*sizeof(uint64_t),
 
255
           &share->state.key_del,
 
256
           (share->state.header.max_block_size_index*sizeof(uint64_t)),
 
257
           NULL))
 
258
      goto err;
 
259
    errpos=4;
 
260
    *share=share_buff;
 
261
    memcpy(share->state.rec_per_key_part, rec_per_key_part,
 
262
           sizeof(long)*key_parts);
 
263
    memcpy(share->state.key_root, key_root,
 
264
           sizeof(internal::my_off_t)*keys);
 
265
    memcpy(share->state.key_del, key_del,
 
266
           sizeof(internal::my_off_t) * share->state.header.max_block_size_index);
 
267
    strcpy(share->unique_file_name, name_buff);
 
268
    share->unique_name_length= strlen(name_buff);
 
269
    strcpy(share->index_file_name,  index_name);
 
270
    strcpy(share->data_file_name,   data_name);
 
271
 
 
272
    share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
 
273
    {
 
274
      HA_KEYSEG *pos=share->keyparts;
 
275
      for (i=0 ; i < keys ; i++)
 
276
      {
 
277
        share->keyinfo[i].share= share;
 
278
        disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
 
279
        disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
 
280
                        end_pos);
 
281
        set_if_smaller(share->blocksize,(uint)share->keyinfo[i].block_length);
 
282
        share->keyinfo[i].seg=pos;
 
283
        for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
 
284
        {
 
285
          disk_pos=mi_keyseg_read(disk_pos, pos);
 
286
          if (pos->flag & HA_BLOB_PART &&
 
287
              ! (share->options & (HA_OPTION_COMPRESS_RECORD |
 
288
                                   HA_OPTION_PACK_RECORD)))
 
289
          {
 
290
            errno= HA_ERR_CRASHED;
 
291
            goto err;
 
292
          }
 
293
          if (pos->type == HA_KEYTYPE_TEXT ||
 
294
              pos->type == HA_KEYTYPE_VARTEXT1 ||
 
295
              pos->type == HA_KEYTYPE_VARTEXT2)
 
296
          {
 
297
            if (!pos->language)
 
298
              pos->charset=default_charset_info;
 
299
            else if (!(pos->charset= get_charset(pos->language)))
 
300
            {
 
301
              errno=HA_ERR_UNKNOWN_CHARSET;
 
302
              goto err;
 
303
            }
 
304
          }
 
305
          else if (pos->type == HA_KEYTYPE_BINARY)
 
306
            pos->charset= &my_charset_bin;
 
307
        }
 
308
        setup_key_functions(share->keyinfo+i);
 
309
        share->keyinfo[i].end=pos;
 
310
        pos->type=HA_KEYTYPE_END;                       /* End */
 
311
        pos->length=share->base.rec_reflength;
 
312
        pos->null_bit=0;
 
313
        pos->flag=0;                                    /* For purify */
 
314
        pos++;
 
315
      }
 
316
      for (i=0 ; i < uniques ; i++)
 
317
      {
 
318
        disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
 
319
        disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
 
320
                        HA_KEYSEG_SIZE, end_pos);
 
321
        share->uniqueinfo[i].seg=pos;
 
322
        for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
 
323
        {
 
324
          disk_pos=mi_keyseg_read(disk_pos, pos);
 
325
          if (pos->type == HA_KEYTYPE_TEXT ||
 
326
              pos->type == HA_KEYTYPE_VARTEXT1 ||
 
327
              pos->type == HA_KEYTYPE_VARTEXT2)
 
328
          {
 
329
            if (!pos->language)
 
330
              pos->charset=default_charset_info;
 
331
            else if (!(pos->charset= get_charset(pos->language)))
 
332
            {
 
333
              errno=HA_ERR_UNKNOWN_CHARSET;
 
334
              goto err;
 
335
            }
 
336
          }
 
337
        }
 
338
        share->uniqueinfo[i].end=pos;
 
339
        pos->type=HA_KEYTYPE_END;                       /* End */
 
340
        pos->null_bit=0;
 
341
        pos->flag=0;
 
342
        pos++;
 
343
      }
 
344
    }
 
345
 
 
346
    disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
 
347
    for (i=j=offset=0 ; i < share->base.fields ; i++)
 
348
    {
 
349
      disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
 
350
      share->rec[i].pack_type=0;
 
351
      share->rec[i].huff_tree=0;
 
352
      share->rec[i].offset=offset;
 
353
      if (share->rec[i].type == (int) FIELD_BLOB)
 
354
      {
 
355
        share->blobs[j].pack_length=
 
356
          share->rec[i].length-portable_sizeof_char_ptr;
 
357
        share->blobs[j].offset=offset;
 
358
        j++;
 
359
      }
 
360
      offset+=share->rec[i].length;
 
361
    }
 
362
    share->rec[i].type=(int) FIELD_LAST;        /* End marker */
 
363
    if (offset > share->base.reclength)
 
364
    {
 
365
      errno= HA_ERR_CRASHED;
 
366
      goto err;
 
367
    }
 
368
 
 
369
    if (! lock_error)
 
370
    {
 
371
      lock_error=1;                     /* Database unlocked */
 
372
    }
 
373
 
 
374
    if (mi_open_datafile(&info, share, -1))
 
375
      goto err;
 
376
    errpos=5;
 
377
 
 
378
    share->kfile=kfile;
 
379
    share->this_process=(ulong) getpid();
 
380
    share->last_process= share->state.process;
 
381
    share->base.key_parts=key_parts;
 
382
    share->base.all_key_parts=key_parts+unique_key_parts;
 
383
    if (!(share->last_version=share->state.version))
 
384
      share->last_version=1;                    /* Safety */
 
385
    share->rec_reflength=share->base.rec_reflength; /* May be changed */
 
386
    share->base.margin_key_file_length=(share->base.max_key_file_length -
 
387
                                        (keys ? MI_INDEX_BLOCK_MARGIN *
 
388
                                         share->blocksize * keys : 0));
 
389
    share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
 
390
    share->data_file_type=STATIC_RECORD;
 
391
    if (share->options & HA_OPTION_PACK_RECORD)
 
392
      share->data_file_type = DYNAMIC_RECORD;
 
393
    free(disk_cache);
 
394
    disk_cache= NULL;
 
395
    mi_setup_functions(share);
 
396
    share->is_log_table= false;
 
397
    if (myisam_concurrent_insert)
 
398
    {
 
399
      share->concurrent_insert=
 
400
        ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
 
401
                           HA_OPTION_COMPRESS_RECORD |
 
402
                           HA_OPTION_TEMP_COMPRESS_RECORD)) ||
 
403
         (open_flags & HA_OPEN_TMP_TABLE) || have_rtree) ? 0 : 1;
 
404
      if (share->concurrent_insert)
 
405
      {
 
406
        assert(0);
 
407
      }
 
408
    }
 
409
  }
 
410
  else
 
411
  {
 
412
    share= old_info->s;
 
413
    if (mode == O_RDWR && share->mode == O_RDONLY)
 
414
    {
 
415
      errno=EACCES;                             /* Can't open in write mode */
 
416
      goto err;
 
417
    }
 
418
    if (mi_open_datafile(&info, share, old_info->dfile))
 
419
      goto err;
 
420
    errpos=5;
 
421
    have_rtree= old_info->rtree_recursion_state != NULL;
 
422
  }
 
423
 
 
424
  /* alloc and set up private structure parts */
 
425
  if (!drizzled::memory::multi_malloc(MY_WME,
 
426
         &m_info,sizeof(MI_INFO),
 
427
         &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
 
428
         &info.buff,(share->base.max_key_block_length*2+
 
429
                     share->base.max_key_length),
 
430
         &info.lastkey,share->base.max_key_length*3+1,
 
431
         &info.first_mbr_key, share->base.max_key_length,
 
432
         &info.filename, identifier.getPath().length()+1,
 
433
         &info.rtree_recursion_state,have_rtree ? 1024 : 0,
 
434
         NULL))
 
435
    goto err;
 
436
  errpos=6;
 
437
 
 
438
  if (!have_rtree)
 
439
    info.rtree_recursion_state= NULL;
 
440
 
 
441
  strcpy(info.filename, identifier.getPath().c_str());
 
442
  memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
 
443
  info.lastkey2=info.lastkey+share->base.max_key_length;
 
444
 
 
445
  info.s=share;
 
446
  info.lastpos= HA_OFFSET_ERROR;
 
447
  info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
 
448
  info.opt_flag=READ_CHECK_USED;
 
449
  info.this_unique= (ulong) info.dfile; /* Uniq number in process */
 
450
  if (share->data_file_type == COMPRESSED_RECORD)
 
451
    info.this_unique= share->state.unique;
 
452
  info.this_loop=0;                             /* Update counter */
 
453
  info.last_unique= share->state.unique;
 
454
  info.last_loop=   share->state.update_count;
 
455
  if (mode == O_RDONLY)
 
456
    share->options|=HA_OPTION_READ_ONLY_DATA;
 
457
  info.lock_type=F_UNLCK;
 
458
  info.quick_mode=0;
 
459
  info.bulk_insert=0;
 
460
  info.errkey= -1;
 
461
  info.page_changed=1;
 
462
  info.read_record=share->read_record;
 
463
  share->reopen++;
 
464
  share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
 
465
  if (share->options & HA_OPTION_READ_ONLY_DATA)
 
466
  {
 
467
    info.lock_type=F_RDLCK;
 
468
    share->r_locks++;
 
469
    share->tot_locks++;
 
470
  }
 
471
  if ((open_flags & HA_OPEN_TMP_TABLE) ||
 
472
      (share->options & HA_OPTION_TMP_TABLE))
 
473
  {
 
474
    share->temporary=share->delay_key_write=1;
 
475
    share->write_flag=MYF(MY_NABP);
 
476
    /*
 
477
     * The following two statements are commented out as a fix of
 
478
     * bug https://bugs.launchpad.net/drizzle/+bug/387627
 
479
     *
 
480
     * UPDATE can be TRUNCATE on TEMPORARY TABLE (MyISAM).
 
481
     * The root cause of why this makes a difference hasn't
 
482
     * been found, but this fixes things for now.
 
483
     */
 
484
//    share->w_locks++;                 // We don't have to update status
 
485
//    share->tot_locks++;
 
486
    info.lock_type=F_WRLCK;
 
487
  }
 
488
 
 
489
  share->delay_key_write= 1;
 
490
  info.state= &share->state.state;      /* Change global values by default */
 
491
 
 
492
  /* Allocate buffer for one record */
 
493
 
 
494
  /* prerequisites: memset(info, 0) && info->s=share; are met. */
 
495
  if (!mi_alloc_rec_buff(&info, SIZE_MAX, &info.rec_buff))
 
496
    goto err;
 
497
  memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
 
498
 
 
499
  *m_info=info;
 
500
  myisam_open_list.push_front(m_info);
 
501
 
 
502
  THR_LOCK_myisam.unlock();
 
503
  return(m_info);
 
504
 
 
505
err:
 
506
  free(disk_cache);
 
507
  save_errno=errno ? errno : HA_ERR_END_OF_FILE;
 
508
  if ((save_errno == HA_ERR_CRASHED) ||
 
509
      (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
 
510
      (save_errno == HA_ERR_CRASHED_ON_REPAIR))
 
511
    mi_report_error(save_errno, identifier.getPath().c_str());
 
512
  switch (errpos) {
 
513
  case 6:
 
514
    free((unsigned char*) m_info);
 
515
    /* fall through */
 
516
  case 5:
 
517
    internal::my_close(info.dfile,MYF(0));
 
518
    if (old_info)
 
519
      break;                                    /* Don't remove open table */
 
520
    /* fall through */
 
521
  case 4:
 
522
    free((unsigned char*) share);
 
523
    /* fall through */
 
524
  case 3:
 
525
    /* fall through */
 
526
  case 1:
 
527
    internal::my_close(kfile,MYF(0));
 
528
    /* fall through */
 
529
  case 0:
 
530
  default:
 
531
    break;
 
532
  }
 
533
  THR_LOCK_myisam.unlock();
 
534
  errno=save_errno;
 
535
  return (NULL);
 
536
} /* mi_open */
 
537
 
 
538
 
 
539
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
 
540
{
 
541
  uint32_t extra;
 
542
  uint32_t old_length= 0;
 
543
 
 
544
  if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
 
545
  {
 
546
    unsigned char *newptr = *buf;
 
547
 
 
548
    /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
 
549
    if (length == SIZE_MAX)
 
550
    {
 
551
      if (info->s->options & HA_OPTION_COMPRESS_RECORD)
 
552
        length= max(info->s->base.pack_reclength, info->s->max_pack_length);
 
553
      else
 
554
        length= info->s->base.pack_reclength;
 
555
      length= max((uint32_t)length, info->s->base.max_key_length);
 
556
      /* Avoid unnecessary realloc */
 
557
      if (newptr && length == old_length)
 
558
        return newptr;
 
559
    }
 
560
 
 
561
    extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
 
562
            ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
 
563
            MI_REC_BUFF_OFFSET : 0);
 
564
    if (extra && newptr)
 
565
      newptr-= MI_REC_BUFF_OFFSET;
 
566
    void *tmpnewptr= NULL;
 
567
    if (!(tmpnewptr= realloc(newptr, length+extra+8))) 
 
568
      return newptr;
 
569
    newptr= (unsigned char *)tmpnewptr;
 
570
    *((uint32_t *) newptr)= (uint32_t) length;
 
571
    *buf= newptr+(extra ?  MI_REC_BUFF_OFFSET : 0);
 
572
  }
 
573
  return *buf;
 
574
}
 
575
 
 
576
 
 
577
static uint64_t mi_safe_mul(uint64_t a, uint64_t b)
 
578
{
 
579
  uint64_t max_val= ~ (uint64_t) 0;             /* internal::my_off_t is unsigned */
 
580
 
 
581
  if (!a || max_val / a < b)
 
582
    return max_val;
 
583
  return a*b;
 
584
}
 
585
 
 
586
        /* Set up functions in structs */
 
587
 
 
588
void mi_setup_functions(register MYISAM_SHARE *share)
 
589
{
 
590
  if (share->options & HA_OPTION_PACK_RECORD)
 
591
  {
 
592
    share->read_record=_mi_read_dynamic_record;
 
593
    share->read_rnd=_mi_read_rnd_dynamic_record;
 
594
    share->delete_record=_mi_delete_dynamic_record;
 
595
    share->compare_record=_mi_cmp_dynamic_record;
 
596
    share->compare_unique=_mi_cmp_dynamic_unique;
 
597
    share->calc_checksum= mi_checksum;
 
598
 
 
599
    /* add bits used to pack data to pack_reclength for faster allocation */
 
600
    share->base.pack_reclength+= share->base.pack_bits;
 
601
    if (share->base.blobs)
 
602
    {
 
603
      share->update_record=_mi_update_blob_record;
 
604
      share->write_record=_mi_write_blob_record;
 
605
    }
 
606
    else
 
607
    {
 
608
      share->write_record=_mi_write_dynamic_record;
 
609
      share->update_record=_mi_update_dynamic_record;
 
610
    }
 
611
  }
 
612
  else
 
613
  {
 
614
    share->read_record=_mi_read_static_record;
 
615
    share->read_rnd=_mi_read_rnd_static_record;
 
616
    share->delete_record=_mi_delete_static_record;
 
617
    share->compare_record=_mi_cmp_static_record;
 
618
    share->update_record=_mi_update_static_record;
 
619
    share->write_record=_mi_write_static_record;
 
620
    share->compare_unique=_mi_cmp_static_unique;
 
621
    share->calc_checksum= mi_static_checksum;
 
622
  }
 
623
  share->file_read= mi_nommap_pread;
 
624
  share->file_write= mi_nommap_pwrite;
 
625
  share->calc_checksum=0;
 
626
}
 
627
 
 
628
 
 
629
static void setup_key_functions(register MI_KEYDEF *keyinfo)
 
630
{
 
631
  {
 
632
    keyinfo->ck_insert = _mi_ck_write;
 
633
    keyinfo->ck_delete = _mi_ck_delete;
 
634
  }
 
635
  if (keyinfo->flag & HA_BINARY_PACK_KEY)
 
636
  {                                             /* Simple prefix compression */
 
637
    keyinfo->bin_search=_mi_seq_search;
 
638
    keyinfo->get_key=_mi_get_binary_pack_key;
 
639
    keyinfo->pack_key=_mi_calc_bin_pack_key_length;
 
640
    keyinfo->store_key=_mi_store_bin_pack_key;
 
641
  }
 
642
  else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
643
  {
 
644
    keyinfo->get_key= _mi_get_pack_key;
 
645
    if (keyinfo->seg[0].flag & HA_PACK_KEY)
 
646
    {                                           /* Prefix compression */
 
647
      /*
 
648
        _mi_prefix_search() compares end-space against ASCII blank (' ').
 
649
        It cannot be used for character sets, that do not encode the
 
650
        blank character like ASCII does. UCS2 is an example. All
 
651
        character sets with a fixed width > 1 or a mimimum width > 1
 
652
        cannot represent blank like ASCII does. In these cases we have
 
653
        to use _mi_seq_search() for the search.
 
654
      */
 
655
      if (not keyinfo->seg->charset || keyinfo->seg->charset->use_strnxfrm() ||
 
656
          (keyinfo->seg->flag & HA_NULL_PART) ||
 
657
          (keyinfo->seg->charset->mbminlen > 1))
 
658
        keyinfo->bin_search=_mi_seq_search;
 
659
      else
 
660
        keyinfo->bin_search=_mi_prefix_search;
 
661
      keyinfo->pack_key=_mi_calc_var_pack_key_length;
 
662
      keyinfo->store_key=_mi_store_var_pack_key;
 
663
    }
 
664
    else
 
665
    {
 
666
      keyinfo->bin_search=_mi_seq_search;
 
667
      keyinfo->pack_key=_mi_calc_var_key_length; /* Variable length key */
 
668
      keyinfo->store_key=_mi_store_static_key;
 
669
    }
 
670
  }
 
671
  else
 
672
  {
 
673
    keyinfo->bin_search=_mi_bin_search;
 
674
    keyinfo->get_key=_mi_get_static_key;
 
675
    keyinfo->pack_key=_mi_calc_static_key_length;
 
676
    keyinfo->store_key=_mi_store_static_key;
 
677
  }
 
678
  return;
 
679
}
 
680
 
 
681
 
 
682
/*
 
683
   Function to save and store the header in the index file (.MYI)
 
684
*/
 
685
 
 
686
uint32_t mi_state_info_write(int file, MI_STATE_INFO *state, uint32_t pWrite)
 
687
{
 
688
  unsigned char  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
689
  unsigned char *ptr=buff;
 
690
  uint  i, keys= (uint) state->header.keys,
 
691
        key_blocks=state->header.max_block_size_index;
 
692
 
 
693
  memcpy(ptr,&state->header,sizeof(state->header));
 
694
  ptr+=sizeof(state->header);
 
695
 
 
696
  /* open_count must be first because of _mi_mark_file_changed ! */
 
697
  mi_int2store(ptr,state->open_count);          ptr +=2;
 
698
  *ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
 
699
  mi_rowstore(ptr,state->state.records);        ptr +=8;
 
700
  mi_rowstore(ptr,state->state.del);            ptr +=8;
 
701
  mi_rowstore(ptr,state->split);                ptr +=8;
 
702
  mi_sizestore(ptr,state->dellink);             ptr +=8;
 
703
  mi_sizestore(ptr,state->state.key_file_length);       ptr +=8;
 
704
  mi_sizestore(ptr,state->state.data_file_length);      ptr +=8;
 
705
  mi_sizestore(ptr,state->state.empty);         ptr +=8;
 
706
  mi_sizestore(ptr,state->state.key_empty);     ptr +=8;
 
707
  mi_int8store(ptr,state->auto_increment);      ptr +=8;
 
708
  mi_int8store(ptr,(uint64_t) state->state.checksum);ptr +=8;
 
709
  mi_int4store(ptr,state->process);             ptr +=4;
 
710
  mi_int4store(ptr,state->unique);              ptr +=4;
 
711
  mi_int4store(ptr,state->status);              ptr +=4;
 
712
  mi_int4store(ptr,state->update_count);        ptr +=4;
 
713
 
 
714
  ptr+=state->state_diff_length;
 
715
 
 
716
  for (i=0; i < keys; i++)
 
717
  {
 
718
    mi_sizestore(ptr,state->key_root[i]);       ptr +=8;
 
719
  }
 
720
  for (i=0; i < key_blocks; i++)
 
721
  {
 
722
    mi_sizestore(ptr,state->key_del[i]);        ptr +=8;
 
723
  }
 
724
  if (pWrite & 2)                               /* From isamchk */
 
725
  {
 
726
    uint32_t key_parts= mi_uint2korr(state->header.key_parts);
 
727
    mi_int4store(ptr,state->sec_index_changed); ptr +=4;
 
728
    mi_int4store(ptr,state->sec_index_used);    ptr +=4;
 
729
    mi_int4store(ptr,state->version);           ptr +=4;
 
730
    mi_int8store(ptr,state->key_map);           ptr +=8;
 
731
    mi_int8store(ptr,(uint64_t) state->create_time);    ptr +=8;
 
732
    mi_int8store(ptr,(uint64_t) state->recover_time);   ptr +=8;
 
733
    mi_int8store(ptr,(uint64_t) state->check_time);     ptr +=8;
 
734
    mi_sizestore(ptr,state->rec_per_key_rows);  ptr+=8;
 
735
    for (i=0 ; i < key_parts ; i++)
 
736
    {
 
737
      mi_int4store(ptr,state->rec_per_key_part[i]);  ptr+=4;
 
738
    }
 
739
  }
 
740
 
 
741
  if (pWrite & 1)
 
742
    return(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
 
743
                          MYF(MY_NABP | MY_THREADSAFE)) != 0);
 
744
  return(internal::my_write(file, buff, (size_t) (ptr-buff),
 
745
                       MYF(MY_NABP)) != 0);
 
746
}
 
747
 
 
748
 
 
749
static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
 
750
{
 
751
  uint32_t i,keys,key_parts,key_blocks;
 
752
  memcpy(&state->header,ptr, sizeof(state->header));
 
753
  ptr +=sizeof(state->header);
 
754
  keys=(uint) state->header.keys;
 
755
  key_parts=mi_uint2korr(state->header.key_parts);
 
756
  key_blocks=state->header.max_block_size_index;
 
757
 
 
758
  state->open_count = mi_uint2korr(ptr);        ptr +=2;
 
759
  state->changed= *ptr++;
 
760
  state->sortkey = (uint) *ptr++;
 
761
  state->state.records= mi_rowkorr(ptr);        ptr +=8;
 
762
  state->state.del = mi_rowkorr(ptr);           ptr +=8;
 
763
  state->split  = mi_rowkorr(ptr);              ptr +=8;
 
764
  state->dellink= mi_sizekorr(ptr);             ptr +=8;
 
765
  state->state.key_file_length = mi_sizekorr(ptr);      ptr +=8;
 
766
  state->state.data_file_length= mi_sizekorr(ptr);      ptr +=8;
 
767
  state->state.empty    = mi_sizekorr(ptr);     ptr +=8;
 
768
  state->state.key_empty= mi_sizekorr(ptr);     ptr +=8;
 
769
  state->auto_increment=mi_uint8korr(ptr);      ptr +=8;
 
770
  state->state.checksum=(ha_checksum) mi_uint8korr(ptr);        ptr +=8;
 
771
  state->process= mi_uint4korr(ptr);            ptr +=4;
 
772
  state->unique = mi_uint4korr(ptr);            ptr +=4;
 
773
  state->status = mi_uint4korr(ptr);            ptr +=4;
 
774
  state->update_count=mi_uint4korr(ptr);        ptr +=4;
 
775
 
 
776
  ptr+= state->state_diff_length;
 
777
 
 
778
  for (i=0; i < keys; i++)
 
779
  {
 
780
    state->key_root[i]= mi_sizekorr(ptr);       ptr +=8;
 
781
  }
 
782
  for (i=0; i < key_blocks; i++)
 
783
  {
 
784
    state->key_del[i] = mi_sizekorr(ptr);       ptr +=8;
 
785
  }
 
786
  state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
 
787
  state->sec_index_used =    mi_uint4korr(ptr); ptr +=4;
 
788
  state->version     = mi_uint4korr(ptr);       ptr +=4;
 
789
  state->key_map     = mi_uint8korr(ptr);       ptr +=8;
 
790
  state->create_time = (time_t) mi_sizekorr(ptr);       ptr +=8;
 
791
  state->recover_time =(time_t) mi_sizekorr(ptr);       ptr +=8;
 
792
  state->check_time =  (time_t) mi_sizekorr(ptr);       ptr +=8;
 
793
  state->rec_per_key_rows=mi_sizekorr(ptr);     ptr +=8;
 
794
  for (i=0 ; i < key_parts ; i++)
 
795
  {
 
796
    state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4;
 
797
  }
 
798
  return ptr;
 
799
}
 
800
 
 
801
 
 
802
uint32_t mi_state_info_read_dsk(int file, MI_STATE_INFO *state, bool pRead)
 
803
{
 
804
  unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
805
 
 
806
  if (pRead)
 
807
  {
 
808
    if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
 
809
      return 1;
 
810
  }
 
811
  else if (internal::my_read(file, buff, state->state_length,MYF(MY_NABP)))
 
812
    return 1;
 
813
  mi_state_info_read(buff, state);
 
814
 
 
815
  return 0;
 
816
}
 
817
 
 
818
 
 
819
/****************************************************************************
 
820
**  store and read of MI_BASE_INFO
 
821
****************************************************************************/
 
822
 
 
823
uint32_t mi_base_info_write(int file, MI_BASE_INFO *base)
 
824
{
 
825
  unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
 
826
 
 
827
  mi_sizestore(ptr,base->keystart);                     ptr +=8;
 
828
  mi_sizestore(ptr,base->max_data_file_length);         ptr +=8;
 
829
  mi_sizestore(ptr,base->max_key_file_length);          ptr +=8;
 
830
  mi_rowstore(ptr,base->records);                       ptr +=8;
 
831
  mi_rowstore(ptr,base->reloc);                         ptr +=8;
 
832
  mi_int4store(ptr,base->mean_row_length);              ptr +=4;
 
833
  mi_int4store(ptr,base->reclength);                    ptr +=4;
 
834
  mi_int4store(ptr,base->pack_reclength);               ptr +=4;
 
835
  mi_int4store(ptr,base->min_pack_length);              ptr +=4;
 
836
  mi_int4store(ptr,base->max_pack_length);              ptr +=4;
 
837
  mi_int4store(ptr,base->min_block_length);             ptr +=4;
 
838
  mi_int4store(ptr,base->fields);                       ptr +=4;
 
839
  mi_int4store(ptr,base->pack_fields);                  ptr +=4;
 
840
  *ptr++=base->rec_reflength;
 
841
  *ptr++=base->key_reflength;
 
842
  *ptr++=base->keys;
 
843
  *ptr++=base->auto_key;
 
844
  mi_int2store(ptr,base->pack_bits);                    ptr +=2;
 
845
  mi_int2store(ptr,base->blobs);                        ptr +=2;
 
846
  mi_int2store(ptr,base->max_key_block_length);         ptr +=2;
 
847
  mi_int2store(ptr,base->max_key_length);               ptr +=2;
 
848
  mi_int2store(ptr,base->extra_alloc_bytes);            ptr +=2;
 
849
  *ptr++= base->extra_alloc_procent;
 
850
  /* old raid info  slots */
 
851
  *ptr++= 0;
 
852
  mi_int2store(ptr,UINT16_C(0));                        ptr +=2;
 
853
  mi_int4store(ptr,UINT32_C(0));                        ptr +=4;
 
854
 
 
855
  memset(ptr, 0, 6);                                    ptr +=6; /* extra */
 
856
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
857
}
 
858
 
 
859
 
 
860
static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
 
861
{
 
862
  base->keystart = mi_sizekorr(ptr);                    ptr +=8;
 
863
  base->max_data_file_length = mi_sizekorr(ptr);        ptr +=8;
 
864
  base->max_key_file_length = mi_sizekorr(ptr);         ptr +=8;
 
865
  base->records =  (ha_rows) mi_sizekorr(ptr);          ptr +=8;
 
866
  base->reloc = (ha_rows) mi_sizekorr(ptr);             ptr +=8;
 
867
  base->mean_row_length = mi_uint4korr(ptr);            ptr +=4;
 
868
  base->reclength = mi_uint4korr(ptr);                  ptr +=4;
 
869
  base->pack_reclength = mi_uint4korr(ptr);             ptr +=4;
 
870
  base->min_pack_length = mi_uint4korr(ptr);            ptr +=4;
 
871
  base->max_pack_length = mi_uint4korr(ptr);            ptr +=4;
 
872
  base->min_block_length = mi_uint4korr(ptr);           ptr +=4;
 
873
  base->fields = mi_uint4korr(ptr);                     ptr +=4;
 
874
  base->pack_fields = mi_uint4korr(ptr);                ptr +=4;
 
875
 
 
876
  base->rec_reflength = *ptr++;
 
877
  base->key_reflength = *ptr++;
 
878
  base->keys=           *ptr++;
 
879
  base->auto_key=       *ptr++;
 
880
  base->pack_bits = mi_uint2korr(ptr);                  ptr +=2;
 
881
  base->blobs = mi_uint2korr(ptr);                      ptr +=2;
 
882
  base->max_key_block_length= mi_uint2korr(ptr);        ptr +=2;
 
883
  base->max_key_length = mi_uint2korr(ptr);             ptr +=2;
 
884
  base->extra_alloc_bytes = mi_uint2korr(ptr);          ptr +=2;
 
885
  base->extra_alloc_procent = *ptr++;
 
886
 
 
887
  /* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
 
888
  ptr+= 7;
 
889
 
 
890
  ptr+=6;
 
891
  return ptr;
 
892
}
 
893
 
 
894
/*--------------------------------------------------------------------------
 
895
  mi_keydef
 
896
---------------------------------------------------------------------------*/
 
897
 
 
898
uint32_t mi_keydef_write(int file, MI_KEYDEF *keydef)
 
899
{
 
900
  unsigned char buff[MI_KEYDEF_SIZE];
 
901
  unsigned char *ptr=buff;
 
902
 
 
903
  *ptr++ = (unsigned char) keydef->keysegs;
 
904
  *ptr++ = keydef->key_alg;                     /* Rtree or Btree */
 
905
  mi_int2store(ptr,keydef->flag);               ptr +=2;
 
906
  mi_int2store(ptr,keydef->block_length);       ptr +=2;
 
907
  mi_int2store(ptr,keydef->keylength);          ptr +=2;
 
908
  mi_int2store(ptr,keydef->minlength);          ptr +=2;
 
909
  mi_int2store(ptr,keydef->maxlength);          ptr +=2;
 
910
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
911
}
 
912
 
 
913
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
 
914
{
 
915
   keydef->keysegs      = (uint) *ptr++;
 
916
   keydef->key_alg      = *ptr++;               /* Rtree or Btree */
 
917
 
 
918
   keydef->flag         = mi_uint2korr(ptr);    ptr +=2;
 
919
   keydef->block_length = mi_uint2korr(ptr);    ptr +=2;
 
920
   keydef->keylength    = mi_uint2korr(ptr);    ptr +=2;
 
921
   keydef->minlength    = mi_uint2korr(ptr);    ptr +=2;
 
922
   keydef->maxlength    = mi_uint2korr(ptr);    ptr +=2;
 
923
   keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
 
924
   keydef->underflow_block_length=keydef->block_length/3;
 
925
   keydef->version      = 0;                    /* Not saved */
 
926
   return ptr;
 
927
}
 
928
 
 
929
/***************************************************************************
 
930
**  mi_keyseg
 
931
***************************************************************************/
 
932
 
 
933
int mi_keyseg_write(int file, const HA_KEYSEG *keyseg)
 
934
{
 
935
  unsigned char buff[HA_KEYSEG_SIZE];
 
936
  unsigned char *ptr=buff;
 
937
  ulong pos;
 
938
 
 
939
  *ptr++= keyseg->type;
 
940
  *ptr++= keyseg->language;
 
941
  *ptr++= keyseg->null_bit;
 
942
  *ptr++= keyseg->bit_start;
 
943
  *ptr++= keyseg->bit_end;
 
944
  *ptr++= keyseg->bit_length;
 
945
  mi_int2store(ptr,keyseg->flag);       ptr+=2;
 
946
  mi_int2store(ptr,keyseg->length);     ptr+=2;
 
947
  mi_int4store(ptr,keyseg->start);      ptr+=4;
 
948
  pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
 
949
  mi_int4store(ptr, pos);
 
950
  ptr+=4;
 
951
 
 
952
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
953
}
 
954
 
 
955
 
 
956
static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
 
957
{
 
958
   keyseg->type         = *ptr++;
 
959
   keyseg->language     = *ptr++;
 
960
   keyseg->null_bit     = *ptr++;
 
961
   keyseg->bit_start    = *ptr++;
 
962
   keyseg->bit_end      = *ptr++;
 
963
   keyseg->bit_length   = *ptr++;
 
964
   keyseg->flag         = mi_uint2korr(ptr);  ptr +=2;
 
965
   keyseg->length       = mi_uint2korr(ptr);  ptr +=2;
 
966
   keyseg->start        = mi_uint4korr(ptr);  ptr +=4;
 
967
   keyseg->null_pos     = mi_uint4korr(ptr);  ptr +=4;
 
968
   keyseg->charset=0;                           /* Will be filled in later */
 
969
   if (keyseg->null_bit)
 
970
     keyseg->bit_pos= (uint16_t)(keyseg->null_pos + (keyseg->null_bit == 7));
 
971
   else
 
972
   {
 
973
     keyseg->bit_pos= (uint16_t)keyseg->null_pos;
 
974
     keyseg->null_pos= 0;
 
975
   }
 
976
   return ptr;
 
977
}
 
978
 
 
979
/*--------------------------------------------------------------------------
 
980
  mi_uniquedef
 
981
---------------------------------------------------------------------------*/
 
982
 
 
983
uint32_t mi_uniquedef_write(int file, MI_UNIQUEDEF *def)
 
984
{
 
985
  unsigned char buff[MI_UNIQUEDEF_SIZE];
 
986
  unsigned char *ptr=buff;
 
987
 
 
988
  mi_int2store(ptr,def->keysegs);               ptr+=2;
 
989
  *ptr++=  (unsigned char) def->key;
 
990
  *ptr++ = (unsigned char) def->null_are_equal;
 
991
 
 
992
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
993
}
 
994
 
 
995
static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
 
996
{
 
997
   def->keysegs = mi_uint2korr(ptr);
 
998
   def->key     = ptr[2];
 
999
   def->null_are_equal=ptr[3];
 
1000
   return ptr+4;                                /* 1 extra byte */
 
1001
}
 
1002
 
 
1003
/***************************************************************************
 
1004
**  MI_COLUMNDEF
 
1005
***************************************************************************/
 
1006
 
 
1007
uint32_t mi_recinfo_write(int file, MI_COLUMNDEF *recinfo)
 
1008
{
 
1009
  unsigned char buff[MI_COLUMNDEF_SIZE];
 
1010
  unsigned char *ptr=buff;
 
1011
 
 
1012
  mi_int2store(ptr,recinfo->type);      ptr +=2;
 
1013
  mi_int2store(ptr,recinfo->length);    ptr +=2;
 
1014
  *ptr++ = recinfo->null_bit;
 
1015
  mi_int2store(ptr,recinfo->null_pos);  ptr+= 2;
 
1016
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1017
}
 
1018
 
 
1019
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
 
1020
{
 
1021
   recinfo->type=  mi_sint2korr(ptr);   ptr +=2;
 
1022
   recinfo->length=mi_uint2korr(ptr);   ptr +=2;
 
1023
   recinfo->null_bit= (uint8_t) *ptr++;
 
1024
   recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
 
1025
   return ptr;
 
1026
}
 
1027
 
 
1028
/**************************************************************************
 
1029
Open data file
 
1030
We can't use dup() here as the data file descriptors need to have different
 
1031
active seek-positions.
 
1032
 
 
1033
The argument file_to_dup is here for the future if there would on some OS
 
1034
exist a dup()-like call that would give us two different file descriptors.
 
1035
*************************************************************************/
 
1036
 
 
1037
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, int file_to_dup)
 
1038
{
 
1039
  (void)file_to_dup; 
 
1040
  info->dfile=internal::my_open(share->data_file_name, share->mode,
 
1041
                      MYF(MY_WME));
 
1042
  return info->dfile >= 0 ? 0 : 1;
 
1043
}
 
1044
 
 
1045
 
 
1046
int mi_open_keyfile(MYISAM_SHARE *share)
 
1047
{
 
1048
  if ((share->kfile=internal::my_open(share->unique_file_name, share->mode,
 
1049
                            MYF(MY_WME))) < 0)
 
1050
    return 1;
 
1051
  return 0;
 
1052
}
 
1053
 
 
1054
 
 
1055
/*
 
1056
  Disable all indexes.
 
1057
 
 
1058
  SYNOPSIS
 
1059
    mi_disable_indexes()
 
1060
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1061
 
 
1062
  DESCRIPTION
 
1063
    Disable all indexes.
 
1064
 
 
1065
  RETURN
 
1066
    0  ok
 
1067
*/
 
1068
 
 
1069
int mi_disable_indexes(MI_INFO *info)
 
1070
{
 
1071
  MYISAM_SHARE *share= info->s;
 
1072
 
 
1073
  mi_clear_all_keys_active(share->state.key_map);
 
1074
  return 0;
 
1075
}
 
1076
 
 
1077
 
 
1078
/*
 
1079
  Enable all indexes
 
1080
 
 
1081
  SYNOPSIS
 
1082
    mi_enable_indexes()
 
1083
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1084
 
 
1085
  DESCRIPTION
 
1086
    Enable all indexes. The indexes might have been disabled
 
1087
    by mi_disable_index() before.
 
1088
    The function works only if both data and indexes are empty,
 
1089
    otherwise a repair is required.
 
1090
    To be sure, call handler::delete_all_rows() before.
 
1091
 
 
1092
  RETURN
 
1093
    0  ok
 
1094
    HA_ERR_CRASHED data or index is non-empty.
 
1095
*/
 
1096
 
 
1097
int mi_enable_indexes(MI_INFO *info)
 
1098
{
 
1099
  int error= 0;
 
1100
  MYISAM_SHARE *share= info->s;
 
1101
 
 
1102
  if (share->state.state.data_file_length ||
 
1103
      (share->state.state.key_file_length != share->base.keystart))
 
1104
  {
 
1105
    mi_print_error(info->s, HA_ERR_CRASHED);
 
1106
    error= HA_ERR_CRASHED;
 
1107
  }
 
1108
  else
 
1109
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
 
1110
  return error;
 
1111
}
 
1112
 
 
1113
 
 
1114
/*
 
1115
  Test if indexes are disabled.
 
1116
 
 
1117
  SYNOPSIS
 
1118
    mi_indexes_are_disabled()
 
1119
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1120
 
 
1121
  DESCRIPTION
 
1122
    Test if indexes are disabled.
 
1123
 
 
1124
  RETURN
 
1125
    0  indexes are not disabled
 
1126
    1  all indexes are disabled
 
1127
    2  non-unique indexes are disabled
 
1128
*/
 
1129
 
 
1130
int mi_indexes_are_disabled(MI_INFO *info)
 
1131
{
 
1132
  MYISAM_SHARE *share= info->s;
 
1133
 
 
1134
  /*
 
1135
    No keys or all are enabled. keys is the number of keys. Left shifted
 
1136
    gives us only one bit set. When decreased by one, gives us all all bits
 
1137
    up to this one set and it gets unset.
 
1138
  */
 
1139
  if (!share->base.keys ||
 
1140
      (mi_is_all_keys_active(share->state.key_map, share->base.keys)))
 
1141
    return 0;
 
1142
 
 
1143
  /* All are disabled */
 
1144
  if (mi_is_any_key_active(share->state.key_map))
 
1145
    return 1;
 
1146
 
 
1147
  /*
 
1148
    We have keys. Some enabled, some disabled.
 
1149
    Don't check for any non-unique disabled but return directly 2
 
1150
  */
 
1151
  return 2;
 
1152
}
 
1153