diff options
Diffstat (limited to 'storage/maria/ma_open.c')
-rw-r--r-- | storage/maria/ma_open.c | 264 |
1 files changed, 196 insertions, 68 deletions
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 05aca8f37e1..c7080daa265 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -24,6 +24,7 @@ #include "ma_trnman.h" #include <m_ctype.h> #include "ma_crypt.h" +#include "s3_func.h" #if defined(MSDOS) || defined(__WIN__) #ifdef __WIN__ @@ -92,7 +93,8 @@ MARIA_HA *_ma_test_if_reopen(const char *filename) static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode, File data_file, - uint internal_table) + uint internal_table, + struct ms3_st *s3) { int save_errno; uint errpos; @@ -130,6 +132,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, goto err; errpos= 6; + info.s3= s3; memcpy(info.blobs,share->blobs,sizeof(MARIA_BLOB)*share->base.blobs); info.lastkey_buff2= info.lastkey_buff + share->base.max_key_length; info.last_key.data= info.lastkey_buff; @@ -238,6 +241,7 @@ err: case 6: (*share->end)(&info); delete_dynamic(&info.pinned_pages); + my_free(m_info->s3); my_free(m_info); /* fall through */ case 5: @@ -259,9 +263,10 @@ err: have an open count of 0. ******************************************************************************/ -MARIA_HA *maria_open(const char *name, int mode, uint open_flags) +MARIA_HA *maria_open(const char *name, int mode, uint open_flags, + S3_INFO *s3) { - int kfile,open_mode,save_errno; + int open_mode= 0,save_errno; uint i,j,len,errpos,head_length,base_pos,keys, realpath_err, key_parts,base_key_parts,unique_key_parts,fulltext_keys,uniques; uint internal_table= MY_TEST(open_flags & HA_OPEN_INTERNAL_TABLE); @@ -277,28 +282,49 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) my_off_t key_root[HA_MAX_POSSIBLE_KEY]; ulonglong max_key_file_length, max_data_file_length; my_bool versioning= 1; - File data_file= -1; + File data_file= -1, kfile= -1; + struct ms3_st *s3_client= 0; + S3_INFO *share_s3= 0; + S3_BLOCK index_header; DBUG_ENTER("maria_open"); - kfile= -1; errpos= 0; head_length=sizeof(share_buff.state.header); bzero((uchar*) &info,sizeof(info)); + bzero((uchar*) &index_header, sizeof(index_header)); - realpath_err= my_realpath(name_buff, fn_format(org_name, name, "", - MARIA_NAME_IEXT, - MY_UNPACK_FILENAME),MYF(0)); - if (realpath_err > 0) /* File not found, no point in looking further. */ +#ifndef WITH_S3_STORAGE_ENGINE + DBUG_ASSERT(!s3); +#endif /* WITH_S3_STORAGE_ENGINE */ + + if (!s3) { - DBUG_RETURN(NULL); - } + realpath_err= my_realpath(name_buff, fn_format(org_name, name, "", + MARIA_NAME_IEXT, + MY_UNPACK_FILENAME),MYF(0)); + if (realpath_err > 0) /* File not found, no point in looking further. */ + { + DBUG_RETURN(NULL); + } - if (my_is_symlink(org_name) && - (realpath_err || mysys_test_invalid_symlink(name_buff))) + if (my_is_symlink(org_name) && + (realpath_err || mysys_test_invalid_symlink(name_buff))) + { + my_errno= HA_WRONG_CREATE_OPTION; + DBUG_RETURN(0); + } + } +#ifdef WITH_S3_STORAGE_ENGINE + else { - my_errno= HA_WRONG_CREATE_OPTION; - DBUG_RETURN(0); + strmake(name_buff, name, sizeof(name_buff)-1); /* test_if_reopen() */ + if (!(s3_client= s3_open_connection(s3))) + { + internal_table= 1; /* Avoid unlock on error */ + goto err; + } } +#endif /* WITH_S3_STORAGE_ENGINE */ old_info= 0; if (!internal_table) @@ -313,32 +339,70 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) (uint) strlen(name_buff), maria_pagecache); - DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_open", - if (strstr(name, "/t1")) - { - my_errno= HA_ERR_CRASHED; - goto err; - }); - DEBUG_SYNC_C("mi_open_kfile"); - if ((kfile=mysql_file_open(key_file_kfile, name_buff, - (open_mode=O_RDWR) | O_SHARE | O_NOFOLLOW | O_CLOEXEC, - MYF(MY_NOSYMLINKS))) < 0) + if (!s3) { - if ((errno != EROFS && errno != EACCES) || - mode != O_RDONLY || - (kfile=mysql_file_open(key_file_kfile, name_buff, - (open_mode=O_RDONLY) | O_SHARE | O_NOFOLLOW | O_CLOEXEC, + DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_open", + if (strstr(name, "/t1")) + { + my_errno= HA_ERR_CRASHED; + goto err; + }); + DEBUG_SYNC_C("mi_open_kfile"); + if ((kfile=mysql_file_open(key_file_kfile, name_buff, + (open_mode=O_RDWR) | O_SHARE | O_NOFOLLOW | O_CLOEXEC, MYF(MY_NOSYMLINKS))) < 0) - goto err; + { + if ((errno != EROFS && errno != EACCES) || + mode != O_RDONLY || + (kfile=mysql_file_open(key_file_kfile, name_buff, + (open_mode=O_RDONLY) | O_SHARE | O_NOFOLLOW | O_CLOEXEC, + MYF(MY_NOSYMLINKS))) < 0) + goto err; + } + errpos= 1; + if (mysql_file_pread(kfile,share->state.header.file_version, head_length, + 0, MYF(MY_NABP))) + { + my_errno= HA_ERR_NOT_A_TABLE; + goto err; + } } - share->mode=open_mode; - errpos= 1; - if (mysql_file_pread(kfile,share->state.header.file_version, head_length, - 0, MYF(MY_NABP))) +#ifdef WITH_S3_STORAGE_ENGINE + else { - my_errno= HA_ERR_NOT_A_TABLE; - goto err; + errpos= 1; + if (set_database_and_table_from_path(s3, name_buff)) + { + my_printf_error(HA_ERR_NO_SUCH_TABLE, + "Can't find database and path from %s", MYF(0), + name_buff); + my_errno= HA_ERR_NO_SUCH_TABLE; + goto err; + } + if (!(share_s3= share->s3_path= s3_info_copy(s3))) + goto err; /* EiOM */ + + /* Check if table has changed in S3 */ + if (s3_check_frm_version(s3_client, share_s3) == 1) + { + my_errno= HA_ERR_TABLE_DEF_CHANGED; + goto err; + } + + if (read_index_header(s3_client, share_s3, &index_header)) + goto err; + if (index_header.length < head_length) + { + my_errno=HA_ERR_NOT_A_TABLE; + goto err; + } + memcpy(share->state.header.file_version, index_header.str, + head_length); + kfile= s3_unique_file_number(); } +#endif /* WITH_S3_STORAGE_ENGINE */ + + share->mode=open_mode; if (memcmp(share->state.header.file_version, maria_file_magic, 4)) { DBUG_PRINT("error",("Wrong header in %s",name_buff)); @@ -367,23 +431,31 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) my_errno= HA_ERR_UNSUPPORTED; goto err; } - /* Don't call realpath() if the name can't be a link */ - if (!strcmp(name_buff, org_name) || - my_readlink(index_name, org_name, MYF(0)) == -1) - (void) strmov(index_name, org_name); - *strrchr(org_name, FN_EXTCHAR)= '\0'; - (void) fn_format(data_name,org_name,"",MARIA_NAME_DEXT, - MY_APPEND_EXT|MY_UNPACK_FILENAME); - if (my_is_symlink(data_name)) + if (!s3) { - if (my_realpath(data_name, data_name, MYF(0))) - goto err; - if (mysys_test_invalid_symlink(data_name)) + /* Don't call realpath() if the name can't be a link */ + if (!strcmp(name_buff, org_name) || + my_readlink(index_name, org_name, MYF(0)) == -1) + (void) strmov(index_name, org_name); + *strrchr(org_name, FN_EXTCHAR)= '\0'; + (void) fn_format(data_name,org_name,"",MARIA_NAME_DEXT, + MY_APPEND_EXT|MY_UNPACK_FILENAME); + if (my_is_symlink(data_name)) { - my_errno= HA_WRONG_CREATE_OPTION; - goto err; + if (my_realpath(data_name, data_name, MYF(0))) + goto err; + if (mysys_test_invalid_symlink(data_name)) + { + my_errno= HA_WRONG_CREATE_OPTION; + goto err; + } + share->mode|= O_NOFOLLOW; /* all symlinks are resolved by realpath() */ } - share->mode|= O_NOFOLLOW; /* all symlinks are resolved by realpath() */ + } + else + { + /* Don't show DIRECTORY in show create table */ + index_name[0]= data_name[0]= 0; } info_length=mi_uint2korr(share->state.header.header_length); @@ -401,11 +473,26 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) end_pos=disk_cache+info_length; errpos= 3; - if (mysql_file_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP))) + if (!s3) { - _ma_set_fatal_error(share, HA_ERR_CRASHED); - goto err; + if (mysql_file_pread(kfile, disk_cache, info_length, 0L, MYF(MY_NABP))) + { + _ma_set_fatal_error(share, HA_ERR_CRASHED); + goto err; + } + } +#ifdef WITH_S3_STORAGE_ENGINE + else + { + if (index_header.length < info_length) + { + my_errno=HA_ERR_NOT_A_TABLE; + goto err; + } + memcpy(disk_cache, index_header.str, info_length); } +#endif /* WITH_S3_STORAGE_ENGINE */ + len=mi_uint2korr(share->state.header.state_info_length); keys= (uint) share->state.header.keys; uniques= (uint) share->state.header.uniques; @@ -436,7 +523,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) file_version= (share->state.header.not_used == 0); if (file_version == 0) share->base.language= share->state.header.not_used; - + share->state.state_length=base_pos; /* For newly opened tables we reset the error-has-been-printed flag */ share->state.changed&= ~STATE_CRASHED_PRINTED; @@ -463,7 +550,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) - share->state.create_trid > trnman_get_max_trid() - Critical as trid as stored releative to create_trid. - uuid is different - + STATE_NOT_MOVABLE is reset when a table is zerofilled (has no LSN's and no trids) @@ -527,7 +614,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) my_errno=HA_ERR_UNSUPPORTED; my_printf_error(my_errno, "Wrong block size %u; Expected %u", MYF(0), - (uint) share->base.block_size, + (uint) share->base.block_size, (uint) maria_block_size); goto err; } @@ -629,6 +716,12 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) disk_pos=_ma_keydef_read(disk_pos, keyinfo); keyinfo->key_nr= i; + /* Calculate length to store a key + nod flag and transaction info */ + keyinfo->max_store_length= (keyinfo->maxlength + + share->base.key_reflength); + if (share->base.born_transactional) + keyinfo->max_store_length+= MARIA_INDEX_OVERHEAD_SIZE; + /* See ma_delete.cc::underflow() */ if (!(keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY))) keyinfo->underflow_block_length= keyinfo->block_length/3; @@ -871,9 +964,16 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if ((share->data_file_type == BLOCK_RECORD || share->data_file_type == COMPRESSED_RECORD)) { - if (_ma_open_datafile(&info, share)) - goto err; - data_file= info.dfile.file; + if (!s3) + { + if (_ma_open_datafile(&info, share)) + goto err; + data_file= info.dfile.file; + } +#ifdef WITH_S3_STORAGE_ENGINE + else + data_file= info.dfile.file= s3_unique_file_number(); +#endif /* WITH_S3_STORAGE_ENGINE */ } errpos= 5; @@ -915,6 +1015,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) max_data_file_length= share->base.max_data_file_length; if ((*share->once_init)(share, info.dfile.file)) goto err; + errpos= 6; if (internal_table) set_if_smaller(share->base.max_data_file_length, max_data_file_length); @@ -1043,6 +1144,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) info.s= share; maria_extra(&info, HA_EXTRA_MMAP, 0); } +#ifdef WITH_S3_STORAGE_ENGINE + if (s3_client) + { + size_t block_size= share->base.s3_block_size; + ms3_set_option(s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size); + } +#endif /* WITH_S3_STORAGE_ENGINE */ } else { @@ -1051,8 +1159,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) data_file= share->bitmap.file.file; /* Only opened once */ } +#ifdef WITH_S3_STORAGE_ENGINE + if (index_header.alloc_ptr) + s3_free(&index_header); +#endif /* WITH_S3_STORAGE_ENGINE */ + if (!(m_info= maria_clone_internal(share, mode, data_file, - internal_table))) + internal_table, s3_client))) goto err; if (maria_is_crashed(m_info)) @@ -1063,6 +1176,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) mysql_mutex_unlock(&THR_LOCK_maria); m_info->open_flags= open_flags; + m_info->stack_end_ptr= &my_thread_var->stack_ends_here; DBUG_PRINT("exit", ("table: %p name: %s",m_info, name)); DBUG_RETURN(m_info); @@ -1079,12 +1193,16 @@ err: _ma_report_error(save_errno, &tmp_name); } switch (errpos) { + case 6: + /* Avoid mutex test in _ma_bitmap_end() */ + share->internal_table= 1; + (*share->once_end)(share); + /* fall through */ case 5: - if (data_file >= 0) + if (data_file >= 0 && !s3_client) mysql_file_close(data_file, MYF(0)); if (old_info) break; /* Don't remove open table */ - (*share->once_end)(share); /* fall through */ case 4: ma_crypt_free(share); @@ -1095,12 +1213,20 @@ err: my_free(share_buff.state.rec_per_key_part); /* fall through */ case 1: - mysql_file_close(kfile,MYF(0)); + if (!s3) + mysql_file_close(kfile,MYF(0)); + my_free(share_s3); /* fall through */ case 0: default: break; } +#ifdef WITH_S3_STORAGE_ENGINE + if (s3_client) + ms3_deinit(s3_client); + if (index_header.alloc_ptr) + s3_free(&index_header); +#endif /* WITH_S3_STORAGE_ENGINE */ if (!internal_table) mysql_mutex_unlock(&THR_LOCK_maria); my_errno= save_errno; @@ -1634,14 +1760,15 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base) *ptr++= base->keys; *ptr++= base->auto_key; *ptr++= base->born_transactional; - *ptr++= 0; /* Reserved */ + *ptr++= base->compression_algorithm; mi_int2store(ptr,base->pack_bytes); ptr+= 2; mi_int2store(ptr,base->blobs); ptr+= 2; mi_int2store(ptr,base->max_key_block_length); ptr+= 2; mi_int2store(ptr,base->max_key_length); ptr+= 2; mi_int2store(ptr,base->extra_alloc_bytes); ptr+= 2; *ptr++= base->extra_alloc_procent; - bzero(ptr,16); ptr+= 16; /* extra */ + mi_int3store(ptr, base->s3_block_size); ptr+= 3; + bzero(ptr,13); ptr+= 13; /* extra */ DBUG_ASSERT((ptr - buff) == MARIA_BASE_INFO_SIZE); return mysql_file_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0; } @@ -1678,14 +1805,15 @@ static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) base->keys= *ptr++; base->auto_key= *ptr++; base->born_transactional= *ptr++; - ptr++; + base->compression_algorithm= *ptr++; base->pack_bytes= mi_uint2korr(ptr); ptr+= 2; base->blobs= mi_uint2korr(ptr); ptr+= 2; base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2; base->max_key_length= mi_uint2korr(ptr); ptr+= 2; base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2; base->extra_alloc_procent= *ptr++; - ptr+= 16; + base->s3_block_size= mi_uint3korr(ptr); ptr+= 3; + ptr+= 13; return ptr; } @@ -1836,7 +1964,7 @@ uchar *_ma_columndef_read(uchar *ptr, MARIA_COLUMNDEF *columndef) columndef->empty_pos= mi_uint2korr(ptr); ptr+= 2; columndef->null_bit= (uint8) *ptr++; columndef->empty_bit= (uint8) *ptr++; - high_offset= mi_uint2korr(ptr); ptr+= 2; + high_offset= mi_uint2korr(ptr); ptr+= 2; columndef->offset|= ((ulong) high_offset << 16); ptr+= 2; return ptr; |