summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2017-05-17 12:11:12 +0300
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-05-17 12:11:12 +0300
commitd8b45b0c004edc0b91029b232d7cc9aad02cc822 (patch)
tree4461fa973957a077ee5daf782617cf65161b68bb /storage/xtradb
parentdfeff407067e2eaa27a51a04306863f912ec4cc6 (diff)
parent360a4a037271d65ab6471f7ab3f9b6a893d90a31 (diff)
downloadmariadb-git-d8b45b0c004edc0b91029b232d7cc9aad02cc822.tar.gz
Merge branch 'merge-xtradb-5.6' into 10.0
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/btr/btr0sea.cc2
-rw-r--r--storage/xtradb/buf/buf0buf.cc2
-rw-r--r--storage/xtradb/buf/buf0dblwr.cc4
-rw-r--r--storage/xtradb/buf/buf0dump.cc4
-rw-r--r--storage/xtradb/buf/buf0flu.cc38
-rw-r--r--storage/xtradb/dict/dict0boot.cc7
-rw-r--r--storage/xtradb/dict/dict0dict.cc21
-rw-r--r--storage/xtradb/dict/dict0stats.cc6
-rw-r--r--storage/xtradb/dict/dict0stats_bg.cc4
-rw-r--r--storage/xtradb/fil/fil0fil.cc29
-rw-r--r--storage/xtradb/fts/fts0que.cc20
-rw-r--r--storage/xtradb/handler/ha_innodb.cc139
-rw-r--r--storage/xtradb/handler/handler0alter.cc6
-rw-r--r--storage/xtradb/include/buf0dblwr.h4
-rw-r--r--storage/xtradb/include/dict0dict.h11
-rw-r--r--storage/xtradb/include/dict0dict.ic9
-rw-r--r--storage/xtradb/include/fil0fil.h16
-rw-r--r--storage/xtradb/include/ha0ha.h6
-rw-r--r--storage/xtradb/include/log0online.h2
-rw-r--r--storage/xtradb/include/os0file.h335
-rw-r--r--storage/xtradb/include/os0file.ic215
-rw-r--r--storage/xtradb/include/row0mysql.h10
-rw-r--r--storage/xtradb/include/srv0srv.h17
-rw-r--r--storage/xtradb/include/srv0start.h4
-rw-r--r--storage/xtradb/include/trx0xa.h15
-rw-r--r--storage/xtradb/include/univ.i12
-rw-r--r--storage/xtradb/log/log0log.cc19
-rw-r--r--storage/xtradb/log/log0online.cc62
-rw-r--r--storage/xtradb/log/log0recv.cc4
-rw-r--r--storage/xtradb/os/os0file.cc221
-rw-r--r--storage/xtradb/pars/pars0opt.cc6
-rw-r--r--storage/xtradb/pars/pars0pars.cc3
-rw-r--r--storage/xtradb/row/row0log.cc17
-rw-r--r--storage/xtradb/row/row0merge.cc35
-rw-r--r--storage/xtradb/row/row0sel.cc195
-rw-r--r--storage/xtradb/srv/srv0srv.cc42
-rw-r--r--storage/xtradb/srv/srv0start.cc66
-rw-r--r--storage/xtradb/trx/trx0purge.cc5
-rw-r--r--storage/xtradb/trx/trx0rec.cc3
-rw-r--r--storage/xtradb/trx/trx0roll.cc4
-rw-r--r--storage/xtradb/trx/trx0sys.cc18
41 files changed, 1204 insertions, 434 deletions
diff --git a/storage/xtradb/btr/btr0sea.cc b/storage/xtradb/btr/btr0sea.cc
index 78cb9dfd6e0..2ed383b0dcb 100644
--- a/storage/xtradb/btr/btr0sea.cc
+++ b/storage/xtradb/btr/btr0sea.cc
@@ -199,7 +199,7 @@ btr_search_sys_create(
&btr_search_latch_arr[i], SYNC_SEARCH_SYS);
btr_search_sys->hash_tables[i]
- = ha_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
+ = ib_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
btr_search_sys->hash_tables[i]->adaptive = TRUE;
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 07b84c60c76..0f989553440 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -1455,7 +1455,7 @@ buf_pool_init_instance(
ut_a(srv_n_page_hash_locks != 0);
ut_a(srv_n_page_hash_locks <= MAX_PAGE_HASH_LOCKS);
- buf_pool->page_hash = ha_create(2 * buf_pool->curr_size,
+ buf_pool->page_hash = ib_create(2 * buf_pool->curr_size,
srv_n_page_hash_locks,
MEM_HEAP_FOR_PAGE_HASH,
SYNC_BUF_PAGE_HASH);
diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc
index 3c12d6da73f..46296814bb6 100644
--- a/storage/xtradb/buf/buf0dblwr.cc
+++ b/storage/xtradb/buf/buf0dblwr.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, 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
@@ -355,7 +355,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages)
{
diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc
index df62c945288..5f83d401f98 100644
--- a/storage/xtradb/buf/buf0dump.cc
+++ b/storage/xtradb/buf/buf0dump.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -680,6 +680,7 @@ DECLARE_THREAD(buf_dump_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
srv_buf_dump_thread_active = TRUE;
@@ -718,6 +719,7 @@ DECLARE_THREAD(buf_dump_thread)(
srv_buf_dump_thread_active = FALSE;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 018b29b7d95..4781b874032 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -357,6 +357,7 @@ buf_flush_insert_into_flush_list(
buf_block_t* block, /*!< in/out: block which is modified */
lsn_t lsn) /*!< in: oldest modification */
{
+ ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
ut_ad(log_flush_order_mutex_own());
ut_ad(mutex_own(&block->mutex));
@@ -415,6 +416,7 @@ buf_flush_insert_sorted_into_flush_list(
buf_page_t* prev_b;
buf_page_t* b;
+ ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
ut_ad(log_flush_order_mutex_own());
ut_ad(mutex_own(&block->mutex));
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
@@ -720,6 +722,7 @@ buf_flush_write_complete(
buf_page_set_io_fix(bpage, BUF_IO_NONE);
buf_pool->n_flush[flush_type]--;
+ ut_ad(buf_pool->n_flush[flush_type] != ULINT_MAX);
if (buf_pool->n_flush[flush_type] == 0
&& buf_pool->init_flush[flush_type] == FALSE) {
@@ -1054,6 +1057,7 @@ buf_flush_page(
}
++buf_pool->n_flush[flush_type];
+ ut_ad(buf_pool->n_flush[flush_type] != 0);
mutex_exit(&buf_pool->flush_state_mutex);
@@ -2196,13 +2200,14 @@ Clears up tail of the LRU lists:
* Flush dirty pages at the tail of LRU to the disk
The depth to which we scan each buffer pool is controlled by dynamic
config parameter innodb_LRU_scan_depth.
-@return number of pages flushed */
+@return number of flushed and evicted pages */
UNIV_INTERN
ulint
buf_flush_LRU_tail(void)
/*====================*/
{
ulint total_flushed = 0;
+ ulint total_evicted = 0;
ulint start_time = ut_time_ms();
ulint scan_depth[MAX_BUFFER_POOLS];
ulint requested_pages[MAX_BUFFER_POOLS];
@@ -2268,6 +2273,7 @@ buf_flush_LRU_tail(void)
limited_scan[i]
= (previous_evicted[i] > n.evicted);
previous_evicted[i] = n.evicted;
+ total_evicted += n.evicted;
requested_pages[i] += lru_chunk_size;
@@ -2300,7 +2306,7 @@ buf_flush_LRU_tail(void)
MONITOR_LRU_BATCH_PAGES,
total_flushed);
}
- return(total_flushed);
+ return(total_flushed + total_evicted);
}
/*********************************************************************//**
@@ -2601,6 +2607,23 @@ buf_get_total_free_list_length(void)
return result;
}
+/** Returns the aggregate LRU list length over all buffer pool instances.
+@return total LRU list length. */
+MY_ATTRIBUTE((warn_unused_result))
+static
+ulint
+buf_get_total_LRU_list_length(void)
+{
+ ulint result = 0;
+
+ for (ulint i = 0; i < srv_buf_pool_instances; i++) {
+
+ result += UT_LIST_GET_LEN(buf_pool_from_array(i)->LRU);
+ }
+
+ return result;
+}
+
/*********************************************************************//**
Adjust the desired page cleaner thread sleep time for LRU flushes. */
MY_ATTRIBUTE((nonnull))
@@ -2613,8 +2636,9 @@ page_cleaner_adapt_lru_sleep_time(
ulint lru_n_flushed) /*!< in: number of flushed in previous batch */
{
- ulint free_len = buf_get_total_free_list_length();
- ulint max_free_len = srv_LRU_scan_depth * srv_buf_pool_instances;
+ ulint free_len = buf_get_total_free_list_length();
+ ulint max_free_len = ut_min(buf_get_total_LRU_list_length(),
+ srv_LRU_scan_depth * srv_buf_pool_instances);
if (free_len < max_free_len / 100 && lru_n_flushed) {
@@ -2626,7 +2650,7 @@ page_cleaner_adapt_lru_sleep_time(
/* Free lists filled more than 20%
or no pages flushed in previous batch, sleep a bit more */
- *lru_sleep_time += 50;
+ *lru_sleep_time += 1;
if (*lru_sleep_time > srv_cleaner_max_lru_time)
*lru_sleep_time = srv_cleaner_max_lru_time;
} else if (free_len < max_free_len / 20 && *lru_sleep_time >= 50) {
@@ -2673,6 +2697,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ulint next_loop_time = ut_time_ms() + 1000;
ulint n_flushed = 0;
ulint last_activity = srv_get_activity_count();
@@ -2806,6 +2831,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_thread)(
thread_exit:
buf_page_cleaner_is_active = FALSE;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc
index 20ab5d75205..5d8cffa8de2 100644
--- a/storage/xtradb/dict/dict0boot.cc
+++ b/storage/xtradb/dict/dict0boot.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -461,7 +461,10 @@ dict_boot(void)
dberr_t err = DB_SUCCESS;
- if (srv_read_only_mode && !ibuf_is_empty()) {
+ /** If innodb_force_recovery is set to 6 then allow
+ the server to start even though ibuf is not empty. */
+ if (srv_force_recovery != SRV_FORCE_NO_LOG_REDO
+ && srv_read_only_mode && !ibuf_is_empty()) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Change buffer must be empty when --innodb-read-only "
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 01eaecb860d..108bdd8f60b 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -876,16 +876,24 @@ dict_index_get_nth_col_or_prefix_pos(
/*=================================*/
const dict_index_t* index, /*!< in: index */
ulint n, /*!< in: column number */
- ibool inc_prefix) /*!< in: TRUE=consider
+ ibool inc_prefix, /*!< in: TRUE=consider
column prefixes too */
+ ulint* prefix_col_pos) /*!< out: col num if prefix */
{
const dict_field_t* field;
const dict_col_t* col;
ulint pos;
ulint n_fields;
+ ulint prefixed_pos_dummy;
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+ ut_ad((inc_prefix && !prefix_col_pos) || (!inc_prefix));
+
+ if (!prefix_col_pos) {
+ prefix_col_pos = &prefixed_pos_dummy;
+ }
+ *prefix_col_pos = ULINT_UNDEFINED;
col = dict_table_get_nth_col(index->table, n);
@@ -899,10 +907,11 @@ dict_index_get_nth_col_or_prefix_pos(
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
- if (col == field->col
- && (inc_prefix || field->prefix_len == 0)) {
-
- return(pos);
+ if (col == field->col) {
+ *prefix_col_pos = pos;
+ if (inc_prefix || field->prefix_len == 0) {
+ return(pos);
+ }
}
}
@@ -1046,7 +1055,7 @@ dict_table_get_nth_col_pos(
ulint n) /*!< in: column number */
{
return(dict_index_get_nth_col_pos(dict_table_get_first_index(table),
- n));
+ n, NULL));
}
/********************************************************************//**
diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc
index c0a83c951a5..0063b6b9ed4 100644
--- a/storage/xtradb/dict/dict0stats.cc
+++ b/storage/xtradb/dict/dict0stats.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2017, 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
@@ -1110,10 +1110,10 @@ dict_stats_analyze_index_level(
leaf-level delete marks because delete marks on
non-leaf level do not make sense. */
- if (level == 0 && srv_stats_include_delete_marked? 0:
+ if (level == 0 && (srv_stats_include_delete_marked ? 0:
rec_get_deleted_flag(
rec,
- page_is_comp(btr_pcur_get_page(&pcur)))) {
+ page_is_comp(btr_pcur_get_page(&pcur))))) {
if (rec_is_last_on_page
&& !prev_rec_is_copied
diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc
index b3c8ef018f7..8cb419c6c37 100644
--- a/storage/xtradb/dict/dict0stats_bg.cc
+++ b/storage/xtradb/dict/dict0stats_bg.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -336,6 +336,7 @@ DECLARE_THREAD(dict_stats_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
ut_a(!srv_read_only_mode);
srv_dict_stats_thread_active = TRUE;
@@ -361,6 +362,7 @@ DECLARE_THREAD(dict_stats_thread)(
srv_dict_stats_thread_active = FALSE;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit instead of return(). */
os_thread_exit(NULL);
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 1a866a693ca..9855eaa87e5 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -154,7 +154,8 @@ initialized. */
fil_system_t* fil_system = NULL;
/** Determine if (i) is a user tablespace id or not. */
-# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
+# define fil_is_user_tablespace_id(i) (i != 0 \
+ && !srv_is_undo_tablespace(i))
/** Determine if user has explicitly disabled fsync(). */
#ifndef __WIN__
@@ -1943,7 +1944,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -3266,7 +3267,7 @@ fil_open_linked_file(
/*===============*/
const char* tablename, /*!< in: database/tablename */
char** remote_filepath,/*!< out: remote filepath */
- os_file_t* remote_file) /*!< out: remote file handle */
+ pfs_os_file_t* remote_file) /*!< out: remote file handle */
{
ibool success;
@@ -3326,7 +3327,8 @@ fil_create_new_single_table_tablespace(
tablespace file in pages,
must be >= FIL_IBD_FILE_INITIAL_SIZE */
{
- os_file_t file;
+ pfs_os_file_t file;
+
ibool ret;
dberr_t err;
byte* buf2;
@@ -5065,19 +5067,10 @@ retry:
int err;
do {
- err = posix_fallocate(node->handle, start_offset, len);
+ err = posix_fallocate(node->handle.m_file, start_offset, len);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
- success = !err;
- if (!success) {
- ib_logf(IB_LOG_LEVEL_ERROR, "extending file %s"
- " from " INT64PF " to " INT64PF " bytes"
- " failed with error %d",
- node->name, start_offset, len + start_offset,
- err);
- }
-
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
success = FALSE; os_has_said_disk_full = TRUE;);
@@ -5843,7 +5836,7 @@ fil_flush(
{
fil_space_t* space;
fil_node_t* node;
- os_file_t file;
+ pfs_os_file_t file;
mutex_enter(&fil_system->mutex);
@@ -6202,7 +6195,7 @@ fil_buf_block_init(
}
struct fil_iterator_t {
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
const char* filepath; /*!< File path name */
os_offset_t start; /*!< From where to start */
os_offset_t end; /*!< Where to stop */
@@ -6337,7 +6330,7 @@ fil_tablespace_iterate(
PageCallback& callback)
{
dberr_t err;
- os_file_t file;
+ pfs_os_file_t file;
char* filepath;
ut_a(n_io_buffers > 0);
diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc
index 2e335c1c255..f24973e26fb 100644
--- a/storage/xtradb/fts/fts0que.cc
+++ b/storage/xtradb/fts/fts0que.cc
@@ -953,6 +953,18 @@ fts_query_free_doc_ids(
query->total_size -= SIZEOF_RBT_CREATE;
}
+/**
+Free the query intersection
+@param[in] query query instance */
+static
+void
+fts_query_free_intersection(
+ fts_query_t* query)
+{
+ fts_query_free_doc_ids(query, query->intersection);
+ query->intersection = NULL;
+}
+
/*******************************************************************//**
Add the word to the documents "list" of matching words from
the query. We make a copy of the word from the query heap. */
@@ -1311,6 +1323,7 @@ fts_query_intersect(
/* error is passed by 'query->error' */
if (query->error != DB_SUCCESS) {
ut_ad(query->error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT);
+ fts_query_free_intersection(query);
return(query->error);
}
@@ -1339,6 +1352,8 @@ fts_query_intersect(
ut_a(!query->multi_exist || (query->multi_exist
&& rbt_size(query->doc_ids) <= n_doc_ids));
+ } else if (query->intersection != NULL) {
+ fts_query_free_intersection(query);
}
}
@@ -1557,6 +1572,11 @@ fts_merge_doc_ids(
query, ranking->doc_id, ranking->rank);
if (query->error != DB_SUCCESS) {
+ if (query->intersection != NULL)
+ {
+ ut_a(query->oper == FTS_EXIST);
+ fts_query_free_intersection(query);
+ }
DBUG_RETURN(query->error);
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 12ae71508c7..684ea9d8222 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
@@ -780,6 +780,32 @@ innobase_is_fake_change(
THD* thd) __attribute__((unused)); /*!< in: MySQL thread handle of the user for
whom the transaction is being committed */
+/** Empty free list algorithm.
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@param[in] algorithm desired algorithm from srv_empty_free_list_t
+@return true if it's possible to enable backoff. */
+static inline
+bool
+innodb_empty_free_list_algorithm_allowed(
+ srv_empty_free_list_t algorithm)
+{
+ long long buf_pool_pages = srv_buf_pool_size / srv_page_size
+ / srv_buf_pool_instances;
+
+ return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
+ || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
+}
+
/** Get the list of foreign keys referencing a specified table
table.
@param thd The thread handle
@@ -1070,6 +1096,10 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_x_lock_spin_rounds, SHOW_LONGLONG},
{"x_lock_spin_waits",
(char*) &export_vars.innodb_x_lock_spin_waits, SHOW_LONGLONG},
+ {"secondary_index_triggered_cluster_reads",
+ (char*) &export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG},
+ {"secondary_index_triggered_cluster_reads_avoided",
+ (char*) &export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG},
{NullS, NullS, SHOW_LONG}
};
@@ -1468,28 +1498,6 @@ normalize_table_name_low(
ibool set_lower_case); /* in: TRUE if we want to set
name to lower case */
-/*************************************************************//**
-Checks if buffer pool is big enough to enable backoff algorithm.
-InnoDB empty free list algorithm backoff requires free pages
-from LRU for the best performance.
-buf_LRU_buf_pool_running_out cancels query if 1/4 of
-buffer pool belongs to LRU or freelist.
-At the same time buf_flush_LRU_list_batch
-keeps up to BUF_LRU_MIN_LEN in LRU.
-In order to avoid deadlock baclkoff requires buffer pool
-to be at least 4*BUF_LRU_MIN_LEN,
-but flush peformance is bad because of trashing
-and additional BUF_LRU_MIN_LEN pages are requested.
-@return true if it's possible to enable backoff. */
-static
-bool
-innodb_empty_free_list_algorithm_backoff_allowed(
- srv_empty_free_list_t
- algorithm, /*!< in: desired algorithm
- from srv_empty_free_list_t */
- long long buf_pool_pages); /*!< in: total number
- of pages inside buffer pool */
-
#ifdef NOT_USED
/*************************************************************//**
Removes old archived transaction log files.
@@ -4011,10 +4019,9 @@ innobase_change_buffering_inited_ok:
srv_use_posix_fallocate = (ibool) innobase_use_fallocate;
#endif
/* Do not enable backoff algorithm for small buffer pool. */
- if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ if (!innodb_empty_free_list_algorithm_allowed(
static_cast<srv_empty_free_list_t>(
- srv_empty_free_list_algorithm),
- innobase_buffer_pool_size / srv_page_size)) {
+ srv_empty_free_list_algorithm))) {
sql_print_information(
"InnoDB: innodb_empty_free_list_algorithm "
"has been changed to legacy "
@@ -7365,9 +7372,31 @@ build_template_field(
}
if (dict_index_is_clust(index)) {
+ templ->rec_field_is_prefix = false;
templ->rec_field_no = templ->clust_rec_field_no;
+ templ->rec_prefix_field_no = ULINT_UNDEFINED;
} else {
- templ->rec_field_no = dict_index_get_nth_col_pos(index, i);
+ /* If we're in a secondary index, keep track of the original
+ index position even if this is just a prefix index; we will use
+ this later to avoid a cluster index lookup in some cases.*/
+
+ templ->rec_field_no = dict_index_get_nth_col_pos(index, i,
+ &templ->rec_prefix_field_no);
+ templ->rec_field_is_prefix
+ = (templ->rec_field_no == ULINT_UNDEFINED)
+ && (templ->rec_prefix_field_no != ULINT_UNDEFINED);
+#ifdef UNIV_DEBUG
+ if (templ->rec_prefix_field_no != ULINT_UNDEFINED)
+ {
+ const dict_field_t* field = dict_index_get_nth_field(
+ index,
+ templ->rec_prefix_field_no);
+ ut_ad(templ->rec_field_is_prefix
+ == (field->prefix_len != 0));
+ } else {
+ ut_ad(!templ->rec_field_is_prefix);
+ }
+#endif
}
if (field->real_maybe_null()) {
@@ -7559,7 +7588,8 @@ ha_innobase::build_template(
} else {
templ->icp_rec_field_no
= dict_index_get_nth_col_pos(
- prebuilt->index, i);
+ prebuilt->index, i,
+ NULL);
}
if (dict_index_is_clust(prebuilt->index)) {
@@ -7589,7 +7619,7 @@ ha_innobase::build_template(
templ->icp_rec_field_no
= dict_index_get_nth_col_or_prefix_pos(
- prebuilt->index, i, TRUE);
+ prebuilt->index, i, TRUE, NULL);
ut_ad(templ->icp_rec_field_no
!= ULINT_UNDEFINED);
@@ -11497,7 +11527,8 @@ ha_innobase::delete_table(
extension, in contrast to ::create */
normalize_table_name(norm_name, name);
- if (srv_read_only_mode) {
+ if (srv_read_only_mode
+ || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
DBUG_RETURN(HA_ERR_TABLE_READONLY);
} else if (row_is_magic_monitor_table(norm_name)
&& check_global_access(thd, PROCESS_ACL)) {
@@ -16858,15 +16889,17 @@ innodb_buffer_pool_evict_uncompressed(void)
ut_ad(block->page.in_LRU_list);
mutex_enter(&block->mutex);
- if (!buf_LRU_free_page(&block->page, false)) {
- mutex_exit(&block->mutex);
- all_evicted = false;
- } else {
- mutex_exit(&block->mutex);
+ all_evicted = buf_LRU_free_page(&block->page, false);
+ mutex_exit(&block->mutex);
+
+ if (all_evicted) {
+
mutex_enter(&buf_pool->LRU_list_mutex);
- }
+ block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
+ } else {
- block = prev_block;
+ block = prev_block;
+ }
}
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -17681,32 +17714,6 @@ innodb_status_output_update(
}
/*************************************************************//**
-Empty free list algorithm.
-Checks if buffer pool is big enough to enable backoff algorithm.
-InnoDB empty free list algorithm backoff requires free pages
-from LRU for the best performance.
-buf_LRU_buf_pool_running_out cancels query if 1/4 of
-buffer pool belongs to LRU or freelist.
-At the same time buf_flush_LRU_list_batch
-keeps up to BUF_LRU_MIN_LEN in LRU.
-In order to avoid deadlock baclkoff requires buffer pool
-to be at least 4*BUF_LRU_MIN_LEN,
-but flush peformance is bad because of trashing
-and additional BUF_LRU_MIN_LEN pages are requested.
-@return true if it's possible to enable backoff. */
-static
-bool
-innodb_empty_free_list_algorithm_backoff_allowed(
- srv_empty_free_list_t algorithm, /*!< in: desired algorithm
- from srv_empty_free_list_t */
- long long buf_pool_pages) /*!< in: total number
- of pages inside buffer pool */
-{
- return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
- || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
-}
-
-/*************************************************************//**
Empty free list algorithm. This function is registered as
a callback with MySQL.
@return 0 for valid algorithm */
@@ -17747,13 +17754,11 @@ innodb_srv_empty_free_list_algorithm_validate(
return(1);
algorithm = static_cast<srv_empty_free_list_t>(algo);
- if (!innodb_empty_free_list_algorithm_backoff_allowed(
- algorithm,
- innobase_buffer_pool_size / srv_page_size)) {
+ if (!innodb_empty_free_list_algorithm_allowed(algorithm)) {
sql_print_warning(
"InnoDB: innodb_empty_free_list_algorithm "
"= 'backoff' requires at least"
- " 20MB buffer pool.\n");
+ " 20MB buffer pool instances.\n");
return(1);
}
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index 3d20c9abccf..444c3095791 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -1260,7 +1260,8 @@ innobase_rec_to_mysql(
field->reset();
- ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE);
+ ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE,
+ NULL);
if (ipos == ULINT_UNDEFINED
|| rec_offs_nth_extern(offsets, ipos)) {
@@ -1312,7 +1313,8 @@ innobase_fields_to_mysql(
field->reset();
- ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE);
+ ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE,
+ NULL);
if (ipos == ULINT_UNDEFINED
|| dfield_is_ext(&fields[ipos])
diff --git a/storage/xtradb/include/buf0dblwr.h b/storage/xtradb/include/buf0dblwr.h
index 5582778825c..8e1b00db83c 100644
--- a/storage/xtradb/include/buf0dblwr.h
+++ b/storage/xtradb/include/buf0dblwr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -56,7 +56,7 @@ recovery, this function loads the pages from double write buffer into memory. */
void
buf_dblwr_init_or_load_pages(
/*=========================*/
- os_file_t file,
+ pfs_os_file_t file,
char* path,
bool load_corrupt_pages);
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index a2481fbad6f..ef6c32b1787 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -1168,8 +1168,9 @@ ulint
dict_index_get_nth_col_pos(
/*=======================*/
const dict_index_t* index, /*!< in: index */
- ulint n) /*!< in: column number */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+ ulint n, /*!< in: column number */
+ ulint* prefix_col_pos) /*!< out: col num if prefix */
+ MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/********************************************************************//**
Looks for column n in an index.
@return position in internal representation of the index;
@@ -1180,9 +1181,11 @@ dict_index_get_nth_col_or_prefix_pos(
/*=================================*/
const dict_index_t* index, /*!< in: index */
ulint n, /*!< in: column number */
- ibool inc_prefix) /*!< in: TRUE=consider
+ ibool inc_prefix, /*!< in: TRUE=consider
column prefixes too */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+ ulint* prefix_col_pos) /*!< out: col num if prefix */
+
+ MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/********************************************************************//**
Returns TRUE if the index contains a column or a prefix of that column.
@return TRUE if contains the column or its prefix */
diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic
index efc2c3f0e68..805092db715 100644
--- a/storage/xtradb/include/dict0dict.ic
+++ b/storage/xtradb/include/dict0dict.ic
@@ -1043,7 +1043,8 @@ dict_index_get_sys_col_pos(
}
return(dict_index_get_nth_col_pos(
- index, dict_table_get_sys_col_no(index->table, type)));
+ index, dict_table_get_sys_col_no(index->table, type),
+ NULL));
}
/*********************************************************************//**
@@ -1095,9 +1096,11 @@ ulint
dict_index_get_nth_col_pos(
/*=======================*/
const dict_index_t* index, /*!< in: index */
- ulint n) /*!< in: column number */
+ ulint n, /*!< in: column number */
+ ulint* prefix_col_pos) /*!< out: col num if prefix */
{
- return(dict_index_get_nth_col_or_prefix_pos(index, n, FALSE));
+ return(dict_index_get_nth_col_or_prefix_pos(index, n, FALSE,
+ prefix_col_pos));
}
#ifndef UNIV_HOTBACKUP
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 3023b29b793..6e7bd742374 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -183,7 +183,7 @@ struct fsp_open_info {
ibool success; /*!< Has the tablespace been opened? */
const char* check_msg; /*!< fil_check_first_page() message */
ibool valid; /*!< Is the tablespace valid? */
- os_file_t file; /*!< File handle */
+ pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */
lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */
@@ -198,7 +198,7 @@ struct fil_node_t {
belongs */
char* name; /*!< path to the file */
ibool open; /*!< TRUE if file open */
- os_file_t handle; /*!< OS handle to the file, if file open */
+ pfs_os_file_t handle; /*!< OS handle to the file, if file open */
os_event_t sync_event;/*!< Condition event to group and
serialize calls to fsync;
os_event_set() and os_event_reset()
@@ -571,7 +571,7 @@ UNIV_INTERN
const char*
fil_read_first_page(
/*================*/
- os_file_t data_file, /*!< in: open data file */
+ pfs_os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
@@ -1087,12 +1087,12 @@ struct PageCallback {
Called for every page in the tablespace. If the page was not
updated then its state must be set to BUF_PAGE_NOT_USED. For
compressed tables the page descriptor memory will be at offset:
- block->frame + UNIV_PAGE_SIZE;
+ block->frame + UNIV_PAGE_SIZE;
@param offset - physical offset within the file
@param block - block read from file, note it is not from the buffer pool
@retval DB_SUCCESS or error code. */
virtual dberr_t operator()(
- os_offset_t offset,
+ os_offset_t offset,
buf_block_t* block) UNIV_NOTHROW = 0;
/**
@@ -1100,7 +1100,7 @@ struct PageCallback {
to open it for the file that is being iterated over.
@param filename - then physical name of the tablespace file.
@param file - OS file handle */
- void set_file(const char* filename, os_file_t file) UNIV_NOTHROW
+ void set_file(const char* filename, pfs_os_file_t file) UNIV_NOTHROW
{
m_file = file;
m_filepath = filename;
@@ -1136,7 +1136,7 @@ struct PageCallback {
ulint m_page_size;
/** File handle to the tablespace */
- os_file_t m_file;
+ pfs_os_file_t m_file;
/** Physical file path. */
const char* m_filepath;
diff --git a/storage/xtradb/include/ha0ha.h b/storage/xtradb/include/ha0ha.h
index 7351b407e8c..58eb581e76a 100644
--- a/storage/xtradb/include/ha0ha.h
+++ b/storage/xtradb/include/ha0ha.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2016, 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
@@ -107,7 +107,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,level,n_m,type)
#else /* UNIV_SYNC_DEBUG */
/** Creates a hash table.
@return own: created table
@@ -116,7 +116,7 @@ chosen to be a slightly bigger prime number.
@param level in: level of the mutexes in the latching order
@param n_m in: number of mutexes to protect the hash table;
must be a power of 2, or 0 */
-# define ha_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
+# define ib_create(n_c,n_m,type,level) ha_create_func(n_c,n_m,type)
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h
index 722336dd6b4..5c3e7d07fd9 100644
--- a/storage/xtradb/include/log0online.h
+++ b/storage/xtradb/include/log0online.h
@@ -130,7 +130,7 @@ log_online_bitmap_iterator_next(
/** Struct for single bitmap file information */
struct log_online_bitmap_file_struct {
char name[FN_REFLEN]; /*!< Name with full path */
- os_file_t file; /*!< Handle to opened file */
+ pfs_os_file_t file; /*!< Handle to opened file */
ib_uint64_t size; /*!< Size of the file */
os_offset_t offset; /*!< Offset of the next read,
or count of already-read bytes
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index b8f30977fbe..5f11ba86275 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -69,7 +69,6 @@ typedef ib_uint64_t os_offset_t;
#define SRV_PATH_SEPARATOR '\\'
/** File handle */
# define os_file_t HANDLE
-# define os_file_invalid INVALID_HANDLE_VALUE
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
@@ -78,13 +77,22 @@ typedef ib_uint64_t os_offset_t;
#define SRV_PATH_SEPARATOR '/'
/** File handle */
typedef int os_file_t;
-# define os_file_invalid (-1)
/** Convert a C file descriptor to a native file handle
@param fd file descriptor
@return native file handle */
# define OS_FILE_FROM_FD(fd) fd
#endif
+/*Common file descriptor for file IO instrumentation with PFS
+on windows and other platforms */
+struct pfs_os_file_t
+{
+ os_file_t m_file;
+#ifdef UNIV_PFS_IO
+ struct PSI_file *m_psi;
+#endif
+};
+
/** Umask for creating files */
extern ulint os_innodb_umask;
@@ -120,6 +128,21 @@ enum os_file_create_t {
ON_ERROR_NO_EXIT is set */
};
+/** Options for os_file_advise_func @{ */
+enum os_file_advise_t {
+ OS_FILE_ADVISE_NORMAL = 1, /*!< no advice on access pattern
+ (default) */
+ OS_FILE_ADVISE_RANDOM = 2, /*!< access in random order */
+ OS_FILE_ADVISE_SEQUENTIAL = 4, /*!< access the specified data
+ sequentially (with lower offsets read
+ before higher ones) */
+ OS_FILE_ADVISE_WILLNEED = 8, /*!< specified data will be accessed
+ in the near future */
+ OS_FILE_ADVISE_DONTNEED = 16, /*!< specified data will not be
+ accessed in the near future */
+ OS_FILE_ADVISE_NOREUSE = 32 /*!< access only once */
+};
+
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
@@ -222,6 +245,8 @@ extern mysql_pfs_key_t innodb_file_bmp_key;
various file I/O operations with performance schema.
1) register_pfs_file_open_begin() and register_pfs_file_open_end() are
used to register file creation, opening, closing and renaming.
+2) register_pfs_file_rename_begin() and register_pfs_file_rename_end()
+are used to register file renaming
2) register_pfs_file_io_begin() and register_pfs_file_io_end() are
used to register actual file read, write and flush
3) register_pfs_file_close_begin() and register_pfs_file_close_end()
@@ -231,17 +256,30 @@ are used to register file deletion operations*/
do { \
locker = PSI_FILE_CALL(get_thread_file_name_locker)( \
state, key, op, name, &locker); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_open_wait)( \
locker, src_file, src_line); \
} \
} while (0)
-# define register_pfs_file_open_end(locker, file) \
+# define register_pfs_file_open_end(locker, file, result) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
- PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(\
- locker, file); \
+ if (locker != NULL) { \
+ file.m_psi = PSI_FILE_CALL( \
+ end_file_open_wait)( \
+ locker, result); \
+ } \
+} while (0)
+
+# define register_pfs_file_rename_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+ register_pfs_file_open_begin(state, locker, key, op, name, \
+ src_file, src_line) \
+
+# define register_pfs_file_rename_end(locker, result) \
+do { \
+ if (locker != NULL) { \
+ PSI_FILE_CALL(end_file_open_wait)(locker, result); \
} \
} while (0)
@@ -267,9 +305,9 @@ do { \
# define register_pfs_file_io_begin(state, locker, file, count, op, \
src_file, src_line) \
do { \
- locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( \
- state, file, op); \
- if (UNIV_LIKELY(locker != NULL)) { \
+ locker = PSI_FILE_CALL(get_thread_file_stream_locker)( \
+ state, file.m_psi, op); \
+ if (locker != NULL) { \
PSI_FILE_CALL(start_file_wait)( \
locker, count, src_file, src_line); \
} \
@@ -277,7 +315,7 @@ do { \
# define register_pfs_file_io_end(locker, count) \
do { \
- if (UNIV_LIKELY(locker != NULL)) { \
+ if (locker != NULL) { \
PSI_FILE_CALL(end_file_wait)(locker, count); \
} \
} while (0)
@@ -291,11 +329,16 @@ os_file_create
os_file_create_simple
os_file_create_simple_no_error_handling
os_file_close
+os_file_close_no_error_handling
os_file_rename
os_aio
os_file_read
os_file_read_no_error_handling
+os_file_read_no_error_handling_int_fd
os_file_write
+os_file_write_int_fd
+os_file_set_eof_at
+os_file_allocate
The wrapper functions have the prefix of "innodb_". */
@@ -313,20 +356,23 @@ The wrapper functions have the prefix of "innodb_". */
pfs_os_file_create_simple_no_error_handling_func( \
key, name, create_mode, access, success, __FILE__, __LINE__)
-# define os_file_close(file) \
+# define os_file_close_pfs(file) \
pfs_os_file_close_func(file, __FILE__, __LINE__)
+# define os_file_close_no_error_handling_pfs(file) \
+ pfs_os_file_close_no_error_handling_func(file, __FILE__, __LINE__)
+
# define os_aio(type, mode, name, file, buf, offset, \
n, message1, message2, space_id, trx) \
pfs_os_aio_func(type, mode, name, file, buf, offset, \
n, message1, message2, space_id, trx, \
__FILE__, __LINE__)
-# define os_file_read(file, buf, offset, n) \
+# define os_file_read_pfs(file, buf, offset, n) \
pfs_os_file_read_func(file, buf, offset, n, NULL, \
__FILE__, __LINE__)
-# define os_file_read_trx(file, buf, offset, n, trx) \
+# define os_file_read_trx_pfs(file, buf, offset, n, trx) \
pfs_os_file_read_func(file, buf, offset, n, trx, \
__FILE__, __LINE__)
@@ -334,11 +380,20 @@ The wrapper functions have the prefix of "innodb_". */
pfs_os_file_read_no_error_handling_func(file, buf, offset, n, \
__FILE__, __LINE__)
-# define os_file_write(name, file, buf, offset, n) \
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ pfs_os_file_read_no_error_handling_int_fd_func( \
+ file, buf, offset, n, __FILE__, __LINE__)
+
+# define os_file_write_pfs(name, file, buf, offset, n) \
pfs_os_file_write_func(name, file, buf, offset, \
n, __FILE__, __LINE__)
-# define os_file_flush(file) \
+# define os_file_write_int_fd(name, file, buf, offset, n) \
+ pfs_os_file_write_int_fd_func(name, file, buf, offset, \
+ n, __FILE__, __LINE__)
+
+# define os_file_flush_pfs(file) \
pfs_os_file_flush_func(file, __FILE__, __LINE__)
# define os_file_rename(key, oldpath, newpath) \
@@ -349,6 +404,15 @@ The wrapper functions have the prefix of "innodb_". */
# define os_file_delete_if_exists(key, name) \
pfs_os_file_delete_if_exists_func(key, name, __FILE__, __LINE__)
+
+# define os_file_set_eof_at_pfs(file, new_len) \
+ pfs_os_file_set_eof_at_func(file, new_len, __FILE__, __LINE__)
+
+# ifdef HAVE_POSIX_FALLOCATE
+# define os_file_allocate_pfs(file, offset, len) \
+ pfs_os_file_allocate_func(file, offset, len, __FILE__, __LINE__)
+# endif
+
#else /* UNIV_PFS_IO */
/* If UNIV_PFS_IO is not defined, these I/O APIs point
@@ -364,26 +428,36 @@ to original un-instrumented file I/O APIs */
os_file_create_simple_no_error_handling_func( \
name, create_mode, access, success)
-# define os_file_close(file) os_file_close_func(file)
+# define os_file_close_pfs(file) \
+ os_file_close_func(file)
+
+# define os_file_close_no_error_handling_pfs(file) \
+ os_file_close_no_error_handling_func(file)
# define os_aio(type, mode, name, file, buf, offset, n, message1, \
message2, space_id, trx) \
os_aio_func(type, mode, name, file, buf, offset, n, \
message1, message2, space_id, trx)
-# define os_file_read(file, buf, offset, n) \
+# define os_file_read_pfs(file, buf, offset, n) \
os_file_read_func(file, buf, offset, n, NULL)
-# define os_file_read_trx(file, buf, offset, n, trx) \
+# define os_file_read_trx_pfs(file, buf, offset, n, trx) \
os_file_read_func(file, buf, offset, n, trx)
# define os_file_read_no_error_handling(file, buf, offset, n) \
os_file_read_no_error_handling_func(file, buf, offset, n)
+# define os_file_read_no_error_handling_int_fd( \
+ file, buf, offset, n) \
+ os_file_read_no_error_handling_func(file, buf, offset, n)
-# define os_file_write(name, file, buf, offset, n) \
+# define os_file_write_int_fd(name, file, buf, offset, n) \
os_file_write_func(name, file, buf, offset, n)
+# define os_file_write_pfs(name, file, buf, offset, n) \
+ os_file_write_func(name, file, buf, offset, n)
+
-# define os_file_flush(file) os_file_flush_func(file)
+# define os_file_flush_pfs(file) os_file_flush_func(file)
# define os_file_rename(key, oldpath, newpath) \
os_file_rename_func(oldpath, newpath)
@@ -393,8 +467,78 @@ to original un-instrumented file I/O APIs */
# define os_file_delete_if_exists(key, name) \
os_file_delete_if_exists_func(name)
+# define os_file_set_eof_at_pfs(file, new_len) \
+ os_file_set_eof_at_func(file, new_len)
+
+# ifdef HAVE_POSIX_FALLOCATE
+# define os_file_allocate_pfs(file, offset, len) \
+ os_file_allocate_func(file, offset, len)
+# endif
+
#endif /* UNIV_PFS_IO */
+#ifdef UNIV_PFS_IO
+ #define os_file_close(file) os_file_close_pfs(file)
+#else
+ #define os_file_close(file) os_file_close_pfs((file).m_file)
+#endif
+
+#ifdef UNIV_PFS_IO
+ #define os_file_close_no_error_handling(file) \
+ os_file_close_no_error_handling_pfs(file)
+#else
+ #define os_file_close_no_error_handling(file) \
+ os_file_close_no_error_handling_pfs((file).m_file)
+#endif
+
+#ifdef UNIV_PFS_IO
+ #define os_file_read(file, buf, offset, n) \
+ os_file_read_pfs(file, buf, offset, n)
+#else
+ #define os_file_read(file, buf, offset, n) \
+ os_file_read_pfs(file.m_file, buf, offset, n)
+#endif
+
+#ifdef UNIV_PFS_IO
+ # define os_file_read_trx(file, buf, offset, n, trx) \
+ os_file_read_trx_pfs(file, buf, offset, n, trx)
+#else
+ # define os_file_read_trx(file, buf, offset, n, trx) \
+ os_file_read_trx_pfs(file.m_file, buf, offset, n, trx)
+#endif
+
+#ifdef UNIV_PFS_IO
+ #define os_file_flush(file) os_file_flush_pfs(file)
+#else
+ #define os_file_flush(file) os_file_flush_pfs(file.m_file)
+#endif
+
+#ifdef UNIV_PFS_IO
+ #define os_file_write(name, file, buf, offset, n) \
+ os_file_write_pfs(name, file, buf, offset, n)
+#else
+ #define os_file_write(name, file, buf, offset, n) \
+ os_file_write_pfs(name, file.m_file, buf, offset, n)
+#endif
+
+#ifdef UNIV_PFS_IO
+ #define os_file_set_eof_at(file, new_len) \
+ os_file_set_eof_at_pfs(file, new_len)
+#else
+ #define os_file_set_eof_at(file, new_len) \
+ os_file_set_eof_at_pfs(file.m_file, new_len)
+#endif
+
+#ifdef HAVE_POSIX_FALLOCATE
+#ifdef UNIV_PFS_IO
+ #define os_file_allocate(file, offset, len) \
+ os_file_allocate_pfs(file, offset, len)
+#else
+ #define os_file_allocate(file, offset, len) \
+ os_file_allocate_pfs(file.m_file, offset, len)
+#endif
+#endif
+
/* File types for directory entry data type */
enum os_file_type_t {
@@ -528,7 +672,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -561,7 +705,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -620,6 +764,42 @@ ibool
os_file_close_func(
/*===============*/
os_file_t file); /*!< in, own: handle to a file */
+/***********************************************************************//**
+NOTE! Use the corresponding macro os_file_close(), not directly this
+function!
+Closes a file handle. In case of error, error number can be retrieved with
+os_file_get_last_error.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_close_no_error_handling_func(
+/*===============*/
+ os_file_t file); /*!< in, own: handle to a file */
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+Truncates a file at the specified position.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_set_eof_at_func(
+ os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len);/*!< in: new file length */
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_allocate_func(
+ os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len); /*!< in: file region length */
+#endif
#ifdef UNIV_PFS_IO
/****************************************************************//**
@@ -630,7 +810,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -653,7 +833,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -677,7 +857,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -706,7 +886,20 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_close_no_error_handling(),
+not directly this function!
+A performance schema instrumented wrapper function for
+os_file_close_no_error_handling().
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_close_no_error_handling_func(
+/*===================*/
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
/*******************************************************************//**
@@ -719,7 +912,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -738,7 +931,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -759,7 +952,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -788,7 +981,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -805,7 +998,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
@@ -857,16 +1050,66 @@ pfs_os_file_delete_if_exists_func(
string */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line);/*!< in: line where the func invoked */
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_set_eof_at()
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_set_eof_at_func(
+ pfs_os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len,/*!< in: new file length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_allocate_func(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line);/*!< in: line where the func invoked */
+#endif
+
#endif /* UNIV_PFS_IO */
/***********************************************************************//**
-Closes a file handle.
-@return TRUE if success */
+Checks if the file is marked as invalid.
+@return TRUE if invalid */
UNIV_INTERN
-ibool
-os_file_close_no_error_handling(
-/*============================*/
- os_file_t file); /*!< in, own: handle to a file */
+bool
+os_file_is_invalid(
+ pfs_os_file_t file); /*!< in, own: handle to a file */
+
+/***********************************************************************//**
+Marks the file as invalid. */
+UNIV_INTERN
+void
+os_file_mark_invalid(
+ pfs_os_file_t* file); /*!< out: pointer to a handle to a file */
+
+/***********************************************************************//**
+Announces an intention to access file data in a specific pattern in the
+future.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_advise(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ ulint advice);/*!< in: advice for access pattern */
+
/***********************************************************************//**
Gets a file size.
@return file size, or (os_offset_t) -1 on failure */
@@ -874,7 +1117,7 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
MY_ATTRIBUTE((warn_unused_result));
/***********************************************************************//**
Write the specified number of zeros to a newly created file.
@@ -885,7 +1128,7 @@ os_file_set_size(
/*=============*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
os_offset_t size) /*!< in: file size */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/***********************************************************************//**
@@ -897,14 +1140,6 @@ os_file_set_eof(
/*============*/
FILE* file); /*!< in: file to be truncated */
/***********************************************************************//**
-Truncates a file at the specified position.
-@return TRUE if success */
-UNIV_INTERN
-ibool
-os_file_set_eof_at(
- os_file_t file, /*!< in: handle to a file */
- ib_uint64_t new_len);/*!< in: new file length */
-/***********************************************************************//**
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
Flushes the write buffers of a given file to the disk.
@return TRUE if success */
@@ -1132,7 +1367,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
diff --git a/storage/xtradb/include/os0file.ic b/storage/xtradb/include/os0file.ic
index 25a1397147e..c82a2559fed 100644
--- a/storage/xtradb/include/os0file.ic
+++ b/storage/xtradb/include/os0file.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2010, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2010, 2017, 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
@@ -34,7 +34,7 @@ os_file_create_simple() which opens or creates a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_func(
/*===========================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -47,7 +47,7 @@ pfs_os_file_create_simple_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -58,11 +58,13 @@ pfs_os_file_create_simple_func(
: PSI_FILE_OPEN),
name, src_file, src_line);
- file = os_file_create_simple_func(name, create_mode,
+ file.m_file = os_file_create_simple_func(name, create_mode,
access_type, success);
+ file.m_psi = NULL;
- /* Regsiter the returning "file" value with the system */
- register_pfs_file_open_end(locker, file);
+ /* Regsiter psi value for the file */
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -76,7 +78,7 @@ monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_simple_no_error_handling_func(
/*=============================================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -91,7 +93,7 @@ pfs_os_file_create_simple_no_error_handling_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -104,8 +106,10 @@ pfs_os_file_create_simple_no_error_handling_func(
file = os_file_create_simple_no_error_handling_func(
name, create_mode, access_type, success);
+ file.m_psi = NULL;
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -118,7 +122,7 @@ Add instrumentation to monitor file creation/open.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INLINE
-os_file_t
+pfs_os_file_t
pfs_os_file_create_func(
/*====================*/
mysql_pfs_key_t key, /*!< in: Performance Schema Key */
@@ -137,7 +141,7 @@ pfs_os_file_create_func(
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
- os_file_t file;
+ pfs_os_file_t file;
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
@@ -149,8 +153,10 @@ pfs_os_file_create_func(
name, src_file, src_line);
file = os_file_create_func(name, create_mode, purpose, type, success);
+ file.m_psi = NULL;
- register_pfs_file_open_end(locker, file);
+ register_pfs_file_open_end(locker, file,
+ (*success == TRUE ? success : 0));
return(file);
}
@@ -164,7 +170,7 @@ UNIV_INLINE
ibool
pfs_os_file_close_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -176,7 +182,35 @@ pfs_os_file_close_func(
register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE,
src_file, src_line);
- result = os_file_close_func(file);
+ result = os_file_close_func(file.m_file);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_close_no_error_handling(),
+not directly this function!
+A performance schema instrumented wrapper function for
+os_file_close_no_error_handling().
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_close_no_error_handling_func(
+/*===================*/
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ /* register the file close */
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CLOSE,
+ src_file, src_line);
+
+ result = os_file_close_no_error_handling_func(file.m_file);
register_pfs_file_io_end(locker, 0);
@@ -197,7 +231,7 @@ pfs_os_aio_func(
ulint mode, /*!< in: OS_AIO_NORMAL etc. I/O mode */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -244,7 +278,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_func(
/*==================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -259,7 +293,7 @@ pfs_os_file_read_func(
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ,
src_file, src_line);
- result = os_file_read_func(file, buf, offset, n, trx);
+ result = os_file_read_func(file.m_file, buf, offset, n, trx);
register_pfs_file_io_end(locker, n);
@@ -278,7 +312,7 @@ UNIV_INLINE
ibool
pfs_os_file_read_no_error_handling_func(
/*====================================*/
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read */
os_offset_t offset, /*!< in: file offset where to read */
ulint n, /*!< in: number of bytes to read */
@@ -292,13 +326,50 @@ pfs_os_file_read_no_error_handling_func(
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_READ,
src_file, src_line);
- result = os_file_read_no_error_handling_func(file, buf, offset, n);
+ result = os_file_read_no_error_handling_func(file.m_file, buf, offset, n);
register_pfs_file_io_end(locker, n);
return(result);
}
+/** NOTE! Please use the corresponding macro
+os_file_read_no_error_handling_int_fd(), not directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_read_no_error_handling_int_fd_func() which requests a
+synchronous read operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_read_no_error_handling_int_fd_func(
+ int file, /*!< in: handle to a file */
+ void* buf, /*!< in: buffer where to read */
+ os_offset_t offset, /*!< in: file offset where to read */
+ ulint n, /*!< in: number of bytes to read */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker = NULL;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_READ);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_read_no_error_handling_func(
+ OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/*******************************************************************//**
NOTE! Please use the corresponding macro os_file_write(), not directly
this function!
@@ -311,7 +382,7 @@ pfs_os_file_write_func(
/*===================*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
const void* buf, /*!< in: buffer from which to write */
os_offset_t offset, /*!< in: file offset where to write */
ulint n, /*!< in: number of bytes to write */
@@ -325,13 +396,50 @@ pfs_os_file_write_func(
register_pfs_file_io_begin(&state, locker, file, n, PSI_FILE_WRITE,
src_file, src_line);
- result = os_file_write_func(name, file, buf, offset, n);
+ result = os_file_write_func(name, file.m_file, buf, offset, n);
register_pfs_file_io_end(locker, n);
return(result);
}
+/** NOTE! Please use the corresponding macro os_file_write(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_write() which requests a synchronous write operation.
+@return TRUE if request was successful, FALSE if fail */
+UNIV_INLINE
+ibool
+pfs_os_file_write_int_fd_func(
+ const char* name, /*!< in: name of the file or path as a
+ null-terminated string */
+ int file, /*!< in: handle to a file */
+ const void* buf, /*!< in: buffer from which to write */
+ os_offset_t offset, /*!< in: file offset where to write */
+ ulint n, /*!< in: number of bytes to write */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ PSI_file_locker_state state;
+ struct PSI_file_locker* locker = NULL;
+
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, file, PSI_FILE_WRITE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, n,
+ __FILE__, __LINE__);
+ }
+ ibool result = os_file_write_func(
+ name, OS_FILE_FROM_FD(file), buf, offset, n);
+
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, n);
+ }
+
+ return(result);
+}
+
/***********************************************************************//**
NOTE! Please use the corresponding macro os_file_flush(), not directly
this function!
@@ -342,7 +450,7 @@ UNIV_INLINE
ibool
pfs_os_file_flush_func(
/*===================*/
- os_file_t file, /*!< in, own: handle to a file */
+ pfs_os_file_t file, /*!< in, own: handle to a file */
const char* src_file,/*!< in: file name where func invoked */
ulint src_line)/*!< in: line where the func invoked */
{
@@ -352,7 +460,7 @@ pfs_os_file_flush_func(
register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_SYNC,
src_file, src_line);
- result = os_file_flush_func(file);
+ result = os_file_flush_func(file.m_file);
register_pfs_file_io_end(locker, 0);
@@ -380,12 +488,12 @@ pfs_os_file_rename_func(
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
+ register_pfs_file_rename_begin(&state, locker, key, PSI_FILE_RENAME, newpath,
src_file, src_line);
result = os_file_rename_func(oldpath, newpath);
- register_pfs_file_open_end(locker, 0);
+ register_pfs_file_rename_end(locker, 0);
return(result);
}
@@ -449,4 +557,61 @@ pfs_os_file_delete_if_exists_func(
return(result);
}
+
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_set_eof_at(), not
+directly this function!
+This is the performance schema instrumented wrapper function for
+os_file_set_eof_at()
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_set_eof_at_func(
+ pfs_os_file_t file, /*!< in: handle to a file */
+ ib_uint64_t new_len,/*!< in: new file length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE,
+ src_file, src_line);
+ result = os_file_set_eof_at_func(file.m_file, new_len);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+NOTE! Please use the corresponding macro os_file_allocate(), not
+directly this function!
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INLINE
+bool
+pfs_os_file_allocate_func(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ const char* src_file,/*!< in: file name where func invoked */
+ ulint src_line)/*!< in: line where the func invoked */
+{
+ bool result;
+ struct PSI_file_locker* locker = NULL;
+ PSI_file_locker_state state;
+
+ register_pfs_file_io_begin(&state, locker, file, 0, PSI_FILE_CHSIZE,
+ src_file, src_line);
+ result = os_file_allocate_func(file.m_file, offset, len);
+
+ register_pfs_file_io_end(locker, 0);
+
+ return(result);
+}
+#endif
+
#endif /* UNIV_PFS_IO */
diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h
index e1148517d99..217a9547f1e 100644
--- a/storage/xtradb/include/row0mysql.h
+++ b/storage/xtradb/include/row0mysql.h
@@ -611,6 +611,12 @@ struct mysql_row_templ_t {
Innobase record in the current index;
not defined if template_type is
ROW_MYSQL_WHOLE_ROW */
+ bool rec_field_is_prefix; /* is this field in a prefix index? */
+ ulint rec_prefix_field_no; /* record field, even if just a
+ prefix; same as rec_field_no when not a
+ prefix, otherwise rec_field_no is
+ ULINT_UNDEFINED but this is the true
+ field number*/
ulint clust_rec_field_no; /*!< field number of the column in an
Innobase record in the clustered index;
not defined if template_type is
@@ -713,7 +719,9 @@ struct row_prebuilt_t {
columns through a secondary index
and at least one column is not in
the secondary index, then this is
- set to TRUE */
+ set to TRUE; note that sometimes this
+ is set but we later optimize out the
+ clustered index lookup */
unsigned templ_contains_blob:1;/*!< TRUE if the template contains
a column with DATA_BLOB ==
get_innobase_type_from_mysql_type();
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 1ca8e6de591..cfd961d9c46 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -610,6 +610,11 @@ extern my_bool srv_print_all_deadlocks;
extern my_bool srv_cmp_per_index_enabled;
+/** Number of times secondary index lookup triggered cluster lookup */
+extern ulint srv_sec_rec_cluster_reads;
+/** Number of times prefix optimization avoided triggering cluster lookup */
+extern ulint srv_sec_rec_cluster_reads_avoided;
+
/** Status variables to be passed to MySQL */
extern struct export_var_t export_vars;
@@ -990,6 +995,13 @@ UNIV_INTERN
void
srv_purge_wakeup();
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id);
+
/** Status variables to be passed to MySQL */
struct export_var_t{
ulint innodb_adaptive_hash_hash_searches;
@@ -1106,6 +1118,9 @@ struct export_var_t{
#endif /* UNIV_DEBUG */
ulint innodb_column_compressed; /*!< srv_column_compressed */
ulint innodb_column_decompressed; /*!< srv_column_decompressed */
+
+ ulint innodb_sec_rec_cluster_reads; /*!< srv_sec_rec_cluster_reads */
+ ulint innodb_sec_rec_cluster_reads_avoided; /*!< srv_sec_rec_cluster_reads_avoided */
};
/** Thread slot in the thread table. */
diff --git a/storage/xtradb/include/srv0start.h b/storage/xtradb/include/srv0start.h
index 963b767f0fb..a60776a4665 100644
--- a/storage/xtradb/include/srv0start.h
+++ b/storage/xtradb/include/srv0start.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, 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
@@ -139,6 +139,8 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
/** TRUE if a raw partition is in use */
extern ibool srv_start_raw_disk_in_use;
+/** Undo tablespaces starts with space_id. */
+extern ulint srv_undo_space_id_start;
/** Shutdown state */
enum srv_shutdown_state {
diff --git a/storage/xtradb/include/trx0xa.h b/storage/xtradb/include/trx0xa.h
index 7caddfb7ba4..4d5adc68dcd 100644
--- a/storage/xtradb/include/trx0xa.h
+++ b/storage/xtradb/include/trx0xa.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, 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
@@ -24,6 +24,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
#ifndef XA_H
#define XA_H
+#include "handler.h"
+
/*
* Transaction branch identification: XID and NULLXID:
*/
@@ -35,17 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define MAXGTRIDSIZE 64 /*!< maximum size in bytes of gtrid */
#define MAXBQUALSIZE 64 /*!< maximum size in bytes of bqual */
-/** X/Open XA distributed transaction identifier */
-struct xid_t {
- long formatID; /*!< format identifier; -1
- means that the XID is null */
- long gtrid_length; /*!< value from 1 through 64 */
- long bqual_length; /*!< value from 1 through 64 */
- char data[XIDDATASIZE]; /*!< distributed transaction
- identifier */
-};
-/** X/Open XA distributed transaction identifier */
-typedef struct xid_t XID;
#endif
/** X/Open XA distributed transaction status codes */
/* @{ */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index fff5c0a67a1..a82faa76eef 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 35
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 80.0
+#define PERCONA_INNODB_VERSION 82.0
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
@@ -146,14 +146,8 @@ HAVE_PSI_INTERFACE is defined. */
#if defined HAVE_PSI_INTERFACE && !defined UNIV_HOTBACKUP
# define UNIV_PFS_MUTEX
# define UNIV_PFS_RWLOCK
-/* For I/O instrumentation, performance schema rely
-on a native descriptor to identify the file, this
-descriptor could conflict with our OS level descriptor.
-Disable IO instrumentation on Windows until this is
-resolved */
-# ifndef __WIN__
-# define UNIV_PFS_IO
-# endif
+
+# define UNIV_PFS_IO
# define UNIV_PFS_THREAD
/* There are mutexes/rwlocks that we want to exclude from
diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc
index 5ef9203ce72..47261aa633a 100644
--- a/storage/xtradb/log/log0log.cc
+++ b/storage/xtradb/log/log0log.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2017, MariaDB Corporation.
@@ -2741,7 +2741,7 @@ log_group_archive(
/*==============*/
log_group_t* group) /*!< in: log group */
{
- os_file_t file_handle;
+ pfs_os_file_t file_handle;
lsn_t start_lsn;
lsn_t end_lsn;
char name[OS_FILE_MAX_PATH];
@@ -3716,9 +3716,15 @@ loop:
lsn = log_sys->lsn;
- if (lsn != log_sys->last_checkpoint_lsn
- || (srv_track_changed_pages
- && (tracked_lsn != log_sys->last_checkpoint_lsn))
+ const bool is_last =
+ ((srv_force_recovery == SRV_FORCE_NO_LOG_REDO
+ && lsn == log_sys->last_checkpoint_lsn
+ + LOG_BLOCK_HDR_SIZE)
+ || lsn == log_sys->last_checkpoint_lsn)
+ && (!srv_track_changed_pages
+ || tracked_lsn == log_sys->last_checkpoint_lsn);
+
+ if (!is_last
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
@@ -3784,7 +3790,8 @@ loop:
ut_a(freed);
ut_a(lsn == log_sys->lsn);
- ut_ad(lsn == log_sys->last_checkpoint_lsn);
+ ut_ad(srv_force_recovery >= SRV_FORCE_NO_LOG_REDO
+ || lsn == log_sys->last_checkpoint_lsn);
if (lsn < srv_start_lsn) {
ib_logf(IB_LOG_LEVEL_ERROR,
diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc
index 764c9e0c52f..3cd1412098d 100644
--- a/storage/xtradb/log/log0online.cc
+++ b/storage/xtradb/log/log0online.cc
@@ -328,7 +328,7 @@ log_online_read_last_tracked_lsn(void)
lsn_t result;
os_offset_t read_offset = log_bmp_sys->out.offset;
- while (!checksum_ok && read_offset > 0 && !is_last_page)
+ while ((!checksum_ok || !is_last_page) && read_offset > 0)
{
read_offset -= MODIFIED_PAGE_BLOCK_SIZE;
log_bmp_sys->out.offset = read_offset;
@@ -556,9 +556,9 @@ log_online_rotate_bitmap_file(
lsn_t next_file_start_lsn) /*!<in: the start LSN name
part */
{
- if (log_bmp_sys->out.file != os_file_invalid) {
+ if (!os_file_is_invalid(log_bmp_sys->out.file)) {
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
log_bmp_sys->out_seq_num++;
log_online_make_bitmap_name(next_file_start_lsn);
@@ -728,7 +728,11 @@ log_online_read_init(void)
}
last_tracked_lsn = log_online_read_last_tracked_lsn();
+ /* Do not rotate if we truncated the file to zero length - we
+ can just start writing there */
+ const bool need_rotate = (last_tracked_lsn != 0);
if (!last_tracked_lsn) {
+
last_tracked_lsn = last_file_start_lsn;
}
@@ -740,7 +744,10 @@ log_online_read_init(void)
} else {
file_start_lsn = tracking_start_lsn;
}
- if (!log_online_rotate_bitmap_file(file_start_lsn)) {
+
+ if (need_rotate
+ && !log_online_rotate_bitmap_file(file_start_lsn)) {
+
exit(1);
}
@@ -780,9 +787,9 @@ log_online_read_shutdown(void)
ib_rbt_node_t *free_list_node = log_bmp_sys->page_free_list;
- if (log_bmp_sys->out.file != os_file_invalid) {
+ if (!os_file_is_invalid(log_bmp_sys->out.file)) {
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
rbt_free(log_bmp_sys->modified_pages);
@@ -1121,6 +1128,18 @@ log_online_write_bitmap_page(
}
});
+ /* A crash injection site that ensures last checkpoint LSN > last
+ tracked LSN, so that LSN tracking for this interval is tested. */
+ DBUG_EXECUTE_IF("crash_before_bitmap_write",
+ {
+ ulint space_id
+ = mach_read_from_4(block
+ + MODIFIED_PAGE_SPACE_ID);
+ if (space_id > 0)
+ DBUG_SUICIDE();
+ });
+
+
ibool success = os_file_write(log_bmp_sys->out.name,
log_bmp_sys->out.file, block,
log_bmp_sys->out.offset,
@@ -1144,10 +1163,8 @@ log_online_write_bitmap_page(
return FALSE;
}
-#ifdef UNIV_LINUX
- posix_fadvise(log_bmp_sys->out.file, log_bmp_sys->out.offset,
- MODIFIED_PAGE_BLOCK_SIZE, POSIX_FADV_DONTNEED);
-#endif
+ os_file_advise(log_bmp_sys->out.file, log_bmp_sys->out.offset,
+ MODIFIED_PAGE_BLOCK_SIZE, OS_FILE_ADVISE_DONTNEED);
log_bmp_sys->out.offset += MODIFIED_PAGE_BLOCK_SIZE;
return TRUE;
@@ -1269,10 +1286,6 @@ log_online_follow_redo_log(void)
group = UT_LIST_GET_NEXT(log_groups, group);
}
- /* A crash injection site that ensures last checkpoint LSN > last
- tracked LSN, so that LSN tracking for this interval is tested. */
- DBUG_EXECUTE_IF("crash_before_bitmap_write", DBUG_SUICIDE(););
-
result = log_online_write_bitmap();
log_bmp_sys->start_lsn = log_bmp_sys->end_lsn;
log_set_tracked_lsn(log_bmp_sys->start_lsn);
@@ -1542,10 +1555,8 @@ log_online_open_bitmap_file_read_only(
bitmap_file->size = os_file_get_size(bitmap_file->file);
bitmap_file->offset = 0;
-#ifdef UNIV_LINUX
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_SEQUENTIAL);
- posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE);
-#endif
+ os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_SEQUENTIAL);
+ os_file_advise(bitmap_file->file, 0, 0, OS_FILE_ADVISE_NOREUSE);
return TRUE;
}
@@ -1631,7 +1642,7 @@ log_online_bitmap_iterator_init(
/* Empty range */
i->in_files.count = 0;
i->in_files.files = NULL;
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
i->page = NULL;
i->failed = FALSE;
return TRUE;
@@ -1649,7 +1660,7 @@ log_online_bitmap_iterator_init(
if (i->in_files.count == 0) {
/* Empty range */
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
i->page = NULL;
i->failed = FALSE;
return TRUE;
@@ -1688,10 +1699,10 @@ log_online_bitmap_iterator_release(
{
ut_a(i);
- if (i->in.file != os_file_invalid) {
+ if (!os_file_is_invalid(i->in.file)) {
os_file_close(i->in.file);
- i->in.file = os_file_invalid;
+ os_file_mark_invalid(&i->in.file);
}
if (i->in_files.files) {
@@ -1745,8 +1756,9 @@ log_online_bitmap_iterator_next(
/* Advance file */
i->in_i++;
- success = os_file_close_no_error_handling(i->in.file);
- i->in.file = os_file_invalid;
+ success = os_file_close_no_error_handling(
+ i->in.file);
+ os_file_mark_invalid(&i->in.file);
if (UNIV_UNLIKELY(!success)) {
os_file_get_last_error(TRUE);
@@ -1855,7 +1867,7 @@ log_online_purge_changed_page_bitmaps(
/* If we have to delete the current output file, close it
first. */
os_file_close(log_bmp_sys->out.file);
- log_bmp_sys->out.file = os_file_invalid;
+ os_file_mark_invalid(&log_bmp_sys->out.file);
}
for (i = 0; i < bitmap_files.count; i++) {
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index 4edfb1e4347..6f76d151af3 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2017, MariaDB Corporation.
@@ -327,6 +327,7 @@ DECLARE_THREAD(recv_writer_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -357,6 +358,7 @@ DECLARE_THREAD(recv_writer_thread)(
recv_writer_thread_active = false;
+ my_thread_end();
/* We count the number of threads in os_thread_exit().
A created thread should always use that to exit and not
use return() to exit. */
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index 9632bb77df9..9e5da12bb41 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -87,9 +87,11 @@ my_umask */
#ifndef __WIN__
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+# define os_file_invalid (-1)
#else
/** Umask for creating files */
UNIV_INTERN ulint os_innodb_umask = 0;
+# define os_file_invalid INVALID_HANDLE_VALUE
#endif /* __WIN__ */
#ifndef UNIV_HOTBACKUP
@@ -184,7 +186,7 @@ struct os_aio_slot_t{
byte* buf; /*!< buffer used in i/o */
ulint type; /*!< OS_FILE_READ or OS_FILE_WRITE */
os_offset_t offset; /*!< file offset in bytes */
- os_file_t file; /*!< file where to read or write */
+ pfs_os_file_t file; /*!< file where to read or write */
const char* name; /*!< file name or path */
ibool io_already_done;/*!< used only in simulated aio:
TRUE if the physical i/o already
@@ -1427,7 +1429,7 @@ A simple function to open or create a file.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_simple_no_error_handling_func(
/*=========================================*/
const char* name, /*!< in: name of the file or path as a
@@ -1441,7 +1443,7 @@ os_file_create_simple_no_error_handling_func(
if it would be enabled otherwise) */
ibool* success)/*!< out: TRUE if succeed, FALSE if error */
{
- os_file_t file;
+ pfs_os_file_t file;
*success = FALSE;
#ifdef __WIN__
@@ -1449,7 +1451,6 @@ os_file_create_simple_no_error_handling_func(
DWORD create_flag;
DWORD attributes = 0;
DWORD share_mode = FILE_SHARE_READ;
-
ut_a(name);
ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT));
@@ -1466,8 +1467,8 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file.m_file = (os_file_t)-1;
+ return(file);
}
if (access_type == OS_FILE_READ_ONLY) {
@@ -1491,11 +1492,11 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file access type (%lu) for file '%s'",
access_type, name);
-
- return((os_file_t) -1);
+ file.m_file = (os_file_t)-1;
+ return(file);
}
- file = CreateFile((LPCTSTR) name,
+ file.m_file = CreateFile((LPCTSTR) name,
access,
share_mode,
NULL, // Security attributes
@@ -1503,11 +1504,10 @@ os_file_create_simple_no_error_handling_func(
attributes,
NULL); // No template file
- *success = (file != INVALID_HANDLE_VALUE);
+ *success = (file.m_file != INVALID_HANDLE_VALUE);
#else /* __WIN__ */
int create_flag;
const char* mode_str = NULL;
-
ut_a(name);
ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT));
@@ -1550,19 +1550,19 @@ os_file_create_simple_no_error_handling_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
-
- return((os_file_t) -1);
+ file.m_file = -1;
+ return(file);
}
- file = ::open(name, create_flag, os_innodb_umask);
+ file.m_file = ::open(name, create_flag, os_innodb_umask);
- *success = file == -1 ? FALSE : TRUE;
+ *success = file.m_file == -1 ? FALSE : TRUE;
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
we open the same file in the same mode, see man page of open(2). */
if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str,
+ os_file_set_nocache_if_needed(file.m_file, name, mode_str,
OS_DATA_FILE, access_type);
}
@@ -1571,11 +1571,11 @@ os_file_create_simple_no_error_handling_func(
&& *success
&& (access_type == OS_FILE_READ_WRITE
|| access_type == OS_FILE_READ_WRITE_CACHED)
- && os_file_lock(file, name)) {
+ && os_file_lock(file.m_file, name)) {
*success = FALSE;
- close(file);
- file = -1;
+ close(file.m_file);
+ file.m_file = -1;
}
#endif /* USE_FILE_LOCK */
@@ -1687,7 +1687,7 @@ Opens an existing file or creates a new.
@return own: handle to the file, not defined if error, error number
can be retrieved with os_file_get_last_error */
UNIV_INTERN
-os_file_t
+pfs_os_file_t
os_file_create_func(
/*================*/
const char* name, /*!< in: name of the file or path as a
@@ -1703,24 +1703,25 @@ os_file_create_func(
ulint type, /*!< in: OS_DATA_FILE or OS_LOG_FILE */
ibool* success)/*!< out: TRUE if succeed, FALSE if error */
{
- os_file_t file;
+ pfs_os_file_t file;
ibool retry;
ibool on_error_no_exit;
ibool on_error_silent;
-
#ifdef __WIN__
DBUG_EXECUTE_IF(
"ib_create_table_fail_disk_full",
*success = FALSE;
SetLastError(ERROR_DISK_FULL);
- return((os_file_t) -1);
+ file.m_file = (os_file_t)-1;
+ return(file);
);
#else /* __WIN__ */
DBUG_EXECUTE_IF(
"ib_create_table_fail_disk_full",
*success = FALSE;
errno = ENOSPC;
- return((os_file_t) -1);
+ file.m_file = -1;
+ return(file);
);
#endif /* __WIN__ */
@@ -1771,7 +1772,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file.m_file = (os_file_t)-1;
+ return(file);
}
DWORD attributes = 0;
@@ -1796,8 +1798,8 @@ os_file_create_func(
ib_logf(IB_LOG_LEVEL_ERROR,
"Unknown purpose flag (%lu) while opening file '%s'",
purpose, name);
-
- return((os_file_t)(-1));
+ file.m_file = (os_file_t)-1;
+ return(file);
}
#ifdef UNIV_NON_BUFFERED_IO
@@ -1834,11 +1836,11 @@ os_file_create_func(
do {
/* Use default security attributes and no template file. */
- file = CreateFile(
+ file.m_file = CreateFile(
(LPCTSTR) name, access, share_mode, NULL,
create_flag, attributes, NULL);
- if (file == INVALID_HANDLE_VALUE) {
+ if (file.m_file == INVALID_HANDLE_VALUE) {
const char* operation;
operation = (create_mode == OS_FILE_CREATE
@@ -1873,7 +1875,6 @@ os_file_create_func(
#else /* __WIN__ */
int create_flag;
const char* mode_str = NULL;
-
on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT
? TRUE : FALSE;
on_error_silent = create_mode & OS_FILE_ON_ERROR_SILENT
@@ -1911,7 +1912,8 @@ os_file_create_func(
"Unknown file create mode (%lu) for file '%s'",
create_mode, name);
- return((os_file_t) -1);
+ file.m_file = -1;
+ return(file);
}
ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
@@ -1931,9 +1933,9 @@ os_file_create_func(
#endif /* O_SYNC */
do {
- file = ::open(name, create_flag, os_innodb_umask);
+ file.m_file = ::open(name, create_flag, os_innodb_umask);
- if (file == -1) {
+ if (file.m_file == -1) {
const char* operation;
operation = (create_mode == OS_FILE_CREATE
@@ -1957,14 +1959,15 @@ os_file_create_func(
if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str, type, 0);
+ os_file_set_nocache_if_needed(file.m_file, name, mode_str,
+ type, 0);
}
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
&& create_mode != OS_FILE_OPEN_RAW
- && os_file_lock(file, name)) {
+ && os_file_lock(file.m_file, name)) {
if (create_mode == OS_FILE_OPEN_RETRY) {
@@ -1976,7 +1979,7 @@ os_file_create_func(
for (int i = 0; i < 100; i++) {
os_thread_sleep(1000000);
- if (!os_file_lock(file, name)) {
+ if (!os_file_lock(file.m_file, name)) {
*success = TRUE;
return(file);
}
@@ -1987,17 +1990,18 @@ os_file_create_func(
}
*success = FALSE;
- close(file);
- file = -1;
+ close(file.m_file);
+ file.m_file = -1;
}
#endif /* USE_FILE_LOCK */
if (srv_use_atomic_writes && type == OS_DATA_FILE
- && file != -1 && !os_file_set_atomic_writes(name, file)) {
+ && file.m_file != -1
+ && !os_file_set_atomic_writes(name, file.m_file)) {
*success = FALSE;
- close(file);
- file = -1;
+ close(file.m_file);
+ file.m_file = -1;
}
#endif /* __WIN__ */
@@ -2226,8 +2230,8 @@ os_file_close_func(
Closes a file handle.
@return TRUE if success */
UNIV_INTERN
-ibool
-os_file_close_no_error_handling(
+bool
+os_file_close_no_error_handling_func(
/*============================*/
os_file_t file) /*!< in, own: handle to a file */
{
@@ -2237,10 +2241,10 @@ os_file_close_no_error_handling(
ret = CloseHandle(file);
if (ret) {
- return(TRUE);
+ return(true);
}
- return(FALSE);
+ return(false);
#else
int ret;
@@ -2248,10 +2252,83 @@ os_file_close_no_error_handling(
if (ret == -1) {
- return(FALSE);
+ return(false);
}
- return(TRUE);
+ return(true);
+#endif /* __WIN__ */
+}
+
+#ifdef HAVE_POSIX_FALLOCATE
+/***********************************************************************//**
+Ensures that disk space is allocated for the file.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_allocate_func(
+ os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len) /*!< in: file region length */
+{
+ return(posix_fallocate(file, offset, len) == 0);
+}
+#endif
+
+/***********************************************************************//**
+Checks if the file is marked as invalid.
+@return TRUE if invalid */
+UNIV_INTERN
+bool
+os_file_is_invalid(
+ pfs_os_file_t file) /*!< in, own: handle to a file */
+{
+ return(file.m_file == os_file_invalid);
+}
+
+/***********************************************************************//**
+Marks the file as invalid. */
+UNIV_INTERN
+void
+os_file_mark_invalid(
+ pfs_os_file_t* file) /*!< out: pointer to a handle to a file */
+{
+ file->m_file = os_file_invalid;
+}
+
+/***********************************************************************//**
+Announces an intention to access file data in a specific pattern in the
+future.
+@return TRUE if success */
+UNIV_INTERN
+bool
+os_file_advise(
+ pfs_os_file_t file, /*!< in, own: handle to a file */
+ os_offset_t offset, /*!< in: file region offset */
+ os_offset_t len, /*!< in: file region length */
+ ulint advice)/*!< in: advice for access pattern */
+{
+#ifdef __WIN__
+ return(true);
+#else
+#ifdef UNIV_LINUX
+ int native_advice = 0;
+ if ((advice & OS_FILE_ADVISE_NORMAL) != 0)
+ native_advice |= POSIX_FADV_NORMAL;
+ if ((advice & OS_FILE_ADVISE_RANDOM) != 0)
+ native_advice |= POSIX_FADV_RANDOM;
+ if ((advice & OS_FILE_ADVISE_SEQUENTIAL) != 0)
+ native_advice |= POSIX_FADV_SEQUENTIAL;
+ if ((advice & OS_FILE_ADVISE_WILLNEED) != 0)
+ native_advice |= POSIX_FADV_WILLNEED;
+ if ((advice & OS_FILE_ADVISE_DONTNEED) != 0)
+ native_advice |= POSIX_FADV_DONTNEED;
+ if ((advice & OS_FILE_ADVISE_NOREUSE) != 0)
+ native_advice |= POSIX_FADV_NOREUSE;
+
+ return(posix_fadvise(file.m_file, offset, len, native_advice) == 0);
+#else
+ return(true);
+#endif
#endif /* __WIN__ */
}
@@ -2262,14 +2339,14 @@ UNIV_INTERN
os_offset_t
os_file_get_size(
/*=============*/
- os_file_t file) /*!< in: handle to a file */
+ pfs_os_file_t file) /*!< in: handle to a file */
{
#ifdef __WIN__
os_offset_t offset;
DWORD high;
DWORD low;
- low = GetFileSize(file, &high);
+ low = GetFileSize(file.m_file, &high);
if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
return((os_offset_t) -1);
@@ -2279,7 +2356,8 @@ os_file_get_size(
return(offset);
#else
- return((os_offset_t) lseek(file, 0, SEEK_END));
+ return((os_offset_t) lseek(file.m_file, 0, SEEK_END));
+
#endif /* __WIN__ */
}
@@ -2292,7 +2370,7 @@ os_file_set_size(
/*=============*/
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
os_offset_t size) /*!< in: file size */
{
ibool ret;
@@ -2304,7 +2382,7 @@ os_file_set_size(
if (srv_use_posix_fallocate) {
int err;
do {
- err = posix_fallocate(file, 0, size);
+ err = posix_fallocate(file.m_file, 0, size);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
@@ -2383,8 +2461,8 @@ os_file_set_eof(
Truncates a file at the specified position.
@return TRUE if success */
UNIV_INTERN
-ibool
-os_file_set_eof_at(
+bool
+os_file_set_eof_at_func(
os_file_t file, /*!< in: handle to a file */
ib_uint64_t new_len)/*!< in: new file length */
{
@@ -4314,7 +4392,7 @@ os_aio_array_reserve_slot(
the aio operation */
void* message2,/*!< in: message to be passed along with
the aio operation */
- os_file_t file, /*!< in: file handle */
+ pfs_os_file_t file, /*!< in: file handle */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
void* buf, /*!< in: buffer where to read or from which
@@ -4437,10 +4515,10 @@ found:
iocb = &slot->control;
if (type == OS_FILE_READ) {
- io_prep_pread(iocb, file, buf, len, aio_offset);
+ io_prep_pread(iocb, file.m_file, buf, len, aio_offset);
} else {
ut_a(type == OS_FILE_WRITE);
- io_prep_pwrite(iocb, file, buf, len, aio_offset);
+ io_prep_pwrite(iocb, file.m_file, buf, len, aio_offset);
}
iocb->data = (void*) slot;
@@ -4674,7 +4752,7 @@ os_aio_func(
caution! */
const char* name, /*!< in: name of the file or path as a
null-terminated string */
- os_file_t file, /*!< in: handle to a file */
+ pfs_os_file_t file, /*!< in: handle to a file */
void* buf, /*!< in: buffer where to read or from which
to write */
os_offset_t offset, /*!< in: file offset where to read or write */
@@ -4697,7 +4775,6 @@ os_aio_func(
BOOL ret;
#endif
ulint wake_later;
-
ut_ad(buf);
ut_ad(n > 0);
ut_ad(n % OS_MIN_LOG_BLOCK_SIZE == 0);
@@ -4719,7 +4796,7 @@ os_aio_func(
no need to use an i/o-handler thread */
if (type == OS_FILE_READ) {
- ret = os_file_read_func(file, buf, offset, n, trx);
+ ret = os_file_read_func(file.m_file, buf, offset, n, trx);
} else {
ut_ad(!srv_read_only_mode);
ut_a(type == OS_FILE_WRITE);
@@ -4795,7 +4872,7 @@ try_again:
os_n_file_reads++;
os_bytes_read_since_printout += n;
#ifdef WIN_ASYNC_IO
- ret = ReadFile(file, buf, (DWORD) n, &len,
+ ret = ReadFile(file.m_file, buf, (DWORD) n, &len,
&(slot->control));
if(!ret && GetLastError() != ERROR_IO_PENDING)
goto err_exit;
@@ -4817,7 +4894,7 @@ try_again:
if (srv_use_native_aio) {
os_n_file_writes++;
#ifdef WIN_ASYNC_IO
- ret = WriteFile(file, buf, (DWORD) n, &len,
+ ret = WriteFile(file.m_file, buf, (DWORD) n, &len,
&(slot->control));
if(!ret && GetLastError() != ERROR_IO_PENDING)
@@ -4937,7 +5014,6 @@ os_aio_windows_handle(
break;
}
}
-
*message1 = slot->message1;
*message2 = slot->message2;
@@ -4964,11 +5040,11 @@ os_aio_windows_handle(
switch (slot->type) {
case OS_FILE_WRITE:
- ret_val = os_file_write(slot->name, slot->file, slot->buf,
+ ret_val = os_file_write(slot->name, slot->file.m_file, slot->buf,
li.QuadPart, slot->len);
break;
case OS_FILE_READ:
- ret_val = os_file_read(slot->file, slot->buf,
+ ret_val = os_file_read(slot->file, slot->buf,
li.QuadPart, slot->len);
break;
default:
@@ -5223,12 +5299,14 @@ found:
iocb = &(slot->control);
if (slot->type == OS_FILE_READ) {
- io_prep_pread(&slot->control, slot->file, slot->buf,
- slot->len, (off_t) slot->offset);
+ io_prep_pread(&slot->control, slot->file.m_file,
+ slot->buf, slot->len,
+ (off_t) slot->offset);
} else {
ut_a(slot->type == OS_FILE_WRITE);
- io_prep_pwrite(&slot->control, slot->file, slot->buf,
- slot->len, (off_t) slot->offset);
+ io_prep_pwrite(&slot->control, slot->file.m_file,
+ slot->buf, slot->len,
+ (off_t) slot->offset);
}
/* Resubmit an I/O request */
submit_ret = io_submit(array->aio_ctx[segment], 1, &iocb);
@@ -5455,12 +5533,11 @@ consecutive_loop:
os_aio_slot_t* slot;
slot = os_aio_array_get_nth_slot(array, i + segment * n);
-
if (slot->reserved
&& slot != aio_slot
&& slot->offset == aio_slot->offset + aio_slot->len
&& slot->type == aio_slot->type
- && slot->file == aio_slot->file) {
+ && slot->file.m_file == aio_slot->file.m_file) {
/* Found a consecutive i/o request */
diff --git a/storage/xtradb/pars/pars0opt.cc b/storage/xtradb/pars/pars0opt.cc
index cbed2b39eeb..5a7e1861d74 100644
--- a/storage/xtradb/pars/pars0opt.cc
+++ b/storage/xtradb/pars/pars0opt.cc
@@ -948,12 +948,14 @@ opt_find_all_cols(
/* Fill in the field_no fields in sym_node */
sym_node->field_nos[SYM_CLUST_FIELD_NO] = dict_index_get_nth_col_pos(
- dict_table_get_first_index(index->table), sym_node->col_no);
+ dict_table_get_first_index(index->table), sym_node->col_no,
+ NULL);
if (!dict_index_is_clust(index)) {
ut_a(plan);
- col_pos = dict_index_get_nth_col_pos(index, sym_node->col_no);
+ col_pos = dict_index_get_nth_col_pos(index, sym_node->col_no,
+ NULL);
if (col_pos == ULINT_UNDEFINED) {
diff --git a/storage/xtradb/pars/pars0pars.cc b/storage/xtradb/pars/pars0pars.cc
index b116357c5b9..ea65d16e9dc 100644
--- a/storage/xtradb/pars/pars0pars.cc
+++ b/storage/xtradb/pars/pars0pars.cc
@@ -1232,7 +1232,8 @@ pars_process_assign_list(
col_sym = assign_node->col;
upd_field_set_field_no(upd_field, dict_index_get_nth_col_pos(
- clust_index, col_sym->col_no),
+ clust_index, col_sym->col_no,
+ NULL),
clust_index, NULL);
upd_field->exp = assign_node->val;
diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc
index 3c5d5773aee..79c249d52ec 100644
--- a/storage/xtradb/row/row0log.cc
+++ b/storage/xtradb/row/row0log.cc
@@ -363,9 +363,9 @@ row_log_online_op(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -479,9 +479,9 @@ row_log_table_close_func(
goto err_exit;
}
- ret = os_file_write(
+ ret = os_file_write_int_fd(
"(modification log)",
- OS_FILE_FROM_FD(log->fd),
+ log->fd,
log->tail.block, byte_offset, srv_sort_buf_size);
log->tail.blocks++;
if (!ret) {
@@ -2609,11 +2609,10 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
-
if (!success) {
fprintf(stderr, "InnoDB: unable to read temporary file"
" for table %s\n", index->table_name);
@@ -3436,8 +3435,8 @@ all_done:
goto func_exit;
}
- success = os_file_read_no_error_handling(
- OS_FILE_FROM_FD(index->online_log->fd),
+ success = os_file_read_no_error_handling_int_fd(
+ index->online_log->fd,
index->online_log->head.block, ofs,
srv_sort_buf_size);
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index 5082aae15cf..fb65507e37d 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -871,8 +871,9 @@ row_merge_read(
}
#endif /* UNIV_DEBUG */
- success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf,
+ success = os_file_read_no_error_handling_int_fd(fd, buf,
ofs, srv_sort_buf_size);
+
#ifdef POSIX_FADV_DONTNEED
/* Each block is read exactly once. Free up the file cache. */
posix_fadvise(fd, ofs, srv_sort_buf_size, POSIX_FADV_DONTNEED);
@@ -906,7 +907,7 @@ row_merge_write(
DBUG_EXECUTE_IF("row_merge_write_failure", return(FALSE););
- ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), buf, ofs, buf_len);
+ ret = os_file_write_int_fd("(merge)", fd, buf, ofs, buf_len);
#ifdef UNIV_DEBUG
if (row_merge_print_block_write) {
@@ -3144,14 +3145,21 @@ row_merge_file_create_low(
performance schema */
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_open_begin(&state, locker, innodb_file_temp_key,
- PSI_FILE_OPEN,
- "Innodb Merge Temp File",
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_name_locker)(
+ &state, innodb_file_temp_key, PSI_FILE_OPEN,
+ "Innodb Merge Temp File", &locker);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_open_wait)(locker,
+ __FILE__,
+ __LINE__);
+ }
#endif
fd = innobase_mysql_tmpfile(path);
#ifdef UNIV_PFS_IO
- register_pfs_file_open_end(locker, fd);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(
+ locker, fd);
+ }
#endif
if (fd < 0) {
@@ -3198,15 +3206,20 @@ row_merge_file_destroy_low(
#ifdef UNIV_PFS_IO
struct PSI_file_locker* locker = NULL;
PSI_file_locker_state state;
- register_pfs_file_io_begin(&state, locker,
- fd, 0, PSI_FILE_CLOSE,
- __FILE__, __LINE__);
+ locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)(
+ &state, fd, PSI_FILE_CLOSE);
+ if (locker != NULL) {
+ PSI_FILE_CALL(start_file_wait)(
+ locker, 0, __FILE__, __LINE__);
+ }
#endif
if (fd >= 0) {
close(fd);
}
#ifdef UNIV_PFS_IO
- register_pfs_file_io_end(locker, 0);
+ if (locker != NULL) {
+ PSI_FILE_CALL(end_file_wait)(locker, 0);
+ }
#endif
}
/*********************************************************************//**
diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc
index fd23d83e0e5..17920c91743 100644
--- a/storage/xtradb/row/row0sel.cc
+++ b/storage/xtradb/row/row0sel.cc
@@ -64,6 +64,8 @@ Created 12/19/1997 Heikki Tuuri
#include "my_compare.h" /* enum icp_result */
+#include <vector>
+
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -2713,7 +2715,8 @@ row_sel_field_store_in_mysql_format_func(
|| !(templ->mysql_col_len % templ->mbmaxlen));
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|| (field_no == templ->icp_rec_field_no
- && field->prefix_len > 0));
+ && field->prefix_len > 0)
+ || templ->rec_field_is_prefix);
ut_ad(!(field->prefix_len % templ->mbmaxlen));
if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
@@ -2755,27 +2758,32 @@ row_sel_field_store_in_mysql_format_func(
# define row_sel_store_mysql_field(m,p,r,i,o,f,t) \
row_sel_store_mysql_field_func(m,p,r,o,f,t)
#endif /* UNIV_DEBUG */
-/**************************************************************//**
-Convert a field in the Innobase format to a field in the MySQL format. */
+/** Convert a field in the Innobase format to a field in the MySQL format.
+@param[out] mysql_rec record in the MySQL format
+@param[in,out] prebuilt prebuilt struct
+@param[in] rec InnoDB record; must be protected
+ by a page latch
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets()
+@param[in] field_no templ->rec_field_no or
+ templ->clust_rec_field_no
+ or templ->icp_rec_field_no
+ or sec field no if clust_templ_for_sec
+ is TRUE
+@param[in] templ row template
+*/
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_field_func(
-/*===========================*/
- byte* mysql_rec, /*!< out: record in the
- MySQL format */
- row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct */
- const rec_t* rec, /*!< in: InnoDB record;
- must be protected by
- a page latch */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
#ifdef UNIV_DEBUG
- const dict_index_t* index, /*!< in: index of rec */
+ const dict_index_t* index,
#endif
- const ulint* offsets, /*!< in: array returned by
- rec_get_offsets() */
- ulint field_no, /*!< in: templ->rec_field_no or
- templ->clust_rec_field_no or
- templ->icp_rec_field_no */
- const mysql_row_templ_t*templ) /*!< in: row template */
+ const ulint* offsets,
+ ulint field_no,
+ const mysql_row_templ_t*templ)
{
const byte* data;
ulint len;
@@ -2904,31 +2912,31 @@ row_sel_store_mysql_field_func(
return(TRUE);
}
-/**************************************************************//**
-Convert a row in the Innobase format to a row in the MySQL format.
+/** Convert a row in the Innobase format to a row in the MySQL format.
Note that the template in prebuilt may advise us to copy only a few
columns to mysql_rec, other columns are left blank. All columns may not
be needed in the query.
+@param[out] mysql_rec row in the MySQL format
+@param[in] prebuilt prebuilt structure
+@param[in] rec Innobase record in the index
+ which was described in prebuilt's
+ template, or in the clustered index;
+ must be protected by a page latch
+@param[in] rec_clust TRUE if the rec in the clustered index
+@param[in] index index of rec
+@param[in] offsets array returned by rec_get_offsets(rec)
@return TRUE on success, FALSE if not all columns could be retrieved */
static MY_ATTRIBUTE((warn_unused_result))
ibool
row_sel_store_mysql_rec(
-/*====================*/
- byte* mysql_rec, /*!< out: row in the MySQL format */
- row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */
- const rec_t* rec, /*!< in: Innobase record in the index
- which was described in prebuilt's
- template, or in the clustered index;
- must be protected by a page latch */
- ibool rec_clust, /*!< in: TRUE if rec is in the
- clustered index instead of
- prebuilt->index */
- const dict_index_t* index, /*!< in: index of rec */
- const ulint* offsets) /*!< in: array returned by
- rec_get_offsets(rec) */
+ byte* mysql_rec,
+ row_prebuilt_t* prebuilt,
+ const rec_t* rec,
+ ibool rec_clust,
+ const dict_index_t* index,
+ const ulint* offsets)
{
ulint i;
-
ut_ad(rec_clust || index == prebuilt->index);
ut_ad(!rec_clust || dict_index_is_clust(index));
@@ -2944,9 +2952,12 @@ row_sel_store_mysql_rec(
? templ->clust_rec_field_no
: templ->rec_field_no;
/* We should never deliver column prefixes to MySQL,
- except for evaluating innobase_index_cond(). */
+ except for evaluating innobase_index_cond() and if the prefix
+ index is longer than the actual row data. */
+
ut_ad(dict_index_get_nth_field(index, field_no)->prefix_len
- == 0);
+ == 0 || templ->rec_field_is_prefix);
+
if (!row_sel_store_mysql_field(mysql_rec, prebuilt,
rec, index, offsets,
@@ -3040,6 +3051,8 @@ row_sel_get_clust_rec_for_mysql(
dberr_t err;
trx_t* trx;
+ os_atomic_increment_ulint(&srv_sec_rec_cluster_reads, 1);
+
*out_rec = NULL;
trx = thr_get_trx(thr);
@@ -3633,6 +3646,30 @@ row_search_idx_cond_check(
return(result);
}
+
+/** Return the record field length in characters.
+@param[in] col table column of the field
+@param[in] field_no field number
+@param[in] rec physical record
+@param[in] offsets field offsets in the physical record
+
+@return field length in characters */
+static
+size_t
+rec_field_len_in_chars(const dict_col_t &col,
+ const ulint field_no,
+ const rec_t *rec,
+ const ulint *offsets)
+{
+ const ulint cset = dtype_get_charset_coll(col.prtype);
+ const CHARSET_INFO* cs = all_charsets[cset];
+ ulint rec_field_len;
+ const char* rec_field = reinterpret_cast<const char *>(
+ rec_get_nth_field(
+ rec, offsets, field_no, &rec_field_len));
+ return(cs->cset->numchars(cs, rec_field, rec_field + rec_field_len));
+}
+
/********************************************************************//**
Searches for rows in the database. This is used in the interface to
MySQL. This function opens a cursor, and also implements fetch next
@@ -3671,7 +3708,7 @@ row_search_for_mysql(
trx_t* trx = prebuilt->trx;
dict_index_t* clust_index;
que_thr_t* thr;
- const rec_t* rec;
+ const rec_t* rec = NULL;
const rec_t* result_rec = NULL;
const rec_t* clust_rec;
dberr_t err = DB_SUCCESS;
@@ -3696,6 +3733,7 @@ row_search_for_mysql(
ulint* offsets = offsets_;
ibool table_lock_waited = FALSE;
byte* next_buf = 0;
+ bool use_clustered_index = false;
rec_offs_init(offsets_);
@@ -3953,7 +3991,8 @@ row_search_for_mysql(
if (!row_sel_store_mysql_rec(
buf, prebuilt,
- rec, FALSE, index, offsets)) {
+ rec, FALSE, index,
+ offsets)) {
/* Only fresh inserts may contain
incomplete externally stored
columns. Pretend that such
@@ -4211,7 +4250,6 @@ rec_loop:
}
if (page_rec_is_supremum(rec)) {
-
if (set_also_gap_locks
&& !(srv_locks_unsafe_for_binlog
|| trx->isolation_level <= TRX_ISO_READ_COMMITTED)
@@ -4724,10 +4762,85 @@ locks_ok:
}
/* Get the clustered index record if needed, if we did not do the
- search using the clustered index. */
+ search using the clustered index... */
+
+ use_clustered_index =
+ (index != clust_index && prebuilt->need_to_access_clustered);
+
+ if (use_clustered_index && prebuilt->n_template <= index->n_fields) {
+ /* ...but, perhaps avoid the clustered index lookup if
+ all of the following are true:
+ 1) all columns are in the secondary index
+ 2) all values for columns that are prefix-only
+ indexes are shorter than the prefix size
+ This optimization can avoid many IOs for certain schemas.
+ */
+ bool row_contains_all_values = true;
+ unsigned int i;
+ for (i = 0; i < prebuilt->n_template; i++) {
+ /* Condition (1) from above: is the field in the
+ index (prefix or not)? */
+ const mysql_row_templ_t* templ =
+ prebuilt->mysql_template + i;
+ ulint secondary_index_field_no =
+ templ->rec_prefix_field_no;
+ if (secondary_index_field_no == ULINT_UNDEFINED) {
+ row_contains_all_values = false;
+ break;
+ }
+ /* Condition (2) from above: if this is a
+ prefix, is this row's value size shorter
+ than the prefix? */
+ if (templ->rec_field_is_prefix) {
+ ulint record_size = rec_offs_nth_size(
+ offsets,
+ secondary_index_field_no);
+ const dict_field_t *field =
+ dict_index_get_nth_field(
+ index,
+ secondary_index_field_no);
+ ut_a(field->prefix_len > 0);
+ if (record_size
+ < field->prefix_len / templ->mbmaxlen) {
+
+ /* Record in bytes shorter than the
+ index prefix length in characters */
+ continue;
+
+ } else if (record_size * templ->mbminlen
+ >= field->prefix_len) {
+
+ /* The shortest represantable string by
+ the byte length of the record is longer
+ than the maximum possible index
+ prefix. */
+ row_contains_all_values = false;
+ break;
+ } else {
+
+ row_contains_all_values = false;
+ break;
+ }
+ }
+ }
+ /* If (1) and (2) were true for all columns above, use
+ rec_prefix_field_no instead of rec_field_no, and skip
+ the clustered lookup below. */
+ if (row_contains_all_values) {
+ for (i = 0; i < prebuilt->n_template; i++) {
+ mysql_row_templ_t* templ =
+ prebuilt->mysql_template + i;
+ templ->rec_field_no =
+ templ->rec_prefix_field_no;
+ ut_a(templ->rec_field_no != ULINT_UNDEFINED);
+ }
+ use_clustered_index = false;
+ os_atomic_increment_ulint(
+ &srv_sec_rec_cluster_reads_avoided, 1);
+ }
+ }
- if (index != clust_index && prebuilt->need_to_access_clustered) {
-
+ if (use_clustered_index) {
requires_clust_rec:
ut_ad(index != clust_index);
/* We use a 'goto' to the preceding label if a consistent
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index 5b3f86d8641..219a6b3c014 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
@@ -156,7 +156,8 @@ UNIV_INTERN unsigned long long srv_online_max_size;
OS (provided we compiled Innobase with it in), otherwise we will
use simulated aio we build below with threads.
Currently we support native aio on windows and linux */
-UNIV_INTERN my_bool srv_use_native_aio = TRUE;
+/* make srv_use_native_aio to be visible for other plugins */
+my_bool srv_use_native_aio = TRUE;
UNIV_INTERN my_bool srv_numa_interleave = FALSE;
#ifdef __WIN__
@@ -596,6 +597,12 @@ static ulint srv_main_shutdown_loops = 0;
/** Log writes involving flush. */
static ulint srv_log_writes_and_flush = 0;
+/** Number of times secondary index lookup triggered cluster lookup */
+ulint srv_sec_rec_cluster_reads = 0;
+
+/** Number of times prefix optimization avoided triggering cluster lookup */
+ulint srv_sec_rec_cluster_reads_avoided = 0;
+
/* This is only ever touched by the master thread. It records the
time when the last flush of log file has happened. The master
thread ensures that we flush the log files at least once per
@@ -1993,6 +2000,12 @@ srv_export_innodb_status(void)
}
#endif /* UNIV_DEBUG */
+ os_rmb;
+ export_vars.innodb_sec_rec_cluster_reads =
+ srv_sec_rec_cluster_reads;
+ export_vars.innodb_sec_rec_cluster_reads_avoided =
+ srv_sec_rec_cluster_reads_avoided;
+
mutex_exit(&srv_innodb_monitor_mutex);
}
@@ -3046,6 +3059,8 @@ DECLARE_THREAD(srv_master_thread)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint old_activity_count = srv_get_activity_count();
ulint old_ibuf_merge_activity_count
@@ -3119,6 +3134,7 @@ suspend_thread:
srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ my_thread_end();
os_thread_exit(NULL);
}
@@ -3205,6 +3221,8 @@ DECLARE_THREAD(srv_worker_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint tid_i = os_atomic_increment_ulint(&purge_tid_i, 1);
@@ -3270,6 +3288,7 @@ DECLARE_THREAD(srv_worker_thread)(
os_thread_pf(os_thread_get_curr_id()));
#endif /* UNIV_DEBUG_THREAD_CREATION */
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
@@ -3438,6 +3457,8 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
required by os_thread_create */
{
+ my_thread_init();
+
srv_slot_t* slot;
ulint n_total_purged = ULINT_UNDEFINED;
@@ -3551,6 +3572,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_release_threads(SRV_WORKER, srv_n_purge_threads - 1);
}
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
@@ -3616,3 +3638,19 @@ srv_purge_wakeup()
}
}
}
+
+/** Check whether given space id is undo tablespace id
+@param[in] space_id space id to check
+@return true if it is undo tablespace else false. */
+bool
+srv_is_undo_tablespace(
+ ulint space_id)
+{
+ if (srv_undo_space_id_start == 0) {
+ return (false);
+ }
+
+ return(space_id >= srv_undo_space_id_start
+ && space_id < (srv_undo_space_id_start
+ + srv_undo_tablespaces_open));
+}
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index d94dfe87783..e5b06a4919c 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2017, MariaDB Corporation.
@@ -112,6 +112,9 @@ UNIV_INTERN ibool srv_have_fullfsync = FALSE;
/** TRUE if a raw partition is in use */
UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE;
+/** UNDO tablespaces starts with space id. */
+ulint srv_undo_space_id_start;
+
/** TRUE if the server is being started, before rolling back any
incomplete transactions */
UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE;
@@ -127,7 +130,7 @@ SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
/** Files comprising the system tablespace */
-static os_file_t files[1000];
+static pfs_os_file_t files[1000];
/** io_handler_thread parameters for thread identification */
static ulint n[SRV_MAX_N_IO_THREADS];
@@ -570,7 +573,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
create_log_file(
/*============*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name) /*!< in: log file name */
{
ibool ret;
@@ -786,7 +789,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
open_log_file(
/*==========*/
- os_file_t* file, /*!< out: file handle */
+ pfs_os_file_t* file, /*!< out: file handle */
const char* name, /*!< in: log file name */
os_offset_t* size) /*!< out: file size */
{
@@ -902,7 +905,7 @@ open_or_create_data_files(
&& os_file_get_last_error(false)
!= OS_FILE_ALREADY_EXISTS
#ifdef UNIV_AIX
- /* AIX 5.1 after security patch ML7 may have
+ /* AIX 5.1 after security patch ML7 may have
errno set to 0 here, which causes our
function to return 100; work around that
AIX problem */
@@ -1199,7 +1202,7 @@ srv_undo_tablespace_create(
const char* name, /*!< in: tablespace name */
ulint size) /*!< in: tablespace size in pages */
{
- os_file_t fh;
+ pfs_os_file_t fh;
ibool ret;
dberr_t err = DB_SUCCESS;
@@ -1276,7 +1279,7 @@ srv_undo_tablespace_open(
const char* name, /*!< in: tablespace name */
ulint space) /*!< in: tablespace id */
{
- os_file_t fh;
+ pfs_os_file_t fh;
dberr_t err = DB_ERROR;
ibool ret;
ulint flags;
@@ -1375,13 +1378,23 @@ srv_undo_tablespaces_init(
for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) {
char name[OS_FILE_MAX_PATH];
+ ulint space_id = i + 1;
+
+ DBUG_EXECUTE_IF("innodb_undo_upgrade",
+ space_id = i + 3;);
ut_snprintf(
name, sizeof(name),
"%s%cundo%03lu",
- srv_undo_dir, SRV_PATH_SEPARATOR, i + 1);
+ srv_undo_dir, SRV_PATH_SEPARATOR, space_id);
+
+ if (i == 0) {
+ srv_undo_space_id_start = space_id;
+ prev_space_id = srv_undo_space_id_start - 1;
+ }
+
+ undo_tablespace_ids[i] = space_id;
- /* Undo space ids start from 1. */
err = srv_undo_tablespace_create(
name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
@@ -1403,14 +1416,16 @@ srv_undo_tablespaces_init(
if (!create_new_db) {
n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces(
undo_tablespace_ids);
- } else {
- n_undo_tablespaces = n_conf_tablespaces;
- for (i = 1; i <= n_undo_tablespaces; ++i) {
- undo_tablespace_ids[i - 1] = i;
+ if (n_undo_tablespaces != 0) {
+ srv_undo_space_id_start = undo_tablespace_ids[0];
+ prev_space_id = srv_undo_space_id_start - 1;
}
- undo_tablespace_ids[i] = ULINT_UNDEFINED;
+ } else {
+ n_undo_tablespaces = n_conf_tablespaces;
+
+ undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED;
}
/* Open all the undo tablespaces that are currently in use. If we
@@ -1434,8 +1449,6 @@ srv_undo_tablespaces_init(
ut_a(undo_tablespace_ids[i] != 0);
ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED);
- /* Undo space ids start from 1. */
-
err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]);
if (err != DB_SUCCESS) {
@@ -1470,11 +1483,23 @@ srv_undo_tablespaces_init(
break;
}
+ /** Note the first undo tablespace id in case of
+ no active undo tablespace. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = i;
+ }
+
++n_undo_tablespaces;
++*n_opened;
}
+ /** Explictly specify the srv_undo_space_id_start
+ as zero when there are no undo tablespaces. */
+ if (n_undo_tablespaces == 0) {
+ srv_undo_space_id_start = 0;
+ }
+
/* If the user says that there are fewer than what we find we
tolerate that discrepancy but not the inverse. Because there could
be unused undo tablespaces for future use. */
@@ -1519,10 +1544,11 @@ srv_undo_tablespaces_init(
mtr_start(&mtr);
/* The undo log tablespace */
- for (i = 1; i <= n_undo_tablespaces; ++i) {
+ for (i = 0; i < n_undo_tablespaces; ++i) {
fsp_header_init(
- i, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
+ undo_tablespace_ids[i],
+ SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
}
mtr_commit(&mtr);
@@ -1633,6 +1659,10 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_free(&srv_os_test_mutex);
+ if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
+ srv_read_only_mode = 1;
+ }
+
high_level_read_only = srv_read_only_mode
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
diff --git a/storage/xtradb/trx/trx0purge.cc b/storage/xtradb/trx/trx0purge.cc
index 6b7b7df4cd8..474ca077ce5 100644
--- a/storage/xtradb/trx/trx0purge.cc
+++ b/storage/xtradb/trx/trx0purge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
@@ -690,7 +690,8 @@ trx_purge_get_rseg_with_min_trx_id(
/* We assume in purge of externally stored fields that space id is
in the range of UNDO tablespace space ids */
- ut_a(purge_sys->rseg->space <= srv_undo_tablespaces_open);
+ ut_a(purge_sys->rseg->space == 0
+ || srv_is_undo_tablespace(purge_sys->rseg->space));
zip_size = purge_sys->rseg->zip_size;
diff --git a/storage/xtradb/trx/trx0rec.cc b/storage/xtradb/trx/trx0rec.cc
index 5fa74846243..74a63b60286 100644
--- a/storage/xtradb/trx/trx0rec.cc
+++ b/storage/xtradb/trx/trx0rec.cc
@@ -781,7 +781,8 @@ trx_undo_page_report_modify(
}
pos = dict_index_get_nth_col_pos(index,
- col_no);
+ col_no,
+ NULL);
ptr += mach_write_compressed(ptr, pos);
/* Save the old value of field */
diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc
index 8ab9511befc..ae5e792a4bb 100644
--- a/storage/xtradb/trx/trx0roll.cc
+++ b/storage/xtradb/trx/trx0roll.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -805,6 +805,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
/*!< in: a dummy parameter required by
os_thread_create */
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
#ifdef UNIV_PFS_THREAD
@@ -815,6 +816,7 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
trx_rollback_or_clean_is_active = false;
+ my_thread_end();
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc
index 1e00fa97299..80ea0374567 100644
--- a/storage/xtradb/trx/trx0sys.cc
+++ b/storage/xtradb/trx/trx0sys.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, 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
@@ -918,18 +918,12 @@ trx_sys_create_rsegs(
ulint new_rsegs = n_rsegs - n_used;
for (i = 0; i < new_rsegs; ++i) {
- ulint space;
+ ulint space_id;
+ space_id = (n_spaces == 0) ? 0
+ : (srv_undo_space_id_start + i % n_spaces);
- /* Tablespace 0 is the system tablespace. All UNDO
- log tablespaces start from 1. */
-
- if (n_spaces > 0) {
- space = (i % n_spaces) + 1;
- } else {
- space = 0; /* System tablespace */
- }
-
- if (trx_rseg_create(space) != NULL) {
+ /* Tablespace 0 is the system tablespace. */
+ if (trx_rseg_create(space_id) != NULL) {
++n_used;
} else {
break;