76
59
have an open count of 0.
77
60
******************************************************************************/
79
MI_INFO *mi_open(const drizzled::TableIdentifier &identifier, int mode, uint32_t open_flags)
62
MI_INFO *mi_open(const char *name, int mode, uint open_flags)
81
64
int lock_error,kfile,open_mode,save_errno,have_rtree=0;
82
uint32_t i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
65
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
83
66
key_parts,unique_key_parts,fulltext_keys,uniques;
84
67
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
85
data_name[FN_REFLEN], rp_buff[PATH_MAX];
86
unsigned char *disk_cache= NULL;
87
unsigned char *disk_pos, *end_pos;
69
uchar *disk_cache, *disk_pos, *end_pos;
88
70
MI_INFO info,*m_info,*old_info;
89
71
MYISAM_SHARE share_buff,*share;
90
72
ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG];
91
internal::my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
92
uint64_t max_key_file_length, max_data_file_length;
73
my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE];
74
ulonglong max_key_file_length, max_data_file_length;
75
DBUG_ENTER("mi_open");
97
80
head_length=sizeof(share_buff.state.header);
98
memset(&info, 0, sizeof(info));
81
bzero((uchar*) &info,sizeof(info));
100
(void)internal::fn_format(org_name,
101
identifier.getPath().c_str(),
105
if (!realpath(org_name,rp_buff))
106
internal::my_load_path(rp_buff,org_name, NULL);
107
rp_buff[FN_REFLEN-1]= '\0';
108
strcpy(name_buff,rp_buff);
109
THR_LOCK_myisam.lock();
83
my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
84
MY_UNPACK_FILENAME),MYF(0));
85
pthread_mutex_lock(&THR_LOCK_myisam);
110
86
if (!(old_info=test_if_reopen(name_buff)))
112
88
share= &share_buff;
113
memset(&share_buff, 0, sizeof(share_buff));
89
bzero((uchar*) &share_buff,sizeof(share_buff));
114
90
share_buff.state.rec_per_key_part=rec_per_key_part;
115
91
share_buff.state.key_root=key_root;
116
92
share_buff.state.key_del=key_del;
117
share_buff.setKeyCache();
93
share_buff.key_cache= multi_key_cache_search((uchar*) name_buff,
119
if ((kfile=internal::my_open(name_buff,(open_mode=O_RDWR),MYF(0))) < 0)
96
DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
97
if (strstr(name, "/t1"))
99
my_errno= HA_ERR_CRASHED;
102
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
121
104
if ((errno != EROFS && errno != EACCES) ||
122
105
mode != O_RDONLY ||
123
(kfile=internal::my_open(name_buff,(open_mode=O_RDONLY),MYF(0))) < 0)
106
(kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
126
109
share->mode=open_mode;
128
if (internal::my_read(kfile, share->state.header.file_version, head_length,
111
if (my_read(kfile, share->state.header.file_version, head_length,
131
errno= HA_ERR_NOT_A_TABLE;
114
my_errno= HA_ERR_NOT_A_TABLE;
134
if (memcmp(share->state.header.file_version, myisam_file_magic, 4))
117
if (memcmp((uchar*) share->state.header.file_version,
118
(uchar*) myisam_file_magic, 4))
136
errno=HA_ERR_NOT_A_TABLE;
120
DBUG_PRINT("error",("Wrong header in %s",name_buff));
121
DBUG_DUMP("error_dump",(uchar*) share->state.header.file_version,
123
my_errno=HA_ERR_NOT_A_TABLE;
139
126
share->options= mi_uint2korr(share->state.header.options);
140
127
if (share->options &
141
128
~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
142
129
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
143
HA_OPTION_TEMP_COMPRESS_RECORD |
147
errno=HA_ERR_OLD_FILE;
130
HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
131
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
132
HA_OPTION_RELIES_ON_SQL_LAYER))
134
DBUG_PRINT("error",("wrong options: 0x%lx", share->options));
135
my_errno=HA_ERR_OLD_FILE;
138
if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
139
! (open_flags & HA_OPEN_FROM_SQL_LAYER))
141
DBUG_PRINT("error", ("table cannot be openned from non-sql layer"));
142
my_errno= HA_ERR_UNSUPPORTED;
151
145
/* Don't call realpath() if the name can't be a link */
152
ssize_t sym_link_size= readlink(org_name,index_name,FN_REFLEN-1);
153
if (sym_link_size >= 0 )
154
index_name[sym_link_size]= '\0';
155
if (!strcmp(name_buff, org_name) || sym_link_size == -1)
156
(void) strcpy(index_name, org_name);
146
if (!strcmp(name_buff, org_name) ||
147
my_readlink(index_name, org_name, MYF(0)) == -1)
148
(void) strmov(index_name, org_name);
157
149
*strrchr(org_name, '.')= '\0';
158
(void) internal::fn_format(data_name,org_name,"",MI_NAME_DEXT,
150
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
159
151
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
161
153
info_length=mi_uint2korr(share->state.header.header_length);
162
154
base_pos=mi_uint2korr(share->state.header.base_pos);
163
if (!(disk_cache= (unsigned char*) malloc(info_length+128)))
155
if (!(disk_cache= (uchar*) my_alloca(info_length+128)))
168
160
end_pos=disk_cache+info_length;
171
lseek(kfile,0,SEEK_SET);
163
VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
164
if (!(open_flags & HA_OPEN_TMP_TABLE))
166
if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
167
MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ?
168
0 : MY_DONT_WAIT))) &&
169
!(open_flags & HA_OPEN_IGNORE_IF_LOCKED))
173
if (internal::my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
173
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
175
errno=HA_ERR_CRASHED;
175
my_errno=HA_ERR_CRASHED;
178
178
len=mi_uint2korr(share->state.header.state_info_length);
181
181
fulltext_keys= (uint) share->state.header.fulltext_keys;
182
182
key_parts= mi_uint2korr(share->state.header.key_parts);
183
183
unique_key_parts= mi_uint2korr(share->state.header.unique_key_parts);
184
if (len != MI_STATE_INFO_SIZE)
186
DBUG_PRINT("warning",
187
("saved_state_info_length: %d state_info_length: %d",
188
len,MI_STATE_INFO_SIZE));
184
190
share->state_diff_length=len-MI_STATE_INFO_SIZE;
186
192
mi_state_info_read(disk_cache, &share->state);
187
193
len= mi_uint2korr(share->state.header.base_info_length);
194
if (len != MI_BASE_INFO_SIZE)
196
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
197
len,MI_BASE_INFO_SIZE));
188
199
disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base);
189
200
share->state.state_length=base_pos;
191
if (share->state.changed & STATE_CRASHED)
202
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
203
((share->state.changed & STATE_CRASHED) ||
204
((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
205
(my_disable_locking && share->state.open_count))))
193
errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
207
DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u "
208
"changed: %u open_count: %u !locking: %d",
209
open_flags, share->state.changed,
210
share->state.open_count, my_disable_locking));
211
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
194
212
HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
198
216
/* sanity check */
199
217
if (share->base.keystart > 65535 || share->base.rec_reflength > 8)
201
errno=HA_ERR_CRASHED;
219
my_errno=HA_ERR_CRASHED;
205
223
if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY ||
206
224
key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG)
208
errno=HA_ERR_UNSUPPORTED;
226
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
227
my_errno=HA_ERR_UNSUPPORTED;
212
231
/* Correct max_file_length based on length of sizeof(off_t) */
213
232
max_data_file_length=
214
233
(share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
215
(((uint64_t) 1 << (share->base.rec_reflength*8))-1) :
234
(((ulonglong) 1 << (share->base.rec_reflength*8))-1) :
216
235
(mi_safe_mul(share->base.pack_reclength,
217
(uint64_t) 1 << (share->base.rec_reflength*8))-1);
236
(ulonglong) 1 << (share->base.rec_reflength*8))-1);
218
237
max_key_file_length=
219
238
mi_safe_mul(MI_MIN_KEY_BLOCK_LENGTH,
220
((uint64_t) 1 << (share->base.key_reflength*8))-1);
239
((ulonglong) 1 << (share->base.key_reflength*8))-1);
221
240
#if SIZEOF_OFF_T == 4
222
set_if_smaller(max_data_file_length, INT32_MAX);
223
set_if_smaller(max_key_file_length, INT32_MAX);
241
set_if_smaller(max_data_file_length, INT_MAX32);
242
set_if_smaller(max_key_file_length, INT_MAX32);
225
244
if (share->base.raid_type)
227
errno=HA_ERR_UNSUPPORTED;
246
DBUG_PRINT("error",("Table uses RAID but we don't have RAID support"));
247
my_errno=HA_ERR_UNSUPPORTED;
230
share->base.max_data_file_length=(internal::my_off_t) max_data_file_length;
231
share->base.max_key_file_length=(internal::my_off_t) max_key_file_length;
250
share->base.max_data_file_length=(my_off_t) max_data_file_length;
251
share->base.max_key_file_length=(my_off_t) max_key_file_length;
233
253
if (share->options & HA_OPTION_COMPRESS_RECORD)
234
254
share->base.max_key_length+=2; /* For safety */
236
256
/* Add space for node pointer */
237
257
share->base.max_key_length+= share->base.key_reflength;
239
if (!drizzled::memory::multi_malloc(false,
240
&share,sizeof(*share),
241
&share->state.rec_per_key_part,sizeof(long)*key_parts,
242
&share->keyinfo,keys*sizeof(MI_KEYDEF),
243
&share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
245
(key_parts+unique_key_parts+keys+uniques) * sizeof(HA_KEYSEG),
246
&share->rec, (share->base.fields+1)*sizeof(MI_COLUMNDEF),
247
&share->blobs,sizeof(MI_BLOB)*share->base.blobs,
248
&share->unique_file_name,strlen(name_buff)+1,
249
&share->index_file_name,strlen(index_name)+1,
250
&share->data_file_name,strlen(data_name)+1,
251
&share->state.key_root,keys*sizeof(uint64_t),
252
&share->state.key_del,
253
(share->state.header.max_block_size_index*sizeof(uint64_t)),
259
if (!my_multi_malloc(MY_WME,
260
&share,sizeof(*share),
261
&share->state.rec_per_key_part,sizeof(long)*key_parts,
262
&share->keyinfo,keys*sizeof(MI_KEYDEF),
263
&share->uniqueinfo,uniques*sizeof(MI_UNIQUEDEF),
265
(key_parts+unique_key_parts+keys+uniques) *
268
(share->base.fields+1)*sizeof(MI_COLUMNDEF),
269
&share->blobs,sizeof(MI_BLOB)*share->base.blobs,
270
&share->unique_file_name,strlen(name_buff)+1,
271
&share->index_file_name,strlen(index_name)+1,
272
&share->data_file_name,strlen(data_name)+1,
273
&share->state.key_root,keys*sizeof(my_off_t),
274
&share->state.key_del,
275
(share->state.header.max_block_size_index*sizeof(my_off_t)),
276
&share->key_root_lock,sizeof(rw_lock_t)*keys,
277
&share->mmap_lock,sizeof(rw_lock_t),
257
281
*share=share_buff;
258
memcpy(share->state.rec_per_key_part, rec_per_key_part,
259
sizeof(long)*key_parts);
260
memcpy(share->state.key_root, key_root,
261
sizeof(internal::my_off_t)*keys);
262
memcpy(share->state.key_del, key_del,
263
sizeof(internal::my_off_t) * share->state.header.max_block_size_index);
264
strcpy(share->unique_file_name, name_buff);
282
memcpy((char*) share->state.rec_per_key_part,
283
(char*) rec_per_key_part, sizeof(long)*key_parts);
284
memcpy((char*) share->state.key_root,
285
(char*) key_root, sizeof(my_off_t)*keys);
286
memcpy((char*) share->state.key_del,
287
(char*) key_del, (sizeof(my_off_t) *
288
share->state.header.max_block_size_index));
289
strmov(share->unique_file_name, name_buff);
265
290
share->unique_name_length= strlen(name_buff);
266
strcpy(share->index_file_name, index_name);
267
strcpy(share->data_file_name, data_name);
291
strmov(share->index_file_name, index_name);
292
strmov(share->data_file_name, data_name);
269
share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
294
share->blocksize=min(IO_SIZE,myisam_block_size);
271
296
HA_KEYSEG *pos=share->keyparts;
272
297
for (i=0 ; i < keys ; i++)
383
411
share->base.margin_key_file_length=(share->base.max_key_file_length -
384
412
(keys ? MI_INDEX_BLOCK_MARGIN *
385
413
share->blocksize * keys : 0));
386
share->blocksize=min((uint32_t)IO_SIZE,myisam_block_size);
414
share->blocksize=min(IO_SIZE,myisam_block_size);
387
415
share->data_file_type=STATIC_RECORD;
388
if (share->options & HA_OPTION_PACK_RECORD)
416
if (share->options & HA_OPTION_COMPRESS_RECORD)
418
share->data_file_type = COMPRESSED_RECORD;
419
share->options|= HA_OPTION_READ_ONLY_DATA;
421
if (_mi_read_pack_info(&info,
423
test(!(share->options &
424
(HA_OPTION_PACK_RECORD |
425
HA_OPTION_TEMP_COMPRESS_RECORD)))))
428
else if (share->options & HA_OPTION_PACK_RECORD)
389
429
share->data_file_type = DYNAMIC_RECORD;
430
my_afree(disk_cache);
392
431
mi_setup_functions(share);
393
share->is_log_table= false;
394
if (myisam_concurrent_insert)
432
share->is_log_table= FALSE;
433
thr_lock_init(&share->lock);
434
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
435
for (i=0; i<keys; i++)
436
VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
437
VOID(my_rwlock_init(&share->mmap_lock, NULL));
438
if (!thr_lock_inited)
440
/* Probably a single threaded program; Don't use concurrent inserts */
441
myisam_concurrent_insert=0;
443
else if (myisam_concurrent_insert)
396
445
share->concurrent_insert=
397
446
((share->options & (HA_OPTION_READ_ONLY_DATA | HA_OPTION_TMP_TABLE |
421
482
/* alloc and set up private structure parts */
422
if (!drizzled::memory::multi_malloc(MY_WME,
423
&m_info,sizeof(MI_INFO),
424
&info.blobs,sizeof(MI_BLOB)*share->base.blobs,
425
&info.buff,(share->base.max_key_block_length*2+
426
share->base.max_key_length),
427
&info.lastkey,share->base.max_key_length*3+1,
428
&info.first_mbr_key, share->base.max_key_length,
429
&info.filename, identifier.getPath().length()+1,
430
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
483
if (!my_multi_malloc(MY_WME,
484
&m_info,sizeof(MI_INFO),
485
&info.blobs,sizeof(MI_BLOB)*share->base.blobs,
486
&info.buff,(share->base.max_key_block_length*2+
487
share->base.max_key_length),
488
&info.lastkey,share->base.max_key_length*3+1,
489
&info.first_mbr_key, share->base.max_key_length,
490
&info.filename,strlen(name)+1,
491
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
436
497
info.rtree_recursion_state= NULL;
438
strcpy(info.filename, identifier.getPath().c_str());
499
strmov(info.filename,name);
439
500
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
440
501
info.lastkey2=info.lastkey+share->base.max_key_length;
471
533
share->temporary=share->delay_key_write=1;
472
534
share->write_flag=MYF(MY_NABP);
474
* The following two statements are commented out as a fix of
475
* bug https://bugs.launchpad.net/drizzle/+bug/387627
477
* UPDATE can be TRUNCATE on TEMPORARY TABLE (MyISAM).
478
* The root cause of why this makes a difference hasn't
479
* been found, but this fixes things for now.
481
// share->w_locks++; // We don't have to update status
482
// share->tot_locks++;
535
share->w_locks++; /* We don't have to update status */
483
537
info.lock_type=F_WRLCK;
486
share->delay_key_write= 1;
539
if (((open_flags & HA_OPEN_DELAY_KEY_WRITE) ||
540
(share->options & HA_OPTION_DELAY_KEY_WRITE)) &&
541
myisam_delay_key_write)
542
share->delay_key_write=1;
487
543
info.state= &share->state.state; /* Change global values by default */
544
pthread_mutex_unlock(&share->intern_lock);
489
546
/* Allocate buffer for one record */
491
/* prerequisites: memset(info, 0) && info->s=share; are met. */
548
/* prerequisites: bzero(info) && info->s=share; are met. */
492
549
if (!mi_alloc_rec_buff(&info, -1, &info.rec_buff))
494
memset(info.rec_buff, 0, mi_get_rec_buff_len(&info, info.rec_buff));
551
bzero(info.rec_buff, mi_get_rec_buff_len(&info, info.rec_buff));
497
myisam_open_list.push_front(m_info);
554
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
555
m_info->open_list.data=(void*) m_info;
556
myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
499
THR_LOCK_myisam.unlock();
558
pthread_mutex_unlock(&THR_LOCK_myisam);
559
if (myisam_log_file >= 0)
561
intern_filename(name_buff,share->index_file_name);
562
_myisam_log(MI_LOG_OPEN, m_info, (uchar*) name_buff, strlen(name_buff));
503
if (disk_cache != NULL)
505
save_errno=errno ? errno : HA_ERR_END_OF_FILE;
567
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
506
568
if ((save_errno == HA_ERR_CRASHED) ||
507
569
(save_errno == HA_ERR_CRASHED_ON_USAGE) ||
508
570
(save_errno == HA_ERR_CRASHED_ON_REPAIR))
509
mi_report_error(save_errno, identifier.getPath().c_str());
571
mi_report_error(save_errno, name);
510
572
switch (errpos) {
512
free((unsigned char*) m_info);
574
my_free((uchar*) m_info,MYF(0));
513
575
/* fall through */
515
internal::my_close(info.dfile,MYF(0));
577
VOID(my_close(info.dfile,MYF(0)));
517
579
break; /* Don't remove open table */
518
580
/* fall through */
520
free((unsigned char*) share);
582
my_free((uchar*) share,MYF(0));
521
583
/* fall through */
586
VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
589
my_afree(disk_cache);
523
590
/* fall through */
525
internal::my_close(kfile,MYF(0));
592
VOID(my_close(kfile,MYF(0)));
526
593
/* fall through */
531
THR_LOCK_myisam.unlock();
598
pthread_mutex_unlock(&THR_LOCK_myisam);
537
unsigned char *mi_alloc_rec_buff(MI_INFO *info, size_t length, unsigned char **buf)
604
uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf)
540
uint32_t old_length= 0;
607
uint32 old_length= 0;
542
609
if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf)))
544
unsigned char *newptr = *buf;
611
uchar *newptr = *buf;
546
613
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
547
614
if (length == (ulong) -1)
1002
1088
** MI_COLUMNDEF
1003
1089
***************************************************************************/
1005
uint32_t mi_recinfo_write(int file, MI_COLUMNDEF *recinfo)
1091
uint mi_recinfo_write(File file, MI_COLUMNDEF *recinfo)
1007
unsigned char buff[MI_COLUMNDEF_SIZE];
1008
unsigned char *ptr=buff;
1093
uchar buff[MI_COLUMNDEF_SIZE];
1010
1096
mi_int2store(ptr,recinfo->type); ptr +=2;
1011
1097
mi_int2store(ptr,recinfo->length); ptr +=2;
1012
1098
*ptr++ = recinfo->null_bit;
1013
1099
mi_int2store(ptr,recinfo->null_pos); ptr+= 2;
1014
return internal::my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1100
return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
1017
static unsigned char *mi_recinfo_read(unsigned char *ptr, MI_COLUMNDEF *recinfo)
1103
uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo)
1019
1105
recinfo->type= mi_sint2korr(ptr); ptr +=2;
1020
1106
recinfo->length=mi_uint2korr(ptr); ptr +=2;
1021
recinfo->null_bit= (uint8_t) *ptr++;
1107
recinfo->null_bit= (uint8) *ptr++;
1022
1108
recinfo->null_pos=mi_uint2korr(ptr); ptr +=2;
1026
1112
/**************************************************************************
1113
Open data file with or without RAID
1028
1114
We can't use dup() here as the data file descriptors need to have different
1029
1115
active seek-positions.