~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_open.c

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* open a isam-database */
17
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/charset_info.h>
27
 
#include <drizzled/internal/m_string.h>
28
 
#include <drizzled/util/test.h>
29
 
#include <drizzled/global_charset_info.h>
30
 
#include <drizzled/charset.h>
31
 
#include <drizzled/memory/multi_malloc.h>
32
 
 
33
 
 
34
 
using namespace std;
35
 
using namespace drizzled;
 
18
#include "myisamdef.h"
 
19
#include <mystrings/m_ctype.h>
36
20
 
37
21
static void setup_key_functions(MI_KEYDEF *keyinfo);
38
 
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef);
39
 
static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg);
40
 
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo);
41
 
static uint64_t mi_safe_mul(uint64_t a, uint64_t b);
42
 
static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state);
43
 
static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def);
44
 
static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base);
 
22
#define get_next_element(to,pos,size) \
 
23
  do {                                \
 
24
    memcpy(to, pos, size);            \
 
25
    pos+=size;                        \
 
26
  } while (0)
 
27
 
45
28
 
46
29
#define disk_pos_assert(pos, end_pos) \
47
30
if (pos > end_pos)             \
48
31
{                              \
49
 
  errno=HA_ERR_CRASHED;     \
 
32
  my_errno=HA_ERR_CRASHED;     \
50
33
  goto err;                    \
51
34
}
52
35
 
58
41
 
59
42
MI_INFO *test_if_reopen(char *filename)
60
43
{
61
 
  list<MI_INFO *>::iterator it= myisam_open_list.begin();
62
 
  while (it != myisam_open_list.end())
 
44
  LIST *pos;
 
45
 
 
46
  for (pos=myisam_open_list ; pos ; pos=pos->next)
63
47
  {
64
 
    MI_INFO *info= *it;
 
48
    MI_INFO *info=(MI_INFO*) pos->data;
65
49
    MYISAM_SHARE *share=info->s;
66
50
    if (!strcmp(share->unique_file_name,filename) && share->last_version)
67
51
      return info;
68
 
    ++it;
69
52
  }
70
53
  return 0;
71
54
}
79
62
  have an open count of 0.
80
63
******************************************************************************/
81
64
 
82
 
MI_INFO *mi_open(const drizzled::identifier::Table &identifier, int mode, uint32_t open_flags)
 
65
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
83
66
{
84
67
  int lock_error,kfile,open_mode,save_errno,have_rtree=0;
85
 
  uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
 
68
  uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
86
69
    key_parts,unique_key_parts,fulltext_keys,uniques;
87
70
  char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
88
 
       data_name[FN_REFLEN], rp_buff[PATH_MAX];
89
 
  unsigned char *disk_cache= NULL;
90
 
  unsigned char *disk_pos, *end_pos;
 
71
       data_name[FN_REFLEN];
 
72
  uchar *disk_cache, *disk_pos, *end_pos;
91
73
  MI_INFO info,*m_info,*old_info;
92
 
  boost::scoped_ptr<MYISAM_SHARE> share_buff_ap(new MYISAM_SHARE);
93
 
  MYISAM_SHARE &share_buff= *share_buff_ap.get();
94
 
  MYISAM_SHARE *share;
95
 
  boost::scoped_array<ulong> rec_per_key_part_ap(new ulong[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]);
96
 
  ulong *rec_per_key_part= rec_per_key_part_ap.get();
97
 
  internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
 
74
  MYISAM_SHARE share_buff,*share;
 
75
  ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
 
76
  my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
98
77
  uint64_t max_key_file_length, max_data_file_length;
99
78
 
100
79
  kfile= -1;
103
82
  head_length=sizeof(share_buff.state.header);
104
83
  memset(&info, 0, sizeof(info));
105
84
 
106
 
  (void)internal::fn_format(org_name,
107
 
                            identifier.getPath().c_str(), 
108
 
                            "",
109
 
                            MI_NAME_IEXT,
110
 
                            MY_UNPACK_FILENAME);
111
 
  if (!realpath(org_name,rp_buff))
112
 
    internal::my_load_path(rp_buff,org_name, NULL);
113
 
  rp_buff[FN_REFLEN-1]= '\0';
114
 
  strcpy(name_buff,rp_buff);
115
 
  THR_LOCK_myisam.lock();
 
85
  my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
 
86
                                   MY_UNPACK_FILENAME),MYF(0));
 
87
  pthread_mutex_lock(&THR_LOCK_myisam);
116
88
  if (!(old_info=test_if_reopen(name_buff)))
117
89
  {
118
90
    share= &share_buff;
120
92
    share_buff.state.rec_per_key_part=rec_per_key_part;
121
93
    share_buff.state.key_root=key_root;
122
94
    share_buff.state.key_del=key_del;
123
 
    share_buff.setKeyCache();
 
95
    share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
 
96
                                                 strlen(name_buff));
124
97
 
125
 
    if ((kfile=internal::my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
 
98
    if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
126
99
    {
127
100
      if ((errno != EROFS && errno != EACCES) ||
128
101
          mode != O_RDONLY ||
129
 
          (kfile=internal::my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
 
102
          (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
130
103
        goto err;
131
104
    }
132
105
    share->mode=open_mode;
133
106
    errpos=1;
134
 
    if (internal::my_read(kfile, share->state.header.file_version, head_length,
 
107
    if (my_read(kfile, share->state.header.file_version, head_length,
135
108
                MYF(MY_NABP)))
136
109
    {
137
 
      errno= HA_ERR_NOT_A_TABLE;
 
110
      my_errno= HA_ERR_NOT_A_TABLE;
138
111
      goto err;
139
112
    }
140
113
    if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
141
114
    {
142
 
      errno=HA_ERR_NOT_A_TABLE;
 
115
      my_errno=HA_ERR_NOT_A_TABLE;
143
116
      goto err;
144
117
    }
145
118
    share->options= mi_uint2korr(share->state.header.options);
146
 
    static const uint64_t OLD_FILE_OPTIONS= HA_OPTION_PACK_RECORD |
147
 
            HA_OPTION_PACK_KEYS |
148
 
            HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
149
 
            HA_OPTION_TEMP_COMPRESS_RECORD |
150
 
            HA_OPTION_TMP_TABLE;
151
 
    if (share->options & ~OLD_FILE_OPTIONS)
152
 
    {
153
 
      errno=HA_ERR_OLD_FILE;
154
 
      goto err;
155
 
    }
156
 
 
 
119
    if (share->options &
 
120
        ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
 
121
          HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
 
122
          HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
 
123
          HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
 
124
          HA_OPTION_RELIES_ON_SQL_LAYER))
 
125
    {
 
126
      my_errno=HA_ERR_OLD_FILE;
 
127
      goto err;
 
128
    }
 
129
    if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
 
130
        ! (open_flags & HA_OPEN_FROM_SQL_LAYER))
 
131
    {
 
132
      my_errno= HA_ERR_UNSUPPORTED;
 
133
      goto err;
 
134
    }
157
135
    /* Don't call realpath() if the name can't be a link */
158
 
    ssize_t sym_link_size= readlink(org_name,index_name,FN_REFLEN-1);
159
 
    if (sym_link_size >= 0 )
160
 
      index_name[sym_link_size]= '\0';
161
 
    if (!strcmp(name_buff, org_name) || sym_link_size == -1)
162
 
      (void) strcpy(index_name, org_name);
 
136
    if (!strcmp(name_buff, org_name) ||
 
137
        my_readlink(index_name, org_name, MYF(0)) == -1)
 
138
      (void) stpcpy(index_name, org_name);
163
139
    *strrchr(org_name, '.')= '\0';
164
 
    (void) internal::fn_format(data_name,org_name,"",MI_NAME_DEXT,
 
140
    (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
165
141
                     MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
166
142
 
167
143
    info_length=mi_uint2korr(share->state.header.header_length);
168
144
    base_pos=mi_uint2korr(share->state.header.base_pos);
169
 
    if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
 
145
    if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
170
146
    {
171
 
      errno=ENOMEM;
 
147
      my_errno=ENOMEM;
172
148
      goto err;
173
149
    }
174
150
    end_pos=disk_cache+info_length;
175
151
    errpos=2;
176
152
 
177
 
    lseek(kfile,0,SEEK_SET);
 
153
    VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
178
154
    errpos=3;
179
 
    if (internal::my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
 
155
    if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
180
156
    {
181
 
      errno=HA_ERR_CRASHED;
 
157
      my_errno=HA_ERR_CRASHED;
182
158
      goto err;
183
159
    }
184
160
    len=mi_uint2korr(share->state.header.state_info_length);
194
170
    disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
195
171
    share->state.state_length=base_pos;
196
172
 
197
 
    if (share->state.changed & STATE_CRASHED)
 
173
    if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
 
174
        ((share->state.changed & STATE_CRASHED) ||
 
175
         ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
 
176
          (share->state.open_count))))
198
177
    {
199
 
      errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
 
178
      my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
200
179
                HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
201
180
      goto err;
202
181
    }
204
183
    /* sanity check */
205
184
    if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
206
185
    {
207
 
      errno=HA_ERR_CRASHED;
 
186
      my_errno=HA_ERR_CRASHED;
208
187
      goto err;
209
188
    }
210
189
 
211
190
    if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
212
191
        key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
213
192
    {
214
 
      errno=HA_ERR_UNSUPPORTED;
 
193
      my_errno=HA_ERR_UNSUPPORTED;
215
194
      goto err;
216
195
    }
217
196
 
225
204
      mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
226
205
                  ((uint64_t) 1 << (share->base.key_reflength*8))-1);
227
206
#if SIZEOF_OFF_T == 4
228
 
    set_if_smaller(max_data_file_length, INT32_MAX);
229
 
    set_if_smaller(max_key_file_length, INT32_MAX);
 
207
    set_if_smaller(max_data_file_length, INT_MAX32);
 
208
    set_if_smaller(max_key_file_length, INT_MAX32);
230
209
#endif
231
210
    if (share->base.raid_type)
232
211
    {
233
 
      errno=HA_ERR_UNSUPPORTED;
 
212
      my_errno=HA_ERR_UNSUPPORTED;
234
213
      goto err;
235
214
    }
236
 
    share->base.max_data_file_length=(internal::my_off_t) max_data_file_length;
237
 
    share->base.max_key_file_length=(internal::my_off_t) max_key_file_length;
 
215
    share->base.max_data_file_length=(my_off_t) max_data_file_length;
 
216
    share->base.max_key_file_length=(my_off_t) max_key_file_length;
238
217
 
239
218
    if (share->options & HA_OPTION_COMPRESS_RECORD)
240
219
      share->base.max_key_length+=2;    /* For safety */
242
221
    /* Add space for node pointer */
243
222
    share->base.max_key_length+= share->base.key_reflength;
244
223
 
245
 
    if (!drizzled::memory::multi_malloc(false,
246
 
           &share,sizeof(*share),
247
 
           &share->state.rec_per_key_part,sizeof(long)*key_parts,
248
 
           &share->keyinfo,keys*sizeof(MI_KEYDEF),
249
 
           &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
250
 
           &share->keyparts,
251
 
           (key_parts+unique_key_parts+keys+uniques) * sizeof(HA_KEYSEG),
252
 
           &share->rec, (share->base.fields+1)*sizeof(MI_COLUMNDEF),
253
 
           &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
254
 
           &share->unique_file_name,strlen(name_buff)+1,
255
 
           &share->index_file_name,strlen(index_name)+1,
256
 
           &share->data_file_name,strlen(data_name)+1,
257
 
           &share->state.key_root,keys*sizeof(uint64_t),
258
 
           &share->state.key_del,
259
 
           (share->state.header.max_block_size_index*sizeof(uint64_t)),
260
 
           NULL))
 
224
    if (!my_multi_malloc(MY_WME,
 
225
                         &share,sizeof(*share),
 
226
                         &share->state.rec_per_key_part,sizeof(long)*key_parts,
 
227
                         &share->keyinfo,keys*sizeof(MI_KEYDEF),
 
228
                         &share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
 
229
                         &share->keyparts,
 
230
                         (key_parts+unique_key_parts+keys+uniques) *
 
231
                         sizeof(HA_KEYSEG),
 
232
                         &share->rec,
 
233
                         (share->base.fields+1)*sizeof(MI_COLUMNDEF),
 
234
                         &share->blobs,sizeof(MI_BLOB)*share->base.blobs,
 
235
                         &share->unique_file_name,strlen(name_buff)+1,
 
236
                         &share->index_file_name,strlen(index_name)+1,
 
237
                         &share->data_file_name,strlen(data_name)+1,
 
238
                         &share->state.key_root,keys*sizeof(my_off_t),
 
239
                         &share->state.key_del,
 
240
                         (share->state.header.max_block_size_index*sizeof(my_off_t)),
 
241
                         &share->key_root_lock,sizeof(rw_lock_t)*keys,
 
242
                         &share->mmap_lock,sizeof(rw_lock_t),
 
243
                         NullS))
261
244
      goto err;
262
245
    errpos=4;
263
246
    *share=share_buff;
264
247
    memcpy(share->state.rec_per_key_part, rec_per_key_part,
265
248
           sizeof(long)*key_parts);
266
249
    memcpy(share->state.key_root, key_root,
267
 
           sizeof(internal::my_off_t)*keys);
 
250
           sizeof(my_off_t)*keys);
268
251
    memcpy(share->state.key_del, key_del,
269
 
           sizeof(internal::my_off_t) * share->state.header.max_block_size_index);
270
 
    strcpy(share->unique_file_name, name_buff);
 
252
           sizeof(my_off_t) * share->state.header.max_block_size_index);
 
253
    stpcpy(share->unique_file_name, name_buff);
271
254
    share->unique_name_length= strlen(name_buff);
272
 
    strcpy(share->index_file_name,  index_name);
273
 
    strcpy(share->data_file_name,   data_name);
 
255
    stpcpy(share->index_file_name,  index_name);
 
256
    stpcpy(share->data_file_name,   data_name);
274
257
 
275
 
    share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
 
258
    share->blocksize=min(IO_SIZE,myisam_block_size);
276
259
    {
277
260
      HA_KEYSEG *pos=share->keyparts;
278
261
      for (i=0 ; i < keys ; i++)
281
264
        disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
282
265
        disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
283
266
                        end_pos);
284
 
        set_if_smaller(share->blocksize,(uint)share->keyinfo[i].block_length);
 
267
        set_if_smaller(share->blocksize,share->keyinfo[i].block_length);
285
268
        share->keyinfo[i].seg=pos;
286
269
        for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
287
270
        {
290
273
              ! (share->options & (HA_OPTION_COMPRESS_RECORD |
291
274
                                   HA_OPTION_PACK_RECORD)))
292
275
          {
293
 
            errno= HA_ERR_CRASHED;
 
276
            my_errno= HA_ERR_CRASHED;
294
277
            goto err;
295
278
          }
296
279
          if (pos->type == HA_KEYTYPE_TEXT ||
299
282
          {
300
283
            if (!pos->language)
301
284
              pos->charset=default_charset_info;
302
 
            else if (!(pos->charset= get_charset(pos->language)))
 
285
            else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
303
286
            {
304
 
              errno=HA_ERR_UNKNOWN_CHARSET;
 
287
              my_errno=HA_ERR_UNKNOWN_CHARSET;
305
288
              goto err;
306
289
            }
307
290
          }
331
314
          {
332
315
            if (!pos->language)
333
316
              pos->charset=default_charset_info;
334
 
            else if (!(pos->charset= get_charset(pos->language)))
 
317
            else if (!(pos->charset= get_charset(pos->language, MYF(MY_WME))))
335
318
            {
336
 
              errno=HA_ERR_UNKNOWN_CHARSET;
 
319
              my_errno=HA_ERR_UNKNOWN_CHARSET;
337
320
              goto err;
338
321
            }
339
322
          }
365
348
    share->rec[i].type=(int) FIELD_LAST;        /* End marker */
366
349
    if (offset > share->base.reclength)
367
350
    {
368
 
      errno= HA_ERR_CRASHED;
 
351
      /* purecov: begin inspected */
 
352
      my_errno= HA_ERR_CRASHED;
369
353
      goto err;
 
354
      /* purecov: end */
370
355
    }
371
356
 
372
357
    if (! lock_error)
389
374
    share->base.margin_key_file_length=(share->base.max_key_file_length -
390
375
                                        (keys ? MI_INDEX_BLOCK_MARGIN *
391
376
                                         share->blocksize * keys : 0));
392
 
    share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
 
377
    share->blocksize=min(IO_SIZE,myisam_block_size);
393
378
    share->data_file_type=STATIC_RECORD;
394
379
    if (share->options & HA_OPTION_PACK_RECORD)
395
380
      share->data_file_type = DYNAMIC_RECORD;
396
 
    free(disk_cache);
397
 
    disk_cache= NULL;
 
381
    my_afree(disk_cache);
398
382
    mi_setup_functions(share);
399
383
    share->is_log_table= false;
400
 
    if (myisam_concurrent_insert)
 
384
    thr_lock_init(&share->lock);
 
385
    VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
 
386
    for (i=0; i<keys; i++)
 
387
      VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
 
388
    VOID(my_rwlock_init(&share->mmap_lock, NULL));
 
389
    if (!thr_lock_inited)
 
390
    {
 
391
      /* Probably a single threaded program; Don't use concurrent inserts */
 
392
      myisam_concurrent_insert=0;
 
393
    }
 
394
    else if (myisam_concurrent_insert)
401
395
    {
402
396
      share->concurrent_insert=
403
397
        ((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
406
400
         (open_flags & HA_OPEN_TMP_TABLE) || have_rtree) ? 0 : 1;
407
401
      if (share->concurrent_insert)
408
402
      {
409
 
        assert(0);
 
403
        share->lock.get_status= mi_get_status;
 
404
        share->lock.copy_status= mi_copy_status;
 
405
        share->lock.update_status= mi_update_status;
 
406
        share->lock.restore_status= mi_restore_status;
 
407
        share->lock.check_status= mi_check_status;
410
408
      }
411
409
    }
 
410
    /*
 
411
      Memory mapping can only be requested after initializing intern_lock.
 
412
    */
 
413
    if (open_flags & HA_OPEN_MMAP)
 
414
    {
 
415
      info.s= share;
 
416
      mi_extra(&info, HA_EXTRA_MMAP, 0);
 
417
    }
412
418
  }
413
419
  else
414
420
  {
415
421
    share= old_info->s;
416
422
    if (mode == O_RDWR && share->mode == O_RDONLY)
417
423
    {
418
 
      errno=EACCES;                             /* Can't open in write mode */
 
424
      my_errno=EACCES;                          /* Can't open in write mode */
419
425
      goto err;
420
426
    }
421
427
    if (mi_open_datafile(&info, share, old_info->dfile))
425
431
  }
426
432
 
427
433
  /* alloc and set up private structure parts */
428
 
  if (!drizzled::memory::multi_malloc(MY_WME,
429
 
         &m_info,sizeof(MI_INFO),
430
 
         &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
431
 
         &info.buff,(share->base.max_key_block_length*2+
432
 
                     share->base.max_key_length),
433
 
         &info.lastkey,share->base.max_key_length*3+1,
434
 
         &info.first_mbr_key, share->base.max_key_length,
435
 
         &info.filename, identifier.getPath().length()+1,
436
 
         &info.rtree_recursion_state,have_rtree ? 1024 : 0,
437
 
         NULL))
 
434
  if (!my_multi_malloc(MY_WME,
 
435
                       &m_info,sizeof(MI_INFO),
 
436
                       &info.blobs,sizeof(MI_BLOB)*share->base.blobs,
 
437
                       &info.buff,(share->base.max_key_block_length*2+
 
438
                                   share->base.max_key_length),
 
439
                       &info.lastkey,share->base.max_key_length*3+1,
 
440
                       &info.first_mbr_key, share->base.max_key_length,
 
441
                       &info.filename,strlen(name)+1,
 
442
                       &info.rtree_recursion_state,have_rtree ? 1024 : 0,
 
443
                       NullS))
438
444
    goto err;
439
445
  errpos=6;
440
446
 
441
447
  if (!have_rtree)
442
448
    info.rtree_recursion_state= NULL;
443
449
 
444
 
  strcpy(info.filename, identifier.getPath().c_str());
 
450
  stpcpy(info.filename,name);
445
451
  memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
446
452
  info.lastkey2=info.lastkey+share->base.max_key_length;
447
453
 
462
468
  info.bulk_insert=0;
463
469
  info.errkey= -1;
464
470
  info.page_changed=1;
 
471
  pthread_mutex_lock(&share->intern_lock);
465
472
  info.read_record=share->read_record;
466
473
  share->reopen++;
467
474
  share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
476
483
  {
477
484
    share->temporary=share->delay_key_write=1;
478
485
    share->write_flag=MYF(MY_NABP);
479
 
    /*
480
 
     * The following two statements are commented out as a fix of
481
 
     * bug https://bugs.launchpad.net/drizzle/+bug/387627
482
 
     *
483
 
     * UPDATE can be TRUNCATE on TEMPORARY TABLE (MyISAM).
484
 
     * The root cause of why this makes a difference hasn't
485
 
     * been found, but this fixes things for now.
486
 
     */
487
 
//    share->w_locks++;                 // We don't have to update status
488
 
//    share->tot_locks++;
 
486
    share->w_locks++;                   /* We don't have to update status */
 
487
    share->tot_locks++;
489
488
    info.lock_type=F_WRLCK;
490
489
  }
491
 
 
492
 
  share->delay_key_write= 1;
 
490
  if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) ||
 
491
      (share->options & HA_OPTION_DELAY_KEY_WRITE)) &&
 
492
      myisam_delay_key_write)
 
493
    share->delay_key_write=1;
493
494
  info.state= &share->state.state;      /* Change global values by default */
 
495
  pthread_mutex_unlock(&share->intern_lock);
494
496
 
495
497
  /* Allocate buffer for one record */
496
498
 
497
499
  /* prerequisites: memset(info, 0) && info->s=share; are met. */
498
 
  if (!mi_alloc_rec_buff(&info, SIZE_MAX, &info.rec_buff))
 
500
  if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff))
499
501
    goto err;
500
502
  memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
501
503
 
502
504
  *m_info=info;
503
 
  myisam_open_list.push_front(m_info);
 
505
  thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
 
506
  m_info->open_list.data=(void*) m_info;
 
507
  myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
504
508
 
505
 
  THR_LOCK_myisam.unlock();
 
509
  pthread_mutex_unlock(&THR_LOCK_myisam);
506
510
  return(m_info);
507
511
 
508
512
err:
509
 
  if (disk_cache != NULL)
510
 
    free(disk_cache);
511
 
  save_errno=errno ? errno : HA_ERR_END_OF_FILE;
 
513
  save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
512
514
  if ((save_errno == HA_ERR_CRASHED) ||
513
515
      (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
514
516
      (save_errno == HA_ERR_CRASHED_ON_REPAIR))
515
 
    mi_report_error(save_errno, identifier.getPath().c_str());
 
517
    mi_report_error(save_errno, name);
516
518
  switch (errpos) {
517
519
  case 6:
518
 
    free((unsigned char*) m_info);
 
520
    my_free((uchar*) m_info,MYF(0));
519
521
    /* fall through */
520
522
  case 5:
521
 
    internal::my_close(info.dfile,MYF(0));
 
523
    VOID(my_close(info.dfile,MYF(0)));
522
524
    if (old_info)
523
525
      break;                                    /* Don't remove open table */
524
526
    /* fall through */
525
527
  case 4:
526
 
    free((unsigned char*) share);
 
528
    my_free((uchar*) share,MYF(0));
527
529
    /* fall through */
528
530
  case 3:
529
531
    /* fall through */
 
532
  case 2:
 
533
    my_afree(disk_cache);
 
534
    /* fall through */
530
535
  case 1:
531
 
    internal::my_close(kfile,MYF(0));
 
536
    VOID(my_close(kfile,MYF(0)));
532
537
    /* fall through */
533
538
  case 0:
534
539
  default:
535
540
    break;
536
541
  }
537
 
  THR_LOCK_myisam.unlock();
538
 
  errno=save_errno;
 
542
  pthread_mutex_unlock(&THR_LOCK_myisam);
 
543
  my_errno=save_errno;
539
544
  return (NULL);
540
545
} /* mi_open */
541
546
 
542
547
 
543
 
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
 
548
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
544
549
{
545
 
  uint32_t extra;
 
550
  uint extra;
546
551
  uint32_t old_length= 0;
547
552
 
548
553
  if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
549
554
  {
550
 
    unsigned char *newptr = *buf;
 
555
    uchar *newptr = *buf;
551
556
 
552
557
    /* to simplify initial init of info->rec_buf in mi_open and mi_extra */
553
 
    if (length == SIZE_MAX)
 
558
    if (length == (ulong) -1)
554
559
    {
555
560
      if (info->s->options & HA_OPTION_COMPRESS_RECORD)
556
561
        length= max(info->s->base.pack_reclength, info->s->max_pack_length);
557
562
      else
558
563
        length= info->s->base.pack_reclength;
559
 
      length= max((uint32_t)length, info->s->base.max_key_length);
 
564
      length= max(length, info->s->base.max_key_length);
560
565
      /* Avoid unnecessary realloc */
561
566
      if (newptr && length == old_length)
562
567
        return newptr;
567
572
            MI_REC_BUFF_OFFSET : 0);
568
573
    if (extra && newptr)
569
574
      newptr-= MI_REC_BUFF_OFFSET;
570
 
    void *tmpnewptr= NULL;
571
 
    if (!(tmpnewptr= realloc(newptr, length+extra+8))) 
 
575
    if (!(newptr=(uchar*) my_realloc((uchar*)newptr, length+extra+8,
 
576
                                     MYF(MY_ALLOW_ZERO_PTR))))
572
577
      return newptr;
573
 
    newptr= (unsigned char *)tmpnewptr;
574
578
    *((uint32_t *) newptr)= (uint32_t) length;
575
579
    *buf= newptr+(extra ?  MI_REC_BUFF_OFFSET : 0);
576
580
  }
578
582
}
579
583
 
580
584
 
581
 
static uint64_t mi_safe_mul(uint64_t a, uint64_t b)
 
585
uint64_t mi_safe_mul(uint64_t a, uint64_t b)
582
586
{
583
 
  uint64_t max_val= ~ (uint64_t) 0;             /* internal::my_off_t is unsigned */
 
587
  uint64_t max_val= ~ (uint64_t) 0;             /* my_off_t is unsigned */
584
588
 
585
589
  if (!a || max_val / a < b)
586
590
    return max_val;
626
630
  }
627
631
  share->file_read= mi_nommap_pread;
628
632
  share->file_write= mi_nommap_pwrite;
629
 
  share->calc_checksum=0;
 
633
  if (!(share->options & HA_OPTION_CHECKSUM))
 
634
    share->calc_checksum=0;
 
635
  return;
630
636
}
631
637
 
632
638
 
687
693
   Function to save and store the header in the index file (.MYI)
688
694
*/
689
695
 
690
 
uint32_t mi_state_info_write(int file, MI_STATE_INFO *state, uint32_t pWrite)
 
696
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
691
697
{
692
 
  unsigned char  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
693
 
  unsigned char *ptr=buff;
 
698
  uchar  buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
699
  uchar *ptr=buff;
694
700
  uint  i, keys= (uint) state->header.keys,
695
701
        key_blocks=state->header.max_block_size_index;
696
702
 
699
705
 
700
706
  /* open_count must be first because of _mi_mark_file_changed ! */
701
707
  mi_int2store(ptr,state->open_count);          ptr +=2;
702
 
  *ptr++= (unsigned char)state->changed; *ptr++= state->sortkey;
 
708
  *ptr++= (uchar)state->changed; *ptr++= state->sortkey;
703
709
  mi_rowstore(ptr,state->state.records);        ptr +=8;
704
710
  mi_rowstore(ptr,state->state.del);            ptr +=8;
705
711
  mi_rowstore(ptr,state->split);                ptr +=8;
727
733
  }
728
734
  if (pWrite & 2)                               /* From isamchk */
729
735
  {
730
 
    uint32_t key_parts= mi_uint2korr(state->header.key_parts);
 
736
    uint key_parts= mi_uint2korr(state->header.key_parts);
731
737
    mi_int4store(ptr,state->sec_index_changed); ptr +=4;
732
738
    mi_int4store(ptr,state->sec_index_used);    ptr +=4;
733
739
    mi_int4store(ptr,state->version);           ptr +=4;
745
751
  if (pWrite & 1)
746
752
    return(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
747
753
                          MYF(MY_NABP | MY_THREADSAFE)) != 0);
748
 
  return(internal::my_write(file, buff, (size_t) (ptr-buff),
 
754
  return(my_write(file, buff, (size_t) (ptr-buff),
749
755
                       MYF(MY_NABP)) != 0);
750
756
}
751
757
 
752
758
 
753
 
static unsigned char *mi_state_info_read(unsigned char *ptr, MI_STATE_INFO *state)
 
759
uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
754
760
{
755
 
  uint32_t i,keys,key_parts,key_blocks;
 
761
  uint i,keys,key_parts,key_blocks;
756
762
  memcpy(&state->header,ptr, sizeof(state->header));
757
763
  ptr +=sizeof(state->header);
758
764
  keys=(uint) state->header.keys;
771
777
  state->state.empty    = mi_sizekorr(ptr);     ptr +=8;
772
778
  state->state.key_empty= mi_sizekorr(ptr);     ptr +=8;
773
779
  state->auto_increment=mi_uint8korr(ptr);      ptr +=8;
774
 
  state->state.checksum=(internal::ha_checksum) mi_uint8korr(ptr);      ptr +=8;
 
780
  state->state.checksum=(ha_checksum) mi_uint8korr(ptr);        ptr +=8;
775
781
  state->process= mi_uint4korr(ptr);            ptr +=4;
776
782
  state->unique = mi_uint4korr(ptr);            ptr +=4;
777
783
  state->status = mi_uint4korr(ptr);            ptr +=4;
803
809
}
804
810
 
805
811
 
806
 
uint32_t mi_state_info_read_dsk(int file, MI_STATE_INFO *state, bool pRead)
 
812
uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, bool pRead)
807
813
{
808
 
  unsigned char buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
 
814
  uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
809
815
 
810
 
  if (pRead)
 
816
  if (!myisam_single_user)
811
817
  {
812
 
    if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
 
818
    if (pRead)
 
819
    {
 
820
      if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
 
821
        return 1;
 
822
    }
 
823
    else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
813
824
      return 1;
 
825
    mi_state_info_read(buff, state);
814
826
  }
815
 
  else if (internal::my_read(file, buff, state->state_length,MYF(MY_NABP)))
816
 
    return 1;
817
 
  mi_state_info_read(buff, state);
818
 
 
819
827
  return 0;
820
828
}
821
829
 
824
832
**  store and read of MI_BASE_INFO
825
833
****************************************************************************/
826
834
 
827
 
uint32_t mi_base_info_write(int file, MI_BASE_INFO *base)
 
835
uint mi_base_info_write(File file, MI_BASE_INFO *base)
828
836
{
829
 
  unsigned char buff[MI_BASE_INFO_SIZE], *ptr=buff;
 
837
  uchar buff[MI_BASE_INFO_SIZE], *ptr=buff;
830
838
 
831
839
  mi_sizestore(ptr,base->keystart);                     ptr +=8;
832
840
  mi_sizestore(ptr,base->max_data_file_length);         ptr +=8;
851
859
  mi_int2store(ptr,base->max_key_length);               ptr +=2;
852
860
  mi_int2store(ptr,base->extra_alloc_bytes);            ptr +=2;
853
861
  *ptr++= base->extra_alloc_procent;
854
 
  /* old raid info  slots */
855
 
  *ptr++= 0;
856
 
  mi_int2store(ptr,UINT16_C(0));                        ptr +=2;
857
 
  mi_int4store(ptr,UINT32_C(0));                        ptr +=4;
858
 
 
 
862
  *ptr++= base->raid_type;
 
863
  mi_int2store(ptr,base->raid_chunks);                  ptr +=2;
 
864
  mi_int4store(ptr,base->raid_chunksize);               ptr +=4;
859
865
  memset(ptr, 0, 6);                                    ptr +=6; /* extra */
860
 
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
866
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
861
867
}
862
868
 
863
869
 
864
 
static unsigned char *my_n_base_info_read(unsigned char *ptr, MI_BASE_INFO *base)
 
870
uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base)
865
871
{
866
872
  base->keystart = mi_sizekorr(ptr);                    ptr +=8;
867
873
  base->max_data_file_length = mi_sizekorr(ptr);        ptr +=8;
887
893
  base->max_key_length = mi_uint2korr(ptr);             ptr +=2;
888
894
  base->extra_alloc_bytes = mi_uint2korr(ptr);          ptr +=2;
889
895
  base->extra_alloc_procent = *ptr++;
890
 
 
891
 
  /* advance past raid_type (1) raid_chunks (2) and raid_chunksize (4) */
892
 
  ptr+= 7;
 
896
  base->raid_type= *ptr++;
 
897
  base->raid_chunks= mi_uint2korr(ptr);                 ptr +=2;
 
898
  base->raid_chunksize= mi_uint4korr(ptr);              ptr +=4;
 
899
  /* TO BE REMOVED: Fix for old RAID files */
 
900
  if (base->raid_type == 0)
 
901
  {
 
902
    base->raid_chunks=0;
 
903
    base->raid_chunksize=0;
 
904
  }
893
905
 
894
906
  ptr+=6;
895
907
  return ptr;
899
911
  mi_keydef
900
912
---------------------------------------------------------------------------*/
901
913
 
902
 
uint32_t mi_keydef_write(int file, MI_KEYDEF *keydef)
 
914
uint mi_keydef_write(File file, MI_KEYDEF *keydef)
903
915
{
904
 
  unsigned char buff[MI_KEYDEF_SIZE];
905
 
  unsigned char *ptr=buff;
 
916
  uchar buff[MI_KEYDEF_SIZE];
 
917
  uchar *ptr=buff;
906
918
 
907
 
  *ptr++ = (unsigned char) keydef->keysegs;
 
919
  *ptr++ = (uchar) keydef->keysegs;
908
920
  *ptr++ = keydef->key_alg;                     /* Rtree or Btree */
909
921
  mi_int2store(ptr,keydef->flag);               ptr +=2;
910
922
  mi_int2store(ptr,keydef->block_length);       ptr +=2;
911
923
  mi_int2store(ptr,keydef->keylength);          ptr +=2;
912
924
  mi_int2store(ptr,keydef->minlength);          ptr +=2;
913
925
  mi_int2store(ptr,keydef->maxlength);          ptr +=2;
914
 
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
926
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
915
927
}
916
928
 
917
 
static unsigned char *mi_keydef_read(unsigned char *ptr, MI_KEYDEF *keydef)
 
929
uchar *mi_keydef_read(uchar *ptr, MI_KEYDEF *keydef)
918
930
{
919
931
   keydef->keysegs      = (uint) *ptr++;
920
932
   keydef->key_alg      = *ptr++;               /* Rtree or Btree */
934
946
**  mi_keyseg
935
947
***************************************************************************/
936
948
 
937
 
int mi_keyseg_write(int file, const HA_KEYSEG *keyseg)
 
949
int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
938
950
{
939
 
  unsigned char buff[HA_KEYSEG_SIZE];
940
 
  unsigned char *ptr=buff;
 
951
  uchar buff[HA_KEYSEG_SIZE];
 
952
  uchar *ptr=buff;
941
953
  ulong pos;
942
954
 
943
955
  *ptr++= keyseg->type;
952
964
  pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
953
965
  mi_int4store(ptr, pos);
954
966
  ptr+=4;
955
 
 
956
 
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
967
  
 
968
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
957
969
}
958
970
 
959
971
 
960
 
static unsigned char *mi_keyseg_read(unsigned char *ptr, HA_KEYSEG *keyseg)
 
972
uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg)
961
973
{
962
974
   keyseg->type         = *ptr++;
963
975
   keyseg->language     = *ptr++;
984
996
  mi_uniquedef
985
997
---------------------------------------------------------------------------*/
986
998
 
987
 
uint32_t mi_uniquedef_write(int file, MI_UNIQUEDEF *def)
 
999
uint mi_uniquedef_write(File file, MI_UNIQUEDEF *def)
988
1000
{
989
 
  unsigned char buff[MI_UNIQUEDEF_SIZE];
990
 
  unsigned char *ptr=buff;
 
1001
  uchar buff[MI_UNIQUEDEF_SIZE];
 
1002
  uchar *ptr=buff;
991
1003
 
992
1004
  mi_int2store(ptr,def->keysegs);               ptr+=2;
993
 
  *ptr++=  (unsigned char) def->key;
994
 
  *ptr++ = (unsigned char) def->null_are_equal;
 
1005
  *ptr++=  (uchar) def->key;
 
1006
  *ptr++ = (uchar) def->null_are_equal;
995
1007
 
996
 
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1008
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
997
1009
}
998
1010
 
999
 
static unsigned char *mi_uniquedef_read(unsigned char *ptr, MI_UNIQUEDEF *def)
 
1011
uchar *mi_uniquedef_read(uchar *ptr, MI_UNIQUEDEF *def)
1000
1012
{
1001
1013
   def->keysegs = mi_uint2korr(ptr);
1002
1014
   def->key     = ptr[2];
1008
1020
**  MI_COLUMNDEF
1009
1021
***************************************************************************/
1010
1022
 
1011
 
uint32_t mi_recinfo_write(int file, MI_COLUMNDEF *recinfo)
 
1023
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1012
1024
{
1013
 
  unsigned char buff[MI_COLUMNDEF_SIZE];
1014
 
  unsigned char *ptr=buff;
 
1025
  uchar buff[MI_COLUMNDEF_SIZE];
 
1026
  uchar *ptr=buff;
1015
1027
 
1016
1028
  mi_int2store(ptr,recinfo->type);      ptr +=2;
1017
1029
  mi_int2store(ptr,recinfo->length);    ptr +=2;
1018
1030
  *ptr++ = recinfo->null_bit;
1019
1031
  mi_int2store(ptr,recinfo->null_pos);  ptr+= 2;
1020
 
  return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
 
1032
  return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1021
1033
}
1022
1034
 
1023
 
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
 
1035
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
1024
1036
{
1025
1037
   recinfo->type=  mi_sint2korr(ptr);   ptr +=2;
1026
1038
   recinfo->length=mi_uint2korr(ptr);   ptr +=2;
1030
1042
}
1031
1043
 
1032
1044
/**************************************************************************
1033
 
Open data file
 
1045
Open data file with or without RAID
1034
1046
We can't use dup() here as the data file descriptors need to have different
1035
1047
active seek-positions.
1036
1048
 
1038
1050
exist a dup()-like call that would give us two different file descriptors.
1039
1051
*************************************************************************/
1040
1052
 
1041
 
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, int file_to_dup)
 
1053
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share,
 
1054
                     File file_to_dup __attribute__((unused)))
1042
1055
{
1043
 
  (void)file_to_dup; 
1044
 
  info->dfile=internal::my_open(share->data_file_name, share->mode,
1045
 
                      MYF(MY_WME));
 
1056
    info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
 
1057
                        MYF(MY_WME));
1046
1058
  return info->dfile >= 0 ? 0 : 1;
1047
1059
}
1048
1060
 
1049
1061
 
1050
1062
int mi_open_keyfile(MYISAM_SHARE *share)
1051
1063
{
1052
 
  if ((share->kfile=internal::my_open(share->unique_file_name, share->mode,
 
1064
  if ((share->kfile=my_open(share->unique_file_name, share->mode | O_SHARE,
1053
1065
                            MYF(MY_WME))) < 0)
1054
1066
    return 1;
1055
1067
  return 0;