mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Merge branch 'merge-innodb-5.6' into 10.0
This commit is contained in:
commit
c8fcaf8aec
22 changed files with 705 additions and 158 deletions
51
mysql-test/suite/innodb/r/tmpdir.result
Normal file
51
mysql-test/suite/innodb/r/tmpdir.result
Normal file
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# Bug #19183565 CREATE DYNAMIC INNODB_TMPDIR VARIABLE TO CONTROL
|
||||
# WHERE INNODB WRITES TEMP FILES
|
||||
#
|
||||
# If innodb_tmpdir is NULL or "", temporary file will be created in
|
||||
# server configuration variable location(--tmpdir)
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
show session variables like 'innodb_tmpdir';
|
||||
Variable_name Value
|
||||
innodb_tmpdir
|
||||
alter table t1 add column b int not null;
|
||||
set global innodb_tmpdir=NULL;
|
||||
# Connection con1
|
||||
show session variables like 'innodb_tmpdir';
|
||||
Variable_name Value
|
||||
innodb_tmpdir
|
||||
alter table t1 add key(b);
|
||||
drop table t1;
|
||||
# innodb_tmpdir with invalid path.
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
set global innodb_tmpdir='wrong_value';
|
||||
ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'wrong_value'
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Warning 1210 InnoDB: Path doesn't exist.
|
||||
Error 1231 Variable 'innodb_tmpdir' can't be set to the value of 'wrong_value'
|
||||
drop table t1;
|
||||
# innodb_tmpdir with mysql data directory path.
|
||||
create table t1(a text, b text, fulltext(a,b))engine=innodb;
|
||||
insert into t1 values('test1', 'test2');
|
||||
insert into t1 values('text1', 'text2');
|
||||
set global innodb_tmpdir = @@global.datadir;
|
||||
ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'MYSQL_DATADIR'
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Warning 1210 InnoDB: Path Location should not be same as mysql data directory location.
|
||||
Error 1231 DATADIR/data/'
|
||||
drop table t1;
|
||||
# innodb_tmpdir with valid location.
|
||||
create table t1(a text, b text, fulltext(a,b))engine=innodb;
|
||||
insert into t1 values('test1', 'test2');
|
||||
insert into t1 values('text1', 'text2');
|
||||
set @tmpdir = @@global.tmpdir;
|
||||
set global innodb_tmpdir = @tmpdir;
|
||||
show session variables like 'innodb_tmpdir';
|
||||
Variable_name Value
|
||||
innodb_tmpdir
|
||||
# Connection con3
|
||||
alter table t1 add fulltext(b);
|
||||
set global innodb_tmpdir=NULL;
|
||||
drop table t1;
|
68
mysql-test/suite/innodb/t/tmpdir.test
Normal file
68
mysql-test/suite/innodb/t/tmpdir.test
Normal file
|
@ -0,0 +1,68 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/count_sessions.inc
|
||||
|
||||
if (`select plugin_auth_version <= "5.6.26-MariaDB-76.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB as of 5.6.26-MariaDB-76.0 or earlier
|
||||
}
|
||||
|
||||
--echo #
|
||||
--echo # Bug #19183565 CREATE DYNAMIC INNODB_TMPDIR VARIABLE TO CONTROL
|
||||
--echo # WHERE INNODB WRITES TEMP FILES
|
||||
--echo #
|
||||
|
||||
--echo # If innodb_tmpdir is NULL or "", temporary file will be created in
|
||||
--echo # server configuration variable location(--tmpdir)
|
||||
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
show session variables like 'innodb_tmpdir';
|
||||
alter table t1 add column b int not null;
|
||||
set global innodb_tmpdir=NULL;
|
||||
--echo # Connection con1
|
||||
connect (con1,localhost,root);
|
||||
show session variables like 'innodb_tmpdir';
|
||||
alter table t1 add key(b);
|
||||
connection default;
|
||||
disconnect con1;
|
||||
drop table t1;
|
||||
|
||||
--echo # innodb_tmpdir with invalid path.
|
||||
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
set global innodb_tmpdir='wrong_value';
|
||||
show warnings;
|
||||
drop table t1;
|
||||
|
||||
|
||||
--echo # innodb_tmpdir with mysql data directory path.
|
||||
|
||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
create table t1(a text, b text, fulltext(a,b))engine=innodb;
|
||||
insert into t1 values('test1', 'test2');
|
||||
insert into t1 values('text1', 'text2');
|
||||
--replace_result $MYSQLD_DATADIR MYSQL_DATADIR
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
set global innodb_tmpdir = @@global.datadir;
|
||||
--replace_regex /.*mysqld.1/DATADIR/
|
||||
show warnings;
|
||||
drop table t1;
|
||||
|
||||
--echo # innodb_tmpdir with valid location.
|
||||
let $MYSQL_TMP_DIR= `select @@tmpdir`;
|
||||
create table t1(a text, b text, fulltext(a,b))engine=innodb;
|
||||
insert into t1 values('test1', 'test2');
|
||||
insert into t1 values('text1', 'text2');
|
||||
set @tmpdir = @@global.tmpdir;
|
||||
set global innodb_tmpdir = @tmpdir;
|
||||
show session variables like 'innodb_tmpdir';
|
||||
--echo # Connection con3
|
||||
connect (con3,localhost,root);
|
||||
# Following alter using innodb_tmpdir as a path to create temporary files
|
||||
alter table t1 add fulltext(b);
|
||||
disconnect con3;
|
||||
connection default;
|
||||
set global innodb_tmpdir=NULL;
|
||||
drop table t1;
|
||||
|
||||
--source include/wait_until_count_sessions.inc
|
35
mysql-test/suite/sys_vars/r/innodb_tmpdir_basic.result
Normal file
35
mysql-test/suite/sys_vars/r/innodb_tmpdir_basic.result
Normal file
|
@ -0,0 +1,35 @@
|
|||
SET @start_global_value = @@global.innodb_tmpdir;
|
||||
SELECT @start_global_value;
|
||||
@start_global_value
|
||||
NULL
|
||||
select @@session.innodb_tmpdir;
|
||||
@@session.innodb_tmpdir
|
||||
NULL
|
||||
show global variables like 'innodb_tmpdir';
|
||||
Variable_name Value
|
||||
innodb_tmpdir
|
||||
show session variables like 'innodb_tmpdir';
|
||||
Variable_name Value
|
||||
innodb_tmpdir
|
||||
select * from information_schema.global_variables where variable_name='innodb_tmpdir';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_TMPDIR
|
||||
select * from information_schema.session_variables where variable_name='innodb_tmpdir';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_TMPDIR
|
||||
set global innodb_tmpdir=@@global.tmpdir;
|
||||
set session innodb_tmpdir=@@global.tmpdir;
|
||||
set global innodb_tmpdir=1.1;
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_tmpdir'
|
||||
set global innodb_tmpdir=1e1;
|
||||
ERROR 42000: Incorrect argument type to variable 'innodb_tmpdir'
|
||||
set global innodb_tmpdir=repeat('a',1000);
|
||||
ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Warning 1210 Path length should not exceed 512 bytes
|
||||
Error 1231 Variable 'innodb_tmpdir' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
||||
SET @@global.innodb_tmpdir = @start_global_value;
|
||||
SELECT @@global.innodb_tmpdir;
|
||||
@@global.innodb_tmpdir
|
||||
NULL
|
48
mysql-test/suite/sys_vars/t/innodb_tmpdir_basic.test
Normal file
48
mysql-test/suite/sys_vars/t/innodb_tmpdir_basic.test
Normal file
|
@ -0,0 +1,48 @@
|
|||
--source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "5.6.26-MariaDB-76.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB as of 5.6.26-MariaDB-76.0 or earlier
|
||||
}
|
||||
|
||||
SET @start_global_value = @@global.innodb_tmpdir;
|
||||
SELECT @start_global_value;
|
||||
|
||||
#
|
||||
# exists as global and session
|
||||
#
|
||||
select @@session.innodb_tmpdir;
|
||||
|
||||
show global variables like 'innodb_tmpdir';
|
||||
show session variables like 'innodb_tmpdir';
|
||||
|
||||
select * from information_schema.global_variables where variable_name='innodb_tmpdir';
|
||||
select * from information_schema.session_variables where variable_name='innodb_tmpdir';
|
||||
#
|
||||
# Show that it is writable
|
||||
#
|
||||
|
||||
set global innodb_tmpdir=@@global.tmpdir;
|
||||
set session innodb_tmpdir=@@global.tmpdir;
|
||||
|
||||
#
|
||||
# incorrect types
|
||||
#
|
||||
--error ER_WRONG_TYPE_FOR_VAR
|
||||
set global innodb_tmpdir=1.1;
|
||||
--error ER_WRONG_TYPE_FOR_VAR
|
||||
set global innodb_tmpdir=1e1;
|
||||
|
||||
#
|
||||
# path len more than 512
|
||||
#
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
set global innodb_tmpdir=repeat('a',1000);
|
||||
show warnings;
|
||||
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
|
||||
SET @@global.innodb_tmpdir = @start_global_value;
|
||||
SELECT @@global.innodb_tmpdir;
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -167,6 +167,25 @@ buf_load_status(
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
/** Returns the directory path where the buffer pool dump file will be created.
|
||||
@return directory path */
|
||||
static
|
||||
const char*
|
||||
get_buf_dump_dir()
|
||||
{
|
||||
const char* dump_dir;
|
||||
|
||||
/* The dump file should be created in the default data directory if
|
||||
innodb_data_home_dir is set as an empty string. */
|
||||
if (strcmp(srv_data_home, "") == 0) {
|
||||
dump_dir = fil_path_to_mysql_datadir;
|
||||
} else {
|
||||
dump_dir = srv_data_home;
|
||||
}
|
||||
|
||||
return(dump_dir);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Perform a buffer pool dump into the file specified by
|
||||
innodb_buffer_pool_filename. If any errors occur then the value of
|
||||
|
@ -190,7 +209,7 @@ buf_dump(
|
|||
int ret;
|
||||
|
||||
ut_snprintf(full_filename, sizeof(full_filename),
|
||||
"%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
|
||||
"%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
|
||||
srv_buf_dump_filename);
|
||||
|
||||
ut_snprintf(tmp_filename, sizeof(tmp_filename),
|
||||
|
@ -463,7 +482,7 @@ buf_load()
|
|||
buf_load_abort_flag = FALSE;
|
||||
|
||||
ut_snprintf(full_filename, sizeof(full_filename),
|
||||
"%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
|
||||
"%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
|
||||
srv_buf_dump_filename);
|
||||
|
||||
buf_load_status(STATUS_NOTICE,
|
||||
|
|
|
@ -1107,7 +1107,7 @@ dict_init(void)
|
|||
&dict_operation_lock, SYNC_DICT_OPERATION);
|
||||
|
||||
if (!srv_read_only_mode) {
|
||||
dict_foreign_err_file = os_file_create_tmpfile();
|
||||
dict_foreign_err_file = os_file_create_tmpfile(NULL);
|
||||
ut_a(dict_foreign_err_file);
|
||||
|
||||
mutex_create(dict_foreign_err_mutex_key,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2009, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -1436,7 +1436,6 @@ on the leaf page.
|
|||
when comparing records
|
||||
@param[out] n_diff number of distinct records
|
||||
@param[out] n_external_pages number of external pages
|
||||
@param[in,out] mtr mini-transaction
|
||||
@return number of distinct records on the leaf page */
|
||||
static
|
||||
void
|
||||
|
@ -1444,8 +1443,7 @@ dict_stats_analyze_index_below_cur(
|
|||
const btr_cur_t* cur,
|
||||
ulint n_prefix,
|
||||
ib_uint64_t* n_diff,
|
||||
ib_uint64_t* n_external_pages,
|
||||
mtr_t* mtr)
|
||||
ib_uint64_t* n_external_pages)
|
||||
{
|
||||
dict_index_t* index;
|
||||
ulint space;
|
||||
|
@ -1459,6 +1457,7 @@ dict_stats_analyze_index_below_cur(
|
|||
ulint* offsets2;
|
||||
ulint* offsets_rec;
|
||||
ulint size;
|
||||
mtr_t mtr;
|
||||
|
||||
index = btr_cur_get_index(cur);
|
||||
|
||||
|
@ -1497,12 +1496,14 @@ dict_stats_analyze_index_below_cur(
|
|||
function without analyzing any leaf pages */
|
||||
*n_external_pages = 0;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* descend to the leaf level on the B-tree */
|
||||
for (;;) {
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
|
||||
NULL /* no guessed block */,
|
||||
BUF_GET, __FILE__, __LINE__, mtr);
|
||||
BUF_GET, __FILE__, __LINE__, &mtr);
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
|
@ -1524,6 +1525,8 @@ dict_stats_analyze_index_below_cur(
|
|||
ut_a(*n_diff > 0);
|
||||
|
||||
if (*n_diff == 1) {
|
||||
mtr_commit(&mtr);
|
||||
|
||||
/* page has all keys equal and the end of the page
|
||||
was reached by dict_stats_scan_page(), no need to
|
||||
descend to the leaf level */
|
||||
|
@ -1548,7 +1551,7 @@ dict_stats_analyze_index_below_cur(
|
|||
}
|
||||
|
||||
/* make sure we got a leaf page as a result from the above loop */
|
||||
ut_ad(btr_page_get_level(page, mtr) == 0);
|
||||
ut_ad(btr_page_get_level(page, &mtr) == 0);
|
||||
|
||||
/* scan the leaf page and find the number of distinct keys,
|
||||
when looking only at the first n_prefix columns; also estimate
|
||||
|
@ -1565,6 +1568,7 @@ dict_stats_analyze_index_below_cur(
|
|||
__func__, page_no, n_diff);
|
||||
#endif
|
||||
|
||||
mtr_commit(&mtr);
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
@ -1774,8 +1778,7 @@ dict_stats_analyze_index_for_n_prefix(
|
|||
dict_stats_analyze_index_below_cur(btr_pcur_get_btr_cur(&pcur),
|
||||
n_prefix,
|
||||
&n_diff_on_leaf_page,
|
||||
&n_external_pages,
|
||||
mtr);
|
||||
&n_external_pages);
|
||||
|
||||
/* We adjust n_diff_on_leaf_page here to avoid counting
|
||||
one record twice - once as the last on some page and once
|
||||
|
|
|
@ -580,7 +580,7 @@ fts_zip_read_word(
|
|||
#ifdef UNIV_DEBUG
|
||||
ulint i;
|
||||
#endif
|
||||
byte len = 0;
|
||||
short len = 0;
|
||||
void* null = NULL;
|
||||
byte* ptr = word->f_str;
|
||||
int flush = Z_NO_FLUSH;
|
||||
|
@ -590,7 +590,7 @@ fts_zip_read_word(
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
zip->zp->next_out = &len;
|
||||
zip->zp->next_out = reinterpret_cast<byte*>(&len);
|
||||
zip->zp->avail_out = sizeof(len);
|
||||
|
||||
while (zip->status == Z_OK && zip->zp->avail_out > 0) {
|
||||
|
@ -688,11 +688,12 @@ fts_fetch_index_words(
|
|||
fts_zip_t* zip = static_cast<fts_zip_t*>(user_arg);
|
||||
que_node_t* exp = sel_node->select_list;
|
||||
dfield_t* dfield = que_node_get_val(exp);
|
||||
byte len = (byte) dfield_get_len(dfield);
|
||||
short len = static_cast<short>(dfield_get_len(dfield));
|
||||
void* data = dfield_get_data(dfield);
|
||||
|
||||
/* Skip the duplicate words. */
|
||||
if (zip->word.f_len == len && !memcmp(zip->word.f_str, data, len)) {
|
||||
if (zip->word.f_len == static_cast<ulint>(len)
|
||||
&& !memcmp(zip->word.f_str, data, len)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -706,7 +707,7 @@ fts_fetch_index_words(
|
|||
ut_a(zip->zp->next_in == NULL);
|
||||
|
||||
/* The string is prefixed by len. */
|
||||
zip->zp->next_in = &len;
|
||||
zip->zp->next_in = reinterpret_cast<byte*>(&len);
|
||||
zip->zp->avail_in = sizeof(len);
|
||||
|
||||
/* Compress the word, create output blocks as necessary. */
|
||||
|
|
|
@ -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);
|
||||
);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -341,6 +341,15 @@ thd_supports_xa(
|
|||
THD* thd); /*!< in: thread handle, or NULL to query
|
||||
the global innodb_supports_xa */
|
||||
|
||||
/** Get status 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);
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the lock wait timeout for the current connection.
|
||||
@return the lock wait timeout, in seconds */
|
||||
|
|
|
@ -432,14 +432,19 @@ UNIV_INTERN
|
|||
void
|
||||
os_io_init_simple(void);
|
||||
/*===================*/
|
||||
/***********************************************************************//**
|
||||
Creates a temporary file. This function is like tmpfile(3), but
|
||||
the temporary file is created in the MySQL temporary directory.
|
||||
@return temporary file handle, or NULL on error */
|
||||
|
||||
|
||||
/** Create a temporary file. This function is like tmpfile(3), but
|
||||
the temporary file is created in the given parameter path. If the path
|
||||
is null then it will create the file in the mysql server configuration
|
||||
parameter (--tmpdir).
|
||||
@param[in] path location for creating temporary file
|
||||
@return temporary file handle, or NULL on error */
|
||||
UNIV_INTERN
|
||||
FILE*
|
||||
os_file_create_tmpfile(void);
|
||||
/*========================*/
|
||||
os_file_create_tmpfile(
|
||||
const char* path);
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***********************************************************************//**
|
||||
The os_file_opendir() function opens a directory stream corresponding to the
|
||||
|
@ -1245,14 +1250,14 @@ os_file_get_status(
|
|||
file can be opened in RW mode */
|
||||
|
||||
#if !defined(UNIV_HOTBACKUP)
|
||||
/*********************************************************************//**
|
||||
Creates a temporary file that will be deleted on close.
|
||||
This function is defined in ha_innodb.cc.
|
||||
/** 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);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -51,8 +51,9 @@ row_log_allocate(
|
|||
const dtuple_t* add_cols,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
const ulint* col_map)/*!< in: mapping of old column
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL if !table */
|
||||
const char* path) /*!< in: where to create temporary file */
|
||||
__attribute__((nonnull(1), warn_unused_result));
|
||||
|
||||
/******************************************************//**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -171,14 +171,14 @@ void
|
|||
row_merge_drop_temp_indexes(void);
|
||||
/*=============================*/
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates temporary merge files, and if UNIV_PFS_IO defined, register
|
||||
the file descriptor with Performance Schema.
|
||||
/** Create temporary merge files in the given paramater path, and if
|
||||
UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
|
||||
@param[in] path location for creating temporary merge files.
|
||||
@return File descriptor */
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_merge_file_create_low(void)
|
||||
/*===========================*/
|
||||
row_merge_file_create_low(
|
||||
const char* path)
|
||||
__attribute__((warn_unused_result));
|
||||
/*********************************************************************//**
|
||||
Destroy a merge file. And de-register the file from Performance Schema
|
||||
|
@ -349,15 +349,17 @@ row_merge_buf_empty(
|
|||
/*================*/
|
||||
row_merge_buf_t* buf) /*!< in,own: sort buffer */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
/*********************************************************************//**
|
||||
Create a merge file.
|
||||
|
||||
/** Create a merge file in the given location.
|
||||
@param[out] merge_file merge file structure
|
||||
@param[in] path location for creating temporary file
|
||||
@return file descriptor, or -1 on failure */
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_merge_file_create(
|
||||
/*==================*/
|
||||
merge_file_t* merge_file) /*!< out: merge file structure */
|
||||
__attribute__((nonnull));
|
||||
merge_file_t* merge_file,
|
||||
const char* path);
|
||||
|
||||
/*********************************************************************//**
|
||||
Merge disk files.
|
||||
@return DB_SUCCESS or error code */
|
||||
|
|
|
@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
|
|||
|
||||
#define INNODB_VERSION_MAJOR 5
|
||||
#define INNODB_VERSION_MINOR 6
|
||||
#define INNODB_VERSION_BUGFIX 27
|
||||
#define INNODB_VERSION_BUGFIX 29
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
SELECT plugin_version FROM information_schema.plugins;
|
||||
|
|
|
@ -633,7 +633,7 @@ lock_sys_create(
|
|||
lock_sys->rec_hash = hash_create(n_cells);
|
||||
|
||||
if (!srv_read_only_mode) {
|
||||
lock_latest_err_file = os_file_create_tmpfile();
|
||||
lock_latest_err_file = os_file_create_tmpfile(NULL);
|
||||
ut_a(lock_latest_err_file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -756,17 +756,19 @@ os_io_init_simple(void)
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Creates a temporary file. This function is like tmpfile(3), but
|
||||
the temporary file is created in the MySQL temporary directory.
|
||||
/** Create a temporary file. This function is like tmpfile(3), but
|
||||
the temporary file is created in the given parameter path. If the path
|
||||
is null then it will create the file in the mysql server configuration
|
||||
parameter (--tmpdir).
|
||||
@param[in] path location for creating temporary file
|
||||
@return temporary file handle, or NULL on error */
|
||||
UNIV_INTERN
|
||||
FILE*
|
||||
os_file_create_tmpfile(void)
|
||||
/*========================*/
|
||||
os_file_create_tmpfile(
|
||||
const char* path)
|
||||
{
|
||||
FILE* file = NULL;
|
||||
int fd = innobase_mysql_tmpfile();
|
||||
int fd = innobase_mysql_tmpfile(path);
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
|
||||
|
@ -3658,7 +3660,7 @@ os_aio_native_aio_supported(void)
|
|||
return(FALSE);
|
||||
} else if (!srv_read_only_mode) {
|
||||
/* Now check if tmpdir supports native aio ops. */
|
||||
fd = innobase_mysql_tmpfile();
|
||||
fd = innobase_mysql_tmpfile(NULL);
|
||||
|
||||
if (fd < 0) {
|
||||
ib_logf(IB_LOG_LEVEL_WARN,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2010, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -220,6 +220,9 @@ row_fts_psort_info_init(
|
|||
common_info->merge_event = os_event_create();
|
||||
common_info->opt_doc_id_size = opt_doc_id_size;
|
||||
|
||||
ut_ad(trx->mysql_thd != NULL);
|
||||
const char* path = thd_innodb_tmpdir(trx->mysql_thd);
|
||||
|
||||
/* There will be FTS_NUM_AUX_INDEX number of "sort buckets" for
|
||||
each parallel sort thread. Each "sort bucket" holds records for
|
||||
a particular "FTS index partition" */
|
||||
|
@ -241,8 +244,8 @@ row_fts_psort_info_init(
|
|||
psort_info[j].merge_buf[i] = row_merge_buf_create(
|
||||
dup->index);
|
||||
|
||||
if (row_merge_file_create(psort_info[j].merge_file[i])
|
||||
< 0) {
|
||||
if (row_merge_file_create(psort_info[j].merge_file[i],
|
||||
path) < 0) {
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
|
@ -610,6 +613,11 @@ fts_parallel_tokenization(
|
|||
ulint retried = 0;
|
||||
dberr_t error = DB_SUCCESS;
|
||||
|
||||
ut_ad(psort_info->psort_common->trx->mysql_thd != NULL);
|
||||
|
||||
const char* path = thd_innodb_tmpdir(
|
||||
psort_info->psort_common->trx->mysql_thd);
|
||||
|
||||
ut_ad(psort_info);
|
||||
|
||||
buf = psort_info->merge_buf;
|
||||
|
@ -840,7 +848,7 @@ exit:
|
|||
continue;
|
||||
}
|
||||
|
||||
tmpfd[i] = row_merge_file_create_low();
|
||||
tmpfd[i] = row_merge_file_create_low(path);
|
||||
if (tmpfd[i] < 0) {
|
||||
error = DB_OUT_OF_MEMORY;
|
||||
goto func_exit;
|
||||
|
|
|
@ -194,8 +194,25 @@ struct row_log_t {
|
|||
or by index->lock X-latch only */
|
||||
row_log_buf_t head; /*!< reader context; protected by MDL only;
|
||||
modifiable by row_log_apply_ops() */
|
||||
const char* path; /*!< where to create temporary file during
|
||||
log operation */
|
||||
};
|
||||
|
||||
/** Create the file or online log if it does not exist.
|
||||
@param[in,out] log online rebuild log
|
||||
@return file descriptor. */
|
||||
static __attribute__((warn_unused_result))
|
||||
int
|
||||
row_log_tmpfile(
|
||||
row_log_t* log)
|
||||
{
|
||||
DBUG_ENTER("row_log_tmpfile");
|
||||
if (log->fd < 0) {
|
||||
log->fd = row_merge_file_create_low(log->path);
|
||||
}
|
||||
|
||||
DBUG_RETURN(log->fd);
|
||||
}
|
||||
|
||||
/** Allocate the memory for the log buffer.
|
||||
@param[in,out] log_buf Buffer used for log operation
|
||||
|
@ -340,6 +357,12 @@ row_log_online_op(
|
|||
log->tail.buf, avail_size);
|
||||
}
|
||||
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
|
||||
|
||||
if (row_log_tmpfile(log) < 0) {
|
||||
log->error = DB_OUT_OF_MEMORY;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
ret = os_file_write(
|
||||
"(modification log)",
|
||||
OS_FILE_FROM_FD(log->fd),
|
||||
|
@ -450,6 +473,12 @@ row_log_table_close_func(
|
|||
log->tail.buf, avail);
|
||||
}
|
||||
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
|
||||
|
||||
if (row_log_tmpfile(log) < 0) {
|
||||
log->error = DB_OUT_OF_MEMORY;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
ret = os_file_write(
|
||||
"(modification log)",
|
||||
OS_FILE_FROM_FD(log->fd),
|
||||
|
@ -469,6 +498,7 @@ write_failed:
|
|||
|
||||
log->tail.total += size;
|
||||
UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
|
||||
err_exit:
|
||||
mutex_exit(&log->mutex);
|
||||
}
|
||||
|
||||
|
@ -2536,7 +2566,8 @@ corruption:
|
|||
if (index->online_log->head.blocks) {
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
/* Truncate the file in order to save space. */
|
||||
if (ftruncate(index->online_log->fd, 0) == -1) {
|
||||
if (index->online_log->fd != -1
|
||||
&& ftruncate(index->online_log->fd, 0) == -1) {
|
||||
fprintf(stderr, "InnoDB: Error: Truncate of file "
|
||||
"\'%s\' failed with error %d:%s\n",
|
||||
index->name + 1, errno, strerror(errno));
|
||||
|
@ -2855,8 +2886,9 @@ row_log_allocate(
|
|||
const dtuple_t* add_cols,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
const ulint* col_map)/*!< in: mapping of old column
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL if !table */
|
||||
const char* path) /*!< in: where to create temporary file */
|
||||
{
|
||||
row_log_t* log;
|
||||
DBUG_ENTER("row_log_allocate");
|
||||
|
@ -2875,11 +2907,7 @@ row_log_allocate(
|
|||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
log->fd = row_merge_file_create_low();
|
||||
if (log->fd < 0) {
|
||||
ut_free(log);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
log->fd = -1;
|
||||
mutex_create(index_online_log_key, &log->mutex,
|
||||
SYNC_INDEX_ONLINE_LOG);
|
||||
log->blobs = NULL;
|
||||
|
@ -2894,6 +2922,7 @@ row_log_allocate(
|
|||
log->tail.block = log->head.block = NULL;
|
||||
log->head.blocks = log->head.bytes = 0;
|
||||
log->head.total = 0;
|
||||
log->path = path;
|
||||
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
|
||||
index->online_log = log;
|
||||
|
||||
|
@ -3371,7 +3400,8 @@ corruption:
|
|||
if (index->online_log->head.blocks) {
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
/* Truncate the file in order to save space. */
|
||||
if (ftruncate(index->online_log->fd, 0) == -1) {
|
||||
if (index->online_log->fd != -1
|
||||
&& ftruncate(index->online_log->fd, 0) == -1) {
|
||||
fprintf(stderr, "InnoDB: Error: Truncate of file "
|
||||
"\'%s\' failed with error %d:%s\n",
|
||||
index->name + 1, errno, strerror(errno));
|
||||
|
|
|
@ -1241,47 +1241,95 @@ row_merge_write_eof(
|
|||
return(&block[0]);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Reads clustered index of the table and create temporary files
|
||||
/** Create a temporary file if it has not been created already.
|
||||
@param[in,out] tmpfd temporary file handle
|
||||
@param[in] path path to create temporary file
|
||||
@return file descriptor, or -1 on failure */
|
||||
static __attribute__((warn_unused_result))
|
||||
int
|
||||
row_merge_tmpfile_if_needed(
|
||||
int* tmpfd,
|
||||
const char* path)
|
||||
{
|
||||
if (*tmpfd < 0) {
|
||||
*tmpfd = row_merge_file_create_low(path);
|
||||
}
|
||||
|
||||
return(*tmpfd);
|
||||
}
|
||||
|
||||
/** Create a temporary file for merge sort if it was not created already.
|
||||
@param[in,out] file merge file structure
|
||||
@param[in,out] tmpfd temporary file structure
|
||||
@param[in] nrec number of records in the file
|
||||
@param[in] path path to create temporary files
|
||||
@return file descriptor, or -1 on failure */
|
||||
static __attribute__((warn_unused_result))
|
||||
int
|
||||
row_merge_file_create_if_needed(
|
||||
merge_file_t* file,
|
||||
int* tmpfd,
|
||||
ulint nrec,
|
||||
const char* path)
|
||||
{
|
||||
ut_ad(file->fd < 0 || *tmpfd >=0);
|
||||
if (file->fd < 0 && row_merge_file_create(file, path) >= 0) {
|
||||
if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
file->n_rec = nrec;
|
||||
}
|
||||
|
||||
ut_ad(file->fd < 0 || *tmpfd >=0);
|
||||
return(file->fd);
|
||||
}
|
||||
|
||||
/** Reads clustered index of the table and create temporary files
|
||||
containing the index entries for the indexes to be built.
|
||||
@return DB_SUCCESS or error */
|
||||
@param[in] trx transaction
|
||||
@param[in,out] table MySQL table object, for reporting erroneous
|
||||
records
|
||||
@param[in] old_table table where rows are read from
|
||||
@param[in] new_table table where indexes are created; identical to
|
||||
old_table unless creating a PRIMARY KEY
|
||||
@param[in] online true if creating indexes online
|
||||
@param[in] index indexes to be created
|
||||
@param[in] fts_sort_idx full-text index to be created, or NULL
|
||||
@param[in] psort_info parallel sort info for fts_sort_idx creation,
|
||||
or NULL
|
||||
@param[in] files temporary files
|
||||
@param[in] key_numbers MySQL key numbers to create
|
||||
@param[in] n_index number of indexes to create
|
||||
@param[in] add_cols default values of added columns, or NULL
|
||||
@param[in] col_map mapping of old column numbers to new ones, or
|
||||
NULL if old_table == new_table
|
||||
@param[in] add_autoinc number of added AUTO_INCREMENT columns, or
|
||||
ULINT_UNDEFINED if none is added
|
||||
@param[in,out] sequence autoinc sequence
|
||||
@param[in,out] block file buffer
|
||||
@param[in,out] tmpfd temporary file handle
|
||||
return DB_SUCCESS or error */
|
||||
static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result))
|
||||
dberr_t
|
||||
row_merge_read_clustered_index(
|
||||
/*===========================*/
|
||||
trx_t* trx, /*!< in: transaction */
|
||||
struct TABLE* table, /*!< in/out: MySQL table object,
|
||||
for reporting erroneous records */
|
||||
const dict_table_t* old_table,/*!< in: table where rows are
|
||||
read from */
|
||||
const dict_table_t* new_table,/*!< in: table where indexes are
|
||||
created; identical to old_table
|
||||
unless creating a PRIMARY KEY */
|
||||
bool online, /*!< in: true if creating indexes
|
||||
online */
|
||||
dict_index_t** index, /*!< in: indexes to be created */
|
||||
trx_t* trx,
|
||||
struct TABLE* table,
|
||||
const dict_table_t* old_table,
|
||||
const dict_table_t* new_table,
|
||||
bool online,
|
||||
dict_index_t** index,
|
||||
dict_index_t* fts_sort_idx,
|
||||
/*!< in: full-text index to be created,
|
||||
or NULL */
|
||||
fts_psort_t* psort_info,
|
||||
/*!< in: parallel sort info for
|
||||
fts_sort_idx creation, or NULL */
|
||||
merge_file_t* files, /*!< in: temporary files */
|
||||
merge_file_t* files,
|
||||
const ulint* key_numbers,
|
||||
/*!< in: MySQL key numbers to create */
|
||||
ulint n_index,/*!< in: number of indexes to create */
|
||||
ulint n_index,
|
||||
const dtuple_t* add_cols,
|
||||
/*!< in: default values of
|
||||
added columns, or NULL */
|
||||
const ulint* col_map,/*!< in: mapping of old column
|
||||
numbers to new ones, or NULL
|
||||
if old_table == new_table */
|
||||
const ulint* col_map,
|
||||
ulint add_autoinc,
|
||||
/*!< in: number of added
|
||||
AUTO_INCREMENT column, or
|
||||
ULINT_UNDEFINED if none is added */
|
||||
ib_sequence_t& sequence,/*!< in/out: autoinc sequence */
|
||||
row_merge_block_t* block) /*!< in/out: file buffer */
|
||||
ib_sequence_t& sequence,
|
||||
row_merge_block_t* block,
|
||||
int* tmpfd)
|
||||
{
|
||||
dict_index_t* clust_index; /* Clustered index */
|
||||
mem_heap_t* row_heap; /* Heap memory to create
|
||||
|
@ -1313,6 +1361,9 @@ row_merge_read_clustered_index(
|
|||
DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n");
|
||||
#endif
|
||||
|
||||
ut_ad(trx->mysql_thd != NULL);
|
||||
const char* path = thd_innodb_tmpdir(trx->mysql_thd);
|
||||
|
||||
/* Create and initialize memory for record buffers */
|
||||
|
||||
merge_buf = static_cast<row_merge_buf_t**>(
|
||||
|
@ -1777,6 +1828,17 @@ write_buffers:
|
|||
dict_index_get_lock(buf->index));
|
||||
}
|
||||
|
||||
if (buf->n_tuples > 0) {
|
||||
|
||||
if (row_merge_file_create_if_needed(
|
||||
file, tmpfd, buf->n_tuples, path) < 0) {
|
||||
err = DB_OUT_OF_MEMORY;
|
||||
trx->error_key_num = i;
|
||||
break;
|
||||
}
|
||||
|
||||
ut_ad(file->n_rec > 0);
|
||||
|
||||
row_merge_buf_write(buf, file, block);
|
||||
|
||||
if (!row_merge_write(file->fd, file->offset++,
|
||||
|
@ -1785,6 +1847,7 @@ write_buffers:
|
|||
trx->error_key_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
|
||||
merge_buf[i] = row_merge_buf_empty(buf);
|
||||
|
@ -1827,6 +1890,7 @@ write_buffers:
|
|||
|
||||
func_exit:
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mem_heap_free(row_heap);
|
||||
|
||||
if (nonnull) {
|
||||
|
@ -3057,14 +3121,15 @@ row_merge_drop_temp_indexes(void)
|
|||
trx_free_for_background(trx);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates temporary merge files, and if UNIV_PFS_IO defined, register
|
||||
the file descriptor with Performance Schema.
|
||||
@return file descriptor, or -1 on failure */
|
||||
|
||||
/** Create temporary merge files in the given paramater path, and if
|
||||
UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
|
||||
@param[in] path location for creating temporary merge files.
|
||||
@return File descriptor */
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_merge_file_create_low(void)
|
||||
/*===========================*/
|
||||
row_merge_file_create_low(
|
||||
const char* path)
|
||||
{
|
||||
int fd;
|
||||
#ifdef UNIV_PFS_IO
|
||||
|
@ -3078,7 +3143,7 @@ row_merge_file_create_low(void)
|
|||
"Innodb Merge Temp File",
|
||||
__FILE__, __LINE__);
|
||||
#endif
|
||||
fd = innobase_mysql_tmpfile();
|
||||
fd = innobase_mysql_tmpfile(path);
|
||||
#ifdef UNIV_PFS_IO
|
||||
register_pfs_file_open_end(locker, fd);
|
||||
#endif
|
||||
|
@ -3091,16 +3156,18 @@ row_merge_file_create_low(void)
|
|||
return(fd);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Create a merge file.
|
||||
|
||||
/** Create a merge file in the given location.
|
||||
@param[out] merge_file merge file structure
|
||||
@param[in] path location for creating temporary file
|
||||
@return file descriptor, or -1 on failure */
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_merge_file_create(
|
||||
/*==================*/
|
||||
merge_file_t* merge_file) /*!< out: merge file structure */
|
||||
merge_file_t* merge_file,
|
||||
const char* path)
|
||||
{
|
||||
merge_file->fd = row_merge_file_create_low();
|
||||
merge_file->fd = row_merge_file_create_low(path);
|
||||
merge_file->offset = 0;
|
||||
merge_file->n_rec = 0;
|
||||
|
||||
|
@ -3620,10 +3687,6 @@ row_merge_build_indexes(
|
|||
}
|
||||
|
||||
for (i = 0; i < n_indexes; i++) {
|
||||
if (row_merge_file_create(&merge_files[i]) < 0) {
|
||||
error = DB_OUT_OF_MEMORY;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (indexes[i]->type & DICT_FTS) {
|
||||
ibool opt_doc_id_size = FALSE;
|
||||
|
@ -3652,13 +3715,6 @@ row_merge_build_indexes(
|
|||
}
|
||||
}
|
||||
|
||||
tmpfd = row_merge_file_create_low();
|
||||
|
||||
if (tmpfd < 0) {
|
||||
error = DB_OUT_OF_MEMORY;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Reset the MySQL row buffer that is used when reporting
|
||||
duplicate keys. */
|
||||
innobase_rec_reset(table);
|
||||
|
@ -3670,7 +3726,7 @@ row_merge_build_indexes(
|
|||
trx, table, old_table, new_table, online, indexes,
|
||||
fts_sort_idx, psort_info, merge_files, key_numbers,
|
||||
n_indexes, add_cols, col_map,
|
||||
add_autoinc, sequence, block);
|
||||
add_autoinc, sequence, block, &tmpfd);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
|
@ -3751,7 +3807,7 @@ wait_again:
|
|||
#ifdef FTS_INTERNAL_DIAG_PRINT
|
||||
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
|
||||
#endif
|
||||
} else {
|
||||
} else if (merge_files[i].fd != -1) {
|
||||
row_merge_dup_t dup = {
|
||||
sort_idx, table, col_map, 0};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, 2009 Google Inc.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
|
||||
|
@ -1733,6 +1733,8 @@ exit_func:
|
|||
/*********************************************************************//**
|
||||
A thread which prints warnings about semaphore waits which have lasted
|
||||
too long. These can be used to track bugs which cause hangs.
|
||||
Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
|
||||
we should avoid waiting any mutexes in this function!
|
||||
@return a dummy parameter */
|
||||
extern "C" UNIV_INTERN
|
||||
os_thread_ret_t
|
||||
|
@ -1772,10 +1774,8 @@ loop:
|
|||
/* Try to track a strange bug reported by Harald Fuchs and others,
|
||||
where the lsn seems to decrease at times */
|
||||
|
||||
/* We have to use nowait to ensure we don't block */
|
||||
new_lsn= log_get_lsn_nowait();
|
||||
|
||||
if (new_lsn && new_lsn < old_lsn) {
|
||||
if (log_peek_lsn(&new_lsn)) {
|
||||
if (new_lsn < old_lsn) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: old log sequence number " LSN_PF
|
||||
|
@ -1787,8 +1787,8 @@ loop:
|
|||
ut_ad(0);
|
||||
}
|
||||
|
||||
if (new_lsn)
|
||||
old_lsn = new_lsn;
|
||||
}
|
||||
|
||||
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
|
||||
/* We referesh InnoDB Monitor values so that averages are
|
||||
|
|
|
@ -1894,7 +1894,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
}
|
||||
} else {
|
||||
srv_monitor_file_name = NULL;
|
||||
srv_monitor_file = os_file_create_tmpfile();
|
||||
srv_monitor_file = os_file_create_tmpfile(NULL);
|
||||
|
||||
if (!srv_monitor_file) {
|
||||
return(DB_ERROR);
|
||||
|
@ -1904,7 +1904,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
mutex_create(srv_dict_tmpfile_mutex_key,
|
||||
&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
|
||||
|
||||
srv_dict_tmpfile = os_file_create_tmpfile();
|
||||
srv_dict_tmpfile = os_file_create_tmpfile(NULL);
|
||||
|
||||
if (!srv_dict_tmpfile) {
|
||||
return(DB_ERROR);
|
||||
|
@ -1913,7 +1913,7 @@ innobase_start_or_create_for_mysql(void)
|
|||
mutex_create(srv_misc_tmpfile_mutex_key,
|
||||
&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
|
||||
|
||||
srv_misc_tmpfile = os_file_create_tmpfile();
|
||||
srv_misc_tmpfile = os_file_create_tmpfile(NULL);
|
||||
|
||||
if (!srv_misc_tmpfile) {
|
||||
return(DB_ERROR);
|
||||
|
|
Loading…
Reference in a new issue