Merge branch 'merge-innodb-5.6' into 10.0

This commit is contained in:
Sergei Golubchik 2016-02-16 18:32:59 +01:00
commit c8fcaf8aec
22 changed files with 705 additions and 158 deletions

View file

@ -505,6 +505,71 @@ ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_trx_read_only
};
/**
Test a file path whether it is same as mysql data directory path.
@param path null terminated character string
@return
@retval TRUE The path is different from mysql data directory.
@retval FALSE The path is same as mysql data directory.
*/
static bool is_mysql_datadir_path(const char *path)
{
if (path == NULL)
return false;
char mysql_data_dir[FN_REFLEN], path_dir[FN_REFLEN];
convert_dirname(path_dir, path, NullS);
convert_dirname(mysql_data_dir, mysql_unpacked_real_data_home, NullS);
size_t mysql_data_home_len= dirname_length(mysql_data_dir);
size_t path_len = dirname_length(path_dir);
if (path_len < mysql_data_home_len)
return true;
if (!lower_case_file_system)
return(memcmp(mysql_data_dir, path_dir, mysql_data_home_len));
return(files_charset_info->coll->strnncoll(files_charset_info,
(uchar *) path_dir, path_len,
(uchar *) mysql_data_dir,
mysql_data_home_len,
TRUE));
}
static int mysql_tmpfile_path(const char *path, const char *prefix)
{
DBUG_ASSERT(path != NULL);
DBUG_ASSERT((strlen(path) + strlen(prefix)) <= FN_REFLEN);
char filename[FN_REFLEN];
File fd = create_temp_file(filename, path, prefix,
#ifdef __WIN__
O_BINARY | O_TRUNC | O_SEQUENTIAL |
O_SHORT_LIVED |
#endif /* __WIN__ */
O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
MYF(MY_WME));
if (fd >= 0) {
#ifndef __WIN__
/*
This can be removed once the following bug is fixed:
Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
(file not removed) (Unix)
*/
unlink(filename);
#endif /* !__WIN__ */
}
return fd;
}
/*************************************************************//**
Check whether valid argument given to innodb_ft_*_stopword_table.
This function is registered as a callback with MySQL.
@ -520,6 +585,108 @@ innodb_stopword_table_validate(
for update function */
struct st_mysql_value* value); /*!< in: incoming string */
/** Validate passed-in "value" is a valid directory name.
This function is registered as a callback with MySQL.
@param[in,out] thd thread handle
@param[in] var pointer to system variable
@param[out] save immediate result for update
@param[in] value incoming string
@return 0 for valid name */
static
int
innodb_tmpdir_validate(
THD* thd,
struct st_mysql_sys_var* var,
void* save,
struct st_mysql_value* value)
{
char* alter_tmp_dir;
char* innodb_tmp_dir;
char buff[OS_FILE_MAX_PATH];
int len = sizeof(buff);
char tmp_abs_path[FN_REFLEN + 2];
ut_ad(save != NULL);
ut_ad(value != NULL);
if (check_global_access(thd, FILE_ACL)) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: FILE Permissions required");
*static_cast<const char**>(save) = NULL;
return(1);
}
alter_tmp_dir = (char*) value->val_str(value, buff, &len);
if (!alter_tmp_dir) {
*static_cast<const char**>(save) = alter_tmp_dir;
return(0);
}
if (strlen(alter_tmp_dir) > FN_REFLEN) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"Path length should not exceed %d bytes", FN_REFLEN);
*static_cast<const char**>(save) = NULL;
return(1);
}
my_realpath(tmp_abs_path, alter_tmp_dir, 0);
size_t tmp_abs_len = strlen(tmp_abs_path);
if (my_access(tmp_abs_path, F_OK)) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: Path doesn't exist.");
*static_cast<const char**>(save) = NULL;
return(1);
} else if (my_access(tmp_abs_path, R_OK | W_OK)) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: Server doesn't have permission in "
"the given location.");
*static_cast<const char**>(save) = NULL;
return(1);
}
MY_STAT stat_info_dir;
if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) {
if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"Given path is not a directory. ");
*static_cast<const char**>(save) = NULL;
return(1);
}
}
if (!is_mysql_datadir_path(tmp_abs_path)) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: Path Location should not be same as "
"mysql data directory location.");
*static_cast<const char**>(save) = NULL;
return(1);
}
innodb_tmp_dir = static_cast<char*>(
thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1));
*static_cast<const char**>(save) = innodb_tmp_dir;
return(0);
}
/** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
system clustered index when there is no primary key. */
const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
@ -572,6 +739,11 @@ static MYSQL_THDVAR_STR(ft_user_stopword_table,
"User supplied stopword table name, effective in the session level.",
innodb_stopword_table_validate, NULL, NULL);
static MYSQL_THDVAR_STR(tmpdir,
PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC,
"Directory for temporary non-tablespace files.",
innodb_tmpdir_validate, NULL, NULL);
static SHOW_VAR innodb_status_variables[]= {
{"buffer_pool_dump_status",
(char*) &export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR},
@ -1306,6 +1478,26 @@ thd_supports_xa(
return(THDVAR(thd, support_xa));
}
/** Get the value of innodb_tmpdir.
@param[in] thd thread handle, or NULL to query
the global innodb_tmpdir.
@retval NULL if innodb_tmpdir="" */
UNIV_INTERN
const char*
thd_innodb_tmpdir(
THD* thd)
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(false));
#endif /* UNIV_SYNC_DEBUG */
const char* tmp_dir = THDVAR(thd, tmpdir);
if (tmp_dir != NULL && *tmp_dir == '\0') {
tmp_dir = NULL;
}
return(tmp_dir);
}
/******************************************************************//**
Returns the lock wait timeout for the current connection.
@return the lock wait timeout, in seconds */
@ -1833,13 +2025,14 @@ innobase_get_lower_case_table_names(void)
return(lower_case_table_names);
}
/*********************************************************************//**
Creates a temporary file.
/** Create a temporary file in the location specified by the parameter
path. If the path is null, then it will be created in tmpdir.
@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
UNIV_INTERN
int
innobase_mysql_tmpfile(void)
/*========================*/
innobase_mysql_tmpfile(
const char* path)
{
int fd2 = -1;
File fd;
@ -1849,7 +2042,11 @@ innobase_mysql_tmpfile(void)
return(-1);
);
fd = mysql_tmpfile("ib");
if (path == NULL) {
fd = mysql_tmpfile("ib");
} else {
fd = mysql_tmpfile_path(path, "ib");
}
if (fd >= 0) {
/* Copy the file descriptor, so that the additional resources
@ -2776,6 +2973,13 @@ ha_innobase::reset_template(void)
ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
ut_ad(prebuilt->magic_n2 == prebuilt->magic_n);
/* Force table to be freed in close_thread_table(). */
DBUG_EXECUTE_IF("free_table_in_fts_query",
if (prebuilt->in_fts_query) {
table->m_needs_reopen = true;
}
);
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
prebuilt->in_fts_query = 0;
@ -15774,15 +15978,12 @@ innobase_fts_close_ranking(
{
fts_result_t* result;
((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false;
result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
fts_query_free_result(result);
my_free((uchar*) fts_hdl);
return;
}
@ -17103,6 +17304,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(sync_array_size),
MYSQL_SYSVAR(compression_failure_threshold_pct),
MYSQL_SYSVAR(compression_pad_pct_max),
MYSQL_SYSVAR(simulate_comp_failures),
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(trx_rseg_n_slots_debug),
MYSQL_SYSVAR(limit_optimistic_insert_debug),
@ -17110,7 +17312,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(fil_make_page_dirty_debug),
MYSQL_SYSVAR(saved_page_number_debug),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(simulate_comp_failures),
MYSQL_SYSVAR(tmpdir),
NULL
};

View file

@ -2712,6 +2712,10 @@ prepare_inplace_alter_table_dict(
ctx->num_to_add_index = ha_alter_info->index_add_count;
ut_ad(ctx->prebuilt->trx->mysql_thd != NULL);
const char* path = thd_innodb_tmpdir(
ctx->prebuilt->trx->mysql_thd);
index_defs = innobase_create_key_defs(
ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index,
num_fts_index,
@ -3054,8 +3058,10 @@ prepare_inplace_alter_table_dict(
error = DB_OUT_OF_MEMORY;
goto error_handling;);
rw_lock_x_lock(&ctx->add_index[a]->lock);
bool ok = row_log_allocate(ctx->add_index[a],
NULL, true, NULL, NULL);
NULL, true, NULL,
NULL, path);
rw_lock_x_unlock(&ctx->add_index[a]->lock);
if (!ok) {
@ -3081,7 +3087,7 @@ prepare_inplace_alter_table_dict(
clust_index, ctx->new_table,
!(ha_alter_info->handler_flags
& Alter_inplace_info::ADD_PK_INDEX),
ctx->add_cols, ctx->col_map);
ctx->add_cols, ctx->col_map, path);
rw_lock_x_unlock(&clust_index->lock);
if (!ok) {
@ -4058,6 +4064,7 @@ ok_exit:
files and merge sort. */
DBUG_EXECUTE_IF("innodb_OOM_inplace_alter",
error = DB_OUT_OF_MEMORY; goto oom;);
error = row_merge_build_indexes(
prebuilt->trx,
prebuilt->table, ctx->new_table,