summaryrefslogtreecommitdiff
path: root/storage/maria/ma_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria/ma_open.c')
-rw-r--r--storage/maria/ma_open.c264
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;