~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_open.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/* open a isam-database */
 
17
 
 
18
#include "fulltext.h"
 
19
#include "sp_defs.h"
 
20
#include "rt_index.h"
 
21
#include <m_ctype.h>
 
22
 
 
23
#if defined(MSDOS) || defined(__WIN__)
 
24
#ifdef __WIN__
 
25
#include <fcntl.h>
 
26
#else
 
27
#include <process.h>                    /* Prototype for getpid */
 
28
#endif
 
29
#endif
 
30
#ifdef VMS
 
31
#include "static.c"
 
32
#endif
 
33
 
 
34
static void setup_key_functions(MI_KEYDEF *keyinfo);
 
35
#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
 
36
                                        pos+=size;}
 
37
 
 
38
 
 
39
#define disk_pos_assert(pos, end_pos) \
 
40
if (pos > end_pos)             \
 
41
{                              \
 
42
  my_errno=HA_ERR_CRASHED;     \
 
43
  goto err;                    \
 
44
}
 
45
 
 
46
 
 
47
/******************************************************************************
 
48
** Return the shared struct if the table is already open.
 
49
** In MySQL the server will handle version issues.
 
50
******************************************************************************/
 
51
 
 
52
MI_INFO *test_if_reopen(char *filename)
 
53
{
 
54
  LIST *pos;
 
55
 
 
56
  for (pos=myisam_open_list ; pos ; pos=pos->next)
 
57
  {
 
58
    MI_INFO *info=(MI_INFO*) pos->data;
 
59
    MYISAM_SHARE *share=info->s;
 
60
    if (!strcmp(share->unique_file_name,filename) && share->last_version)
 
61
      return info;
 
62
  }
 
63
  return 0;
 
64
}
 
65
 
 
66
 
 
67
/******************************************************************************
 
68
  open a MyISAM database.
 
69
  See my_base.h for the handle_locking argument
 
70
  if handle_locking and HA_OPEN_ABORT_IF_CRASHED then abort if the table
 
71
  is marked crashed or if we are not using locking and the table doesn't
 
72
  have an open count of 0.
 
73
******************************************************************************/
 
74
 
 
75
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
 
76
{
 
77
  int lock_error,kfile,open_mode,save_errno,have_rtree=0;
 
78
  uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
 
79
    key_parts,unique_key_parts,fulltext_keys,uniques;
 
80
  char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
 
81
       data_name[FN_REFLEN];
 
82
  uchar *disk_cache, *disk_pos, *end_pos;
 
83
  MI_INFO info,*m_info,*old_info;
 
84
  MYISAM_SHARE share_buff,*share;
 
85
  ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
 
86
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
 
87
  ulonglong max_key_file_length, max_data_file_length;
 
88
  DBUG_ENTER("mi_open");
 
89
 
 
90
  kfile= -1;
 
91
  lock_error=1;
 
92
  errpos=0;
 
93
  head_length=sizeof(share_buff.state.header);
 
94
  bzero((uchar*) &info,sizeof(info));
 
95
 
 
96
  my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
 
97
                                   MY_UNPACK_FILENAME),MYF(0));
 
98
  pthread_mutex_lock(&THR_LOCK_myisam);
 
99
  if (!(old_info=test_if_reopen(name_buff)))
 
100
  {
 
101
    share= &share_buff;
 
102
    bzero((uchar*) &share_buff,sizeof(share_buff));
 
103
    share_buff.state.rec_per_key_part=rec_per_key_part;
 
104
    share_buff.state.key_root=key_root;
 
105
    share_buff.state.key_del=key_del;
 
106
    share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
 
107
                                                 strlen(name_buff));
 
108
 
 
109
    DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
 
110
                    if (strstr(name, "/t1"))
 
111
                    {
 
112
                      my_errno= HA_ERR_CRASHED;
 
113
                      goto err;
 
114
                    });
 
115
    if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
 
116
    {
 
117
      if ((errno != EROFS && errno != EACCES) ||
 
118
          mode != O_RDONLY ||
 
119
          (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
 
120
        goto err;
 
121
    }
 
122
    share->mode=open_mode;
 
123
    errpos=1;
 
124
    if (my_read(kfile, share->state.header.file_version, head_length,
 
125
                MYF(MY_NABP)))
 
126
    {
 
127
      my_errno= HA_ERR_NOT_A_TABLE;
 
128
      goto err;
 
129
    }
 
130
    if (memcmp((uchar*) share->state.header.file_version,
 
131
               (uchar*) myisam_file_magic, 4))
 
132
    {
 
133
      DBUG_PRINT("error",("Wrong header in %s",name_buff));
 
134
      DBUG_DUMP("error_dump",(uchar*) share->state.header.file_version,
 
135
                head_length);
 
136
      my_errno=HA_ERR_NOT_A_TABLE;
 
137
      goto err;
 
138
    }
 
139
    share->options= mi_uint2korr(share->state.header.options);
 
140
    if (share->options &
 
141
        ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
 
142
          HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
 
143
          HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
 
144
          HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
 
145
          HA_OPTION_RELIES_ON_SQL_LAYER))
 
146
    {
 
147
      DBUG_PRINT("error",("wrong options: 0x%lx", share->options));
 
148
      my_errno=HA_ERR_OLD_FILE;
 
149
      goto err;
 
150
    }
 
151
    if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
 
152
        ! (open_flags & HA_OPEN_FROM_SQL_LAYER))
 
153
    {
 
154
      DBUG_PRINT("error", ("table cannot be openned from non-sql layer"));
 
155
      my_errno= HA_ERR_UNSUPPORTED;
 
156
      goto err;
 
157
    }
 
158
    /* Don't call realpath() if the name can't be a link */
 
159
    if (!strcmp(name_buff, org_name) ||
 
160
        my_readlink(index_name, org_name, MYF(0)) == -1)
 
161
      (void) strmov(index_name, org_name);
 
162
    *strrchr(org_name, '.')= '\0';
 
163
    (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
 
164
                     MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
 
165
 
 
166
    info_length=mi_uint2korr(share->state.header.header_length);
 
167
    base_pos=mi_uint2korr(share->state.header.base_pos);
 
168
    if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
 
169
    {
 
170
      my_errno=ENOMEM;
 
171
      goto err;
 
172
    }
 
173
    end_pos=disk_cache+info_length;
 
174
    errpos=2;
 
175
 
 
176
    VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
 
177
    if (!(open_flags & HA_OPEN_TMP_TABLE))
 
178
    {
 
179
      if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
 
180
                              MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ?
 
181
                                  0 : MY_DONT_WAIT))) &&
 
182
          !(open_flags & HA_OPEN_IGNORE_IF_LOCKED))
 
183
        goto err;
 
184
    }
 
185
    errpos=3;
 
186
    if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
 
187
    {
 
188
      my_errno=HA_ERR_CRASHED;
 
189
      goto err;
 
190
    }
 
191
    len=mi_uint2korr(share->state.header.state_info_length);
 
192
    keys=    (uint) share->state.header.keys;
 
193
    uniques= (uint) share->state.header.uniques;
 
194
    fulltext_keys= (uint) share->state.header.fulltext_keys;
 
195
    key_parts= mi_uint2korr(share->state.header.key_parts);
 
196
    unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
 
197
    if (len != MI_STATE_INFO_SIZE)
 
198
    {
 
199
      DBUG_PRINT("warning",
 
200
                 ("saved_state_info_length: %d  state_info_length: %d",
 
201
                  len,MI_STATE_INFO_SIZE));
 
202
    }
 
203
    share->state_diff_length=len-MI_STATE_INFO_SIZE;
 
204
 
 
205
    mi_state_info_read(disk_cache, &share->state);
 
206
    len= mi_uint2korr(share->state.header.base_info_length);
 
207
    if (len != MI_BASE_INFO_SIZE)
 
208
    {
 
209
      DBUG_PRINT("warning",("saved_base_info_length: %d  base_info_length: %d",
 
210
                            len,MI_BASE_INFO_SIZE));
 
211
    }
 
212
    disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
 
213
    share->state.state_length=base_pos;
 
214
 
 
215
    if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
 
216
        ((share->state.changed & STATE_CRASHED) ||
 
217
         ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
 
218
          (my_disable_locking && share->state.open_count))))
 
219
    {
 
220
      DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u  "
 
221
                          "changed: %u  open_count: %u  !locking: %d",
 
222
                          open_flags, share->state.changed,
 
223
                          share->state.open_count, my_disable_locking));
 
224
      my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
 
225
                HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
 
226
      goto err;
 
227
    }
 
228
 
 
229
    /* sanity check */
 
230
    if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
 
231
    {
 
232
      my_errno=HA_ERR_CRASHED;
 
233
      goto err;
 
234
    }
 
235
 
 
236
    key_parts+=fulltext_keys*FT_SEGS;
 
237
    if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
 
238
        key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
 
239
    {
 
240
      DBUG_PRINT("error",("Wrong key info:  Max_key_length: %d  keys: %d  key_parts: %d", share->base.max_key_length, keys, key_parts));
 
241
      my_errno=HA_ERR_UNSUPPORTED;
 
242
      goto err;
 
243
    }
 
244
 
 
245
    /* Correct max_file_length based on length of sizeof(off_t) */
 
246
    max_data_file_length=
 
247
      (share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
 
248
      (((ulonglong) 1 << (share->base.rec_reflength*8))-1) :
 
249
      (mi_safe_mul(share->base.pack_reclength,
 
250
                   (ulonglong) 1 << (share->base.rec_reflength*8))-1);
 
251
    max_key_file_length=
 
252
      mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
 
253
                  ((ulonglong) 1 << (share->base.key_reflength*8))-1);
 
254
#if SIZEOF_OFF_T == 4
 
255
    set_if_smaller(max_data_file_length, INT_MAX32);
 
256
    set_if_smaller(max_key_file_length, INT_MAX32);
 
257
#endif
 
258
#if USE_RAID && SYSTEM_SIZEOF_OFF_T == 4
 
259
    set_if_smaller(max_key_file_length, INT_MAX32);
 
260
    if (!share->base.raid_type)
 
261
    {
 
262
      set_if_smaller(max_data_file_length, INT_MAX32);
 
263
    }
 
264
    else
 
265
    {
 
266
      set_if_smaller(max_data_file_length,
 
267
                     (ulonglong) share->base.raid_chunks << 31);
 
268
    }
 
269
#elif !defined(USE_RAID)
 
270
    if (share->base.raid_type)
 
271
    {
 
272
      DBUG_PRINT("error",("Table uses RAID but we don't have RAID support"));
 
273
      my_errno=HA_ERR_UNSUPPORTED;
 
274
      goto err;
 
275
    }
 
276
#endif
 
277
    share->base.max_data_file_length=(my_off_t) max_data_file_length;
 
278
    share->base.max_key_file_length=(my_off_t) max_key_file_length;
 
279
 
 
280
    if (share->options & HA_OPTION_COMPRESS_RECORD)
 
281
      share->base.max_key_length+=2;    /* For safety */
 
282
 
 
283
    /* Add space for node pointer */
 
284
    share->base.max_key_length+= share->base.key_reflength;
 
285
 
 
286
    if (!my_multi_malloc(MY_WME,
 
287
                         &share,sizeof(*share),
 
288
                         &share->state.rec_per_key_part,sizeof(long)*key_parts,
 
289
                         &share->keyinfo,keys*sizeof(MI_KEYDEF),
 
290
                         &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
 
291
                         &share->keyparts,
 
292
                         (key_parts+unique_key_parts+keys+uniques) *
 
293
                         sizeof(HA_KEYSEG),
 
294
                         &share->rec,
 
295
                         (share->base.fields+1)*sizeof(MI_COLUMNDEF),
 
296
                         &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
 
297
                         &share->unique_file_name,strlen(name_buff)+1,
 
298
                         &share->index_file_name,strlen(index_name)+1,
 
299
                         &share->data_file_name,strlen(data_name)+1,
 
300
                         &share->state.key_root,keys*sizeof(my_off_t),
 
301
                         &share->state.key_del,
 
302
                         (share->state.header.max_block_size_index*sizeof(my_off_t)),
 
303
#ifdef THREAD
 
304
                         &share->key_root_lock,sizeof(rw_lock_t)*keys,
 
305
#endif
 
306
                         &share->mmap_lock,sizeof(rw_lock_t),
 
307
                         NullS))
 
308
      goto err;
 
309
    errpos=4;
 
310
    *share=share_buff;
 
311
    memcpy((char*) share->state.rec_per_key_part,
 
312
           (char*) rec_per_key_part, sizeof(long)*key_parts);
 
313
    memcpy((char*) share->state.key_root,
 
314
           (char*) key_root, sizeof(my_off_t)*keys);
 
315
    memcpy((char*) share->state.key_del,
 
316
           (char*) key_del, (sizeof(my_off_t) *
 
317
                             share->state.header.max_block_size_index));
 
318
    strmov(share->unique_file_name, name_buff);
 
319
    share->unique_name_length= strlen(name_buff);
 
320
    strmov(share->index_file_name,  index_name);
 
321
    strmov(share->data_file_name,   data_name);
 
322
 
 
323
    share->blocksize=min(IO_SIZE,myisam_block_size);
 
324
    {
 
325
      HA_KEYSEG *pos=share->keyparts;
 
326
      for (i=0 ; i < keys ; i++)
 
327
      {
 
328
        share->keyinfo[i].share= share;
 
329
        disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
 
330
        disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
 
331
                        end_pos);
 
332
        if (share->keyinfo[i].key_alg == HA_KEY_ALG_RTREE)
 
333
          have_rtree=1;
 
334
        set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
 
335
        share->keyinfo[i].seg=pos;
 
336
        for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
 
337
        {
 
338
          disk_pos=mi_keyseg_read(disk_pos, pos);
 
339
          if (pos->flag & HA_BLOB_PART &&
 
340
              ! (share->options & (HA_OPTION_COMPRESS_RECORD |
 
341
                                   HA_OPTION_PACK_RECORD)))
 
342
          {
 
343
            my_errno= HA_ERR_CRASHED;
 
344
            goto err;
 
345
          }
 
346
          if (pos->type == HA_KEYTYPE_TEXT ||
 
347
              pos->type == HA_KEYTYPE_VARTEXT1 ||
 
348
              pos->type == HA_KEYTYPE_VARTEXT2)
 
349
          {
 
350
            if (!pos->language)
 
351
              pos->charset=default_charset_info;
 
352
            else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
 
353
            {
 
354
              my_errno=HA_ERR_UNKNOWN_CHARSET;
 
355
              goto err;
 
356
            }
 
357
          }
 
358
          else if (pos->type == HA_KEYTYPE_BINARY)
 
359
            pos->charset= &my_charset_bin;
 
360
        }
 
361
        if (share->keyinfo[i].flag & HA_SPATIAL)
 
362
        {
 
363
#ifdef HAVE_SPATIAL
 
364
          uint sp_segs=SPDIMS*2;
 
365
          share->keyinfo[i].seg=pos-sp_segs;
 
366
          share->keyinfo[i].keysegs--;
 
367
#else
 
368
          my_errno=HA_ERR_UNSUPPORTED;
 
369
          goto err;
 
370
#endif
 
371
        }
 
372
        else if (share->keyinfo[i].flag & HA_FULLTEXT)
 
373
        {
 
374
          if (!fulltext_keys)
 
375
          { /* 4.0 compatibility code, to be removed in 5.0 */
 
376
            share->keyinfo[i].seg=pos-FT_SEGS;
 
377
            share->keyinfo[i].keysegs-=FT_SEGS;
 
378
          }
 
379
          else
 
380
          {
 
381
            uint k;
 
382
            share->keyinfo[i].seg=pos;
 
383
            for (k=0; k < FT_SEGS; k++)
 
384
            {
 
385
              *pos= ft_keysegs[k];
 
386
              pos[0].language= pos[-1].language;
 
387
              if (!(pos[0].charset= pos[-1].charset))
 
388
              {
 
389
                my_errno=HA_ERR_CRASHED;
 
390
                goto err;
 
391
              }
 
392
              pos++;
 
393
            }
 
394
          }
 
395
          if (!share->ft2_keyinfo.seg)
 
396
          {
 
397
            memcpy(& share->ft2_keyinfo, & share->keyinfo[i], sizeof(MI_KEYDEF));
 
398
            share->ft2_keyinfo.keysegs=1;
 
399
            share->ft2_keyinfo.flag=0;
 
400
            share->ft2_keyinfo.keylength=
 
401
            share->ft2_keyinfo.minlength=
 
402
            share->ft2_keyinfo.maxlength=HA_FT_WLEN+share->base.rec_reflength;
 
403
            share->ft2_keyinfo.seg=pos-1;
 
404
            share->ft2_keyinfo.end=pos;
 
405
            setup_key_functions(& share->ft2_keyinfo);
 
406
          }
 
407
        }
 
408
        setup_key_functions(share->keyinfo+i);
 
409
        share->keyinfo[i].end=pos;
 
410
        pos->type=HA_KEYTYPE_END;                       /* End */
 
411
        pos->length=share->base.rec_reflength;
 
412
        pos->null_bit=0;
 
413
        pos->flag=0;                                    /* For purify */
 
414
        pos++;
 
415
      }
 
416
      for (i=0 ; i < uniques ; i++)
 
417
      {
 
418
        disk_pos=mi_uniquedef_read(disk_pos, &share->uniqueinfo[i]);
 
419
        disk_pos_assert(disk_pos + share->uniqueinfo[i].keysegs *
 
420
                        HA_KEYSEG_SIZE, end_pos);
 
421
        share->uniqueinfo[i].seg=pos;
 
422
        for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
 
423
        {
 
424
          disk_pos=mi_keyseg_read(disk_pos, pos);
 
425
          if (pos->type == HA_KEYTYPE_TEXT ||
 
426
              pos->type == HA_KEYTYPE_VARTEXT1 ||
 
427
              pos->type == HA_KEYTYPE_VARTEXT2)
 
428
          {
 
429
            if (!pos->language)
 
430
              pos->charset=default_charset_info;
 
431
            else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
 
432
            {
 
433
              my_errno=HA_ERR_UNKNOWN_CHARSET;
 
434
              goto err;
 
435
            }
 
436
          }
 
437
        }
 
438
        share->uniqueinfo[i].end=pos;
 
439
        pos->type=HA_KEYTYPE_END;                       /* End */
 
440
        pos->null_bit=0;
 
441
        pos->flag=0;
 
442
        pos++;
 
443
      }
 
444
      share->ftparsers= 0;
 
445
    }
 
446
 
 
447
    disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
 
448
    for (i=j=offset=0 ; i < share->base.fields ; i++)
 
449
    {
 
450
      disk_pos=mi_recinfo_read(disk_pos,&share->rec[i]);
 
451
      share->rec[i].pack_type=0;
 
452
      share->rec[i].huff_tree=0;
 
453
      share->rec[i].offset=offset;
 
454
      if (share->rec[i].type == (int) FIELD_BLOB)
 
455
      {
 
456
        share->blobs[j].pack_length=
 
457
          share->rec[i].length-portable_sizeof_char_ptr;
 
458
        share->blobs[j].offset=offset;
 
459
        j++;
 
460
      }
 
461
      offset+=share->rec[i].length;
 
462
    }
 
463
    share->rec[i].type=(int) FIELD_LAST;        /* End marker */
 
464
    if (offset > share->base.reclength)
 
465
    {
 
466
      /* purecov: begin inspected */
 
467
      my_errno= HA_ERR_CRASHED;
 
468
      goto err;
 
469
      /* purecov: end */
 
470
    }
 
471
 
 
472
    if (! lock_error)
 
473
    {
 
474
      VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
 
475
      lock_error=1;                     /* Database unlocked */
 
476
    }
 
477
 
 
478
    if (mi_open_datafile(&info, share, -1))
 
479
      goto err;
 
480
    errpos=5;
 
481
 
 
482
    share->kfile=kfile;
 
483
    share->this_process=(ulong) getpid();
 
484
    share->last_process= share->state.process;
 
485
    share->base.key_parts=key_parts;
 
486
    share->base.all_key_parts=key_parts+unique_key_parts;
 
487
    if (!(share->last_version=share->state.version))
 
488
      share->last_version=1;                    /* Safety */
 
489
    share->rec_reflength=share->base.rec_reflength; /* May be changed */
 
490
    share->base.margin_key_file_length=(share->base.max_key_file_length -
 
491
                                        (keys ? MI_INDEX_BLOCK_MARGIN *
 
492
                                         share->blocksize * keys : 0));
 
493
    share->blocksize=min(IO_SIZE,myisam_block_size);
 
494
    share->data_file_type=STATIC_RECORD;
 
495
    if (share->options & HA_OPTION_COMPRESS_RECORD)
 
496
    {
 
497
      share->data_file_type = COMPRESSED_RECORD;
 
498
      share->options|= HA_OPTION_READ_ONLY_DATA;
 
499
      info.s=share;
 
500
      if (_mi_read_pack_info(&info,
 
501
                             (pbool)
 
502
                             test(!(share->options &
 
503
                                    (HA_OPTION_PACK_RECORD |
 
504
                                     HA_OPTION_TEMP_COMPRESS_RECORD)))))
 
505
        goto err;
 
506
    }
 
507
    else if (share->options & HA_OPTION_PACK_RECORD)
 
508
      share->data_file_type = DYNAMIC_RECORD;
 
509
    my_afree(disk_cache);
 
510
    mi_setup_functions(share);
 
511
    share->is_log_table= FALSE;
 
512
#ifdef THREAD
 
513
    thr_lock_init(&share->lock);
 
514
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
 
515
    for (i=0; i<keys; i++)
 
516
      VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
 
517
    VOID(my_rwlock_init(&share->mmap_lock, NULL));
 
518
    if (!thr_lock_inited)
 
519
    {
 
520
      /* Probably a single threaded program; Don't use concurrent inserts */
 
521
      myisam_concurrent_insert=0;
 
522
    }
 
523
    else if (myisam_concurrent_insert)
 
524
    {
 
525
      share->concurrent_insert=
 
526
        ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
 
527
                           HA_OPTION_COMPRESS_RECORD |
 
528
                           HA_OPTION_TEMP_COMPRESS_RECORD)) ||
 
529
         (open_flags & HA_OPEN_TMP_TABLE) ||
 
530
         have_rtree) ? 0 : 1;
 
531
      if (share->concurrent_insert)
 
532
      {
 
533
        share->lock.get_status=mi_get_status;
 
534
        share->lock.copy_status=mi_copy_status;
 
535
        share->lock.update_status=mi_update_status;
 
536
        share->lock.restore_status= mi_restore_status;
 
537
        share->lock.check_status=mi_check_status;
 
538
      }
 
539
    }
 
540
#endif
 
541
    /*
 
542
      Memory mapping can only be requested after initializing intern_lock.
 
543
    */
 
544
    if (open_flags & HA_OPEN_MMAP)
 
545
    {
 
546
      info.s= share;
 
547
      mi_extra(&info, HA_EXTRA_MMAP, 0);
 
548
    }
 
549
  }
 
550
  else
 
551
  {
 
552
    share= old_info->s;
 
553
    if (mode == O_RDWR && share->mode == O_RDONLY)
 
554
    {
 
555
      my_errno=EACCES;                          /* Can't open in write mode */
 
556
      goto err;
 
557
    }
 
558
    if (mi_open_datafile(&info, share, old_info->dfile))
 
559
      goto err;
 
560
    errpos=5;
 
561
    have_rtree= old_info->rtree_recursion_state != NULL;
 
562
  }
 
563
 
 
564
  /* alloc and set up private structure parts */
 
565
  if (!my_multi_malloc(MY_WME,
 
566
                       &m_info,sizeof(MI_INFO),
 
567
                       &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
 
568
                       &info.buff,(share->base.max_key_block_length*2+
 
569
                                   share->base.max_key_length),
 
570
                       &info.lastkey,share->base.max_key_length*3+1,
 
571
                       &info.first_mbr_key, share->base.max_key_length,
 
572
                       &info.filename,strlen(name)+1,
 
573
                       &info.rtree_recursion_state,have_rtree ? 1024 : 0,
 
574
                       NullS))
 
575
    goto err;
 
576
  errpos=6;
 
577
 
 
578
  if (!have_rtree)
 
579
    info.rtree_recursion_state= NULL;
 
580
 
 
581
  strmov(info.filename,name);
 
582
  memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
 
583
  info.lastkey2=info.lastkey+share->base.max_key_length;
 
584
 
 
585
  info.s=share;
 
586
  info.lastpos= HA_OFFSET_ERROR;
 
587
  info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
 
588
  info.opt_flag=READ_CHECK_USED;
 
589
  info.this_unique= (ulong) info.dfile; /* Uniq number in process */
 
590
  if (share->data_file_type == COMPRESSED_RECORD)
 
591
    info.this_unique= share->state.unique;
 
592
  info.this_loop=0;                             /* Update counter */
 
593
  info.last_unique= share->state.unique;
 
594
  info.last_loop=   share->state.update_count;
 
595
  if (mode == O_RDONLY)
 
596
    share->options|=HA_OPTION_READ_ONLY_DATA;
 
597
  info.lock_type=F_UNLCK;
 
598
  info.quick_mode=0;
 
599
  info.bulk_insert=0;
 
600
  info.ft1_to_ft2=0;
 
601
  info.errkey= -1;
 
602
  info.page_changed=1;
 
603
  pthread_mutex_lock(&share->intern_lock);
 
604
  info.read_record=share->read_record;
 
605
  share->reopen++;
 
606
  share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
 
607
  if (share->options & HA_OPTION_READ_ONLY_DATA)
 
608
  {
 
609
    info.lock_type=F_RDLCK;
 
610
    share->r_locks++;
 
611
    share->tot_locks++;
 
612
  }
 
613
  if ((open_flags & HA_OPEN_TMP_TABLE) ||
 
614
      (share->options & HA_OPTION_TMP_TABLE))
 
615
  {
 
616
    share->temporary=share->delay_key_write=1;
 
617
    share->write_flag=MYF(MY_NABP);
 
618
    share->w_locks++;                   /* We don't have to update status */
 
619
    share->tot_locks++;
 
620
    info.lock_type=F_WRLCK;
 
621
  }
 
622
  if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) ||
 
623
      (share->options & HA_OPTION_DELAY_KEY_WRITE)) &&
 
624
      myisam_delay_key_write)
 
625
    share->delay_key_write=1;
 
626
  info.state= &share->state.state;      /* Change global values by default */
 
627
  pthread_mutex_unlock(&share->intern_lock);
 
628
 
 
629
  /* Allocate buffer for one record */
 
630
 
 
631
  /* prerequisites: bzero(info) && info->s=share; are met. */
 
632
  if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff))
 
633
    goto err;
 
634
  bzero(info.rec_buff, mi_get_rec_buff_len(&info, info.rec_buff));
 
635
 
 
636
  *m_info=info;
 
637
#ifdef THREAD
 
638
  thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
 
639
#endif
 
640
  m_info->open_list.data=(void*) m_info;
 
641
  myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
 
642
 
 
643
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
644
  if (myisam_log_file >= 0)
 
645
  {
 
646
    intern_filename(name_buff,share->index_file_name);
 
647
    _myisam_log(MI_LOG_OPEN, m_info, (uchar*) name_buff, strlen(name_buff));
 
648
  }
 
649
  DBUG_RETURN(m_info);
 
650
 
 
651
err:
 
652
  save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
 
653
  if ((save_errno == HA_ERR_CRASHED) ||
 
654
      (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
 
655
      (save_errno == HA_ERR_CRASHED_ON_REPAIR))
 
656
    mi_report_error(save_errno, name);
 
657
  switch (errpos) {
 
658
  case 6:
 
659
    my_free((uchar*) m_info,MYF(0));
 
660
    /* fall through */
 
661
  case 5:
 
662
    VOID(my_close(info.dfile,MYF(0)));
 
663
    if (old_info)
 
664
      break;                                    /* Don't remove open table */
 
665
    /* fall through */
 
666
  case 4:
 
667
    my_free((uchar*) share,MYF(0));
 
668
    /* fall through */
 
669
  case 3:
 
670
    if (! lock_error)
 
671
      VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
 
672
    /* fall through */
 
673
  case 2:
 
674
    my_afree(disk_cache);
 
675
    /* fall through */
 
676
  case 1:
 
677
    VOID(my_close(kfile,MYF(0)));
 
678
    /* fall through */
 
679
  case 0:
 
680
  default:
 
681
    break;
 
682
  }
 
683
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
684
  my_errno=save_errno;
 
685
  DBUG_RETURN (NULL);
 
686
} /* mi_open */
 
687
 
 
688
 
 
689
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
 
690
{
 
691
  uint extra;
 
692
  uint32 old_length= 0;
 
693
 
 
694
  if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
 
695
  {
 
696
    uchar *newptr = *buf;
 
697
 
 
698
    /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
 
699
    if (length == (ulong) -1)
 
700
    {
 
701
      if (info->s->options & HA_OPTION_COMPRESS_RECORD)
 
702
        length= max(info->s->base.pack_reclength, info->s->max_pack_length);
 
703
      else
 
704
        length= info->s->base.pack_reclength;
 
705
      length= max(length, info->s->base.max_key_length);
 
706
      /* Avoid unnecessary realloc */
 
707
      if (newptr && length == old_length)
 
708
        return newptr;
 
709
    }
 
710
 
 
711
    extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
 
712
            ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
 
713
            MI_REC_BUFF_OFFSET : 0);
 
714
    if (extra && newptr)
 
715
      newptr-= MI_REC_BUFF_OFFSET;
 
716
    if (!(newptr=(uchar*) my_realloc((uchar*)newptr, length+extra+8,
 
717
                                     MYF(MY_ALLOW_ZERO_PTR))))
 
718
      return newptr;
 
719
    *((uint32 *) newptr)= (uint32) length;
 
720
    *buf= newptr+(extra ?  MI_REC_BUFF_OFFSET : 0);
 
721
  }
 
722
  return *buf;
 
723
}
 
724
 
 
725
 
 
726
ulonglong mi_safe_mul(ulonglong a, ulonglong b)
 
727
{
 
728
  ulonglong max_val= ~ (ulonglong) 0;           /* my_off_t is unsigned */
 
729
 
 
730
  if (!a || max_val / a < b)
 
731
    return max_val;
 
732
  return a*b;
 
733
}
 
734
 
 
735
        /* Set up functions in structs */
 
736
 
 
737
void mi_setup_functions(register MYISAM_SHARE *share)
 
738
{
 
739
  if (share->options & HA_OPTION_COMPRESS_RECORD)
 
740
  {
 
741
    share->read_record=_mi_read_pack_record;
 
742
    share->read_rnd=_mi_read_rnd_pack_record;
 
743
    if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD))
 
744
      share->calc_checksum=0;                           /* No checksum */
 
745
    else if (share->options & HA_OPTION_PACK_RECORD)
 
746
      share->calc_checksum= mi_checksum;
 
747
    else
 
748
      share->calc_checksum= mi_static_checksum;
 
749
  }
 
750
  else if (share->options & HA_OPTION_PACK_RECORD)
 
751
  {
 
752
    share->read_record=_mi_read_dynamic_record;
 
753
    share->read_rnd=_mi_read_rnd_dynamic_record;
 
754
    share->delete_record=_mi_delete_dynamic_record;
 
755
    share->compare_record=_mi_cmp_dynamic_record;
 
756
    share->compare_unique=_mi_cmp_dynamic_unique;
 
757
    share->calc_checksum= mi_checksum;
 
758
 
 
759
    /* add bits used to pack data to pack_reclength for faster allocation */
 
760
    share->base.pack_reclength+= share->base.pack_bits;
 
761
    if (share->base.blobs)
 
762
    {
 
763
      share->update_record=_mi_update_blob_record;
 
764
      share->write_record=_mi_write_blob_record;
 
765
    }
 
766
    else
 
767
    {
 
768
      share->write_record=_mi_write_dynamic_record;
 
769
      share->update_record=_mi_update_dynamic_record;
 
770
    }
 
771
  }
 
772
  else
 
773
  {
 
774
    share->read_record=_mi_read_static_record;
 
775
    share->read_rnd=_mi_read_rnd_static_record;
 
776
    share->delete_record=_mi_delete_static_record;
 
777
    share->compare_record=_mi_cmp_static_record;
 
778
    share->update_record=_mi_update_static_record;
 
779
    share->write_record=_mi_write_static_record;
 
780
    share->compare_unique=_mi_cmp_static_unique;
 
781
    share->calc_checksum= mi_static_checksum;
 
782
  }
 
783
  share->file_read= mi_nommap_pread;
 
784
  share->file_write= mi_nommap_pwrite;
 
785
  if (!(share->options & HA_OPTION_CHECKSUM))
 
786
    share->calc_checksum=0;
 
787
  return;
 
788
}
 
789
 
 
790
 
 
791
static void setup_key_functions(register MI_KEYDEF *keyinfo)
 
792
{
 
793
  if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
 
794
  {
 
795
#ifdef HAVE_RTREE_KEYS
 
796
    keyinfo->ck_insert = rtree_insert;
 
797
    keyinfo->ck_delete = rtree_delete;
 
798
#else
 
799
    DBUG_ASSERT(0); /* mi_open should check it never happens */
 
800
#endif
 
801
  }
 
802
  else
 
803
  {
 
804
    keyinfo->ck_insert = _mi_ck_write;
 
805
    keyinfo->ck_delete = _mi_ck_delete;
 
806
  }
 
807
  if (keyinfo->flag & HA_BINARY_PACK_KEY)
 
808
  {                                             /* Simple prefix compression */
 
809
    keyinfo->bin_search=_mi_seq_search;
 
810
    keyinfo->get_key=_mi_get_binary_pack_key;
 
811
    keyinfo->pack_key=_mi_calc_bin_pack_key_length;
 
812
    keyinfo->store_key=_mi_store_bin_pack_key;
 
813
  }
 
814
  else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
 
815
  {
 
816
    keyinfo->get_key= _mi_get_pack_key;
 
817
    if (keyinfo->seg[0].flag & HA_PACK_KEY)
 
818
    {                                           /* Prefix compression */
 
819
      /*
 
820
        _mi_prefix_search() compares end-space against ASCII blank (' ').
 
821
        It cannot be used for character sets, that do not encode the
 
822
        blank character like ASCII does. UCS2 is an example. All
 
823
        character sets with a fixed width > 1 or a mimimum width > 1
 
824
        cannot represent blank like ASCII does. In these cases we have
 
825
        to use _mi_seq_search() for the search.
 
826
      */
 
827
      if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
 
828
          (keyinfo->seg->flag & HA_NULL_PART) ||
 
829
          (keyinfo->seg->charset->mbminlen > 1))
 
830
        keyinfo->bin_search=_mi_seq_search;
 
831
      else
 
832
        keyinfo->bin_search=_mi_prefix_search;
 
833
      keyinfo->pack_key=_mi_calc_var_pack_key_length;
 
834
      keyinfo->store_key=_mi_store_var_pack_key;
 
835
    }
 
836
    else
 
837
    {
 
838
      keyinfo->bin_search=_mi_seq_search;
 
839
      keyinfo->pack_key=_mi_calc_var_key_length; /* Variable length key */
 
840
      keyinfo->store_key=_mi_store_static_key;
 
841
    }
 
842
  }
 
843
  else
 
844
  {
 
845
    keyinfo->bin_search=_mi_bin_search;
 
846
    keyinfo->get_key=_mi_get_static_key;
 
847
    keyinfo->pack_key=_mi_calc_static_key_length;
 
848
    keyinfo->store_key=_mi_store_static_key;
 
849
  }
 
850
  return;
 
851
}
 
852
 
 
853
 
 
854
/*
 
855
   Function to save and store the header in the index file (.MYI)
 
856
*/
 
857
 
 
858
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
 
859
{
 
860
  uchar  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
861
  uchar *ptr=buff;
 
862
  uint  i, keys= (uint) state->header.keys,
 
863
        key_blocks=state->header.max_block_size_index;
 
864
  DBUG_ENTER("mi_state_info_write");
 
865
 
 
866
  memcpy_fixed(ptr,&state->header,sizeof(state->header));
 
867
  ptr+=sizeof(state->header);
 
868
 
 
869
  /* open_count must be first because of _mi_mark_file_changed ! */
 
870
  mi_int2store(ptr,state->open_count);          ptr +=2;
 
871
  *ptr++= (uchar)state->changed; *ptr++= state->sortkey;
 
872
  mi_rowstore(ptr,state->state.records);        ptr +=8;
 
873
  mi_rowstore(ptr,state->state.del);            ptr +=8;
 
874
  mi_rowstore(ptr,state->split);                ptr +=8;
 
875
  mi_sizestore(ptr,state->dellink);             ptr +=8;
 
876
  mi_sizestore(ptr,state->state.key_file_length);       ptr +=8;
 
877
  mi_sizestore(ptr,state->state.data_file_length);      ptr +=8;
 
878
  mi_sizestore(ptr,state->state.empty);         ptr +=8;
 
879
  mi_sizestore(ptr,state->state.key_empty);     ptr +=8;
 
880
  mi_int8store(ptr,state->auto_increment);      ptr +=8;
 
881
  mi_int8store(ptr,(ulonglong) state->state.checksum);ptr +=8;
 
882
  mi_int4store(ptr,state->process);             ptr +=4;
 
883
  mi_int4store(ptr,state->unique);              ptr +=4;
 
884
  mi_int4store(ptr,state->status);              ptr +=4;
 
885
  mi_int4store(ptr,state->update_count);        ptr +=4;
 
886
 
 
887
  ptr+=state->state_diff_length;
 
888
 
 
889
  for (i=0; i < keys; i++)
 
890
  {
 
891
    mi_sizestore(ptr,state->key_root[i]);       ptr +=8;
 
892
  }
 
893
  for (i=0; i < key_blocks; i++)
 
894
  {
 
895
    mi_sizestore(ptr,state->key_del[i]);        ptr +=8;
 
896
  }
 
897
  if (pWrite & 2)                               /* From isamchk */
 
898
  {
 
899
    uint key_parts= mi_uint2korr(state->header.key_parts);
 
900
    mi_int4store(ptr,state->sec_index_changed); ptr +=4;
 
901
    mi_int4store(ptr,state->sec_index_used);    ptr +=4;
 
902
    mi_int4store(ptr,state->version);           ptr +=4;
 
903
    mi_int8store(ptr,state->key_map);           ptr +=8;
 
904
    mi_int8store(ptr,(ulonglong) state->create_time);   ptr +=8;
 
905
    mi_int8store(ptr,(ulonglong) state->recover_time);  ptr +=8;
 
906
    mi_int8store(ptr,(ulonglong) state->check_time);    ptr +=8;
 
907
    mi_sizestore(ptr,state->rec_per_key_rows);  ptr+=8;
 
908
    for (i=0 ; i < key_parts ; i++)
 
909
    {
 
910
      mi_int4store(ptr,state->rec_per_key_part[i]);  ptr+=4;
 
911
    }
 
912
  }
 
913
 
 
914
  if (pWrite & 1)
 
915
    DBUG_RETURN(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
 
916
                          MYF(MY_NABP | MY_THREADSAFE)) != 0);
 
917
  DBUG_RETURN(my_write(file, buff, (size_t) (ptr-buff),
 
918
                       MYF(MY_NABP)) != 0);
 
919
}
 
920
 
 
921
 
 
922
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
 
923
{
 
924
  uint i,keys,key_parts,key_blocks;
 
925
  memcpy_fixed(&state->header,ptr, sizeof(state->header));
 
926
  ptr +=sizeof(state->header);
 
927
  keys=(uint) state->header.keys;
 
928
  key_parts=mi_uint2korr(state->header.key_parts);
 
929
  key_blocks=state->header.max_block_size_index;
 
930
 
 
931
  state->open_count = mi_uint2korr(ptr);        ptr +=2;
 
932
  state->changed= *ptr++;
 
933
  state->sortkey = (uint) *ptr++;
 
934
  state->state.records= mi_rowkorr(ptr);        ptr +=8;
 
935
  state->state.del = mi_rowkorr(ptr);           ptr +=8;
 
936
  state->split  = mi_rowkorr(ptr);              ptr +=8;
 
937
  state->dellink= mi_sizekorr(ptr);             ptr +=8;
 
938
  state->state.key_file_length = mi_sizekorr(ptr);      ptr +=8;
 
939
  state->state.data_file_length= mi_sizekorr(ptr);      ptr +=8;
 
940
  state->state.empty    = mi_sizekorr(ptr);     ptr +=8;
 
941
  state->state.key_empty= mi_sizekorr(ptr);     ptr +=8;
 
942
  state->auto_increment=mi_uint8korr(ptr);      ptr +=8;
 
943
  state->state.checksum=(ha_checksum) mi_uint8korr(ptr);        ptr +=8;
 
944
  state->process= mi_uint4korr(ptr);            ptr +=4;
 
945
  state->unique = mi_uint4korr(ptr);            ptr +=4;
 
946
  state->status = mi_uint4korr(ptr);            ptr +=4;
 
947
  state->update_count=mi_uint4korr(ptr);        ptr +=4;
 
948
 
 
949
  ptr+= state->state_diff_length;
 
950
 
 
951
  for (i=0; i < keys; i++)
 
952
  {
 
953
    state->key_root[i]= mi_sizekorr(ptr);       ptr +=8;
 
954
  }
 
955
  for (i=0; i < key_blocks; i++)
 
956
  {
 
957
    state->key_del[i] = mi_sizekorr(ptr);       ptr +=8;
 
958
  }
 
959
  state->sec_index_changed = mi_uint4korr(ptr); ptr +=4;
 
960
  state->sec_index_used =    mi_uint4korr(ptr); ptr +=4;
 
961
  state->version     = mi_uint4korr(ptr);       ptr +=4;
 
962
  state->key_map     = mi_uint8korr(ptr);       ptr +=8;
 
963
  state->create_time = (time_t) mi_sizekorr(ptr);       ptr +=8;
 
964
  state->recover_time =(time_t) mi_sizekorr(ptr);       ptr +=8;
 
965
  state->check_time =  (time_t) mi_sizekorr(ptr);       ptr +=8;
 
966
  state->rec_per_key_rows=mi_sizekorr(ptr);     ptr +=8;
 
967
  for (i=0 ; i < key_parts ; i++)
 
968
  {
 
969
    state->rec_per_key_part[i]= mi_uint4korr(ptr); ptr+=4;
 
970
  }
 
971
  return ptr;
 
972
}
 
973
 
 
974
 
 
975
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead)
 
976
{
 
977
  uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
978
 
 
979
  if (!myisam_single_user)
 
980
  {
 
981
    if (pRead)
 
982
    {
 
983
      if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
 
984
        return 1;
 
985
    }
 
986
    else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
 
987
      return 1;
 
988
    mi_state_info_read(buff, state);
 
989
  }
 
990
  return 0;
 
991
}
 
992
 
 
993
 
 
994
/****************************************************************************
 
995
**  store and read of MI_BASE_INFO
 
996
****************************************************************************/
 
997
 
 
998
uint mi_base_info_write(File file, MI_BASE_INFO *base)
 
999
{
 
1000
  uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
 
1001
 
 
1002
  mi_sizestore(ptr,base->keystart);                     ptr +=8;
 
1003
  mi_sizestore(ptr,base->max_data_file_length);         ptr +=8;
 
1004
  mi_sizestore(ptr,base->max_key_file_length);          ptr +=8;
 
1005
  mi_rowstore(ptr,base->records);                       ptr +=8;
 
1006
  mi_rowstore(ptr,base->reloc);                         ptr +=8;
 
1007
  mi_int4store(ptr,base->mean_row_length);              ptr +=4;
 
1008
  mi_int4store(ptr,base->reclength);                    ptr +=4;
 
1009
  mi_int4store(ptr,base->pack_reclength);               ptr +=4;
 
1010
  mi_int4store(ptr,base->min_pack_length);              ptr +=4;
 
1011
  mi_int4store(ptr,base->max_pack_length);              ptr +=4;
 
1012
  mi_int4store(ptr,base->min_block_length);             ptr +=4;
 
1013
  mi_int4store(ptr,base->fields);                       ptr +=4;
 
1014
  mi_int4store(ptr,base->pack_fields);                  ptr +=4;
 
1015
  *ptr++=base->rec_reflength;
 
1016
  *ptr++=base->key_reflength;
 
1017
  *ptr++=base->keys;
 
1018
  *ptr++=base->auto_key;
 
1019
  mi_int2store(ptr,base->pack_bits);                    ptr +=2;
 
1020
  mi_int2store(ptr,base->blobs);                        ptr +=2;
 
1021
  mi_int2store(ptr,base->max_key_block_length);         ptr +=2;
 
1022
  mi_int2store(ptr,base->max_key_length);               ptr +=2;
 
1023
  mi_int2store(ptr,base->extra_alloc_bytes);            ptr +=2;
 
1024
  *ptr++= base->extra_alloc_procent;
 
1025
  *ptr++= base->raid_type;
 
1026
  mi_int2store(ptr,base->raid_chunks);                  ptr +=2;
 
1027
  mi_int4store(ptr,base->raid_chunksize);               ptr +=4;
 
1028
  bzero(ptr,6);                                         ptr +=6; /* extra */
 
1029
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1030
}
 
1031
 
 
1032
 
 
1033
uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
 
1034
{
 
1035
  base->keystart = mi_sizekorr(ptr);                    ptr +=8;
 
1036
  base->max_data_file_length = mi_sizekorr(ptr);        ptr +=8;
 
1037
  base->max_key_file_length = mi_sizekorr(ptr);         ptr +=8;
 
1038
  base->records =  (ha_rows) mi_sizekorr(ptr);          ptr +=8;
 
1039
  base->reloc = (ha_rows) mi_sizekorr(ptr);             ptr +=8;
 
1040
  base->mean_row_length = mi_uint4korr(ptr);            ptr +=4;
 
1041
  base->reclength = mi_uint4korr(ptr);                  ptr +=4;
 
1042
  base->pack_reclength = mi_uint4korr(ptr);             ptr +=4;
 
1043
  base->min_pack_length = mi_uint4korr(ptr);            ptr +=4;
 
1044
  base->max_pack_length = mi_uint4korr(ptr);            ptr +=4;
 
1045
  base->min_block_length = mi_uint4korr(ptr);           ptr +=4;
 
1046
  base->fields = mi_uint4korr(ptr);                     ptr +=4;
 
1047
  base->pack_fields = mi_uint4korr(ptr);                ptr +=4;
 
1048
 
 
1049
  base->rec_reflength = *ptr++;
 
1050
  base->key_reflength = *ptr++;
 
1051
  base->keys=           *ptr++;
 
1052
  base->auto_key=       *ptr++;
 
1053
  base->pack_bits = mi_uint2korr(ptr);                  ptr +=2;
 
1054
  base->blobs = mi_uint2korr(ptr);                      ptr +=2;
 
1055
  base->max_key_block_length= mi_uint2korr(ptr);        ptr +=2;
 
1056
  base->max_key_length = mi_uint2korr(ptr);             ptr +=2;
 
1057
  base->extra_alloc_bytes = mi_uint2korr(ptr);          ptr +=2;
 
1058
  base->extra_alloc_procent = *ptr++;
 
1059
  base->raid_type= *ptr++;
 
1060
  base->raid_chunks= mi_uint2korr(ptr);                 ptr +=2;
 
1061
  base->raid_chunksize= mi_uint4korr(ptr);              ptr +=4;
 
1062
  /* TO BE REMOVED: Fix for old RAID files */
 
1063
  if (base->raid_type == 0)
 
1064
  {
 
1065
    base->raid_chunks=0;
 
1066
    base->raid_chunksize=0;
 
1067
  }
 
1068
 
 
1069
  ptr+=6;
 
1070
  return ptr;
 
1071
}
 
1072
 
 
1073
/*--------------------------------------------------------------------------
 
1074
  mi_keydef
 
1075
---------------------------------------------------------------------------*/
 
1076
 
 
1077
uint mi_keydef_write(File file, MI_KEYDEF *keydef)
 
1078
{
 
1079
  uchar buff[MI_KEYDEF_SIZE];
 
1080
  uchar *ptr=buff;
 
1081
 
 
1082
  *ptr++ = (uchar) keydef->keysegs;
 
1083
  *ptr++ = keydef->key_alg;                     /* Rtree or Btree */
 
1084
  mi_int2store(ptr,keydef->flag);               ptr +=2;
 
1085
  mi_int2store(ptr,keydef->block_length);       ptr +=2;
 
1086
  mi_int2store(ptr,keydef->keylength);          ptr +=2;
 
1087
  mi_int2store(ptr,keydef->minlength);          ptr +=2;
 
1088
  mi_int2store(ptr,keydef->maxlength);          ptr +=2;
 
1089
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1090
}
 
1091
 
 
1092
uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef)
 
1093
{
 
1094
   keydef->keysegs      = (uint) *ptr++;
 
1095
   keydef->key_alg      = *ptr++;               /* Rtree or Btree */
 
1096
 
 
1097
   keydef->flag         = mi_uint2korr(ptr);    ptr +=2;
 
1098
   keydef->block_length = mi_uint2korr(ptr);    ptr +=2;
 
1099
   keydef->keylength    = mi_uint2korr(ptr);    ptr +=2;
 
1100
   keydef->minlength    = mi_uint2korr(ptr);    ptr +=2;
 
1101
   keydef->maxlength    = mi_uint2korr(ptr);    ptr +=2;
 
1102
   keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
 
1103
   keydef->underflow_block_length=keydef->block_length/3;
 
1104
   keydef->version      = 0;                    /* Not saved */
 
1105
   keydef->parser       = &ft_default_parser;
 
1106
   keydef->ftparser_nr  = 0;
 
1107
   return ptr;
 
1108
}
 
1109
 
 
1110
/***************************************************************************
 
1111
**  mi_keyseg
 
1112
***************************************************************************/
 
1113
 
 
1114
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
 
1115
{
 
1116
  uchar buff[HA_KEYSEG_SIZE];
 
1117
  uchar *ptr=buff;
 
1118
  ulong pos;
 
1119
 
 
1120
  *ptr++= keyseg->type;
 
1121
  *ptr++= keyseg->language;
 
1122
  *ptr++= keyseg->null_bit;
 
1123
  *ptr++= keyseg->bit_start;
 
1124
  *ptr++= keyseg->bit_end;
 
1125
  *ptr++= keyseg->bit_length;
 
1126
  mi_int2store(ptr,keyseg->flag);       ptr+=2;
 
1127
  mi_int2store(ptr,keyseg->length);     ptr+=2;
 
1128
  mi_int4store(ptr,keyseg->start);      ptr+=4;
 
1129
  pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
 
1130
  mi_int4store(ptr, pos);
 
1131
  ptr+=4;
 
1132
  
 
1133
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1134
}
 
1135
 
 
1136
 
 
1137
uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
 
1138
{
 
1139
   keyseg->type         = *ptr++;
 
1140
   keyseg->language     = *ptr++;
 
1141
   keyseg->null_bit     = *ptr++;
 
1142
   keyseg->bit_start    = *ptr++;
 
1143
   keyseg->bit_end      = *ptr++;
 
1144
   keyseg->bit_length   = *ptr++;
 
1145
   keyseg->flag         = mi_uint2korr(ptr);  ptr +=2;
 
1146
   keyseg->length       = mi_uint2korr(ptr);  ptr +=2;
 
1147
   keyseg->start        = mi_uint4korr(ptr);  ptr +=4;
 
1148
   keyseg->null_pos     = mi_uint4korr(ptr);  ptr +=4;
 
1149
   keyseg->charset=0;                           /* Will be filled in later */
 
1150
   if (keyseg->null_bit)
 
1151
     keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7));
 
1152
   else
 
1153
   {
 
1154
     keyseg->bit_pos= (uint16)keyseg->null_pos;
 
1155
     keyseg->null_pos= 0;
 
1156
   }
 
1157
   return ptr;
 
1158
}
 
1159
 
 
1160
/*--------------------------------------------------------------------------
 
1161
  mi_uniquedef
 
1162
---------------------------------------------------------------------------*/
 
1163
 
 
1164
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
 
1165
{
 
1166
  uchar buff[MI_UNIQUEDEF_SIZE];
 
1167
  uchar *ptr=buff;
 
1168
 
 
1169
  mi_int2store(ptr,def->keysegs);               ptr+=2;
 
1170
  *ptr++=  (uchar) def->key;
 
1171
  *ptr++ = (uchar) def->null_are_equal;
 
1172
 
 
1173
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1174
}
 
1175
 
 
1176
uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *def)
 
1177
{
 
1178
   def->keysegs = mi_uint2korr(ptr);
 
1179
   def->key     = ptr[2];
 
1180
   def->null_are_equal=ptr[3];
 
1181
   return ptr+4;                                /* 1 extra byte */
 
1182
}
 
1183
 
 
1184
/***************************************************************************
 
1185
**  MI_COLUMNDEF
 
1186
***************************************************************************/
 
1187
 
 
1188
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
 
1189
{
 
1190
  uchar buff[MI_COLUMNDEF_SIZE];
 
1191
  uchar *ptr=buff;
 
1192
 
 
1193
  mi_int2store(ptr,recinfo->type);      ptr +=2;
 
1194
  mi_int2store(ptr,recinfo->length);    ptr +=2;
 
1195
  *ptr++ = recinfo->null_bit;
 
1196
  mi_int2store(ptr,recinfo->null_pos);  ptr+= 2;
 
1197
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1198
}
 
1199
 
 
1200
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
 
1201
{
 
1202
   recinfo->type=  mi_sint2korr(ptr);   ptr +=2;
 
1203
   recinfo->length=mi_uint2korr(ptr);   ptr +=2;
 
1204
   recinfo->null_bit= (uint8) *ptr++;
 
1205
   recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
 
1206
   return ptr;
 
1207
}
 
1208
 
 
1209
/**************************************************************************
 
1210
Open data file with or without RAID
 
1211
We can't use dup() here as the data file descriptors need to have different
 
1212
active seek-positions.
 
1213
 
 
1214
The argument file_to_dup is here for the future if there would on some OS
 
1215
exist a dup()-like call that would give us two different file descriptors.
 
1216
*************************************************************************/
 
1217
 
 
1218
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
 
1219
                     File file_to_dup __attribute__((unused)))
 
1220
{
 
1221
#ifdef USE_RAID
 
1222
  if (share->base.raid_type)
 
1223
  {
 
1224
    info->dfile=my_raid_open(share->data_file_name,
 
1225
                             share->mode | O_SHARE,
 
1226
                             share->base.raid_type,
 
1227
                             share->base.raid_chunks,
 
1228
                             share->base.raid_chunksize,
 
1229
                             MYF(MY_WME | MY_RAID));
 
1230
  }
 
1231
  else
 
1232
#endif
 
1233
    info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
 
1234
                        MYF(MY_WME));
 
1235
  return info->dfile >= 0 ? 0 : 1;
 
1236
}
 
1237
 
 
1238
 
 
1239
int mi_open_keyfile(MYISAM_SHARE *share)
 
1240
{
 
1241
  if ((share->kfile=my_open(share->unique_file_name, share->mode | O_SHARE,
 
1242
                            MYF(MY_WME))) < 0)
 
1243
    return 1;
 
1244
  return 0;
 
1245
}
 
1246
 
 
1247
 
 
1248
/*
 
1249
  Disable all indexes.
 
1250
 
 
1251
  SYNOPSIS
 
1252
    mi_disable_indexes()
 
1253
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1254
 
 
1255
  DESCRIPTION
 
1256
    Disable all indexes.
 
1257
 
 
1258
  RETURN
 
1259
    0  ok
 
1260
*/
 
1261
 
 
1262
int mi_disable_indexes(MI_INFO *info)
 
1263
{
 
1264
  MYISAM_SHARE *share= info->s;
 
1265
 
 
1266
  mi_clear_all_keys_active(share->state.key_map);
 
1267
  return 0;
 
1268
}
 
1269
 
 
1270
 
 
1271
/*
 
1272
  Enable all indexes
 
1273
 
 
1274
  SYNOPSIS
 
1275
    mi_enable_indexes()
 
1276
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1277
 
 
1278
  DESCRIPTION
 
1279
    Enable all indexes. The indexes might have been disabled
 
1280
    by mi_disable_index() before.
 
1281
    The function works only if both data and indexes are empty,
 
1282
    otherwise a repair is required.
 
1283
    To be sure, call handler::delete_all_rows() before.
 
1284
 
 
1285
  RETURN
 
1286
    0  ok
 
1287
    HA_ERR_CRASHED data or index is non-empty.
 
1288
*/
 
1289
 
 
1290
int mi_enable_indexes(MI_INFO *info)
 
1291
{
 
1292
  int error= 0;
 
1293
  MYISAM_SHARE *share= info->s;
 
1294
 
 
1295
  if (share->state.state.data_file_length ||
 
1296
      (share->state.state.key_file_length != share->base.keystart))
 
1297
  {
 
1298
    mi_print_error(info->s, HA_ERR_CRASHED);
 
1299
    error= HA_ERR_CRASHED;
 
1300
  }
 
1301
  else
 
1302
    mi_set_all_keys_active(share->state.key_map, share->base.keys);
 
1303
  return error;
 
1304
}
 
1305
 
 
1306
 
 
1307
/*
 
1308
  Test if indexes are disabled.
 
1309
 
 
1310
  SYNOPSIS
 
1311
    mi_indexes_are_disabled()
 
1312
    info        A pointer to the MyISAM storage engine MI_INFO struct.
 
1313
 
 
1314
  DESCRIPTION
 
1315
    Test if indexes are disabled.
 
1316
 
 
1317
  RETURN
 
1318
    0  indexes are not disabled
 
1319
    1  all indexes are disabled
 
1320
    2  non-unique indexes are disabled
 
1321
*/
 
1322
 
 
1323
int mi_indexes_are_disabled(MI_INFO *info)
 
1324
{
 
1325
  MYISAM_SHARE *share= info->s;
 
1326
 
 
1327
  /*
 
1328
    No keys or all are enabled. keys is the number of keys. Left shifted
 
1329
    gives us only one bit set. When decreased by one, gives us all all bits
 
1330
    up to this one set and it gets unset.
 
1331
  */
 
1332
  if (!share->base.keys ||
 
1333
      (mi_is_all_keys_active(share->state.key_map, share->base.keys)))
 
1334
    return 0;
 
1335
 
 
1336
  /* All are disabled */
 
1337
  if (mi_is_any_key_active(share->state.key_map))
 
1338
    return 1;
 
1339
 
 
1340
  /*
 
1341
    We have keys. Some enabled, some disabled.
 
1342
    Don't check for any non-unique disabled but return directly 2
 
1343
  */
 
1344
  return 2;
 
1345
}
 
1346