~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_open.c

  • Committer: Lee
  • Date: 2008-10-07 17:11:23 UTC
  • mto: (489.1.1 codestyle)
  • mto: This revision was merged to the branch mainline in revision 491.
  • Revision ID: lbieber@lbieber-desktop-20081007171123-s6ex14jq8jfuql8e
breakĀ outĀ Field_longstr

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