~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mi_open.cc

  • Committer: Mark Atwood
  • Date: 2011-12-28 02:50:31 UTC
  • Revision ID: me@mark.atwood.name-20111228025031-eh4h1zwv4ig88g0i
fix tests/r/basic.result

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