Commit 5b8ac230 authored by Sergei Golubchik's avatar Sergei Golubchik

5.6.29-76.2

parent d76eba6a
/*****************************************************************************
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),
......@@ -387,7 +406,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,
......
......@@ -67,12 +67,6 @@ UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key;
UNIV_INTERN mysql_pfs_key_t buf_lru_manager_thread_key;
#endif /* UNIV_PFS_THREAD */
/** If LRU list of a buf_pool is less than this size then LRU eviction
should not happen. This is because when we do LRU flushing we also put
the blocks on free list. If LRU list is very small then we can end up
in thrashing. */
#define BUF_LRU_MIN_LEN 256
/* @} */
/** Handled page counters for a single flush */
......
......@@ -1066,7 +1066,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,
......
/*****************************************************************************
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
......@@ -1434,7 +1434,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
......@@ -1442,8 +1441,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;
......@@ -1457,6 +1455,7 @@ dict_stats_analyze_index_below_cur(
ulint* offsets2;
ulint* offsets_rec;
ulint size;
mtr_t mtr;
index = btr_cur_get_index(cur);
......@@ -1495,12 +1494,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);
......@@ -1522,6 +1523,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 */
......@@ -1546,7 +1549,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
......@@ -1563,6 +1566,7 @@ dict_stats_analyze_index_below_cur(
__func__, page_no, n_diff);
#endif
mtr_commit(&mtr);
mem_heap_free(heap);
}
......@@ -1772,8 +1776,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. */
......
This diff is collapsed.
......@@ -642,3 +642,26 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
/*******************************************************************//**
This function builds a translation table in INNOBASE_SHARE
structure for fast index location with mysql array number from its
table->key_info structure. This also provides the necessary translation
between the key order in mysql key_info and Innodb ib_table->indexes if
they are not fully matched with each other.
Note we do not have any mutex protecting the translation table
building based on the assumption that there is no concurrent
index creation/drop and DMLs that requires index lookup. All table
handle will be closed before the index creation/drop.
@return TRUE if index translation table built successfully */
UNIV_INTERN
ibool
innobase_build_index_translation(
/*=============================*/
const TABLE* table, /*!< in: table in MySQL data
dictionary */
dict_table_t* ib_table, /*!< in: table in Innodb data
dictionary */
INNOBASE_SHARE* share); /*!< in/out: share structure
where index translation table
will be constructed in. */
......@@ -2613,6 +2613,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,
......@@ -2951,8 +2955,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) {
......@@ -2978,7 +2984,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) {
......@@ -3951,6 +3957,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,
......@@ -5971,6 +5978,21 @@ foreign_fail:
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
/* Rebuild index translation table now for temporary tables if we are
restoring secondary keys, as ha_innobase::open will not be called for
the next access. */
if (dict_table_is_temporary(ctx0->new_table)
&& ctx0->num_to_add_index > 0) {
ut_ad(!ctx0->num_to_drop_index);
ut_ad(!ctx0->num_to_drop_fk);
if (!innobase_build_index_translation(altered_table,
ctx0->new_table,
share)) {
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
DBUG_RETURN(true);
}
}
/* TODO: The following code could be executed
while allowing concurrent access to the table
(MDL downgrade). */
......
......@@ -304,6 +304,12 @@ buf_flush_flush_list_in_progress(void)
/*==================================*/
__attribute__((warn_unused_result));
/** If LRU list of a buf_pool is less than this size then LRU eviction
should not happen. This is because when we do LRU flushing we also put
the blocks on free list. If LRU list is very small then we can end up
in thrashing. */
#define BUF_LRU_MIN_LEN 256
#ifndef UNIV_NONINL
#include "buf0flu.ic"
#endif
......
/*****************************************************************************
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
......@@ -335,6 +335,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);
/******************************************************************//**
Check the status of fake changes mode (innodb_fake_changes)
@return true if fake change mode is enabled. */
......
......@@ -455,14 +455,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
......@@ -1284,14 +1289,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.
@return temporary file descriptor, or < 0 on error */
/** 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 */
......
/*****************************************************************************
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));
/******************************************************//**
......
/*****************************************************************************
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
......@@ -170,14 +170,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
......@@ -348,15 +348,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 */
......
......@@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 76.1
#define PERCONA_INNODB_VERSION 76.2
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
......
......@@ -619,7 +619,7 @@ lock_sys_create(
lock_sys->rec_num = 0;
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);
}
}
......
......@@ -764,17 +764,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.
@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)
{
FILE* file = NULL;
int fd = innobase_mysql_tmpfile();
int fd = innobase_mysql_tmpfile(path);
ut_ad(!srv_read_only_mode);
......@@ -3815,7 +3817,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,
......
/*****************************************************************************
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
......@@ -223,6 +223,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" */
......@@ -244,8 +247,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;
}
......@@ -613,6 +616,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;
......@@ -842,7 +850,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) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
......@@ -2852,8 +2883,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");
......@@ -2872,11 +2904,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;
......@@ -2891,6 +2919,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;
......@@ -3368,7 +3397,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) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
......
......@@ -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**>(
......@@ -1783,13 +1834,25 @@ write_buffers:
dict_index_get_lock(buf->index));
}
row_merge_buf_write(buf, file, block);
if (buf->n_tuples > 0) {
if (!row_merge_write(file->fd, file->offset++,
block)) {
err = DB_TEMP_FILE_WRITE_FAILURE;
trx->error_key_num = i;
break;
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++,
block)) {
err = DB_TEMP_FILE_WRITE_FAILURE;
trx->error_key_num = i;
break;
}
}
UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
......@@ -1833,6 +1896,7 @@ write_buffers:
func_exit:
mtr_commit(&mtr);
mem_heap_free(row_heap);
if (nonnull) {
......@@ -3045,14 +3109,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
......@@ -3066,7 +3131,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
......@@ -3079,16 +3144,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;
......@@ -3604,10 +3671,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;
......@@ -3636,13 +3699,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);
......@@ -3654,7 +3710,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) {
......@@ -3735,7 +3791,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};
......
/*****************************************************************************
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.
......@@ -2043,6 +2043,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
......@@ -2082,22 +2084,22 @@ loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
new_lsn = log_get_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
" was greater\n"
"InnoDB: than the new log sequence number " LSN_PF "!\n"
"InnoDB: Please submit a bug report"
" to http://bugs.mysql.com\n",
old_lsn, new_lsn);
ut_ad(0);
}
if (new_lsn < old_lsn) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: old log sequence number " LSN_PF
" was greater\n"
"InnoDB: than the new log sequence number " LSN_PF "!\n"
"InnoDB: Please submit a bug report"
" to http://bugs.mysql.com\n",
old_lsn, new_lsn);
ut_ad(0);
old_lsn = new_lsn;
}
old_lsn = new_lsn;
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
/* We referesh InnoDB Monitor values so that averages are
printed from at most 60 last seconds */
......
......@@ -1938,7 +1938,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);
......@@ -1948,7 +1948,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);
......@@ -1957,7 +1957,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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment