~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_open.c

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:59 UTC
  • mfrom: (518 drizzle)
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063259-fwbqogq7lnezct0l
Merged with trunk.

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