summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-05-07 23:51:18 +0400
committerAlexander Barkov <bar@mariadb.org>2017-05-07 23:51:18 +0400
commit314350a722e65081472113c53657ad239f3bef72 (patch)
tree8b72cd2bf6f2b352b379dbfcbb1a99a48c422335 /storage
parent39e31671935bc019f556e945571f37d2d1f3a77f (diff)
parentc619fbeafe8d5019e37fcb7ba5e1a6ce2d431270 (diff)
downloadmariadb-git-314350a722e65081472113c53657ad239f3bef72.tar.gz
Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0cur.cc2
-rw-r--r--storage/innobase/btr/btr0sea.cc37
-rw-r--r--storage/innobase/buf/buf0buf.cc286
-rw-r--r--storage/innobase/buf/buf0dblwr.cc16
-rw-r--r--storage/innobase/buf/buf0dump.cc6
-rw-r--r--storage/innobase/buf/buf0flu.cc10
-rw-r--r--storage/innobase/buf/buf0lru.cc57
-rw-r--r--storage/innobase/buf/buf0rea.cc21
-rw-r--r--storage/innobase/dict/dict0boot.cc6
-rw-r--r--storage/innobase/dict/dict0mem.cc7
-rw-r--r--storage/innobase/dict/dict0stats.cc16
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc10
-rw-r--r--storage/innobase/fil/fil0crypt.cc29
-rw-r--r--storage/innobase/fil/fil0fil.cc146
-rw-r--r--storage/innobase/fil/fil0pagecompress.cc9
-rw-r--r--storage/innobase/fts/fts0fts.cc31
-rw-r--r--storage/innobase/fts/fts0opt.cc7
-rw-r--r--storage/innobase/ha/ha0ha.cc29
-rw-r--r--storage/innobase/handler/ha_innodb.cc334
-rw-r--r--storage/innobase/handler/ha_innodb.h5
-rw-r--r--storage/innobase/handler/ha_innopart.cc37
-rw-r--r--storage/innobase/handler/ha_innopart.h4
-rw-r--r--storage/innobase/handler/handler0alter.cc131
-rw-r--r--storage/innobase/handler/i_s.cc6
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc4
-rw-r--r--storage/innobase/include/btr0sea.h2
-rw-r--r--storage/innobase/include/buf0buf.h112
-rw-r--r--storage/innobase/include/buf0buf.ic1
-rw-r--r--storage/innobase/include/buf0dblwr.h15
-rw-r--r--storage/innobase/include/dict0dict.ic11
-rw-r--r--storage/innobase/include/fil0crypt.h8
-rw-r--r--storage/innobase/include/fil0fil.h106
-rw-r--r--storage/innobase/include/fts0fts.h10
-rw-r--r--storage/innobase/include/ha_prototypes.h1
-rw-r--r--storage/innobase/include/lock0lock.h5
-rw-r--r--storage/innobase/include/log0log.h8
-rw-r--r--storage/innobase/include/mtr0mtr.h10
-rw-r--r--storage/innobase/include/os0thread.h14
-rw-r--r--storage/innobase/include/page0zip.h14
-rw-r--r--storage/innobase/include/row0mysql.h5
-rw-r--r--storage/innobase/include/srv0srv.h35
-rw-r--r--storage/innobase/include/srv0start.h2
-rw-r--r--storage/innobase/include/sync0types.h26
-rw-r--r--storage/innobase/include/trx0rseg.h5
-rw-r--r--storage/innobase/include/trx0rseg.ic8
-rw-r--r--storage/innobase/include/trx0sys.h6
-rw-r--r--storage/innobase/include/trx0trx.h60
-rw-r--r--storage/innobase/include/univ.i6
-rw-r--r--storage/innobase/lock/lock0lock.cc85
-rw-r--r--storage/innobase/log/log0log.cc14
-rw-r--r--storage/innobase/log/log0recv.cc36
-rw-r--r--storage/innobase/mach/mach0data.cc65
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc27
-rw-r--r--storage/innobase/os/os0file.cc3
-rw-r--r--storage/innobase/os/os0thread.cc31
-rw-r--r--storage/innobase/page/page0zip.cc30
-rw-r--r--storage/innobase/rem/rem0rec.cc8
-rw-r--r--storage/innobase/row/row0ftsort.cc9
-rw-r--r--storage/innobase/row/row0ins.cc30
-rw-r--r--storage/innobase/row/row0log.cc45
-rw-r--r--storage/innobase/row/row0merge.cc99
-rw-r--r--storage/innobase/row/row0mysql.cc47
-rw-r--r--storage/innobase/row/row0purge.cc20
-rw-r--r--storage/innobase/row/row0trunc.cc21
-rw-r--r--storage/innobase/row/row0uins.cc20
-rw-r--r--storage/innobase/row/row0umod.cc35
-rw-r--r--storage/innobase/srv/srv0srv.cc378
-rw-r--r--storage/innobase/srv/srv0start.cc31
-rw-r--r--storage/innobase/sync/sync0arr.cc40
-rw-r--r--storage/innobase/sync/sync0debug.cc260
-rw-r--r--storage/innobase/trx/trx0purge.cc58
-rw-r--r--storage/innobase/trx/trx0roll.cc5
-rw-r--r--storage/innobase/trx/trx0rseg.cc2
-rw-r--r--storage/innobase/trx/trx0sys.cc31
-rw-r--r--storage/innobase/trx/trx0trx.cc116
-rw-r--r--storage/rocksdb/CMakeLists.txt7
-rw-r--r--storage/spider/ha_spider.cc80
-rw-r--r--storage/spider/ha_spider.h2
-rw-r--r--storage/spider/spd_db_handlersocket.cc9
-rw-r--r--storage/spider/spd_db_handlersocket.h3
-rw-r--r--storage/spider/spd_db_include.h3
-rw-r--r--storage/spider/spd_db_mysql.cc59
-rw-r--r--storage/spider/spd_db_mysql.h3
-rw-r--r--storage/spider/spd_db_oracle.cc59
-rw-r--r--storage/spider/spd_db_oracle.h3
-rw-r--r--storage/xtradb/btr/btr0btr.cc2
-rw-r--r--storage/xtradb/btr/btr0defragment.cc2
-rw-r--r--storage/xtradb/buf/buf0buf.cc141
-rw-r--r--storage/xtradb/buf/buf0dblwr.cc8
-rw-r--r--storage/xtradb/buf/buf0flu.cc16
-rw-r--r--storage/xtradb/buf/buf0rea.cc14
-rw-r--r--storage/xtradb/dict/dict0stats.cc4
-rw-r--r--storage/xtradb/fil/fil0crypt.cc61
-rw-r--r--storage/xtradb/fil/fil0fil.cc80
-rw-r--r--storage/xtradb/fil/fil0pagecompress.cc124
-rw-r--r--storage/xtradb/include/buf0buf.h18
-rw-r--r--storage/xtradb/include/dict0dict.ic101
-rw-r--r--storage/xtradb/include/fil0crypt.h6
-rw-r--r--storage/xtradb/include/fil0fil.h37
-rw-r--r--storage/xtradb/include/fil0fil.ic60
-rw-r--r--storage/xtradb/include/fil0pagecompress.h30
-rw-r--r--storage/xtradb/include/fsp0pagecompress.ic63
-rw-r--r--storage/xtradb/include/os0file.h12
-rw-r--r--storage/xtradb/include/os0sync.h5
-rw-r--r--storage/xtradb/include/srv0mon.h63
-rw-r--r--storage/xtradb/include/trx0trx.h17
-rw-r--r--storage/xtradb/include/univ.i28
-rw-r--r--storage/xtradb/lock/lock0lock.cc8
-rw-r--r--storage/xtradb/log/log0recv.cc6
-rw-r--r--storage/xtradb/os/os0file.cc184
-rw-r--r--storage/xtradb/row/row0ftsort.cc7
-rw-r--r--storage/xtradb/row/row0import.cc130
-rw-r--r--storage/xtradb/row/row0merge.cc155
-rw-r--r--storage/xtradb/srv/srv0mon.cc6
-rw-r--r--storage/xtradb/srv/srv0srv.cc4
-rw-r--r--storage/xtradb/sync/sync0arr.cc48
-rw-r--r--storage/xtradb/trx/trx0trx.cc112
117 files changed, 2850 insertions, 2192 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 39d6508adf3..773b03775be 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -3683,6 +3683,8 @@ btr_cur_update_in_place(
btr_search_x_lock(index);
}
+
+ assert_block_ahi_valid(block);
#endif /* BTR_CUR_HASH_ADAPT */
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index f7a430591ac..3ae9e95819a 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -611,6 +611,7 @@ btr_search_update_hash_ref(
|| rw_lock_own(&(block->lock), RW_LOCK_X));
ut_ad(page_align(btr_cur_get_rec(cursor))
== buf_block_get_frame(block));
+ assert_block_ahi_valid(block);
index = block->index;
@@ -1122,14 +1123,13 @@ btr_search_drop_page_hash_index(buf_block_t* block)
rw_lock_t* latch;
btr_search_t* info;
- if (!btr_search_enabled) {
- return;
- }
-
retry:
/* Do a dirty check on block->index, return if the block is
not in the adaptive hash index. */
index = block->index;
+ /* This debug check uses a dirty read that could theoretically cause
+ false positives while buf_pool_clear_hash_index() is executing. */
+ assert_block_ahi_valid(block);
if (index == NULL) {
return;
@@ -1156,6 +1156,7 @@ retry:
ut_ad(!btr_search_own_any(RW_LOCK_X));
rw_lock_s_lock(latch);
+ assert_block_ahi_valid(block);
if (block->index == NULL) {
rw_lock_s_unlock(latch);
@@ -1172,6 +1173,7 @@ retry:
#ifdef MYSQL_INDEX_DISABLE_AHI
ut_ad(!index->disable_ahi);
#endif
+ ut_ad(btr_search_enabled);
ut_ad(block->page.id.space() == index->space);
ut_a(index_id == index->id);
@@ -1290,23 +1292,8 @@ next_rec:
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_REMOVED, n_cached);
cleanup:
-#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- if (UNIV_UNLIKELY(block->n_pointers)) {
- /* Corruption */
- ib::error() << "Corruption of adaptive hash index."
- << " After dropping, the hash index to a page of "
- << index->name
- << ", still " << block->n_pointers
- << " hash nodes remain.";
- rw_lock_x_unlock(latch);
-
- ut_ad(btr_search_validate());
- } else {
- rw_lock_x_unlock(latch);
- }
-#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ assert_block_ahi_valid(block);
rw_lock_x_unlock(latch);
-#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
ut_free(folds);
}
@@ -1533,6 +1520,7 @@ btr_search_build_page_hash_index(
have to take care not to increment the counter in that
case. */
if (!block->index) {
+ assert_block_ahi_empty(block);
index->search_info->ref_count++;
}
@@ -1551,6 +1539,7 @@ btr_search_build_page_hash_index(
MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
exit_func:
+ assert_block_ahi_valid(block);
btr_search_x_unlock(index);
ut_free(folds);
@@ -1590,6 +1579,8 @@ btr_search_move_or_delete_hash_entries(
ut_a(!block->index || block->index == index);
ut_a(!(new_block->index || block->index)
|| !dict_index_is_ibuf(index));
+ assert_block_ahi_valid(block);
+ assert_block_ahi_valid(new_block);
if (new_block->index) {
@@ -1650,6 +1641,7 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_X));
+ assert_block_ahi_valid(block);
index = block->index;
if (!index) {
@@ -1674,6 +1666,7 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
}
btr_search_x_lock(index);
+ assert_block_ahi_valid(block);
if (block->index) {
ut_a(block->index == index);
@@ -1684,6 +1677,8 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
MONITOR_INC(
MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND);
}
+
+ assert_block_ahi_valid(block);
}
btr_search_x_unlock(index);
@@ -1747,6 +1742,7 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
}
func_exit:
+ assert_block_ahi_valid(block);
btr_search_x_unlock(index);
} else {
btr_search_x_unlock(index);
@@ -1791,6 +1787,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
block = btr_cur_get_block(cursor);
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_X));
+ assert_block_ahi_valid(block);
index = block->index;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index d2902580924..754b2cd1c25 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -347,7 +347,7 @@ typedef std::map<
const byte*,
buf_chunk_t*,
std::less<const byte*>,
- ut_allocator<std::pair<const byte*, buf_chunk_t*> > >
+ ut_allocator<std::pair<const byte* const, buf_chunk_t*> > >
buf_pool_chunk_map_t;
static buf_pool_chunk_map_t* buf_chunk_map_reg;
@@ -405,10 +405,22 @@ buf_pool_register_chunk(
/** Decrypt a page.
@param[in,out] bpage Page control block
+@param[in,out] space tablespace
@return whether the operation was successful */
static
bool
-buf_page_decrypt_after_read(buf_page_t* bpage);
+buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
+ MY_ATTRIBUTE((nonnull));
+
+/** Check if page is maybe compressed, encrypted or both when we encounter
+corrupted page. Note that we can't be 100% sure if page is corrupted
+or decrypt/decompress just failed.
+@param[in,out] bpage Page
+@return true if page corrupted, false if not */
+static
+bool
+buf_page_check_corrupt(buf_page_t* bpage)
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
@@ -600,10 +612,6 @@ buf_page_is_zeroes(
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@param[in] use_legacy_big_endian use legacy big endian algorithm
@return true if the page is in crc32 checksum format. */
bool
@@ -611,24 +619,18 @@ buf_page_is_checksum_valid_crc32(
const byte* read_buf,
ulint checksum_field1,
ulint checksum_field2,
-#ifdef UNIV_INNOCHECKSUM
- uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo,
-#endif /* UNIV_INNOCHECKSUM */
bool use_legacy_big_endian)
{
const uint32_t crc32 = buf_calc_page_crc32(read_buf,
use_legacy_big_endian);
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled
- && curr_algo == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ if (log_file
+ && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
fprintf(log_file, "page::%lu;"
" crc32 calculated = %u;"
" recorded checksum field1 = %lu recorded"
- " checksum field2 =%lu\n", page_no,
+ " checksum field2 =%lu\n", cur_page_num,
crc32, checksum_field1, checksum_field2);
}
#endif /* UNIV_INNOCHECKSUM */
@@ -659,23 +661,12 @@ invalid:
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@return true if the page is in innodb checksum format. */
bool
buf_page_is_checksum_valid_innodb(
const byte* read_buf,
ulint checksum_field1,
- ulint checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )
+ ulint checksum_field2)
{
/* There are 2 valid formulas for
checksum_field2 (old checksum field) which algo=innodb could have
@@ -691,31 +682,31 @@ buf_page_is_checksum_valid_innodb(
ulint new_checksum = buf_calc_page_new_checksum(read_buf);
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled
- && curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB) {
+ if (log_file
+ && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) {
fprintf(log_file, "page::%lu;"
" old style: calculated ="
" %lu; recorded = %lu\n",
- page_no, old_checksum,
+ cur_page_num, old_checksum,
checksum_field2);
fprintf(log_file, "page::%lu;"
" new style: calculated ="
" %lu; crc32 = %u; recorded = %lu\n",
- page_no, new_checksum,
+ cur_page_num, new_checksum,
buf_calc_page_crc32(read_buf), checksum_field1);
}
- if (is_log_enabled
- && curr_algo == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ if (log_file
+ && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
fprintf(log_file, "page::%lu;"
" old style: calculated ="
" %lu; recorded checksum = %lu\n",
- page_no, old_checksum,
+ cur_page_num, old_checksum,
checksum_field2);
fprintf(log_file, "page::%lu;"
" new style: calculated ="
" %lu; recorded checksum = %lu\n",
- page_no, new_checksum,
+ cur_page_num, new_checksum,
checksum_field1);
}
#endif /* UNIV_INNOCHECKSUM */
@@ -755,23 +746,12 @@ buf_page_is_checksum_valid_innodb(
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@return true if the page is in none checksum format. */
bool
buf_page_is_checksum_valid_none(
const byte* read_buf,
ulint checksum_field1,
- ulint checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )
+ ulint checksum_field2)
{
#ifndef DBUG_OFF
if (checksum_field1 != checksum_field2
@@ -787,13 +767,13 @@ buf_page_is_checksum_valid_none(
#endif /* DBUG_OFF */
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled
- && curr_algo == SRV_CHECKSUM_ALGORITHM_STRICT_NONE) {
+ if (log_file
+ && srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_NONE) {
fprintf(log_file,
"page::%lu; none checksum: calculated"
" = %lu; recorded checksum_field1 = %lu"
" recorded checksum_field2 = %lu\n",
- page_no, BUF_NO_CHECKSUM_MAGIC,
+ cur_page_num, BUF_NO_CHECKSUM_MAGIC,
checksum_field1, checksum_field2);
}
#endif /* UNIV_INNOCHECKSUM */
@@ -808,10 +788,6 @@ the LSN
@param[in] read_buf database page
@param[in] page_size page size
@param[in] space tablespace
-@param[in] page_no page number of given read_buf
-@param[in] strict_check true if strict-check option is enabled
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
@return TRUE if corrupted */
bool
buf_page_is_corrupted(
@@ -819,12 +795,6 @@ buf_page_is_corrupted(
const byte* read_buf,
const page_size_t& page_size,
const fil_space_t* space
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no,
- bool strict_check,
- bool is_log_enabled,
- FILE* log_file
-#endif /* UNIV_INNOCHECKSUM */
)
{
ulint checksum_field1;
@@ -914,15 +884,8 @@ buf_page_is_corrupted(
}
if (page_size.is_compressed()) {
-#ifdef UNIV_INNOCHECKSUM
- return(!page_zip_verify_checksum(read_buf,
- page_size.physical(),
- page_no, strict_check,
- is_log_enabled, log_file));
-#else
return(!page_zip_verify_checksum(read_buf,
page_size.physical()));
-#endif /* UNIV_INNOCHECKSUM */
}
checksum_field1 = mach_read_from_4(
@@ -964,10 +927,10 @@ buf_page_is_corrupted(
}
#ifdef UNIV_INNOCHECKSUM
if (i >= page_size.logical()) {
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "Page::%lu"
" is empty and uncorrupted\n",
- page_no);
+ cur_page_num);
}
return(false);
}
@@ -993,20 +956,13 @@ buf_page_is_corrupted(
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
if (buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
-#ifdef UNIV_INNOCHECKSUM
- page_no, is_log_enabled, log_file, curr_algo,
-#endif /* UNIV_INNOCHECKSUM */
- false)) {
+ checksum_field1, checksum_field2, false)) {
return(false);
}
if (buf_page_is_checksum_valid_none(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo)) {
-#else /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
+#ifndef UNIV_INNOCHECKSUM
if (curr_algo
== SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
page_warn_strict_checksum(
@@ -1014,20 +970,20 @@ buf_page_is_corrupted(
SRV_CHECKSUM_ALGORITHM_NONE,
page_id);
}
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "page::%lu;"
" old style: calculated = " ULINTPF ";"
- " recorded = " ULINTPF "\n", page_no,
+ " recorded = " ULINTPF "\n", cur_page_num,
buf_calc_page_old_checksum(read_buf),
checksum_field2);
fprintf(log_file, "page::%lu;"
" new style: calculated = " ULINTPF ";"
" crc32 = %u; recorded = " ULINTPF "\n",
- page_no,
+ cur_page_num,
buf_calc_page_new_checksum(read_buf),
buf_calc_page_crc32(read_buf),
checksum_field1);
@@ -1043,11 +999,7 @@ buf_page_is_corrupted(
Otherwise we check innodb checksum first. */
if (legacy_big_endian_checksum) {
if (buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
-#ifdef UNIV_INNOCHECKSUM
- page_no, is_log_enabled, log_file, curr_algo,
-#endif /* UNIV_INNOCHECKSUM */
- true)) {
+ checksum_field1, checksum_field2, true)) {
return(false);
}
@@ -1055,11 +1007,8 @@ buf_page_is_corrupted(
}
if (buf_page_is_checksum_valid_innodb(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo)) {
-#else /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
+#ifndef UNIV_INNOCHECKSUM
if (curr_algo
== SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
page_warn_strict_checksum(
@@ -1067,27 +1016,23 @@ buf_page_is_corrupted(
SRV_CHECKSUM_ALGORITHM_INNODB,
page_id);
}
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
return(false);
}
/* If legacy checksum is not checked, do it now. */
if (!legacy_checksum_checked && buf_page_is_checksum_valid_crc32(
- read_buf, checksum_field1, checksum_field2,
-#ifdef UNIV_INNOCHECKSUM
- page_no, is_log_enabled, log_file, curr_algo,
-#endif /* UNIV_INNOCHECKSUM */
- true)) {
+ read_buf, checksum_field1, checksum_field2, true)) {
legacy_big_endian_checksum = true;
return(false);
}
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "Fail; page %lu"
" invalid (fails crc32 checksum)\n",
- page_no);
+ cur_page_num);
}
#endif /* UNIV_INNOCHECKSUM */
return(true);
@@ -1096,20 +1041,13 @@ buf_page_is_corrupted(
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
if (buf_page_is_checksum_valid_innodb(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
return(false);
}
if (buf_page_is_checksum_valid_none(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo)) {
-#else /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
+#ifndef UNIV_INNOCHECKSUM
if (curr_algo
== SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
page_warn_strict_checksum(
@@ -1117,19 +1055,19 @@ buf_page_is_corrupted(
SRV_CHECKSUM_ALGORITHM_NONE,
page_id);
}
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "page::%lu;"
" old style: calculated = %lu;"
- " recorded = %lu\n", page_no,
+ " recorded = %lu\n", cur_page_num,
buf_calc_page_old_checksum(read_buf),
checksum_field2);
fprintf(log_file, "page::%lu;"
" new style: calculated = %lu;"
" crc32 = %u; recorded = %lu\n",
- page_no,
+ cur_page_num,
buf_calc_page_new_checksum(read_buf),
buf_calc_page_crc32(read_buf),
checksum_field1);
@@ -1138,19 +1076,11 @@ buf_page_is_corrupted(
return(false);
}
-#ifdef UNIV_INNOCHECKSUM
- if (buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
- page_no, is_log_enabled, log_file, curr_algo, false)
- || buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
- page_no, is_log_enabled, log_file, curr_algo, true)) {
-#else /* UNIV_INNOCHECKSUM */
if (buf_page_is_checksum_valid_crc32(read_buf,
checksum_field1, checksum_field2, false)
|| buf_page_is_checksum_valid_crc32(read_buf,
checksum_field1, checksum_field2, true)) {
-
+#ifndef UNIV_INNOCHECKSUM
if (curr_algo
== SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
page_warn_strict_checksum(
@@ -1158,16 +1088,16 @@ buf_page_is_corrupted(
SRV_CHECKSUM_ALGORITHM_CRC32,
page_id);
}
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
return(false);
}
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "Fail; page %lu"
" invalid (fails innodb checksum)\n",
- page_no);
+ cur_page_num);
}
#endif /* UNIV_INNOCHECKSUM */
return(true);
@@ -1175,54 +1105,39 @@ buf_page_is_corrupted(
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
if (buf_page_is_checksum_valid_none(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
return(false);
}
-#ifdef UNIV_INNOCHECKSUM
- if (buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
- page_no, is_log_enabled, log_file, curr_algo, false)
- || buf_page_is_checksum_valid_crc32(read_buf,
- checksum_field1, checksum_field2,
- page_no, is_log_enabled, log_file, curr_algo, true)) {
-#else /* UNIV_INNOCHECKSUM */
if (buf_page_is_checksum_valid_crc32(read_buf,
checksum_field1, checksum_field2, false)
|| buf_page_is_checksum_valid_crc32(read_buf,
checksum_field1, checksum_field2, true)) {
-
+#ifndef UNIV_INNOCHECKSUM
page_warn_strict_checksum(
curr_algo,
SRV_CHECKSUM_ALGORITHM_CRC32,
page_id);
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
return(false);
}
if (buf_page_is_checksum_valid_innodb(read_buf,
- checksum_field1, checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- , page_no, is_log_enabled, log_file, curr_algo)) {
-#else /* UNIV_INNOCHECKSUM */
- )) {
+ checksum_field1, checksum_field2)) {
+#ifndef UNIV_INNOCHECKSUM
page_warn_strict_checksum(
curr_algo,
SRV_CHECKSUM_ALGORITHM_INNODB,
page_id);
-#endif /* UNIV_INNOCHECKSUM */
+#endif /* !UNIV_INNOCHECKSUM */
return(false);
}
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "Fail; page %lu"
" invalid (fails none checksum)\n",
- page_no);
+ cur_page_num);
}
#endif /* UNIV_INNOCHECKSUM */
return(true);
@@ -1496,6 +1411,10 @@ buf_block_init(
{
UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE);
+ /* This function should only be executed at database startup or by
+ buf_pool_resize(). Either way, adaptive hash index must not exist. */
+ assert_block_ahi_empty_on_init(block);
+
block->frame = frame;
block->page.buf_pool_index = buf_pool_index(buf_pool);
@@ -1526,11 +1445,6 @@ buf_block_init(
ut_d(block->in_unzip_LRU_list = FALSE);
ut_d(block->in_withdraw_list = FALSE);
-#ifdef BTR_CUR_HASH_ADAPT
-# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- block->n_pointers = 0;
-# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-#endif /* BTR_CUR_HASH_ADAPT */
page_zip_des_init(&block->page.zip);
mutex_create(LATCH_ID_BUF_BLOCK_MUTEX, &block->mutex);
@@ -1763,7 +1677,9 @@ buf_chunk_not_freed(
== block->page.newest_modification);
ut_ad(block->page.oldest_modification == 0
|| block->page.oldest_modification
- == recv_sys->recovered_lsn);
+ == recv_sys->recovered_lsn
+ || srv_force_recovery
+ == SRV_FORCE_NO_LOG_REDO);
ut_ad(block->page.buf_fix_count == 0);
ut_ad(block->page.io_fix == BUF_IO_NONE);
break;
@@ -2244,6 +2160,10 @@ buf_page_realloc(
/* set other flags of buf_block_t */
#ifdef BTR_CUR_HASH_ADAPT
+ /* This code should only be executed by buf_pool_resize(),
+ while the adaptive hash index is disabled. */
+ assert_block_ahi_empty(block);
+ assert_block_ahi_empty_on_init(new_block);
ut_ad(!block->index);
new_block->index = NULL;
new_block->n_hash_helps = 0;
@@ -3210,20 +3130,23 @@ buf_pool_clear_hash_index()
for (; i--; block++) {
dict_index_t* index = block->index;
+ assert_block_ahi_valid(block);
/* We can set block->index = NULL
- when we have an x-latch on search latch;
- see the comment in buf0buf.h */
+ and block->n_pointers = 0
+ when btr_search_own_all(RW_LOCK_X);
+ see the comments in buf0buf.h */
if (!index) {
- /* Not hashed */
continue;
}
- block->index = NULL;
+ ut_ad(buf_block_get_state(block)
+ == BUF_BLOCK_FILE_PAGE);
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
block->n_pointers = 0;
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+ block->index = NULL;
}
}
}
@@ -3915,6 +3838,9 @@ buf_block_init_low(
{
block->skip_flush_check = false;
#ifdef BTR_CUR_HASH_ADAPT
+ /* No adaptive hash index entries may point to a previously
+ unused (and now freshly allocated) block. */
+ assert_block_ahi_empty_on_init(block);
block->index = NULL;
block->n_hash_helps = 0;
@@ -5833,16 +5759,14 @@ buf_mark_space_corrupt(
return(ret);
}
-/********************************************************************//**
-Check if page is maybe compressed, encrypted or both when we encounter
+/** Check if page is maybe compressed, encrypted or both when we encounter
corrupted page. Note that we can't be 100% sure if page is corrupted
or decrypt/decompress just failed.
@param[in,out] bpage Page
@return true if page corrupted, false if not */
-UNIV_INTERN
+static
bool
-buf_page_check_corrupt(
- buf_page_t* bpage)
+buf_page_check_corrupt(buf_page_t* bpage)
{
byte* dst_frame = (bpage->zip.data) ? bpage->zip.data :
((buf_block_t*) bpage)->frame;
@@ -5945,8 +5869,13 @@ buf_page_io_complete(
ulint read_space_id;
ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL);
+ fil_space_t* space = fil_space_acquire_for_io(
+ bpage->id.space());
+ if (!space) {
+ return false;
+ }
- buf_page_decrypt_after_read(bpage);
+ buf_page_decrypt_after_read(bpage, space);
if (bpage->size.is_compressed()) {
frame = bpage->zip.data;
@@ -6020,21 +5949,17 @@ database_corrupted:
&& buf_mark_space_corrupt(bpage)) {
ib::info() << "Simulated IMPORT "
"corruption";
+ fil_space_release_for_io(space);
return(true);
}
goto page_not_corrupt;
);
if (!bpage->encrypted) {
- fil_system_enter();
- fil_space_t* space = fil_space_get_by_id(bpage->id.space());
- fil_system_exit();
-
ib::error()
<< "Database page corruption on disk"
" or a failed file read of tablespace "
- << (space->name ? space->name : "NULL")
- << " page " << bpage->id
+ << space->name << " page " << bpage->id
<< ". You may have to recover from "
<< "a backup.";
@@ -6063,6 +5988,7 @@ database_corrupted:
if (bpage->id.space() > TRX_SYS_SPACE
&& buf_mark_space_corrupt(bpage)) {
+ fil_space_release_for_io(space);
return(false);
} else {
if (!bpage->encrypted) {
@@ -6088,6 +6014,7 @@ database_corrupted:
ut_error;
}
+ fil_space_release_for_io(space);
return(false);
}
}
@@ -6131,6 +6058,8 @@ database_corrupted:
}
}
+
+ fil_space_release_for_io(space);
} else {
/* io_type == BUF_IO_WRITE */
if (bpage->slot) {
@@ -7398,7 +7327,7 @@ buf_page_encrypt_before_write(
ut_ad(bpage->key_version == 0);
return src_frame;
case TRX_SYS_PAGE_NO:
- if (bpage->id.space() == 0) {
+ if (bpage->id.space() == TRX_SYS_SPACE) {
/* don't encrypt/compress page as it contains
address to dblwr buffer */
bpage->key_version = 0;
@@ -7491,11 +7420,15 @@ buf_page_encrypt_before_write(
/** Decrypt a page.
@param[in,out] bpage Page control block
+@param[in,out] space tablespace
@return whether the operation was successful */
static
bool
-buf_page_decrypt_after_read(buf_page_t* bpage)
+buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
{
+ ut_ad(space->n_pending_ios > 0);
+ ut_ad(space->id == bpage->id.space());
+
bool compressed = bpage->size.is_compressed();
const page_size_t& size = bpage->size;
byte* dst_frame = compressed ? bpage->zip.data :
@@ -7514,12 +7447,10 @@ buf_page_decrypt_after_read(buf_page_t* bpage)
return (true);
}
- FilSpace space(bpage->id.space(), true);
-
/* Page is encrypted if encryption information is found from
tablespace and page contains used key_version. This is true
also for pages first compressed and then encrypted. */
- if (!space() || !space()->crypt_data) {
+ if (!space->crypt_data) {
key_version = 0;
}
@@ -7591,6 +7522,7 @@ buf_page_decrypt_after_read(buf_page_t* bpage)
}
}
+ ut_ad(space->n_pending_ios > 0);
return (success);
}
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 6a0179f36ad..f99fc6434de 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -168,8 +168,7 @@ doublewrite buffer is placed on the trx system header page.
@return true if successful, false if not. */
MY_ATTRIBUTE((warn_unused_result))
bool
-buf_dblwr_create(void)
-/*==================*/
+buf_dblwr_create()
{
buf_block_t* block2;
buf_block_t* new_block;
@@ -510,7 +509,7 @@ buf_dblwr_init_or_load_pages(
/** Process and remove the double write buffer pages for all tablespaces. */
void
-buf_dblwr_process(void)
+buf_dblwr_process()
{
ulint page_no_dblwr = 0;
byte* read_buf;
@@ -527,9 +526,7 @@ buf_dblwr_process(void)
i != recv_dblwr.pages.end();
++i, ++page_no_dblwr) {
byte* page = *i;
- ulint page_no = page_get_page_no(page);
ulint space_id = page_get_space_id(page);
-
fil_space_t* space = fil_space_get(space_id);
if (space == NULL) {
@@ -540,6 +537,7 @@ buf_dblwr_process(void)
fil_space_open_if_needed(space);
+ const ulint page_no = page_get_page_no(page);
const page_id_t page_id(space_id, page_no);
if (page_no >= space->size) {
@@ -676,8 +674,7 @@ buf_dblwr_process(void)
/****************************************************************//**
Frees doublewrite buffer. */
void
-buf_dblwr_free(void)
-/*================*/
+buf_dblwr_free()
{
/* Free the double write data structures. */
ut_a(buf_dblwr != NULL);
@@ -932,8 +929,7 @@ important to call this function after a batch of writes has been posted,
and also when we may have to wait for a page latch! Otherwise a deadlock
of threads can occur. */
void
-buf_dblwr_flush_buffered_writes(void)
-/*=================================*/
+buf_dblwr_flush_buffered_writes()
{
byte* write_buf;
ulint first_free;
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index 9b86b1c16da..ce7488e3d1f 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2011, 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
the terms of the GNU General Public License as published by the Free Software
@@ -796,6 +796,7 @@ extern "C"
os_thread_ret_t
DECLARE_THREAD(buf_dump_thread)(void*)
{
+ my_thread_init();
ut_ad(!srv_read_only_mode);
/* JAN: TODO: MySQL 5.7 PSI
#ifdef UNIV_PFS_THREAD
@@ -836,6 +837,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
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();
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 366e92a7112..d0c0316bf13 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1006,7 +1006,7 @@ buf_flush_write_block_low(
buf_flush_t flush_type, /*!< in: type of flush */
bool sync) /*!< in: true if sync IO request */
{
- fil_space_t* space = fil_space_acquire(bpage->id.space(), true);
+ fil_space_t* space = fil_space_acquire_for_io(bpage->id.space());
if (!space) {
return;
}
@@ -1121,10 +1121,16 @@ buf_flush_write_block_low(
/* true means we want to evict this page from the
LRU list as well. */
+ /* The tablespace could already have been dropped,
+ because fil_io(request, sync) would already have
+ decremented the node->n_pending. However,
+ buf_page_io_complete() only needs to look up the
+ tablespace during read requests, not during writes. */
+ ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE);
buf_page_io_complete(bpage, true);
}
- fil_space_release(space);
+ fil_space_release_for_io(space);
/* Increment the counter of I/O operations used
for selecting LRU policy. */
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index c492ec60494..10a8561d38d 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -295,21 +295,29 @@ next_page:
continue;
}
- mutex_enter(&((buf_block_t*) bpage)->mutex);
+ buf_block_t* block = reinterpret_cast<buf_block_t*>(bpage);
- {
- bool skip = bpage->buf_fix_count > 0
- || !((buf_block_t*) bpage)->index;
+ mutex_enter(&block->mutex);
- mutex_exit(&((buf_block_t*) bpage)->mutex);
+ /* This debug check uses a dirty read that could
+ theoretically cause false positives while
+ buf_pool_clear_hash_index() is executing.
+ (Other conflicting access paths to the adaptive hash
+ index should not be possible, because when a
+ tablespace is being discarded or dropped, there must
+ be no concurrect access to the contained tables.) */
+ assert_block_ahi_valid(block);
- if (skip) {
- /* Skip this block, because there are
- no adaptive hash index entries
- pointing to it, or because we cannot
- drop them due to the buffer-fix. */
- goto next_page;
- }
+ bool skip = bpage->buf_fix_count > 0 || !block->index;
+
+ mutex_exit(&block->mutex);
+
+ if (skip) {
+ /* Skip this block, because there are
+ no adaptive hash index entries
+ pointing to it, or because we cannot
+ drop them due to the buffer-fix. */
+ goto next_page;
}
/* Store the page number so that we can drop the hash
@@ -800,6 +808,17 @@ scan_again:
bpage->id, bpage->size);
goto scan_again;
+ } else {
+ /* This debug check uses a dirty read that could
+ theoretically cause false positives while
+ buf_pool_clear_hash_index() is executing,
+ if the writes to block->index=NULL and
+ block->n_pointers=0 are reordered.
+ (Other conflicting access paths to the adaptive hash
+ index should not be possible, because when a
+ tablespace is being discarded or dropped, there must
+ be no concurrect access to the contained tables.) */
+ assert_block_ahi_empty((buf_block_t*) bpage);
}
#endif /* BTR_CUR_HASH_ADAPT */
@@ -1156,6 +1175,9 @@ buf_LRU_get_free_only(
|| !buf_block_will_withdrawn(buf_pool, block)) {
/* found valid free block */
buf_page_mutex_enter(block);
+ /* No adaptive hash index entries may point to
+ a free block. */
+ assert_block_ahi_empty(block);
buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE);
UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
@@ -2030,17 +2052,10 @@ buf_LRU_block_free_non_file_page(
case BUF_BLOCK_READY_FOR_USE:
break;
default:
- ib::error() << "Block:" << block
- << " incorrect state:" << buf_get_state_name(block)
- << " in buf_LRU_block_free_non_file_page";
- return; /* Continue */
+ ut_error;
}
-#ifdef BTR_CUR_HASH_ADAPT
-# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- ut_a(block->n_pointers == 0);
-# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
-#endif /* BTR_CUR_HASH_ADAPT */
+ assert_block_ahi_empty(block);
ut_ad(!block->page.in_free_list);
ut_ad(!block->page.in_flush_list);
ut_ad(!block->page.in_LRU_list);
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 4d68ad5ac51..f5bd088ce5c 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2016 MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -290,6 +290,24 @@ buf_read_ahead_random(
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
do not try to read outside the bounds of the tablespace! */
if (fil_space_t* space = fil_space_acquire(page_id.space())) {
+
+#ifdef UNIV_DEBUG
+ if (srv_file_per_table) {
+ ulint size = 0;
+
+ for (const fil_node_t* node =
+ UT_LIST_GET_FIRST(space->chain);
+ node != NULL;
+ node = UT_LIST_GET_NEXT(chain, node)) {
+
+ size += os_file_get_size(node->handle)
+ / page_size.physical();
+ }
+
+ ut_ad(size == space->size);
+ }
+#endif /* UNIV_DEBUG */
+
if (high > space->size) {
high = space->size;
}
@@ -896,4 +914,3 @@ buf_read_recv_pages(
DBUG_PRINT("ib_buf", ("recovery read-ahead (%u pages)",
unsigned(n_stored)));
}
-
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 8d5bde4e0e2..3ae6639cd73 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.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, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -488,7 +488,9 @@ dict_boot(void)
err = ibuf_init_at_db_start();
if (err == DB_SUCCESS) {
- if (srv_read_only_mode && !ibuf_is_empty()) {
+ if (srv_read_only_mode
+ && srv_force_recovery != SRV_FORCE_NO_LOG_REDO
+ && !ibuf_is_empty()) {
if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
ib::error() << "Change buffer must be empty when"
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 13db213259c..7a6f09569a6 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -810,7 +810,12 @@ dict_mem_fill_vcol_from_v_indexes(
index;
index = dict_table_get_next_index(index)) {
- if (!dict_index_has_virtual(index)) {
+ /* Skip if the index have newly added
+ virtual column because field name is NULL.
+ Later virtual column set will be
+ refreshed during loading of table. */
+ if (!dict_index_has_virtual(index)
+ || index->has_new_v_col) {
continue;
}
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index 47bab4141de..537a70c2069 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -139,7 +139,7 @@ then we would store 5,7,10,11,12 in the array. */
typedef std::vector<ib_uint64_t, ut_allocator<ib_uint64_t> > boundaries_t;
/** Allocator type used for index_map_t. */
-typedef ut_allocator<std::pair<const char*, dict_index_t*> >
+typedef ut_allocator<std::pair<const char* const, dict_index_t*> >
index_map_t_allocator;
/** Auxiliary map used for sorting indexes by name in dict_stats_save(). */
@@ -1152,10 +1152,11 @@ dict_stats_analyze_index_level(
them away) which brings non-determinism. We skip only
leaf-level delete marks because delete marks on
non-leaf level do not make sense. */
- if (level == 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
@@ -1176,7 +1177,6 @@ dict_stats_analyze_index_level(
continue;
}
-
rec_offsets = rec_get_offsets(
rec, index, rec_offsets, n_uniq, &heap);
@@ -1334,8 +1334,12 @@ enum page_scan_method_t {
the given page and count the number of
distinct ones, also ignore delete marked
records */
- QUIT_ON_FIRST_NON_BORING/* quit when the first record that differs
+ QUIT_ON_FIRST_NON_BORING,/* quit when the first record that differs
from its right neighbor is found */
+ COUNT_ALL_NON_BORING_INCLUDE_DEL_MARKED/* scan all records on
+ the given page and count the number of
+ distinct ones, include delete marked
+ records */
};
/* @} */
@@ -1608,6 +1612,8 @@ dict_stats_analyze_index_below_cur(
offsets_rec = dict_stats_scan_page(
&rec, offsets1, offsets2, index, page, n_prefix,
+ srv_stats_include_delete_marked ?
+ COUNT_ALL_NON_BORING_INCLUDE_DEL_MARKED:
COUNT_ALL_NON_BORING_AND_SKIP_DEL_MARKED, n_diff,
n_external_pages);
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 4ffee160c9f..876d1bcb342 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2012, 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
the terms of the GNU General Public License as published by the Free Software
@@ -31,6 +31,7 @@ Created Apr 25, 2012 Vasil Dimov
#include "row0mysql.h"
#include "srv0start.h"
#include "ut0new.h"
+#include "fil0fil.h"
#include <vector>
@@ -318,8 +319,9 @@ dict_stats_process_entry_from_recalc_pool()
return;
}
- /* Check whether table is corrupted */
- if (table->corrupted) {
+ ut_ad(!dict_table_is_temporary(table));
+
+ if (!fil_table_accessible(table)) {
dict_table_close(table, TRUE, FALSE);
mutex_exit(&dict_sys->mutex);
return;
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 016b7c3d24e..b031a77baa8 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -629,7 +629,7 @@ fil_space_encrypt(
fil_space_crypt_t* crypt_data = space->crypt_data;
const page_size_t page_size(space->flags);
- ut_ad(space->n_pending_ops);
+ ut_ad(space->n_pending_ios > 0);
byte* tmp = fil_encrypt_buf(crypt_data, space->id, offset, lsn,
src_frame, page_size, dst_frame);
@@ -821,7 +821,7 @@ fil_space_decrypt(
*decrypted = false;
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
- ut_ad(space->n_pending_ops > 0);
+ ut_ad(space->n_pending_ios > 0);
bool encrypted = fil_space_decrypt(space->crypt_data, tmp_frame,
page_size, src_frame, &err);
@@ -2492,10 +2492,6 @@ bool
fil_space_verify_crypt_checksum(
byte* page,
const page_size_t& page_size,
-#ifdef UNIV_INNOCHECKSUM
- bool strict_check, /*!< --strict-check */
- FILE* log_file, /*!< --log */
-#endif /* UNIV_INNOCHECKSUM */
ulint space,
ulint offset)
{
@@ -2541,14 +2537,7 @@ fil_space_verify_crypt_checksum(
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
bool valid = page_zip_verify_checksum(page,
- page_size.physical()
-#ifdef UNIV_INNOCHECKSUM
- , offset,
- strict_check,
- log_file != NULL,
- log_file
-#endif
- );
+ page_size.physical());
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, old);
@@ -2594,19 +2583,11 @@ fil_space_verify_crypt_checksum(
ulint checksum2 = mach_read_from_4(
page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
-#ifdef UNIV_INNOCHECKSUM
-# define CKARGS page, checksum1, checksum2, \
- offset, log_file != NULL, log_file, algorithm
-#else
-# define CKARGS page, checksum1, checksum2
-#endif
-
bool valid = buf_page_is_checksum_valid_crc32(
- CKARGS, false
+ page, checksum1, checksum2, false
/* FIXME: also try the original crc32 that was
buggy on big-endian architectures? */)
- || buf_page_is_checksum_valid_innodb(CKARGS);
-#undef CKARGS
+ || buf_page_is_checksum_valid_innodb(page, checksum1, checksum2);
if (encrypted && valid) {
/* If page is encrypted and traditional checksums match,
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index d91ab3530a1..7a169c0bf2c 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/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.
This program is free software; you can redistribute it and/or modify it under
@@ -30,6 +30,7 @@ Created 10/25/1995 Heikki Tuuri
#include "fil0crypt.h"
#include "btr0btr.h"
+#include "btr0sea.h"
#include "buf0buf.h"
#include "dict0boot.h"
#include "dict0dict.h"
@@ -39,6 +40,7 @@ Created 10/25/1995 Heikki Tuuri
#include "fsp0space.h"
#include "fsp0sysspace.h"
#include "hash0hash.h"
+#include "log0log.h"
#include "log0recv.h"
#include "mach0data.h"
#include "mem0mem.h"
@@ -55,9 +57,6 @@ Created 10/25/1995 Heikki Tuuri
#include "os0event.h"
#include "sync0sync.h"
#include "buf0flu.h"
-#include "srv0start.h"
-#include "trx0purge.h"
-#include "ut0new.h"
#include "os0api.h"
/** Tries to close a file in the LRU list. The caller must hold the fil_sys
@@ -1507,6 +1506,13 @@ fil_space_free_low(
ut_ad(srv_fast_shutdown == 2 || !srv_was_started
|| space->max_lsn == 0);
+ /* Wait for fil_space_release_for_io(); after
+ fil_space_detach(), the tablespace cannot be found, so
+ fil_space_acquire_for_io() would return NULL */
+ while (space->n_pending_ios) {
+ os_thread_sleep(100);
+ }
+
for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
node != NULL; ) {
ut_d(space->size -= node->size);
@@ -2268,13 +2274,11 @@ Used by background threads that do not necessarily hold proper locks
for concurrency control.
@param[in] id tablespace ID
@param[in] silent whether to silently ignore missing tablespaces
-@param[in] for_io whether to look up the tablespace while performing I/O
- (possibly executing TRUNCATE)
@return the tablespace
@retval NULL if missing or being deleted or truncated */
inline
fil_space_t*
-fil_space_acquire_low(ulint id, bool silent, bool for_io = false)
+fil_space_acquire_low(ulint id, bool silent)
{
fil_space_t* space;
@@ -2287,7 +2291,7 @@ fil_space_acquire_low(ulint id, bool silent, bool for_io = false)
ib::warn() << "Trying to access missing"
" tablespace " << id;
}
- } else if (!for_io && space->is_stopping()) {
+ } else if (space->is_stopping()) {
space = NULL;
} else {
space->n_pending_ops++;
@@ -2302,14 +2306,12 @@ fil_space_acquire_low(ulint id, bool silent, bool for_io = false)
Used by background threads that do not necessarily hold proper locks
for concurrency control.
@param[in] id tablespace ID
-@param[in] for_io whether to look up the tablespace while performing I/O
- (possibly executing TRUNCATE)
@return the tablespace
@retval NULL if missing or being deleted or truncated */
fil_space_t*
-fil_space_acquire(ulint id, bool for_io)
+fil_space_acquire(ulint id)
{
- return(fil_space_acquire_low(id, false, for_io));
+ return(fil_space_acquire_low(id, false));
}
/** Acquire a tablespace that may not exist.
@@ -2336,6 +2338,39 @@ fil_space_release(fil_space_t* space)
mutex_exit(&fil_system->mutex);
}
+/** Acquire a tablespace for reading or writing a block,
+when it could be dropped concurrently.
+@param[in] id tablespace ID
+@return the tablespace
+@retval NULL if missing */
+fil_space_t*
+fil_space_acquire_for_io(ulint id)
+{
+ mutex_enter(&fil_system->mutex);
+
+ fil_space_t* space = fil_space_get_by_id(id);
+
+ if (space) {
+ space->n_pending_ios++;
+ }
+
+ mutex_exit(&fil_system->mutex);
+
+ return(space);
+}
+
+/** Release a tablespace acquired with fil_space_acquire_for_io().
+@param[in,out] space tablespace to release */
+void
+fil_space_release_for_io(fil_space_t* space)
+{
+ mutex_enter(&fil_system->mutex);
+ ut_ad(space->magic_n == FIL_SPACE_MAGIC_N);
+ ut_ad(space->n_pending_ios > 0);
+ space->n_pending_ios--;
+ mutex_exit(&fil_system->mutex);
+}
+
/********************************************************//**
Creates the database directory for a table if it does not exist yet. */
void
@@ -2837,15 +2872,15 @@ enum fil_operation_t {
@return 0 if no operations else count + 1. */
static
ulint
-fil_check_pending_ops(
- fil_space_t* space,
- ulint count)
+fil_check_pending_ops(const fil_space_t* space, ulint count)
{
ut_ad(mutex_own(&fil_system->mutex));
- const ulint n_pending_ops = space ? space->n_pending_ops : 0;
+ if (space == NULL) {
+ return 0;
+ }
- if (n_pending_ops) {
+ if (ulint n_pending_ops = space->n_pending_ops) {
if (count > 5000) {
ib::warn() << "Trying to close/delete/truncate"
@@ -3057,6 +3092,32 @@ fil_close_tablespace(
return(err);
}
+/** Determine whether a table can be accessed in operations that are
+not (necessarily) protected by meta-data locks.
+(Rollback would generally be protected, but rollback of
+FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
+but only by InnoDB table locks, which may be broken by TRUNCATE TABLE.)
+@param[in] table persistent table
+checked @return whether the table is accessible */
+bool
+fil_table_accessible(const dict_table_t* table)
+{
+ if (UNIV_UNLIKELY(table->ibd_file_missing || table->corrupted)) {
+ return(false);
+ }
+
+ if (fil_space_t* space = fil_space_acquire(table->space)) {
+ bool accessible = !space->is_stopping();
+ fil_space_release(space);
+ ut_ad(accessible || dict_table_is_file_per_table(table));
+ return(accessible);
+ } else {
+ /* The tablespace may momentarily be missing during
+ TRUNCATE TABLE. */
+ return(false);
+ }
+}
+
/** Deletes an IBD tablespace, either general or single-table.
The tablespace must be cached in the memory cache. This will delete the
datafile, fil_space_t & fil_node_t entries from the file_system_t cache.
@@ -3266,20 +3327,34 @@ fil_prepare_for_truncate(
return(err);
}
-/**********************************************************************//**
-Reinitialize the original tablespace header with the same space id
-for single tablespace */
+/** Reinitialize the original tablespace header with the same space id
+for single tablespace
+@param[in] id space id of the tablespace
+@param[in] size size in blocks
+@param[in] trx Transaction covering truncate */
void
fil_reinit_space_header(
-/*====================*/
- ulint id, /*!< in: space id */
- ulint size) /*!< in: size in blocks */
+ ulint id,
+ ulint size,
+ trx_t* trx)
{
ut_a(!is_system_tablespace(id));
/* Invalidate in the buffer pool all pages belonging
- to the tablespace */
+ to the tablespace. The buffer pool scan may take long
+ time to complete, therefore we release dict_sys->mutex
+ and the dict operation lock during the scan and aquire
+ it again after the buffer pool scan.*/
+
+ row_mysql_unlock_data_dictionary(trx);
+
+ /* Lock the search latch in shared mode to prevent user
+ from disabling AHI during the scan */
+ btr_search_s_lock_all();
+ DEBUG_SYNC_C("buffer_pool_scan");
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_ALL_NO_WRITE, 0);
+ btr_search_s_unlock_all();
+ row_mysql_lock_data_dictionary(trx);
/* Remove all insert buffer entries for the tablespace */
ibuf_delete_for_discarded_space(id);
@@ -5492,7 +5567,7 @@ fil_flush(
void
fil_flush(fil_space_t* space)
{
- ut_ad(space->n_pending_ops > 0);
+ ut_ad(space->n_pending_ios > 0);
ut_ad(space->purpose == FIL_TYPE_TABLESPACE
|| space->purpose == FIL_TYPE_IMPORT);
@@ -6498,6 +6573,12 @@ fil_names_clear(
bool do_write)
{
mtr_t mtr;
+ ulint mtr_checkpoint_size = LOG_CHECKPOINT_FREE_PER_THREAD;
+
+ DBUG_EXECUTE_IF(
+ "increase_mtr_checkpoint_size",
+ mtr_checkpoint_size = 75 * 1024;
+ );
ut_ad(log_mutex_own());
@@ -6531,11 +6612,24 @@ fil_names_clear(
fil_names_write(space, &mtr);
do_write = true;
+ const mtr_buf_t* mtr_log = mtr_get_log(&mtr);
+
+ /** If the mtr buffer size exceeds the size of
+ LOG_CHECKPOINT_FREE_PER_THREAD then commit the multi record
+ mini-transaction, start the new mini-transaction to
+ avoid the parsing buffer overflow error during recovery. */
+
+ if (mtr_log->size() > mtr_checkpoint_size) {
+ ut_ad(mtr_log->size() < (RECV_PARSING_BUF_SIZE / 2));
+ mtr.commit_checkpoint(lsn, false);
+ mtr.start();
+ }
+
space = next;
}
if (do_write) {
- mtr.commit_checkpoint(lsn);
+ mtr.commit_checkpoint(lsn, true);
} else {
ut_ad(!mtr.has_modifications());
}
diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc
index 65c39eae89d..5f7ce530776 100644
--- a/storage/innobase/fil/fil0pagecompress.cc
+++ b/storage/innobase/fil/fil0pagecompress.cc
@@ -107,7 +107,7 @@ fil_compress_page(
/* page_compression does not apply to tables or tablespaces
that use ROW_FORMAT=COMPRESSED */
- ut_ad(!space || !page_size_t(space->flags).is_compressed());
+ ut_ad(!space || !FSP_FLAGS_GET_ZIP_SSIZE(space->flags));
if (encrypted) {
header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE;
@@ -137,7 +137,6 @@ fil_compress_page(
case FIL_PAGE_TYPE_XDES:
case FIL_PAGE_PAGE_COMPRESSED:
*out_len = len;
-
goto err_exit;
}
@@ -323,7 +322,6 @@ fil_compress_page(
/* Actual write needs to be alligned on block size */
if (write_size % block_size) {
size_t tmp = write_size;
-
write_size = (size_t)ut_uint64_align_up((ib_uint64_t)write_size, block_size);
/* Clean up the end of buffer */
memset(out_buf+tmp, 0, write_size - tmp);
@@ -626,11 +624,11 @@ err_exit:
/* Note that as we have found the page is corrupted, so
all this could be incorrect. */
ulint space_id = mach_read_from_4(buf+FIL_PAGE_SPACE_ID);
- const FilSpace space(space_id, true);
+ fil_space_t* space = fil_space_acquire_for_io(space_id);
ib::error() << "Corruption: Page is marked as compressed"
<< " space: " << space_id << " name: "
- << (space() ? space()->name : "NULL")
+ << (space ? space->name : "NULL")
<< " but uncompress failed with error: " << err
<< " size: " << actual_size
<< " len: " << len
@@ -638,4 +636,5 @@ err_exit:
<< fil_get_compression_alg_name(compression_alg) << ".";
buf_page_print(buf, univ_page_size, 0);
+ fil_space_release_for_io(space);
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index dd0e036170c..79020fb4442 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -93,6 +93,7 @@ static const ulint FTS_DEADLOCK_RETRY_WAIT = 100000;
/** variable to record innodb_fts_internal_tbl_name for information
schema table INNODB_FTS_INSERTED etc. */
char* fts_internal_tbl_name = NULL;
+char* fts_internal_tbl_name2 = NULL;
/** InnoDB default stopword list:
There are different versions of stopwords, the stop words listed
@@ -6496,6 +6497,36 @@ fts_check_corrupt_index(
return(0);
}
+/* Get parent table name if it's a fts aux table
+@param[in] aux_table_name aux table name
+@param[in] aux_table_len aux table length
+@return parent table name, or NULL */
+char*
+fts_get_parent_table_name(
+ const char* aux_table_name,
+ ulint aux_table_len)
+{
+ fts_aux_table_t aux_table;
+ char* parent_table_name = NULL;
+
+ if (fts_is_aux_table_name(&aux_table, aux_table_name, aux_table_len)) {
+ dict_table_t* parent_table;
+
+ parent_table = dict_table_open_on_id(
+ aux_table.parent_id, TRUE, DICT_TABLE_OP_NORMAL);
+
+ if (parent_table != NULL) {
+ parent_table_name = mem_strdupl(
+ parent_table->name.m_name,
+ strlen(parent_table->name.m_name));
+
+ dict_table_close(parent_table, TRUE, FALSE);
+ }
+ }
+
+ return(parent_table_name);
+}
+
/** Check the validity of the parent table.
@param[in] aux_table auxiliary table
@return true if it is a valid table or false if it is not */
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index f1e717c353a..820e82dc600 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -578,9 +578,6 @@ fts_zip_read_word(
fts_zip_t* zip, /*!< in: Zip state + data */
fts_string_t* word) /*!< out: uncompressed word */
{
-#ifdef UNIV_DEBUG
- ulint i;
-#endif
short len = 0;
void* null = NULL;
byte* ptr = word->f_str;
@@ -656,10 +653,9 @@ fts_zip_read_word(
}
}
-#ifdef UNIV_DEBUG
/* All blocks must be freed at end of inflate. */
if (zip->status != Z_OK) {
- for (i = 0; i < ib_vector_size(zip->blocks); ++i) {
+ for (ulint i = 0; i < ib_vector_size(zip->blocks); ++i) {
if (ib_vector_getp(zip->blocks, i)) {
ut_free(ib_vector_getp(zip->blocks, i));
ib_vector_set(zip->blocks, i, &null);
@@ -670,7 +666,6 @@ fts_zip_read_word(
if (ptr != NULL) {
ut_ad(word->f_len == strlen((char*) ptr));
}
-#endif /* UNIV_DEBUG */
return(zip->status == Z_OK || zip->status == Z_STREAM_END ? ptr : NULL);
}
diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc
index 5822bd6755c..f620db6f62e 100644
--- a/storage/innobase/ha/ha0ha.cc
+++ b/storage/innobase/ha/ha0ha.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, 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
the terms of the GNU General Public License as published by the Free Software
@@ -189,6 +190,12 @@ ha_clear(
}
#ifdef BTR_CUR_HASH_ADAPT
+# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
+/** Maximum number of records in a page */
+static const lint MAX_N_POINTERS
+ = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES;
+# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+
/*************************************************************//**
Inserts an entry into a hash table. If an entry with the same fold number
is found, its node is updated to point to the new data, and no new node
@@ -235,9 +242,11 @@ ha_insert_for_fold_func(
buf_block_t* prev_block = prev_node->block;
ut_a(prev_block->frame
== page_align(prev_node->data));
- ut_a(prev_block->n_pointers > 0);
- prev_block->n_pointers--;
- block->n_pointers++;
+ ut_a(my_atomic_addlint(
+ &prev_block->n_pointers, -1)
+ < MAX_N_POINTERS);
+ ut_a(my_atomic_addlint(&block->n_pointers, 1)
+ < MAX_N_POINTERS);
}
prev_node->block = block;
@@ -268,7 +277,8 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
- block->n_pointers++;
+ ut_a(my_atomic_addlint(&block->n_pointers, 1)
+ < MAX_N_POINTERS);
}
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -329,8 +339,8 @@ ha_delete_hash_node(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
ut_a(del_node->block->frame = page_align(del_node->data));
- ut_a(del_node->block->n_pointers > 0);
- del_node->block->n_pointers--;
+ ut_a(my_atomic_addlint(&del_node->block->n_pointers, -1)
+ < MAX_N_POINTERS);
}
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -372,9 +382,10 @@ ha_search_and_update_if_found_func(
if (node) {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
- ut_a(node->block->n_pointers > 0);
- node->block->n_pointers--;
- new_block->n_pointers++;
+ ut_a(my_atomic_addlint(&node->block->n_pointers, -1)
+ < MAX_N_POINTERS);
+ ut_a(my_atomic_addlint(&new_block->n_pointers, 1)
+ < MAX_N_POINTERS);
}
node->block = new_block;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 950aae729fd..72cf0418e81 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -215,45 +215,45 @@ static uint innobase_old_blocks_pct;
/* The default values for the following char* start-up parameters
are determined in innobase_init below: */
-static char* innobase_data_home_dir = NULL;
-static char* innobase_data_file_path = NULL;
-static char* innobase_temp_data_file_path = NULL;
-static char* innobase_file_format_name = NULL;
-static char* innobase_change_buffering = NULL;
-static char* innobase_enable_monitor_counter = NULL;
-static char* innobase_disable_monitor_counter = NULL;
-static char* innobase_reset_monitor_counter = NULL;
-static char* innobase_reset_all_monitor_counter = NULL;
+static char* innobase_data_home_dir;
+static char* innobase_data_file_path;
+static char* innobase_temp_data_file_path;
+static char* innobase_file_format_name;
+static char* innobase_change_buffering;
+static char* innobase_enable_monitor_counter;
+static char* innobase_disable_monitor_counter;
+static char* innobase_reset_monitor_counter;
+static char* innobase_reset_all_monitor_counter;
/* The highest file format being used in the database. The value can be
set by user, however, it will be adjusted to the newer file format if
a table of such format is created/opened. */
-char* innobase_file_format_max = NULL;
+char* innobase_file_format_max;
/** Default value of innodb_file_format */
static const char* innodb_file_format_default = "Barracuda";
/** Default value of innodb_file_format_max */
static const char* innodb_file_format_max_default = "Antelope";
-static char* innobase_file_flush_method = NULL;
+static char* innobase_file_flush_method;
/* This variable can be set in the server configure file, specifying
stopword table to be used */
-static char* innobase_server_stopword_table = NULL;
+static char* innobase_server_stopword_table;
/* Below we have boolean-valued start-up parameters, and their default
values */
-static my_bool innobase_file_format_check = TRUE;
-static my_bool innobase_use_atomic_writes = TRUE;
-static my_bool innobase_use_doublewrite = TRUE;
-static my_bool innobase_use_checksums = TRUE;
-static my_bool innobase_locks_unsafe_for_binlog = FALSE;
-static my_bool innobase_rollback_on_timeout = FALSE;
-static my_bool innobase_create_status_file = FALSE;
-my_bool innobase_stats_on_metadata = TRUE;
-static my_bool innobase_large_prefix = FALSE;
-static my_bool innodb_optimize_fulltext_only = FALSE;
+static my_bool innobase_file_format_check;
+static my_bool innobase_use_atomic_writes;
+static my_bool innobase_use_doublewrite;
+static my_bool innobase_use_checksums;
+static my_bool innobase_locks_unsafe_for_binlog;
+static my_bool innobase_rollback_on_timeout;
+static my_bool innobase_create_status_file;
+my_bool innobase_stats_on_metadata;
+static my_bool innobase_large_prefix;
+static my_bool innodb_optimize_fulltext_only;
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
@@ -1322,15 +1322,11 @@ void
innobase_commit_concurrency_init_default();
/*=======================================*/
-/** @brief Initialize the default and max value of innodb_undo_logs.
-
-Once InnoDB is running, the default value and the max value of
-innodb_undo_logs must be equal to the available undo logs,
-given by srv_available_undo_logs. */
+/** @brief Adjust some InnoDB startup parameters based on file contents
+or innodb_page_size. */
static
void
-innobase_undo_logs_init_default_max();
-/*==================================*/
+innodb_params_adjust();
/************************************************************//**
Validate the file format name and return its corresponding id.
@@ -4235,6 +4231,11 @@ innobase_change_buffering_inited_ok:
if (UNIV_PAGE_SIZE_DEF != srv_page_size) {
ib::info() << "innodb_page_size=" << srv_page_size;
+
+ srv_max_undo_log_size = std::max(
+ srv_max_undo_log_size,
+ ulonglong(SRV_UNDO_TABLESPACE_SIZE_IN_PAGES)
+ * srv_page_size);
}
if (srv_log_write_ahead_size > srv_page_size) {
@@ -4395,12 +4396,6 @@ innobase_change_buffering_inited_ok:
}
*/
- /* Since we in this module access directly the fields of a trx
- struct, and due to different headers and flags it might happen that
- ib_mutex_t has a different size in this module and in InnoDB
- modules, we check at run time that the size is the same in
- these compilation modules. */
-
err = innobase_start_or_create_for_mysql();
if (srv_buf_pool_size_org != 0) {
@@ -4425,9 +4420,8 @@ innobase_change_buffering_inited_ok:
os_thread_sleep(20);
}
- srv_was_started = TRUE;
- /* Adjust the innodb_undo_logs config object */
- innobase_undo_logs_init_default_max();
+ srv_was_started = true;
+ innodb_params_adjust();
innobase_old_blocks_pct = static_cast<uint>(
buf_LRU_old_ratio_update(innobase_old_blocks_pct, TRUE));
@@ -10415,13 +10409,7 @@ ha_innobase::rnd_init(
bool scan) /*!< in: true if table/index scan FALSE otherwise */
{
TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
-
- if (trx_in_innodb.is_aborted()) {
-
- return(innobase_rollback(ht, m_user_thd, false));
- }
-
- int err;
+ int err;
/* Store the active index value so that we can restore the original
value after a scan */
@@ -13755,7 +13743,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);
}
@@ -14188,116 +14177,6 @@ ha_innobase::rename_table(
}
/*********************************************************************//**
-Returns the exact number of records that this client can see using this
-handler object.
-@return Error code in case something goes wrong.
-These errors will abort the current query:
- case HA_ERR_LOCK_DEADLOCK:
- case HA_ERR_LOCK_TABLE_FULL:
- case HA_ERR_LOCK_WAIT_TIMEOUT:
- case HA_ERR_QUERY_INTERRUPTED:
-For other error codes, the server will fall back to counting records. */
-
-#ifdef MYSQL_57_SELECT_COUNT_OPTIMIZATION
-int
-ha_innobase::records(
-/*==================*/
- ha_rows* num_rows) /*!< out: number of rows */
-{
- DBUG_ENTER("ha_innobase::records()");
-
- dberr_t ret;
- ulint n_rows = 0; /* Record count in this view */
-
- update_thd();
-
- if (dict_table_is_discarded(m_prebuilt->table)) {
- ib_senderrf(
- m_user_thd,
- IB_LOG_LEVEL_ERROR,
- ER_TABLESPACE_DISCARDED,
- table->s->table_name.str);
-
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
-
- } else if (m_prebuilt->table->ibd_file_missing) {
- ib_senderrf(
- m_user_thd, IB_LOG_LEVEL_ERROR,
- ER_TABLESPACE_MISSING,
- table->s->table_name.str);
-
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_TABLESPACE_MISSING);
-
- } else if (m_prebuilt->table->corrupted) {
- ib_errf(m_user_thd, IB_LOG_LEVEL_WARN,
- ER_INNODB_INDEX_CORRUPT,
- "Table '%s' is corrupt.",
- table->s->table_name.str);
-
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_INDEX_CORRUPT);
- }
-
- TrxInInnoDB trx_in_innodb(m_prebuilt->trx);
-
- m_prebuilt->trx->op_info = "counting records";
-
- dict_index_t* index = dict_table_get_first_index(m_prebuilt->table);
-
- ut_ad(dict_index_is_clust(index));
-
- m_prebuilt->index_usable = row_merge_is_index_usable(
- m_prebuilt->trx, index);
-
- if (!m_prebuilt->index_usable) {
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
- }
-
- /* (Re)Build the m_prebuilt->mysql_template if it is null to use
- the clustered index and just the key, no off-record data. */
- m_prebuilt->index = index;
- dtuple_set_n_fields(m_prebuilt->search_tuple, 0);
- m_prebuilt->read_just_key = 1;
- build_template(false);
-
- /* Count the records in the clustered index */
- ret = row_scan_index_for_mysql(m_prebuilt, index, false, &n_rows);
- reset_template();
- switch (ret) {
- case DB_SUCCESS:
- break;
- case DB_DEADLOCK:
- case DB_LOCK_TABLE_FULL:
- case DB_LOCK_WAIT_TIMEOUT:
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(convert_error_code_to_mysql(ret, 0, m_user_thd));
- case DB_INTERRUPTED:
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_QUERY_INTERRUPTED);
- default:
- /* No other error besides the three below is returned from
- row_scan_index_for_mysql(). Make a debug catch. */
- *num_rows = HA_POS_ERROR;
- ut_ad(0);
- DBUG_RETURN(-1);
- }
-
- m_prebuilt->trx->op_info = "";
-
- if (thd_killed(m_user_thd)) {
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(HA_ERR_QUERY_INTERRUPTED);
- }
-
- *num_rows= n_rows;
- DBUG_RETURN(0);
-}
-#endif /* MYSQL_57_SELECT_COUNT_OPTIMIZATION */
-
-/*********************************************************************//**
Estimates the number of index records in a range.
@return estimated number of rows */
@@ -15543,7 +15422,7 @@ ha_innobase::check(
ret = row_count_rtree_recs(m_prebuilt, &n_rows);
} else {
ret = row_scan_index_for_mysql(
- m_prebuilt, index, true, &n_rows);
+ m_prebuilt, index, &n_rows);
}
DBUG_EXECUTE_IF(
@@ -15821,6 +15700,28 @@ get_foreign_key_info(
f_key_info.update_method = FK_OPTION_RESTRICT;
}
+ /* Load referenced table to update FK referenced key name. */
+ if (foreign->referenced_table == NULL) {
+
+ dict_table_t* ref_table;
+
+ ut_ad(mutex_own(&dict_sys->mutex));
+ ref_table = dict_table_open_on_name(
+ foreign->referenced_table_name_lookup,
+ TRUE, FALSE, DICT_ERR_IGNORE_NONE);
+
+ if (ref_table == NULL) {
+
+ ib::info() << "Foreign Key referenced table "
+ << foreign->referenced_table_name
+ << " not found for foreign table "
+ << foreign->foreign_table_name;
+ } else {
+
+ dict_table_close(ref_table, TRUE, FALSE);
+ }
+ }
+
if (foreign->referenced_index
&& foreign->referenced_index->name != NULL) {
referenced_key_name = thd_make_lex_string(
@@ -17617,6 +17518,37 @@ ha_innobase::get_auto_increment(
whether we update the table autoinc counter or not. */
ulonglong col_max_value = innobase_get_int_col_max_value(table->next_number_field);
+ /** The following logic is needed to avoid duplicate key error
+ for autoincrement column.
+
+ (1) InnoDB gives the current autoincrement value with respect
+ to increment and offset value.
+
+ (2) Basically it does compute_next_insert_id() logic inside InnoDB
+ to avoid the current auto increment value changed by handler layer.
+
+ (3) It is restricted only for insert operations. */
+
+ if (increment > 1 && thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE
+ && autoinc < col_max_value) {
+
+ ulonglong prev_auto_inc = autoinc;
+
+ autoinc = ((autoinc - 1) + increment - offset)/ increment;
+
+ autoinc = autoinc * increment + offset;
+
+ /* If autoinc exceeds the col_max_value then reset
+ to old autoinc value. Because in case of non-strict
+ sql mode, boundary value is not considered as error. */
+
+ if (autoinc >= col_max_value) {
+ autoinc = prev_auto_inc;
+ }
+
+ ut_ad(autoinc > 0);
+ }
+
/* Called for the first time ? */
if (trx->n_autoinc_rows == 0) {
@@ -18722,6 +18654,41 @@ innodb_internal_table_validate(
return(ret);
}
+/****************************************************************//**
+Update global variable "fts_internal_tbl_name" with the "saved"
+stopword table name value. This function is registered as a callback
+with MySQL. */
+static
+void
+innodb_internal_table_update(
+/*=========================*/
+ THD* thd, /*!< in: thread handle */
+ struct st_mysql_sys_var* var, /*!< in: pointer to
+ system variable */
+ void* var_ptr,/*!< out: where the
+ formal string goes */
+ const void* save) /*!< in: immediate result
+ from check function */
+{
+ const char* table_name;
+ char* old;
+
+ ut_a(save != NULL);
+ ut_a(var_ptr != NULL);
+
+ table_name = *static_cast<const char*const*>(save);
+ old = *(char**) var_ptr;
+ *(char**) var_ptr = table_name ? my_strdup(table_name, MYF(0)) : NULL;
+ my_free(old);
+
+ fts_internal_tbl_name2 = *(char**) var_ptr;
+ if (fts_internal_tbl_name2 == NULL) {
+ fts_internal_tbl_name = const_cast<char*>("default");
+ } else {
+ fts_internal_tbl_name = fts_internal_tbl_name2;
+ }
+}
+
#ifdef BTR_CUR_HASH_ADAPT
/****************************************************************//**
Update the system variable innodb_adaptive_hash_index using the "saved"
@@ -20610,6 +20577,12 @@ static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes,
"the directFS filesystem or with Shannon cards using any file system.",
NULL, NULL, TRUE);
+static MYSQL_SYSVAR_BOOL(stats_include_delete_marked,
+ srv_stats_include_delete_marked,
+ PLUGIN_VAR_OPCMDARG,
+ "Include delete marked records when calculating persistent statistics",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
PLUGIN_VAR_RQCMDARG,
"Number of IOPs the server can do. Tunes the background IO rate",
@@ -21118,6 +21091,13 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter,
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
NULL, NULL, 5000L, 1L, ~0UL, 0);
+static MYSQL_SYSVAR_BOOL(deadlock_detect, innobase_deadlock_detect,
+ PLUGIN_VAR_NOCMDARG,
+ "Enable/disable InnoDB deadlock detector (default ON)."
+ " if set to OFF, deadlock detection is skipped,"
+ " and we rely on innodb_lock_wait_timeout in case of deadlock.",
+ NULL, NULL, TRUE);
+
static MYSQL_SYSVAR_LONG(fill_factor, innobase_fill_factor,
PLUGIN_VAR_RQCMDARG,
"Percentage of B-tree page filled during bulk insert",
@@ -21133,11 +21113,11 @@ static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache,
"Whether to disable OS system file cache for sort I/O",
NULL, NULL, FALSE);
-static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name2,
+ PLUGIN_VAR_RQCMDARG,
"FTS internal auxiliary table to be checked",
innodb_internal_table_validate,
- NULL, NULL);
+ innodb_internal_table_update, NULL);
static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
@@ -21305,11 +21285,11 @@ static MYSQL_SYSVAR_STR(undo_directory, srv_undo_dir,
static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Number of undo tablespaces to use. ",
+ "Number of undo tablespaces to use.",
NULL, NULL,
0L, /* Default seting */
0L, /* Minimum value */
- 95L, 0); /* Maximum value */
+ TRX_SYS_MAX_UNDO_SPACES, 0); /* Maximum value */
static MYSQL_SYSVAR_ULONG(undo_logs, srv_undo_logs,
PLUGIN_VAR_OPCMDARG,
@@ -21321,12 +21301,10 @@ static MYSQL_SYSVAR_ULONG(undo_logs, srv_undo_logs,
static MYSQL_SYSVAR_ULONGLONG(max_undo_log_size, srv_max_undo_log_size,
PLUGIN_VAR_OPCMDARG,
- "Maximum size of UNDO tablespace in MB (If UNDO tablespace grows"
- " beyond this size it will be truncated in due course). ",
+ "Desired maximum UNDO tablespace size in bytes",
NULL, NULL,
- 1024 * 1024 * 1024L,
- 10 * 1024 * 1024L,
- ~0ULL, 0);
+ 10 << 20, 10 << 20,
+ 1ULL << (32 + UNIV_PAGE_SIZE_SHIFT_MAX), 0);
static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency,
srv_purge_rseg_truncate_frequency,
@@ -21789,6 +21767,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(temp_data_file_path),
MYSQL_SYSVAR(data_home_dir),
MYSQL_SYSVAR(doublewrite),
+ MYSQL_SYSVAR(stats_include_delete_marked),
MYSQL_SYSVAR(use_atomic_writes),
MYSQL_SYSVAR(fast_shutdown),
MYSQL_SYSVAR(read_io_threads),
@@ -21815,6 +21794,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(lock_schedule_algorithm),
MYSQL_SYSVAR(locks_unsafe_for_binlog),
MYSQL_SYSVAR(lock_wait_timeout),
+ MYSQL_SYSVAR(deadlock_detect),
MYSQL_SYSVAR(page_size),
MYSQL_SYSVAR(log_buffer_size),
MYSQL_SYSVAR(log_file_size),
@@ -22034,19 +22014,25 @@ innobase_commit_concurrency_init_default()
= innobase_commit_concurrency;
}
-/** @brief Initialize the default and max value of innodb_undo_logs.
-
-Once InnoDB is running, the default value and the max value of
-innodb_undo_logs must be equal to the available undo logs,
-given by srv_available_undo_logs. */
+/** @brief Adjust some InnoDB startup parameters based on file contents
+or innodb_page_size. */
static
void
-innobase_undo_logs_init_default_max()
-/*=================================*/
+innodb_params_adjust()
{
+ /* The default value and the max value of
+ innodb_undo_logs must be equal to the available undo logs. */
MYSQL_SYSVAR_NAME(undo_logs).max_val
= MYSQL_SYSVAR_NAME(undo_logs).def_val
= srv_available_undo_logs;
+ MYSQL_SYSVAR_NAME(max_undo_log_size).max_val
+ = 1ULL << (32 + UNIV_PAGE_SIZE_SHIFT);
+ MYSQL_SYSVAR_NAME(max_undo_log_size).min_val
+ = MYSQL_SYSVAR_NAME(max_undo_log_size).def_val
+ = ulonglong(SRV_UNDO_TABLESPACE_SIZE_IN_PAGES)
+ * srv_page_size;
+ MYSQL_SYSVAR_NAME(max_undo_log_size).max_val
+ = 1ULL << (32 + UNIV_PAGE_SIZE_SHIFT);
}
/****************************************************************************
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 297b73ed02f..64147291338 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -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) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -219,9 +219,6 @@ public:
ha_rows estimate_rows_upper_bound();
- // JAN: TODO: MySQL 5.7
- // int records(ha_rows* num_rows);
-
void update_create_info(HA_CREATE_INFO* create_info);
int create(
diff --git a/storage/innobase/handler/ha_innopart.cc b/storage/innobase/handler/ha_innopart.cc
index 7abc1f29b60..1041871805e 100644
--- a/storage/innobase/handler/ha_innopart.cc
+++ b/storage/innobase/handler/ha_innopart.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2014, 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
@@ -3004,41 +3004,6 @@ ha_innopart::truncate()
DBUG_RETURN(error);
}
-/** Total number of rows in all used partitions.
-Returns the exact number of records that this client can see using this
-handler object.
-@param[out] num_rows Number of rows.
-@return 0 or error number. */
-int
-ha_innopart::records(
- ha_rows* num_rows)
-{
- ha_rows n_rows;
- int err;
- DBUG_ENTER("ha_innopart::records()");
-
- *num_rows = 0;
-
- /* The index scan is probably so expensive, so the overhead
- of the rest of the function is neglectable for each partition.
- So no current reason for optimizing this further. */
-
- for (uint i = m_part_info->get_first_used_partition();
- i < m_tot_parts;
- i = m_part_info->get_next_used_partition(i)) {
-
- set_partition(i);
- err = ha_innobase::records(&n_rows);
- update_partition(i);
- if (err != 0) {
- *num_rows = HA_POS_ERROR;
- DBUG_RETURN(err);
- }
- *num_rows += n_rows;
- }
- DBUG_RETURN(0);
-}
-
/** Estimates the number of index records in a range.
@param[in] keynr Index number.
@param[in] min_key Start key value (or NULL).
diff --git a/storage/innobase/handler/ha_innopart.h b/storage/innobase/handler/ha_innopart.h
index 5f3f8eaa318..67db9e07150 100644
--- a/storage/innobase/handler/ha_innopart.h
+++ b/storage/innobase/handler/ha_innopart.h
@@ -1222,10 +1222,6 @@ protected:
uchar* pos);
int
- records(
- ha_rows* num_rows);
-
- int
index_next(
uchar* record)
{
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index f9791f5fa97..153484c9941 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -400,7 +400,10 @@ innobase_need_rebuild(
const Alter_inplace_info* ha_alter_info,
const TABLE* altered_table)
{
- if (ha_alter_info->handler_flags
+ Alter_inplace_info::HA_ALTER_FLAGS alter_inplace_flags =
+ ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE);
+
+ if (alter_inplace_flags
== Alter_inplace_info::CHANGE_CREATE_OPTION
&& !(ha_alter_info->create_info->used_fields
& (HA_CREATE_USED_ROW_FORMAT
@@ -1293,7 +1296,6 @@ innobase_find_fk_index(
while (index != NULL) {
if (!(index->type & DICT_FTS)
- && !dict_index_has_virtual(index)
&& dict_foreign_qualify_index(
table, col_names, columns, n_cols,
index, NULL, true, 0,
@@ -2466,6 +2468,7 @@ innobase_fts_check_doc_id_index_in_def(
return(FTS_NOT_EXIST_DOC_ID_INDEX);
}
+
/*******************************************************************//**
Create an index table where indexes are ordered as follows:
@@ -2534,35 +2537,16 @@ innobase_create_key_defs(
(only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
- if (n_add > 0 && !new_primary && got_default_clust
- && (key_info[*add].flags & HA_NOSAME)
- && !(key_info[*add].flags & HA_KEY_HAS_PART_KEY_SEG)) {
- uint key_part = key_info[*add].user_defined_key_parts;
-
- new_primary = true;
-
- while (key_part--) {
- const uint maybe_null
- = key_info[*add].key_part[key_part].key_type
- & FIELDFLAG_MAYBE_NULL;
- bool is_v
- = innobase_is_v_fld(
- key_info[*add].key_part[key_part].field);
- DBUG_ASSERT(!maybe_null
- == !key_info[*add].key_part[key_part].
- field->real_maybe_null());
-
- if (maybe_null || is_v) {
- new_primary = false;
- break;
- }
- }
+ ut_ad(altered_table->s->primary_key == 0
+ || altered_table->s->primary_key == MAX_KEY);
+
+ if (got_default_clust && !new_primary) {
+ new_primary = (altered_table->s->primary_key != MAX_KEY);
}
const bool rebuild = new_primary || add_fts_doc_id
|| innobase_need_rebuild(ha_alter_info, table);
-
/* Reserve one more space if new_primary is true, and we might
need to add the FTS_DOC_ID_INDEX */
indexdef = indexdefs = static_cast<index_def_t*>(
@@ -2576,8 +2560,14 @@ innobase_create_key_defs(
ulint primary_key_number;
if (new_primary) {
- DBUG_ASSERT(n_add > 0);
- primary_key_number = *add;
+ if (n_add == 0) {
+ DBUG_ASSERT(got_default_clust);
+ DBUG_ASSERT(altered_table->s->primary_key
+ == 0);
+ primary_key_number = 0;
+ } else {
+ primary_key_number = *add;
+ }
} else if (got_default_clust) {
/* Create the GEN_CLUST_INDEX */
index_def_t* index = indexdef++;
@@ -4782,6 +4772,8 @@ new_clustered_failed:
ctx->add_cols = add_cols;
} else {
DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table));
+ DBUG_ASSERT(old_table->s->primary_key
+ == altered_table->s->primary_key);
for (dict_index_t* index
= dict_table_get_first_index(user_table);
@@ -6082,7 +6074,7 @@ err_exit:
}
if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA)
- || (ha_alter_info->handler_flags
+ || ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)
== Alter_inplace_info::CHANGE_CREATE_OPTION
&& !innobase_need_rebuild(ha_alter_info, table))) {
@@ -6306,6 +6298,26 @@ alter_templ_needs_rebuild(
return(false);
}
+/** Get the name of an erroneous key.
+@param[in] error_key_num InnoDB number of the erroneus key
+@param[in] ha_alter_info changes that were being performed
+@param[in] table InnoDB table
+@return the name of the erroneous key */
+static
+const char*
+get_error_key_name(
+ ulint error_key_num,
+ const Alter_inplace_info* ha_alter_info,
+ const dict_table_t* table)
+{
+ if (error_key_num == ULINT_UNDEFINED) {
+ return(FTS_DOC_ID_INDEX_NAME);
+ } else if (ha_alter_info->key_count == 0) {
+ return(dict_table_get_first_index(table)->name);
+ } else {
+ return(ha_alter_info->key_info_buffer[error_key_num].name);
+ }
+}
/** Alter the table structure in-place with operations
specified using Alter_inplace_info.
@@ -6346,7 +6358,7 @@ ok_exit:
DBUG_RETURN(false);
}
- if (ha_alter_info->handler_flags
+ if ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)
== Alter_inplace_info::CHANGE_CREATE_OPTION
&& !innobase_need_rebuild(ha_alter_info, table)) {
goto ok_exit;
@@ -6443,15 +6455,6 @@ ok_exit:
ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort,
ctx->m_stage, add_v, eval_table);
- if (s_templ) {
- ut_ad(ctx->need_rebuild() || ctx->num_to_add_vcol > 0
- || rebuild_templ);
- dict_free_vc_templ(s_templ);
- UT_DELETE(s_templ);
-
- ctx->new_table->vc_templ = old_templ;
- }
-
#ifndef DBUG_OFF
oom:
#endif /* !DBUG_OFF */
@@ -6467,6 +6470,15 @@ oom:
onlineddl_rowlog_pct_used = 0;
onlineddl_pct_progress = 0;
+ if (s_templ) {
+ ut_ad(ctx->need_rebuild() || ctx->num_to_add_vcol > 0
+ || rebuild_templ);
+ dict_free_vc_templ(s_templ);
+ UT_DELETE(s_templ);
+
+ ctx->new_table->vc_templ = old_templ;
+ }
+
DEBUG_SYNC_C("inplace_after_index_build");
DBUG_EXECUTE_IF("create_index_fail",
@@ -6506,17 +6518,13 @@ oom:
case DB_ONLINE_LOG_TOO_BIG:
DBUG_ASSERT(ctx->online);
my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
- (m_prebuilt->trx->error_key_num == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[
- m_prebuilt->trx->error_key_num].name);
+ get_error_key_name(m_prebuilt->trx->error_key_num,
+ ha_alter_info, m_prebuilt->table));
break;
case DB_INDEX_CORRUPT:
my_error(ER_INDEX_CORRUPT, MYF(0),
- (m_prebuilt->trx->error_key_num == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[
- m_prebuilt->trx->error_key_num].name);
+ get_error_key_name(m_prebuilt->trx->error_key_num,
+ ha_alter_info, m_prebuilt->table));
break;
case DB_DECRYPTION_FAILED: {
String str;
@@ -7724,11 +7732,31 @@ commit_try_rebuild(
if (ctx->online) {
DEBUG_SYNC_C("row_log_table_apply2_before");
+ dict_vcol_templ_t* s_templ = NULL;
+
+ if (ctx->new_table->n_v_cols > 0) {
+ s_templ = UT_NEW_NOKEY(
+ dict_vcol_templ_t());
+ s_templ->vtempl = NULL;
+
+ innobase_build_v_templ(
+ altered_table, ctx->new_table, s_templ,
+ NULL, true);
+ ctx->new_table->vc_templ = s_templ;
+ }
+
error = row_log_table_apply(
ctx->thr, user_table, altered_table,
static_cast<ha_innobase_inplace_ctx*>(
ha_alter_info->handler_ctx)->m_stage);
+ if (s_templ) {
+ ut_ad(ctx->need_rebuild());
+ dict_free_vc_templ(s_templ);
+ UT_DELETE(s_templ);
+ ctx->new_table->vc_templ = NULL;
+ }
+
ulint err_key = thr_get_trx(ctx->thr)->error_key_num;
switch (error) {
@@ -7750,14 +7778,13 @@ commit_try_rebuild(
DBUG_RETURN(true);
case DB_ONLINE_LOG_TOO_BIG:
my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
- ha_alter_info->key_info_buffer[0].name);
+ get_error_key_name(err_key, ha_alter_info,
+ rebuilt_table));
DBUG_RETURN(true);
case DB_INDEX_CORRUPT:
my_error(ER_INDEX_CORRUPT, MYF(0),
- (err_key == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[err_key]
- .name);
+ get_error_key_name(err_key, ha_alter_info,
+ rebuilt_table));
DBUG_RETURN(true);
default:
my_error_innodb(error, table_name, user_table->flags);
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 6bf16573efd..3d764ef6e7a 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -3955,6 +3955,8 @@ i_s_fts_config_fill(
DBUG_RETURN(0);
}
+ DEBUG_SYNC_C("i_s_fts_config_fille_check");
+
fields = table->field;
/* Prevent DDL to drop fts aux tables. */
@@ -5147,6 +5149,10 @@ i_s_innodb_buffer_page_get_info(
block = reinterpret_cast<const buf_block_t*>(bpage);
frame = block->frame;
#ifdef BTR_CUR_HASH_ADAPT
+ /* Note: this may be a false positive, that
+ is, block->index will not always be set to
+ NULL when the last adaptive hash index
+ reference is dropped. */
page_info->hashed = (block->index != NULL);
#endif /* BTR_CUR_HASH_ADAPT */
} else {
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 7a4dc610694..c7ffecd00c1 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -3953,7 +3953,11 @@ ibuf_insert_to_index_page(
ut_ad(ibuf_inside(mtr));
ut_ad(dtuple_check_typed(entry));
#ifdef BTR_CUR_HASH_ADAPT
+ /* A change buffer merge must occur before users are granted
+ any access to the page. No adaptive hash index entries may
+ point to a freshly read page. */
ut_ad(!block->index);
+ assert_block_ahi_empty(block);
#endif /* BTR_CUR_HASH_ADAPT */
ut_ad(mtr->is_named_space(block->page.id.space()));
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index 8887a3f81ad..fad0dac93c4 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -247,6 +247,8 @@ btr_get_search_table(const dict_index_t* index);
# define btr_search_drop_page_hash_index(block)
# define btr_search_s_lock(index)
# define btr_search_s_unlock(index)
+# define btr_search_s_lock_all(index)
+# define btr_search_s_unlock_all(index)
# define btr_search_x_lock(index)
# define btr_search_x_unlock(index)
# define btr_search_info_update(index, cursor)
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index c0b635ab8c9..7dee52d8f74 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -769,10 +769,6 @@ buf_block_unfix(
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@param[in] use_legacy_big_endian use legacy big endian algorithm
@return true if the page is in crc32 checksum format. */
bool
@@ -780,12 +776,6 @@ buf_page_is_checksum_valid_crc32(
const byte* read_buf,
ulint checksum_field1,
ulint checksum_field2,
-#ifdef UNIV_INNOCHECKSUM
- uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo,
-#endif /* UNIV_INNOCHECKSUM */
bool use_legacy_big_endian)
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
@@ -793,59 +783,26 @@ buf_page_is_checksum_valid_crc32(
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@return true if the page is in innodb checksum format. */
bool
buf_page_is_checksum_valid_innodb(
const byte* read_buf,
ulint checksum_field1,
- ulint checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )
+ ulint checksum_field2)
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/** Checks if the page is in none checksum format.
@param[in] read_buf database page
@param[in] checksum_field1 new checksum field
@param[in] checksum_field2 old checksum field
-@param[in] page_no page number of given read_buf
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
-@param[in] curr_algo current checksum algorithm
@return true if the page is in none checksum format. */
bool
buf_page_is_checksum_valid_none(
const byte* read_buf,
ulint checksum_field1,
- ulint checksum_field2
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no,
- bool is_log_enabled,
- FILE* log_file,
- const srv_checksum_algorithm_t curr_algo
-#endif /* UNIV_INNOCHECKSUM */
- )
+ ulint checksum_field2)
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
-/********************************************************************//**
-Check if page is maybe compressed, encrypted or both when we encounter
-corrupted page. Note that we can't be 100% sure if page is corrupted
-or decrypt/decompress just failed.
-@param[in] bpage Page
-@return true if page corrupted, false if not */
-bool
-buf_page_check_corrupt(
- buf_page_t* bpage) /*!< in/out: buffer page read from disk */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
-
/** Checks if a page contains only zeroes.
@param[in] read_buf database page
@param[in] page_size page size
@@ -861,10 +818,6 @@ the LSN
@param[in] read_buf database page
@param[in] page_size page size
@param[in] space tablespace
-@param[in] page_no page number of given read_buf
-@param[in] strict_check true if strict-check option is enabled
-@param[in] is_log_enabled true if log option is enabled
-@param[in] log_file file pointer to log_file
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
@@ -872,12 +825,6 @@ buf_page_is_corrupted(
const byte* read_buf,
const page_size_t& page_size,
const fil_space_t* space = NULL
-#ifdef UNIV_INNOCHECKSUM
- ,uintmax_t page_no = 0,
- bool strict_check = false,
- bool is_log_enabled = false,
- FILE* log_file = NULL
-#endif /* UNIV_INNOCHECKSUM */
) MY_ATTRIBUTE((warn_unused_result));
#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
@@ -1836,23 +1783,58 @@ struct buf_block_t{
/* @} */
/** @name Hash search fields
- These 5 fields may only be modified when we have
- an x-latch on search system AND
- - we are holding an s-latch or x-latch on buf_block_t::lock or
- - we know that buf_block_t::buf_fix_count == 0.
+ These 5 fields may only be modified when:
+ we are holding the appropriate x-latch in btr_search_latches[], and
+ one of the following holds:
+ (1) the block state is BUF_BLOCK_FILE_PAGE, and
+ we are holding an s-latch or x-latch on buf_block_t::lock, or
+ (2) buf_block_t::buf_fix_count == 0, or
+ (3) the block state is BUF_BLOCK_REMOVE_HASH.
An exception to this is when we init or create a page
in the buffer pool in buf0buf.cc.
- Another exception is that assigning block->index = NULL
- is allowed whenever holding an x-latch on search system. */
+ Another exception for buf_pool_clear_hash_index() is that
+ assigning block->index = NULL (and block->n_pointers = 0)
+ is allowed whenever btr_search_own_all(RW_LOCK_X).
+
+ Another exception is that ha_insert_for_fold_func() may
+ decrement n_pointers without holding the appropriate latch
+ in btr_search_latches[]. Thus, n_pointers must be
+ protected by atomic memory access.
+
+ This implies that the fields may be read without race
+ condition whenever any of the following hold:
+ - the btr_search_latches[] s-latch or x-latch is being held, or
+ - the block state is not BUF_BLOCK_FILE_PAGE or BUF_BLOCK_REMOVE_HASH,
+ and holding some latch prevents the state from changing to that.
+
+ Some use of assert_block_ahi_empty() or assert_block_ahi_valid()
+ is prone to race conditions while buf_pool_clear_hash_index() is
+ executing (the adaptive hash index is being disabled). Such use
+ is explicitly commented. */
/* @{ */
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ulint n_pointers; /*!< used in debugging: the number of
pointers in the adaptive hash index
- pointing to this frame */
+ pointing to this frame;
+ protected by atomic memory access
+ or btr_search_own_all(). */
+# define assert_block_ahi_empty(block) \
+ ut_a(my_atomic_addlint(&(block)->n_pointers, 0) == 0)
+# define assert_block_ahi_empty_on_init(block) do { \
+ UNIV_MEM_VALID(&(block)->n_pointers, sizeof (block)->n_pointers); \
+ assert_block_ahi_empty(block); \
+} while (0)
+# define assert_block_ahi_valid(block) \
+ ut_a((block)->index \
+ || my_atomic_addlint(&(block)->n_pointers, 0) == 0)
+# else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
+# define assert_block_ahi_empty(block) /* nothing */
+# define assert_block_ahi_empty_on_init(block) /* nothing */
+# define assert_block_ahi_valid(block) /* nothing */
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
number of full fields */
@@ -1868,11 +1850,15 @@ struct buf_block_t{
complete, though: there may
have been hash collisions,
record deletions, etc. */
+ /* @} */
+#else /* BTR_CUR_HASH_ADAPT */
+# define assert_block_ahi_empty(block) /* nothing */
+# define assert_block_ahi_empty_on_init(block) /* nothing */
+# define assert_block_ahi_valid(block) /* nothing */
#endif /* BTR_CUR_HASH_ADAPT */
bool skip_flush_check;
/*!< Skip check in buf_dblwr_check_block
during bulk load, protected by lock.*/
- /* @} */
# ifdef UNIV_DEBUG
/** @name Debug fields */
/* @{ */
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 429c7fd3ba6..f22dcc48a01 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -920,6 +920,7 @@ buf_block_modify_clock_inc(
RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
}
#endif /* UNIV_DEBUG */
+ assert_block_ahi_valid(block);
block->modify_clock++;
}
diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h
index bf2bf6ab32b..e1ecb6baf56 100644
--- a/storage/innobase/include/buf0dblwr.h
+++ b/storage/innobase/include/buf0dblwr.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2017, MariaDB Corporation.
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
@@ -44,8 +44,7 @@ doublewrite buffer is placed on the trx system header page.
@return true if successful, false if not. */
MY_ATTRIBUTE((warn_unused_result))
bool
-buf_dblwr_create(void);
-/*==================*/
+buf_dblwr_create();
/****************************************************************//**
At a database startup initializes the doublewrite buffer memory structure if
@@ -61,13 +60,13 @@ buf_dblwr_init_or_load_pages(
/** Process and remove the double write buffer pages for all tablespaces. */
void
-buf_dblwr_process(void);
+buf_dblwr_process();
/****************************************************************//**
frees doublewrite buffer. */
void
-buf_dblwr_free(void);
-/*================*/
+buf_dblwr_free();
+
/********************************************************************//**
Updates the doublewrite buffer when an IO request is completed. */
void
@@ -105,8 +104,8 @@ important to call this function after a batch of writes has been posted,
and also when we may have to wait for a page latch! Otherwise a deadlock
of threads can occur. */
void
-buf_dblwr_flush_buffered_writes(void);
-/*=================================*/
+buf_dblwr_flush_buffered_writes();
+
/********************************************************************//**
Writes a page to the doublewrite buffer on disk, sync it, then write
the page to the datafile and sync the datafile. This function is used
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index de4a983ba81..8849be1206d 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -793,7 +793,8 @@ dict_sys_tables_type_validate(
} else if (zip_ssize) {
/* Antelope does not support COMPRESSED format. */
ib::error()
- << "SYS_TABLES::TYPE=" << type << "zip_ssize:" << zip_ssize;
+ << "SYS_TABLES::TYPE=" << type
+ << ", zip_ssize:" << zip_ssize;
return(ULINT_UNDEFINED);
}
@@ -805,16 +806,16 @@ dict_sys_tables_type_validate(
low_order_bit and DICT_N_COLS_COMPACT flags. */
if (!atomic_blobs) {
ib::error() << "SYS_TABLES::TYPE=" << type
- << " zip_ssize:" << zip_ssize
- << " atomic_blobs:" << atomic_blobs;
+ << ", zip_ssize:" << zip_ssize
+ << ", atomic_blobs:" << atomic_blobs;
return(ULINT_UNDEFINED);
}
/* Validate that the number is within allowed range. */
if (zip_ssize > PAGE_ZIP_SSIZE_MAX) {
ib::error() << "SYS_TABLES::TYPE=" << type
- << " zip_ssize:" << zip_ssize
- << " max:" << PAGE_ZIP_SSIZE_MAX;
+ << ", zip_ssize:" << zip_ssize
+ << " > " << PAGE_ZIP_SSIZE_MAX;
return(ULINT_UNDEFINED);
}
}
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index 831d61445d8..ca65df21402 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -116,10 +116,10 @@ struct fil_space_crypt_t : st_encryption_scheme
min_key_version(new_min_key_version),
page0_offset(0),
encryption(new_encryption),
- key_found(),
+ mutex(),
+ key_found(new_min_key_version),
rotate_state()
{
- key_found = new_min_key_version;
key_id = new_key_id;
my_random_bytes(iv, sizeof(iv));
mutex_create(LATCH_ID_FIL_CRYPT_DATA_MUTEX, &mutex);
@@ -492,10 +492,6 @@ bool
fil_space_verify_crypt_checksum(
byte* page,
const page_size_t& page_size,
-#ifdef UNIV_INNOCHECKSUM
- bool strict_check, /*!< --strict-check */
- FILE* log_file, /*!< --log */
-#endif /* UNIV_INNOCHECKSUM */
ulint space,
ulint offset)
MY_ATTRIBUTE((warn_unused_result));
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 4583b81c983..cef5b578a4a 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/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) 2013, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -142,14 +142,21 @@ struct fil_space_t {
ulint n_pending_flushes; /*!< this is positive when flushing
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
- ulint n_pending_ops;/*!< this is positive when we
- have pending operations against this
- tablespace. The pending operations can
- be ibuf merges or lock validation code
- trying to read a block.
- Dropping of the tablespace is forbidden
- if this is positive.
- Protected by fil_system->mutex. */
+ /** Number of pending buffer pool operations accessing the tablespace
+ without holding a table lock or dict_operation_lock S-latch
+ that would prevent the table (and tablespace) from being
+ dropped. An example is change buffer merge.
+ The tablespace cannot be dropped while this is nonzero,
+ or while fil_node_t::n_pending is nonzero.
+ Protected by fil_system->mutex. */
+ ulint n_pending_ops;
+ /** Number of pending block read or write operations
+ (when a write is imminent or a read has recently completed).
+ The tablespace object cannot be freed while this is nonzero,
+ but it can be detached from fil_system.
+ Note that fil_node_t::n_pending tracks actual pending I/O requests.
+ Protected by fil_system->mutex. */
+ ulint n_pending_ios;
hash_node_t hash; /*!< hash chain node */
hash_node_t name_hash;/*!< hash chain the name_hash table */
rw_lock_t latch; /*!< latch protecting the file space storage
@@ -552,15 +559,6 @@ void
fil_space_set_imported(
ulint id);
-#ifdef UNIV_DEBUG
-/** Determine if a tablespace is temporary.
-@param[in] id tablespace identifier
-@return whether it is a temporary tablespace */
-bool
-fsp_is_temporary(ulint id)
-MY_ATTRIBUTE((warn_unused_result, pure));
-#endif /* UNIV_DEBUG */
-
/** Append a file to the chain of files of a space.
@param[in] name file name of a file that is not open
@param[in] size file size in entire database blocks
@@ -735,12 +733,10 @@ MY_ATTRIBUTE((warn_unused_result));
Used by background threads that do not necessarily hold proper locks
for concurrency control.
@param[in] id tablespace ID
-@param[in] for_io whether to look up the tablespace while performing I/O
- (possibly executing TRUNCATE)
@return the tablespace
@retval NULL if missing or being deleted or truncated */
fil_space_t*
-fil_space_acquire(ulint id, bool for_io = false)
+fil_space_acquire(ulint id)
MY_ATTRIBUTE((warn_unused_result));
/** Acquire a tablespace that may not exist.
@@ -758,6 +754,19 @@ fil_space_acquire_silent(ulint id)
void
fil_space_release(fil_space_t* space);
+/** Acquire a tablespace for reading or writing a block,
+when it could be dropped concurrently.
+@param[in] id tablespace ID
+@return the tablespace
+@retval NULL if missing */
+fil_space_t*
+fil_space_acquire_for_io(ulint id);
+
+/** Release a tablespace acquired with fil_space_acquire_for_io().
+@param[in,out] space tablespace to release */
+void
+fil_space_release_for_io(fil_space_t* space);
+
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
@@ -794,12 +803,9 @@ public:
/** Constructor: Look up the tablespace and increment the
reference count if found.
- @param[in] space_id tablespace ID
- @param[in] for_io whether to look up the tablespace
- while performing I/O
- (possibly executing TRUNCATE) */
- explicit FilSpace(ulint space_id, bool for_io = false)
- : m_space(fil_space_acquire(space_id, for_io)) {}
+ @param[in] space_id tablespace ID */
+ explicit FilSpace(ulint space_id)
+ : m_space(fil_space_acquire(space_id)) {}
/** Assignment operator: This assumes that fil_space_acquire()
has already been done for the fil_space_t. The caller must
@@ -892,6 +898,17 @@ fil_op_replay_rename(
const char* new_name)
MY_ATTRIBUTE((warn_unused_result));
+/** Determine whether a table can be accessed in operations that are
+not (necessarily) protected by meta-data locks.
+(Rollback would generally be protected, but rollback of
+FOREIGN KEY CASCADE/SET NULL is not protected by meta-data locks
+but only by InnoDB table locks, which may be broken by TRUNCATE TABLE.)
+@param[in] table persistent table
+checked @return whether the table is accessible */
+bool
+fil_table_accessible(const dict_table_t* table)
+ MY_ATTRIBUTE((warn_unused_result, nonnull));
+
/** Deletes an IBD tablespace, either general or single-table.
The tablespace must be cached in the memory cache. This will delete the
datafile, fil_space_t & fil_node_t entries from the file_system_t cache.
@@ -923,14 +940,18 @@ dberr_t
fil_prepare_for_truncate(
/*=====================*/
ulint id); /*!< in: space id */
-/**********************************************************************//**
-Reinitialize the original tablespace header with the same space id
-for single tablespace */
+
+/** Reinitialize the original tablespace header with the same space id
+for single tablespace
+@param[in] id space id of the tablespace
+@param[in] size size in blocks
+@param[in] trx Transaction covering truncate */
void
fil_reinit_space_header(
-/*====================*/
- ulint id, /*!< in: space id */
- ulint size); /*!< in: size in blocks */
+ ulint id,
+ ulint size,
+ trx_t* trx);
+
/*******************************************************************//**
Closes a single-table tablespace. The tablespace must be cached in the
memory cache. Free all pages used by the tablespace.
@@ -1479,7 +1500,7 @@ fil_mtr_rename_log(
const dict_table_t* new_table,
const char* tmp_name,
mtr_t* mtr)
- MY_ATTRIBUTE((warn_unused_result));
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Acquire the fil_system mutex. */
#define fil_system_enter() mutex_enter(&fil_system->mutex)
@@ -1586,7 +1607,6 @@ fil_names_clear(
void test_make_filepath();
#endif /* UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */
-
/** Determine the block size of the data file.
@param[in] space tablespace
@param[in] offset page number
@@ -1594,22 +1614,6 @@ void test_make_filepath();
UNIV_INTERN
ulint
fil_space_get_block_size(const fil_space_t* space, unsigned offset);
-/*******************************************************************//**
-Increments the count of pending operation, if space is not being deleted.
-@return TRUE if being deleted, and operation should be skipped */
-UNIV_INTERN
-ibool
-fil_inc_pending_ops(
-/*================*/
- ulint id, /*!< in: space id */
- ibool print_err); /*!< in: need to print error or not */
-/*******************************************************************//**
-Decrements the count of pending operations. */
-UNIV_INTERN
-void
-fil_decr_pending_ops(
-/*=================*/
- ulint id); /*!< in: space id */
#include "fil0fil.ic"
#endif /* UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index 21354b1b605..f1d53165cdd 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -409,6 +409,7 @@ extern bool fts_need_sync;
/** Variable specifying the table that has Fulltext index to display its
content through information schema table */
extern char* fts_internal_tbl_name;
+extern char* fts_internal_tbl_name2;
#define fts_que_graph_free(graph) \
do { \
@@ -842,6 +843,15 @@ fts_init_doc_id(
/*============*/
const dict_table_t* table); /*!< in: table */
+/* Get parent table name if it's a fts aux table
+@param[in] aux_table_name aux table name
+@param[in] aux_table_len aux table length
+@return parent table name, or NULL */
+char*
+fts_get_parent_table_name(
+ const char* aux_table_name,
+ ulint aux_table_len);
+
/******************************************************************//**
compare two character string according to their charset. */
extern
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index 6992f4a6689..7b3726b1fef 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -38,7 +38,6 @@ simple headers.
class THD;
// JAN: TODO missing features:
-#undef MYSQL_57_SELECT_COUNT_OPTIMIZATION
#undef MYSQL_FT_INIT_EXT
#undef MYSQL_INNODB_PARTITIONING
#undef MYSQL_PFS
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index e9ec01f6eb2..b3de1bf27f2 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2017, MariaDB Corporation.
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
@@ -55,6 +55,9 @@ extern ulong innodb_lock_schedule_algorithm;
// Forward declaration
class ReadView;
+/** The value of innodb_deadlock_detect */
+extern my_bool innobase_deadlock_detect;
+
/*********************************************************************//**
Gets the size of a lock struct.
@return size in bytes */
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 35a94513632..d1aae64227e 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.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, Google Inc.
Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
@@ -46,6 +46,12 @@ struct log_group_t;
/** Magic value to use instead of log checksums when they are disabled */
#define LOG_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
+/* Margin for the free space in the smallest log group, before a new query
+step which modifies the database, is started */
+
+#define LOG_CHECKPOINT_FREE_PER_THREAD (4 * UNIV_PAGE_SIZE)
+#define LOG_CHECKPOINT_EXTRA_FREE (8 * UNIV_PAGE_SIZE)
+
typedef ulint (*log_checksum_func_t)(const byte* log_block);
/** Pointer to the log checksum calculation function. Protected with
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index a02333109cc..045a14221a3 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.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) 2012, Facebook Inc.
Copyright (c) 2013, 2017, MariaDB Corporation
@@ -269,8 +269,12 @@ struct mtr_t {
MLOG_FILE_NAME records and a MLOG_CHECKPOINT marker.
The caller must invoke log_mutex_enter() and log_mutex_exit().
This is to be used at log_checkpoint().
- @param[in] checkpoint_lsn the LSN of the log checkpoint */
- void commit_checkpoint(lsn_t checkpoint_lsn);
+ @param[in] checkpoint_lsn the LSN of the log checkpoint
+ @param[in] write_mlog_checkpoint Write MLOG_CHECKPOINT marker
+ if it is enabled. */
+ void commit_checkpoint(
+ lsn_t checkpoint_lsn,
+ bool write_mlog_checkpoint);
/** Return current size of the buffer.
@return savepoint */
diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h
index 7aea976a37e..6f521b5a2ec 100644
--- a/storage/innobase/include/os0thread.h
+++ b/storage/innobase/include/os0thread.h
@@ -118,9 +118,19 @@ os_thread_create_func(
os_thread_id_t* thread_id); /*!< out: id of the created
thread, or NULL */
-/** Exits the current thread. */
+/** Waits until the specified thread completes and joins it.
+Its return value is ignored.
+@param[in,out] thread thread to join */
void
-os_thread_exit()
+os_thread_join(
+ os_thread_id_t thread);
+
+/** Exits the current thread.
+@param[in] detach if true, the thread will be detached right before
+exiting. If false, another thread is responsible for joining this thread */
+void
+os_thread_exit(
+ bool detach = true)
UNIV_COLD MY_ATTRIBUTE((noreturn));
/*****************************************************************//**
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index e1062c00a6f..c1d5443d9e5 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -512,19 +512,7 @@ ibool
page_zip_verify_checksum(
/*=====================*/
const void* data, /*!< in: compressed page */
- ulint size /*!< in: size of compressed page */
-#ifdef UNIV_INNOCHECKSUM
- /* these variables are used only for innochecksum tool. */
- ,uintmax_t page_no, /*!< in: page number of
- given read_buf */
- bool strict_check, /*!< in: true if strict-check
- option is enable */
- bool is_log_enabled, /*!< in: true if log option is
- enable */
- FILE* log_file /*!< in: file pointer to
- log_file */
-#endif /* UNIV_INNOCHECKSUM */
-);
+ ulint size); /*!< in: size of compressed page */
#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 59bd786d25c..0557b585ae1 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -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) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -540,9 +540,6 @@ row_scan_index_for_mysql(
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct
in MySQL handle */
const dict_index_t* index, /*!< in: index */
- bool check_keys, /*!< in: true=check for mis-
- ordered or duplicate records,
- false=count the rows only */
ulint* n_rows) /*!< out: number of entries
seen in the consistent read */
MY_ATTRIBUTE((warn_unused_result));
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 994800794a8..799bef58a72 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -298,6 +298,9 @@ extern long srv_mtflush_threads;
/* If this flag is TRUE, then we will use multi threaded flush. */
extern my_bool srv_use_mtflush;
+/** TRUE if the server was successfully started */
+extern bool srv_was_started;
+
/** Server undo tablespaces directory, can be absolute path. */
extern char* srv_undo_dir;
@@ -469,6 +472,7 @@ extern unsigned long long srv_stats_transient_sample_pages;
extern my_bool srv_stats_persistent;
extern unsigned long long srv_stats_persistent_sample_pages;
extern my_bool srv_stats_auto_recalc;
+extern my_bool srv_stats_include_delete_marked;
extern unsigned long long srv_stats_modified_counter;
extern my_bool srv_stats_sample_traditional;
@@ -509,7 +513,6 @@ extern ulong srv_n_spin_wait_rounds;
extern ulong srv_n_free_tickets_to_enter;
extern ulong srv_thread_sleep_delay;
extern uint srv_spin_wait_delay;
-extern ibool srv_priority_boost;
extern ulint srv_truncated_status_writes;
/** Number of initialized rollback segments for persistent undo log */
@@ -743,36 +746,24 @@ srv_set_io_thread_op_info(
Resets the info describing an i/o thread current state. */
void
srv_reset_io_thread_op_info();
-/*=========================*/
-/*******************************************************************//**
-Tells the purge thread that there has been activity in the database
-and wakes up the purge thread if it is suspended (not sleeping). Note
-that there is a small chance that the purge thread stays suspended
-(we do not protect our operation with the srv_sys_t:mutex, for
-performance reasons). */
+
+/** Wake up the purge threads if there is work to do. */
void
-srv_wake_purge_thread_if_not_active(void);
-/*=====================================*/
-/*******************************************************************//**
-Tells the Innobase server that there has been activity in the database
-and wakes up the master thread if it is suspended (not sleeping). Used
-in the MySQL interface. Note that there is a small chance that the master
-thread stays suspended (we do not protect our operation with the kernel
-mutex, for performace reasons). */
+srv_wake_purge_thread_if_not_active();
+/** Wake up the InnoDB master thread if it was suspended (not sleeping). */
void
-srv_active_wake_master_thread_low(void);
-/*===================================*/
+srv_active_wake_master_thread_low();
+
#define srv_active_wake_master_thread() \
do { \
if (!srv_read_only_mode) { \
srv_active_wake_master_thread_low(); \
} \
} while (0)
-/*******************************************************************//**
-Wakes up the master thread if it is suspended or being suspended. */
+/** Wake up the master thread if it is suspended or being suspended. */
void
-srv_wake_master_thread(void);
-/*========================*/
+srv_wake_master_thread();
+
/******************************************************************//**
Outputs to a file the output of the InnoDB Monitor.
@return FALSE if not all information printed
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index d7a5922c954..4f2f4a312ff 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -121,8 +121,6 @@ extern lsn_t srv_start_lsn;
extern bool srv_is_being_started;
/** TRUE if SYS_TABLESPACES is available for lookups */
extern bool srv_sys_tablespaces_open;
-/** TRUE if the server was successfully started */
-extern ibool srv_was_started;
/** TRUE if the server is being started, before rolling back any
incomplete transactions */
extern bool srv_startup_is_before_trx_rollback_phase;
diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h
index 736c5454711..1d11bfa7811 100644
--- a/storage/innobase/include/sync0types.h
+++ b/storage/innobase/include/sync0types.h
@@ -505,14 +505,32 @@ private:
};
#ifdef UNIV_PFS_MUTEX
-/** Latch element
+/** Latch element.
+Used for mutexes which have PFS keys defined under UNIV_PFS_MUTEX.
@param[in] id Latch id
@param[in] level Latch level
@param[in] key PFS key */
-# define LATCH_ADD(id, level, key) latch_meta[LATCH_ID_ ## id] = \
+# define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
+ UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
+
+#ifdef UNIV_PFS_RWLOCK
+/** Latch element.
+Used for rwlocks which have PFS keys defined under UNIV_PFS_RWLOCK.
+@param[in] id Latch id
+@param[in] level Latch level
+@param[in] key PFS key */
+# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, key))
#else
-# define LATCH_ADD(id, level, key) latch_meta[LATCH_ID_ ## id] = \
+# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
+ UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level, \
+ PSI_NOT_INSTRUMENTED))
+#endif /* UNIV_PFS_RWLOCK */
+
+#else
+# define LATCH_ADD_MUTEX(id, level, key) latch_meta[LATCH_ID_ ## id] =\
+ UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
+# define LATCH_ADD_RWLOCK(id, level, key) latch_meta[LATCH_ID_ ## id] =\
UT_NEW_NOKEY(latch_meta_t(LATCH_ID_ ## id, #id, level, #level))
#endif /* UNIV_PFS_MUTEX */
@@ -919,7 +937,7 @@ sync_latch_get_level(latch_id_t id)
return(meta.get_level());
}
-#ifdef HAVE_PSI_INTERFACE
+#ifdef UNIV_PFS_MUTEX
/** Get the latch PFS key from the latch ID
@param[in] id Latch ID
@return the PFS key */
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index 95774cbf476..4c162526384 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -200,7 +200,10 @@ struct trx_rseg_t {
bool is_persistent() const
{
ut_ad(space == SRV_TMP_SPACE_ID
- || space <= srv_undo_tablespaces);
+ || space <= TRX_SYS_MAX_UNDO_SPACES);
+ ut_ad(space == SRV_TMP_SPACE_ID
+ || space <= srv_undo_tablespaces_active
+ || !srv_was_started);
return(space != SRV_TMP_SPACE_ID);
}
};
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index 0a33c747668..45ee3ef8d66 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -42,7 +42,9 @@ trx_rsegf_get(
buf_block_t* block;
trx_rsegf_t* header;
- ut_ad(space <= srv_undo_tablespaces || space == SRV_TMP_SPACE_ID);
+ ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID
+ || !srv_was_started);
+ ut_ad(space <= TRX_SYS_MAX_UNDO_SPACES || space == SRV_TMP_SPACE_ID);
block = buf_page_get(
page_id_t(space, page_no), univ_page_size, RW_X_LATCH, mtr);
@@ -69,7 +71,9 @@ trx_rsegf_get_new(
buf_block_t* block;
trx_rsegf_t* header;
- ut_ad(space <= srv_undo_tablespaces || space == SRV_TMP_SPACE_ID);
+ ut_ad(space <= srv_undo_tablespaces_active || space == SRV_TMP_SPACE_ID
+ || !srv_was_started);
+ ut_ad(space <= TRX_SYS_MAX_UNDO_SPACES || space == SRV_TMP_SPACE_ID);
block = buf_page_get(
page_id_t(space, page_no), univ_page_size, RW_X_LATCH, mtr);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index b867600653d..bf8cf2481eb 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -403,10 +403,8 @@ byte, therefore 128; each slot is currently 8 bytes in size. If you want
to raise the level to 256 then you will need to fix some assertions that
impose the 7 bit restriction. e.g., mach_write_to_3() */
#define TRX_SYS_N_RSEGS 128
-/* Originally, InnoDB defined TRX_SYS_N_RSEGS as 256 but created only one
-rollback segment. It initialized some arrays with this number of entries.
-We must remember this limit in order to keep file compatibility. */
-#define TRX_SYS_OLD_N_RSEGS 256
+/** Maximum number of undo tablespaces (not counting the system tablespace) */
+#define TRX_SYS_MAX_UNDO_SPACES (TRX_SYS_N_RSEGS - 1)
/** Maximum length of MySQL binlog file name, in bytes. */
#define TRX_SYS_MYSQL_LOG_NAME_LEN 512
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index b08148578dc..446e619abb9 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -386,6 +386,22 @@ trx_print_latched(
ulint max_query_len); /*!< in: max query length to print,
or 0 to use the default max length */
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+ FILE* f, /*!< in: output stream */
+ const trx_t* trx, /*!< in: transaction */
+ ulint max_query_len) /*!< in: max query length to print,
+ or 0 to use the default max length */
+ MY_ATTRIBUTE((nonnull));
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */
@@ -1468,10 +1484,30 @@ private:
return;
}
- /* Avoid excessive mutex acquire/release */
-
ut_ad(!is_async_rollback(trx));
+ /* If it hasn't already been marked for async rollback.
+ and it will be committed/rolled back. */
+ if (disable) {
+
+ trx_mutex_enter(trx);
+ if (!is_forced_rollback(trx)
+ && is_started(trx)
+ && !trx_is_autocommit_non_locking(trx)) {
+
+ ut_ad(trx->killed_by == 0);
+
+ /* This transaction has crossed the point of
+ no return and cannot be rolled back
+ asynchronously now. It must commit or rollback
+ synhronously. */
+
+ trx->in_innodb |= TRX_FORCE_ROLLBACK_DISABLE;
+ }
+ trx_mutex_exit(trx);
+ }
+
+ /* Avoid excessive mutex acquire/release */
++trx->in_depth;
/* If trx->in_depth is greater than 1 then
@@ -1489,25 +1525,7 @@ private:
wait(trx);
- ut_ad((trx->in_innodb & TRX_FORCE_ROLLBACK_MASK)
- < (TRX_FORCE_ROLLBACK_MASK - 1));
-
- /* If it hasn't already been marked for async rollback.
- and it will be committed/rolled back. */
-
- if (!is_forced_rollback(trx)
- && disable
- && is_started(trx)
- && !trx_is_autocommit_non_locking(trx)) {
-
- ut_ad(trx->killed_by == 0);
-
- /* This transaction has crossed the point of no
- return and cannot be rolled back asynchronously
- now. It must commit or rollback synhronously. */
-
- trx->in_innodb |= TRX_FORCE_ROLLBACK_DISABLE;
- }
+ ut_ad((trx->in_innodb & TRX_FORCE_ROLLBACK_MASK) == 0);
++trx->in_innodb;
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index faf5387a5d1..ee759534301 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -108,6 +108,12 @@ support cross-platform development and expose comonly used SQL names. */
#include <unistd.h>
#endif
+#ifdef UNIV_INNOCHECKSUM
+extern bool strict_verify;
+extern FILE* log_file;
+extern uintmax_t cur_page_num;
+#endif /* UNIV_INNOCHECKSUM */
+
#include "my_pthread.h"
/* Following defines are to enable performance schema
instrumentation in each of five InnoDB modules if
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index c3574913c7c..295833cb1d6 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -56,6 +56,9 @@ Created 5/7/1996 Heikki Tuuri
/** Lock scheduling algorithm */
ulong innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS;
+/** The value of innodb_deadlock_detect */
+my_bool innobase_deadlock_detect;
+
/** Total number of cached record locks */
static const ulint REC_LOCK_CACHE = 8;
@@ -124,7 +127,7 @@ public:
@return id of transaction chosen as victim or 0 */
static const trx_t* check_and_resolve(
const lock_t* lock,
- const trx_t* trx);
+ trx_t* trx);
private:
/** Do a shallow copy. Default destructor OK.
@@ -1378,24 +1381,20 @@ wsrep_kill_victim(
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
- mutex_enter(&trx_sys->mutex);
if (bf_this) {
ib::info() << "*** Priority TRANSACTION:";
} else {
ib::info() << "*** Victim TRANSACTION:";
}
- trx_print_latched(stderr, trx, 3000);
+ wsrep_trx_print_locking(stderr, trx, 3000);
if (bf_other) {
ib::info() << "*** Priority TRANSACTION:";
} else {
ib::info() << "*** Victim TRANSACTION:";
}
-
- trx_print_latched(stderr, lock->trx, 3000);
-
- mutex_exit(&trx_sys->mutex);
+ wsrep_trx_print_locking(stderr, lock->trx, 3000);
ib::info() << "*** WAITING FOR THIS LOCK TO BE GRANTED:";
@@ -2136,25 +2135,8 @@ RecLock::deadlock_check(lock_t* lock)
ut_ad(lock->trx == m_trx);
ut_ad(trx_mutex_own(m_trx));
- bool async_rollback = m_trx->in_innodb & TRX_FORCE_ROLLBACK_ASYNC;
-
- /* This is safe, because DeadlockChecker::check_and_resolve()
- is invoked when a lock wait is enqueued for the currently
- running transaction. Because m_trx is a running transaction
- (it is not currently suspended because of a lock wait),
- its state can only be changed by this thread, which is
- currently associated with the transaction. */
-
- trx_mutex_exit(m_trx);
-
- /* If transaction is marked for ASYNC rollback then we should
- not allow it to wait for another lock causing possible deadlock.
- We return current transaction as deadlock victim here. */
-
- const trx_t* victim_trx = async_rollback ? m_trx
- : DeadlockChecker::check_and_resolve(lock, m_trx);
-
- trx_mutex_enter(m_trx);
+ const trx_t* victim_trx =
+ DeadlockChecker::check_and_resolve(lock, m_trx);
/* Check the outcome of the deadlock test. It is possible that
the transaction that blocked our lock was rolled back and we
@@ -4658,25 +4640,8 @@ lock_table_enqueue_waiting(
/* Enqueue the lock request that will wait to be granted */
lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx);
- bool async_rollback = trx->in_innodb & TRX_FORCE_ROLLBACK_ASYNC;
- /* Release the mutex to obey the latching order.
- This is safe, because DeadlockChecker::check_and_resolve()
- is invoked when a lock wait is enqueued for the currently
- running transaction. Because trx is a running transaction
- (it is not currently suspended because of a lock wait),
- its state can only be changed by this thread, which is
- currently associated with the transaction. */
-
- trx_mutex_exit(trx);
-
- /* If transaction is marked for ASYNC rollback then we should
- not allow it to wait for another lock causing possible deadlock.
- We return current transaction as deadlock victim here. */
-
- const trx_t* victim_trx = async_rollback ? trx
- : DeadlockChecker::check_and_resolve(lock, trx);
-
- trx_mutex_enter(trx);
+ const trx_t* victim_trx =
+ DeadlockChecker::check_and_resolve(lock, trx);
if (victim_trx != 0) {
ut_ad(victim_trx == trx);
@@ -8446,17 +8411,37 @@ and rolling it back. It will attempt to resolve all deadlocks. The returned
transaction id will be the joining transaction instance or NULL if some other
transaction was chosen as a victim and rolled back or no deadlock found.
-@param lock lock the transaction is requesting
-@param trx transaction requesting the lock
+@param[in] lock lock the transaction is requesting
+@param[in,out] trx transaction requesting the lock
@return transaction instanace chosen as victim or 0 */
const trx_t*
-DeadlockChecker::check_and_resolve(const lock_t* lock, const trx_t* trx)
+DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx)
{
ut_ad(lock_mutex_own());
+ ut_ad(trx_mutex_own(trx));
check_trx_state(trx);
ut_ad(!srv_read_only_mode);
+ /* If transaction is marked for ASYNC rollback then we should
+ not allow it to wait for another lock causing possible deadlock.
+ We return current transaction as deadlock victim here. */
+ if (trx->in_innodb & TRX_FORCE_ROLLBACK_ASYNC) {
+ return(trx);
+ } else if (!innobase_deadlock_detect) {
+ return(NULL);
+ }
+
+ /* Release the mutex to obey the latching order.
+ This is safe, because DeadlockChecker::check_and_resolve()
+ is invoked when a lock wait is enqueued for the currently
+ running transaction. Because m_trx is a running transaction
+ (it is not currently suspended because of a lock wait),
+ its state can only be changed by this thread, which is
+ currently associated with the transaction. */
+
+ trx_mutex_exit(trx);
+
const trx_t* victim_trx;
THD* start_mysql_thd;
bool report_waits = false;
@@ -8496,7 +8481,7 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, const trx_t* trx)
break;
- } else if (victim_trx != 0 && victim_trx != trx) {
+ } else if (victim_trx != NULL && victim_trx != trx) {
ut_ad(victim_trx == checker.m_wait_lock->trx);
@@ -8517,6 +8502,8 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, const trx_t* trx)
lock_deadlock_found = true;
}
+ trx_mutex_enter(trx);
+
return(victim_trx);
}
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index c96260ca1ac..7d4e0459610 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/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) 2014, 2017, MariaDB Corporation.
@@ -106,12 +106,6 @@ static time_t log_last_margine_warning_time;
#define LOG_BUF_FLUSH_RATIO 2
#define LOG_BUF_FLUSH_MARGIN (LOG_BUF_WRITE_MARGIN + 4 * UNIV_PAGE_SIZE)
-/* Margin for the free space in the smallest log group, before a new query
-step which modifies the database, is started */
-
-#define LOG_CHECKPOINT_FREE_PER_THREAD (4 * UNIV_PAGE_SIZE)
-#define LOG_CHECKPOINT_EXTRA_FREE (8 * UNIV_PAGE_SIZE)
-
/* This parameter controls asynchronous making of a new checkpoint; the value
should be bigger than LOG_POOL_PREFLUSH_RATIO_SYNC */
@@ -2178,7 +2172,8 @@ wait_suspend_loop:
bool freed = buf_all_freed();
ut_a(freed);
- ut_a(lsn == log_sys->lsn);
+ ut_a(lsn == log_sys->lsn
+ || srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
if (lsn < srv_start_lsn) {
ib::error() << "Shutdown LSN=" << lsn
@@ -2204,7 +2199,8 @@ wait_suspend_loop:
freed = buf_all_freed();
ut_a(freed);
- ut_a(lsn == log_sys->lsn);
+ ut_a(lsn == log_sys->lsn
+ || srv_force_recovery == SRV_FORCE_NO_LOG_REDO);
}
/******************************************************//**
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index adf2d3aca0a..0b46c92f00a 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/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) 2013, 2017, MariaDB Corporation.
@@ -532,6 +532,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
@@ -568,6 +569,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. */
@@ -2480,6 +2482,8 @@ loop:
ulint total_len = 0;
ulint n_recs = 0;
+ bool only_mlog_file = true;
+ ulint mlog_rec_len = 0;
for (;;) {
len = recv_parse_log_rec(
@@ -2508,6 +2512,22 @@ loop:
= recv_sys->recovered_offset + total_len;
recv_previous_parsed_rec_is_multi = 1;
+ /* MLOG_FILE_NAME redo log records doesn't make changes
+ to persistent data. If only MLOG_FILE_NAME redo
+ log record exists then reset the parsing buffer pointer
+ by changing recovered_lsn and recovered_offset. */
+ if (type != MLOG_FILE_NAME && only_mlog_file == true) {
+ only_mlog_file = false;
+ }
+
+ if (only_mlog_file) {
+ new_recovered_lsn = recv_calc_lsn_on_data_add(
+ recv_sys->recovered_lsn, len);
+ mlog_rec_len += len;
+ recv_sys->recovered_offset += len;
+ recv_sys->recovered_lsn = new_recovered_lsn;
+ }
+
total_len += len;
n_recs++;
@@ -2521,6 +2541,7 @@ loop:
" n=" ULINTPF,
recv_sys->recovered_lsn,
total_len, n_recs));
+ total_len -= mlog_rec_len;
break;
}
@@ -2740,6 +2761,7 @@ recv_scan_log_recs(
ulint data_len;
bool more_data = false;
bool apply = recv_sys->mlog_checkpoint_lsn != 0;
+ ulint recv_parsing_buf_size = RECV_PARSING_BUF_SIZE;
ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(end_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
@@ -2812,8 +2834,14 @@ recv_scan_log_recs(
parsing buffer if parse_start_lsn is already
non-zero */
+ DBUG_EXECUTE_IF(
+ "reduce_recv_parsing_buf",
+ recv_parsing_buf_size
+ = (70 * 1024);
+ );
+
if (recv_sys->len + 4 * OS_FILE_LOG_BLOCK_SIZE
- >= RECV_PARSING_BUF_SIZE) {
+ >= recv_parsing_buf_size) {
ib::error() << "Log parsing buffer overflow."
" Recovery may have failed!";
@@ -2863,7 +2891,7 @@ recv_scan_log_recs(
*store_to_hash = STORE_NO;
}
- if (recv_sys->recovered_offset > RECV_PARSING_BUF_SIZE / 4) {
+ if (recv_sys->recovered_offset > recv_parsing_buf_size / 4) {
/* Move parsing buffer data to the buffer start */
recv_sys_justify_left_parsing_buf();
@@ -2986,7 +3014,7 @@ recv_init_missing_space(dberr_t err, const recv_spaces_t::const_iterator& i)
@return error code or DB_SUCCESS */
static MY_ATTRIBUTE((warn_unused_result))
dberr_t
-recv_init_crash_recovery_spaces(void)
+recv_init_crash_recovery_spaces()
{
typedef std::set<ulint> space_set_t;
bool flag_deleted = false;
diff --git a/storage/innobase/mach/mach0data.cc b/storage/innobase/mach/mach0data.cc
index b22da00c0f1..6cb33715898 100644
--- a/storage/innobase/mach/mach0data.cc
+++ b/storage/innobase/mach/mach0data.cc
@@ -49,7 +49,22 @@ mach_parse_compressed(
/* 0nnnnnnn (7 bits) */
++*ptr;
return(static_cast<ib_uint32_t>(val));
- } else if (val < 0xC0) {
+ }
+
+ /* Workaround GCC bug
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77673:
+ the compiler moves mach_read_from_4 right to the beginning of the
+ function, causing and out-of-bounds read if we are reading a short
+ integer close to the end of buffer. */
+#if defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__clang__)
+#define DEPLOY_FENCE
+#endif
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (val < 0xC0) {
/* 10nnnnnn nnnnnnnn (14 bits) */
if (end_ptr >= *ptr + 2) {
val = mach_read_from_2(*ptr) & 0x3FFF;
@@ -57,7 +72,15 @@ mach_parse_compressed(
*ptr += 2;
return(static_cast<ib_uint32_t>(val));
}
- } else if (val < 0xE0) {
+ *ptr = NULL;
+ return(0);
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (val < 0xE0) {
/* 110nnnnn nnnnnnnn nnnnnnnn (21 bits) */
if (end_ptr >= *ptr + 3) {
val = mach_read_from_3(*ptr) & 0x1FFFFF;
@@ -65,7 +88,15 @@ mach_parse_compressed(
*ptr += 3;
return(static_cast<ib_uint32_t>(val));
}
- } else if (val < 0xF0) {
+ *ptr = NULL;
+ return(0);
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (val < 0xF0) {
/* 1110nnnn nnnnnnnn nnnnnnnn nnnnnnnn (28 bits) */
if (end_ptr >= *ptr + 4) {
val = mach_read_from_4(*ptr) & 0xFFFFFFF;
@@ -73,16 +104,24 @@ mach_parse_compressed(
*ptr += 4;
return(static_cast<ib_uint32_t>(val));
}
- } else {
- ut_ad(val == 0xF0);
-
- /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */
- if (end_ptr >= *ptr + 5) {
- val = mach_read_from_4(*ptr + 1);
- ut_ad(val > 0xFFFFFFF);
- *ptr += 5;
- return(static_cast<ib_uint32_t>(val));
- }
+ *ptr = NULL;
+ return(0);
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+#undef DEPLOY_FENCE
+
+ ut_ad(val == 0xF0);
+
+ /* 11110000 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn (32 bits) */
+ if (end_ptr >= *ptr + 5) {
+ val = mach_read_from_4(*ptr + 1);
+ ut_ad(val > 0xFFFFFFF);
+ *ptr += 5;
+ return(static_cast<ib_uint32_t>(val));
}
*ptr = NULL;
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index c626937b0d8..d8c7d59fe27 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.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.
This program is free software; you can redistribute it and/or modify it under
@@ -580,9 +580,13 @@ but generated some redo log on a higher level, such as
MLOG_FILE_NAME records and a MLOG_CHECKPOINT marker.
The caller must invoke log_mutex_enter() and log_mutex_exit().
This is to be used at log_checkpoint().
-@param[in] checkpoint_lsn the LSN of the log checkpoint */
+@param[in] checkpoint_lsn the LSN of the log checkpoint
+@param[in] write_mlog_checkpoint Write MLOG_CHECKPOINT marker
+ if it is enabled. */
void
-mtr_t::commit_checkpoint(lsn_t checkpoint_lsn)
+mtr_t::commit_checkpoint(
+ lsn_t checkpoint_lsn,
+ bool write_mlog_checkpoint)
{
ut_ad(log_mutex_own());
ut_ad(is_active());
@@ -593,6 +597,7 @@ mtr_t::commit_checkpoint(lsn_t checkpoint_lsn)
ut_ad(m_impl.m_memo.size() == 0);
ut_ad(!srv_read_only_mode);
ut_d(m_impl.m_state = MTR_STATE_COMMITTING);
+ ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1);
/* This is a dirty read, for debugging. */
ut_ad(!recv_no_log_write);
@@ -608,20 +613,24 @@ mtr_t::commit_checkpoint(lsn_t checkpoint_lsn)
&m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
}
- byte* ptr = m_impl.m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT);
+ if (write_mlog_checkpoint) {
+ byte* ptr = m_impl.m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT);
#if SIZE_OF_MLOG_CHECKPOINT != 9
# error SIZE_OF_MLOG_CHECKPOINT != 9
#endif
- *ptr = MLOG_CHECKPOINT;
- mach_write_to_8(ptr + 1, checkpoint_lsn);
+ *ptr = MLOG_CHECKPOINT;
+ mach_write_to_8(ptr + 1, checkpoint_lsn);
+ }
Command cmd(this);
cmd.finish_write(m_impl.m_log.size());
cmd.release_resources();
- DBUG_PRINT("ib_log",
- ("MLOG_CHECKPOINT(" LSN_PF ") written at " LSN_PF,
- checkpoint_lsn, log_sys->lsn));
+ if (write_mlog_checkpoint) {
+ DBUG_PRINT("ib_log",
+ ("MLOG_CHECKPOINT(" LSN_PF ") written at " LSN_PF,
+ checkpoint_lsn, log_sys->lsn));
+ }
}
#ifdef UNIV_DEBUG
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index f5c42abf365..76ae46827ea 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -3496,7 +3496,8 @@ SyncFileIO::execute(Slot* slot)
/* Wait for async io to complete */
ret = GetOverlappedResult(slot->file, &slot->control, &slot->n_bytes, TRUE);
}
- return(ret ? slot->n_bytes : -1);
+
+ return(ret ? static_cast<ssize_t>(slot->n_bytes) : -1);
}
/* Startup/shutdown */
diff --git a/storage/innobase/os/os0thread.cc b/storage/innobase/os/os0thread.cc
index 4012c281f8d..72199b4cf0b 100644
--- a/storage/innobase/os/os0thread.cc
+++ b/storage/innobase/os/os0thread.cc
@@ -161,9 +161,32 @@ os_thread_create_func(
return((os_thread_t)new_thread_id);
}
-/** Exits the current thread. */
+/** Waits until the specified thread completes and joins it.
+Its return value is ignored.
+@param[in,out] thread thread to join */
void
-os_thread_exit()
+os_thread_join(
+ os_thread_id_t thread)
+{
+#ifdef _WIN32
+ /* Do nothing. */
+#else
+#ifdef UNIV_DEBUG
+ const int ret =
+#endif /* UNIV_DEBUG */
+ pthread_join(thread, NULL);
+
+ /* Waiting on already-quit threads is allowed. */
+ ut_ad(ret == 0 || ret == ESRCH);
+#endif /* _WIN32 */
+}
+
+/** Exits the current thread.
+@param[in] detach if true, the thread will be detached right before
+exiting. If false, another thread is responsible for joining this thread */
+void
+os_thread_exit(
+ bool detach)
{
#ifdef UNIV_DEBUG_THREAD_CREATION
ib::info() << "Thread exits, id "
@@ -184,7 +207,9 @@ os_thread_exit()
ExitThread(0);
#else
mutex_exit(&thread_mutex);
- pthread_detach(pthread_self());
+ if (detach) {
+ pthread_detach(pthread_self());
+ }
pthread_exit(NULL);
#endif
}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 88c5a425818..e718081ed63 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -4973,19 +4973,7 @@ ibool
page_zip_verify_checksum(
/*=====================*/
const void* data, /*!< in: compressed page */
- ulint size /*!< in: size of compressed page */
-#ifdef UNIV_INNOCHECKSUM
- /* these variables are used only for innochecksum tool. */
- ,uintmax_t page_no, /*!< in: page number of
- given read_buf */
- bool strict_check, /*!< in: true if strict-check
- option is enable */
- bool is_log_enabled, /*!< in: true if log option is
- enabled */
- FILE* log_file /*!< in: file pointer to
- log_file */
-#endif /* UNIV_INNOCHECKSUM */
-)
+ ulint size) /*!< in: size of compressed page */
{
const unsigned char* p = static_cast<const unsigned char*>(data)
+ FIL_PAGE_SPACE_OR_CHKSUM;
@@ -5023,9 +5011,9 @@ page_zip_verify_checksum(
break;
}
if (i >= size) {
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "Page::%lu is empty and"
- " uncorrupted\n", page_no);
+ " uncorrupted\n", cur_page_num);
}
return(TRUE);
@@ -5061,28 +5049,28 @@ page_zip_verify_checksum(
const uint32_t calc = page_zip_calc_checksum(data, size, curr_algo);
#ifdef UNIV_INNOCHECKSUM
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "page::%lu;"
" %s checksum: calculated = %u;"
- " recorded = %u\n", page_no,
+ " recorded = %u\n", cur_page_num,
buf_checksum_algorithm_name(
static_cast<srv_checksum_algorithm_t>(
srv_checksum_algorithm)),
calc, stored);
}
- if (!strict_check) {
+ if (!strict_verify) {
const uint32_t crc32 = page_zip_calc_checksum(
data, size, SRV_CHECKSUM_ALGORITHM_CRC32);
- if (is_log_enabled) {
+ if (log_file) {
fprintf(log_file, "page::%lu: crc32 checksum:"
" calculated = %u; recorded = %u\n",
- page_no, crc32, stored);
+ cur_page_num, crc32, stored);
fprintf(log_file, "page::%lu: none checksum:"
" calculated = %lu; recorded = %u\n",
- page_no, BUF_NO_CHECKSUM_MAGIC, stored);
+ cur_page_num, BUF_NO_CHECKSUM_MAGIC, stored);
}
}
#endif /* UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 6d974e7accb..26bb12e8a03 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -1652,6 +1652,7 @@ rec_copy_prefix_to_buf(
ulint prefix_len;
ulint null_mask;
ulint status;
+ bool is_rtr_node_ptr = false;
UNIV_PREFETCH_RW(*buf);
@@ -1673,6 +1674,7 @@ rec_copy_prefix_to_buf(
/* For R-tree, we need to copy the child page number field. */
if (dict_index_is_spatial(index)) {
ut_ad(n_fields == DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1);
+ is_rtr_node_ptr = true;
} else {
/* it doesn't make sense to copy the child page number
field */
@@ -1717,7 +1719,11 @@ rec_copy_prefix_to_buf(
null_mask <<= 1;
}
- if (field->fixed_len) {
+ if (is_rtr_node_ptr && i == 1) {
+ /* For rtree node ptr rec, we need to
+ copy the page no field with 4 bytes len. */
+ prefix_len += 4;
+ } else if (field->fixed_len) {
prefix_len += field->fixed_len;
} else {
ulint len = *lens--;
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 2adf32b79d9..fca6ae5a1bf 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1144,7 +1144,7 @@ fts_parallel_merge(
os_event_set(psort_info->psort_common->merge_event);
psort_info->child_status = FTS_CHILD_EXITING;
- os_thread_exit();
+ os_thread_exit(false);
OS_THREAD_DUMMY_RETURN;
}
@@ -1157,15 +1157,16 @@ row_fts_start_parallel_merge(
fts_psort_t* merge_info) /*!< in: parallel sort info */
{
int i = 0;
- os_thread_id_t thd_id;
/* Kick off merge/insert threads */
for (i = 0; i < FTS_NUM_AUX_INDEX; i++) {
merge_info[i].psort_id = i;
merge_info[i].child_status = 0;
- merge_info[i].thread_hdl = os_thread_create(fts_parallel_merge,
- (void*) &merge_info[i], &thd_id);
+ merge_info[i].thread_hdl = os_thread_create(
+ fts_parallel_merge,
+ (void*) &merge_info[i],
+ &merge_info[i].thread_hdl);
}
}
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index f596f3d8f27..5152d499bad 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1596,6 +1596,10 @@ row_ins_check_foreign_constraint(
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
+ bool skip_gap_lock;
+
+ skip_gap_lock = (trx->isolation_level <= TRX_ISO_READ_COMMITTED);
+
DBUG_ENTER("row_ins_check_foreign_constraint");
rec_offs_init(offsets_);
@@ -1725,6 +1729,11 @@ row_ins_check_foreign_constraint(
if (page_rec_is_supremum(rec)) {
+ if (skip_gap_lock) {
+
+ continue;
+ }
+
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
rec, check_index,
offsets, thr);
@@ -1740,10 +1749,17 @@ row_ins_check_foreign_constraint(
cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
+
+ ulint lock_type;
+
+ lock_type = skip_gap_lock
+ ? LOCK_REC_NOT_GAP
+ : LOCK_ORDINARY;
+
if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) {
err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY, block,
+ lock_type, block,
rec, check_index, offsets, thr);
switch (err) {
case DB_SUCCESS_LOCKED_REC:
@@ -1824,9 +1840,13 @@ row_ins_check_foreign_constraint(
} else {
ut_a(cmp < 0);
- err = row_ins_set_shared_rec_lock(
- LOCK_GAP, block,
- rec, check_index, offsets, thr);
+ err = DB_SUCCESS;
+
+ if (!skip_gap_lock) {
+ err = row_ins_set_shared_rec_lock(
+ LOCK_GAP, block,
+ rec, check_index, offsets, thr);
+ }
switch (err) {
case DB_SUCCESS_LOCKED_REC:
@@ -1878,6 +1898,8 @@ do_possible_lock_wait:
my_atomic_addlint(
&check_table->n_foreign_key_checks_running, 1);
+ trx_kill_blocking(trx);
+
lock_wait_suspend_thread(thr);
thr->lock_state = QUE_THR_LOCK_NOLOCK;
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 7e6975a67f1..36ad6cdd3d9 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -649,7 +649,7 @@ row_log_table_delete(
&old_pk_extra_size);
ut_ad(old_pk_extra_size < 0x100);
- mrec_size = 4 + old_pk_size;
+ mrec_size = 6 + old_pk_size;
/* Log enough prefix of the BLOB unless both the
old and new table are in COMPACT or REDUNDANT format,
@@ -686,8 +686,8 @@ row_log_table_delete(
*b++ = static_cast<byte>(old_pk_extra_size);
/* Log the size of external prefix we saved */
- mach_write_to_2(b, ext_size);
- b += 2;
+ mach_write_to_4(b, ext_size);
+ b += 4;
rec_convert_dtuple_to_temp(
b + old_pk_extra_size, new_index,
@@ -820,12 +820,9 @@ row_log_table_low_redundant(
mrec_size = ROW_LOG_HEADER_SIZE + size + (extra_size >= 0x80);
- if (ventry && ventry->n_v_fields > 0) {
- ulint v_extra = 0;
- mrec_size += rec_get_converted_size_temp(
- index, NULL, 0, ventry, &v_extra);
-
+ if (num_v) {
if (o_ventry) {
+ ulint v_extra = 0;
mrec_size += rec_get_converted_size_temp(
index, NULL, 0, o_ventry, &v_extra);
}
@@ -878,11 +875,7 @@ row_log_table_low_redundant(
ventry);
b += size;
- if (ventry && ventry->n_v_fields > 0) {
- rec_convert_dtuple_to_temp(
- b, new_index, NULL, 0, ventry);
- b += mach_read_from_2(b);
-
+ if (num_v) {
if (o_ventry) {
rec_convert_dtuple_to_temp(
b, new_index, NULL, 0, o_ventry);
@@ -943,6 +936,13 @@ row_log_table_low(
ut_ad(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
ut_ad(page_is_leaf(page_align(rec)));
ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets));
+ /* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix
+ of the clustered index record (PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR),
+ with no information on virtual columns */
+ ut_ad(!old_pk || !insert);
+ ut_ad(!old_pk || old_pk->n_v_fields == 0);
+ ut_ad(!o_ventry || !insert);
+ ut_ad(!o_ventry || ventry);
if (dict_index_is_corrupted(index)
|| !dict_index_is_online_ddl(index)
@@ -996,7 +996,7 @@ row_log_table_low(
old_pk_size = rec_get_converted_size_temp(
new_index, old_pk->fields, old_pk->n_fields,
- old_pk, &old_pk_extra_size);
+ NULL, &old_pk_extra_size);
ut_ad(old_pk_extra_size < 0x100);
mrec_size += 1/*old_pk_extra_size*/ + old_pk_size;
}
@@ -2195,8 +2195,9 @@ func_exit_committed:
goto func_exit_committed;
}
- dtuple_t* entry = row_build_index_entry(
- row, NULL, index, heap);
+ /** It allows to create tuple with virtual column information. */
+ dtuple_t* entry = row_build_index_entry_low(
+ row, NULL, index, heap, ROW_BUILD_FOR_INSERT);
upd_t* update = row_upd_build_difference_binary(
index, entry, btr_pcur_get_rec(&pcur), cur_offsets,
false, NULL, heap, dup->table);
@@ -2441,14 +2442,14 @@ row_log_table_apply_op(
break;
case ROW_T_DELETE:
- /* 1 (extra_size) + 2 (ext_size) + at least 1 (payload) */
- if (mrec + 4 >= mrec_end) {
+ /* 1 (extra_size) + 4 (ext_size) + at least 1 (payload) */
+ if (mrec + 6 >= mrec_end) {
return(NULL);
}
extra_size = *mrec++;
- ext_size = mach_read_from_2(mrec);
- mrec += 2;
+ ext_size = mach_read_from_4(mrec);
+ mrec += 4;
ut_ad(mrec < mrec_end);
/* We assume extra_size < 0x100 for the PRIMARY KEY prefix.
@@ -2459,6 +2460,10 @@ row_log_table_apply_op(
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets) + ext_size;
if (log->table->n_v_cols) {
+ if (next_mrec + 2 >= mrec_end) {
+ return(NULL);
+ }
+
next_mrec += mach_read_from_2(next_mrec);
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 85f0ce2c9e6..aeff27c31eb 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2014, 2017, MariaDB Corporation.
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
@@ -26,6 +26,7 @@ Completed by Sunny Bains and Marko Makela
*******************************************************/
#include <my_config.h>
#include <log.h>
+#include <sql_class.h>
#include <math.h>
@@ -3300,7 +3301,11 @@ row_merge_sort(
}
#endif /* UNIV_SOLARIS */
- sql_print_information("InnoDB: Online DDL : merge-sorting has estimated %lu runs", num_runs);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : merge-sorting"
+ " has estimated " ULINTPF " runs",
+ num_runs);
+ }
/* Merge the runs until we have one big run */
do {
@@ -4765,9 +4770,11 @@ row_merge_build_indexes(
duplicate keys. */
innobase_rec_reset(table);
- sql_print_information("InnoDB: Online DDL : Start");
- sql_print_information("InnoDB: Online DDL : Start reading clustered "
- "index of the table and create temporary files");
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : Start reading"
+ " clustered index of the table"
+ " and create temporary files");
+ }
pct_cost = COST_READ_CLUSTERED_INDEX * 100 / (total_static_cost + total_dynamic_cost);
@@ -4795,8 +4802,11 @@ row_merge_build_indexes(
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : End of reading "
- "clustered index of the table and create temporary files");
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : End of reading "
+ "clustered index of the table"
+ " and create temporary files");
+ }
for (i = 0; i < n_indexes; i++) {
total_index_blocks += merge_files[i].offset;
@@ -4875,6 +4885,13 @@ wait_again:
" threads exited when creating"
" FTS index '"
<< indexes[i]->name << "'";
+ } else {
+ for (j = 0; j < FTS_NUM_AUX_INDEX;
+ j++) {
+
+ os_thread_join(merge_info[j]
+ .thread_hdl);
+ }
}
} else {
/* This cannot report duplicates; an
@@ -4888,8 +4905,7 @@ wait_again:
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
#endif
} else if (merge_files[i].fd >= 0) {
- char buf[3 * NAME_LEN];
- char *bufend;
+ char buf[NAME_LEN + 1];
row_merge_dup_t dup = {
sort_idx, table, col_map, 0};
@@ -4898,17 +4914,24 @@ wait_again:
total_index_blocks)) /
(total_static_cost + total_dynamic_cost)
* PCT_COST_MERGESORT_INDEX * 100;
-
- bufend = innobase_convert_name(
+ char* bufend = innobase_convert_name(
buf, sizeof buf,
- indexes[i]->name, strlen(indexes[i]->name),
+ indexes[i]->name,
+ strlen(indexes[i]->name),
trx->mysql_thd);
-
buf[bufend - buf]='\0';
- sql_print_information("InnoDB: Online DDL : Start merge-sorting"
- " index %s (%lu / %lu), estimated cost : %2.4f",
- buf, (i+1), n_indexes, pct_cost);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL :"
+ " Start merge-sorting"
+ " index %s"
+ " (" ULINTPF
+ " / " ULINTPF "),"
+ " estimated cost :"
+ " %2.4f",
+ buf, i + 1, n_indexes,
+ pct_cost);
+ }
error = row_merge_sort(
trx, &dup, &merge_files[i],
@@ -4918,9 +4941,14 @@ wait_again:
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : End of "
- " merge-sorting index %s (%lu / %lu)",
- buf, (i+1), n_indexes);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL :"
+ " End of "
+ " merge-sorting index %s"
+ " (" ULINTPF
+ " / " ULINTPF ")",
+ buf, i + 1, n_indexes);
+ }
DBUG_EXECUTE_IF(
"ib_merge_wait_after_sort",
@@ -4937,10 +4965,15 @@ wait_again:
(total_static_cost + total_dynamic_cost) *
PCT_COST_INSERT_INDEX * 100;
- sql_print_information("InnoDB: Online DDL : Start "
- "building index %s (%lu / %lu), estimated "
- "cost : %2.4f", buf, (i+1),
- n_indexes, pct_cost);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : Start "
+ "building index %s"
+ " (" ULINTPF
+ " / " ULINTPF "), estimated "
+ "cost : %2.4f", buf, i + 1,
+ n_indexes, pct_cost);
+ }
error = row_merge_insert_index_tuples(
trx->id, sort_idx, old_table,
@@ -4953,9 +4986,13 @@ wait_again:
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : "
- "End of building index %s (%lu / %lu)",
- buf, (i+1), n_indexes);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : "
+ "End of building index %s"
+ " (" ULINTPF " / " ULINTPF ")",
+ buf, i + 1, n_indexes);
+ }
}
}
@@ -4973,19 +5010,19 @@ wait_again:
== ONLINE_INDEX_COMPLETE);
} else {
ut_ad(need_flush_observer);
- sql_print_information("InnoDB: Online DDL : Start applying row log");
-
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : Applying"
+ " log to index");
+ }
flush_observer->flush();
row_merge_write_redo(indexes[i]);
DEBUG_SYNC_C("row_log_apply_before");
error = row_log_apply(trx, sort_idx, table, stage);
DEBUG_SYNC_C("row_log_apply_after");
- sql_print_information("InnoDB: Online DDL : End of applying row log");
}
- sql_print_information("InnoDB: Online DDL : Completed");
-
if (error != DB_SUCCESS) {
trx->error_key_num = key_numbers[i];
goto func_exit;
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 7d8c1a683e2..aed59070396 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.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) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -1505,6 +1505,8 @@ run_again:
row_ins_step(thr);
+ DEBUG_SYNC_C("ib_after_row_insert_step");
+
err = trx->error_state;
if (err != DB_SUCCESS) {
@@ -2888,6 +2890,10 @@ loop:
return(n_tables + n_tables_dropped);
}
+ DBUG_EXECUTE_IF("row_drop_tables_in_background_sleep",
+ os_thread_sleep(5000000);
+ );
+
table = dict_table_open_on_name(drop->table_name, FALSE, FALSE,
DICT_ERR_IGNORE_NONE);
@@ -2898,6 +2904,16 @@ loop:
goto already_dropped;
}
+ if (!table->to_be_dropped) {
+ /* There is a scenario: the old table is dropped
+ just after it's added into drop list, and new
+ table with the same name is created, then we try
+ to drop the new table in background. */
+ dict_table_close(table, FALSE, FALSE);
+
+ goto already_dropped;
+ }
+
ut_a(!table->can_be_evicted);
dict_table_close(table, FALSE, FALSE);
@@ -3766,6 +3782,13 @@ row_drop_table_for_mysql(
}
}
+
+ DBUG_EXECUTE_IF("row_drop_table_add_to_background",
+ row_add_table_to_background_drop_list(table->name.m_name);
+ err = DB_SUCCESS;
+ goto funct_exit;
+ );
+
/* TODO: could we replace the counter n_foreign_key_checks_running
with lock checks on the table? Acquire here an exclusive lock on the
table, and rewrite lock0lock.cc and the lock wait in srv0srv.cc so that
@@ -4272,6 +4295,19 @@ loop:
row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
+ /* Drop parent table if it is a fts aux table, to
+ avoid accessing dropped fts aux tables in information
+ scheam when parent table still exists.
+ Note: Drop parent table will drop fts aux tables. */
+ char* parent_table_name;
+ parent_table_name = fts_get_parent_table_name(
+ table_name, strlen(table_name));
+
+ if (parent_table_name != NULL) {
+ ut_free(table_name);
+ table_name = parent_table_name;
+ }
+
ut_a(memcmp(table_name, name, namelen) == 0);
table = dict_table_open_on_name(
@@ -5010,9 +5046,6 @@ row_scan_index_for_mysql(
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct
in MySQL handle */
const dict_index_t* index, /*!< in: index */
- bool check_keys, /*!< in: true=check for mis-
- ordered or duplicate records,
- false=count the rows only */
ulint* n_rows) /*!< out: number of entries
seen in the consistent read */
{
@@ -5079,7 +5112,7 @@ loop:
goto func_exit;
default:
{
- const char* doing = check_keys? "CHECK TABLE" : "COUNT(*)";
+ const char* doing = "CHECK TABLE";
ib::warn() << doing << " on index " << index->name << " of"
" table " << index->table->name << " returned " << ret;
/* fall through (this error is ignored by CHECK TABLE) */
@@ -5095,9 +5128,6 @@ func_exit:
*n_rows = *n_rows + 1;
- if (!check_keys) {
- goto next_rec;
- }
/* else this code is doing handler::check() for CHECK TABLE */
/* row_search... returns the index record in buf, record origin offset
@@ -5179,7 +5209,6 @@ not_ok:
}
}
-next_rec:
ret = row_search_for_mysql(
buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 2a13203b747..492d864ec96 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.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.
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
@@ -43,6 +43,7 @@ Created 3/14/1997 Heikki Tuuri
#include "srv0start.h"
#include "handler.h"
#include "ha_innodb.h"
+#include "fil0fil.h"
/*************************************************************************
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -852,8 +853,15 @@ try_again:
/* The table has been dropped: no need to do purge */
goto err_exit;
}
+
ut_ad(!dict_table_is_temporary(node->table));
+ if (!fil_table_accessible(node->table)) {
+ dict_table_close(node->table, FALSE, FALSE);
+ node->table = NULL;
+ goto err_exit;
+ }
+
if (node->table->n_v_cols && !node->table->vc_templ
&& dict_table_has_indexed_v_cols(node->table)) {
/* Need server fully up for virtual column computation */
@@ -872,16 +880,6 @@ try_again:
innobase_init_vc_templ(node->table);
}
- if (node->table->ibd_file_missing) {
- /* We skip purge of missing .ibd files */
-
- dict_table_close(node->table, FALSE, FALSE);
-
- node->table = NULL;
-
- goto err_exit;
- }
-
clust_index = dict_table_get_first_index(node->table);
if (clust_index == NULL
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc
index 46cff288059..1fc30e714f4 100644
--- a/storage/innobase/row/row0trunc.cc
+++ b/storage/innobase/row/row0trunc.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2013, 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
@@ -2000,9 +2000,22 @@ row_truncate_table_for_mysql(
}
if (is_file_per_table && fsp_flags != ULINT_UNDEFINED) {
- fil_reinit_space_header(
- table->space,
- table->indexes.count + FIL_IBD_FILE_INITIAL_SIZE + 1);
+ /* A single-table tablespace has initially
+ FIL_IBD_FILE_INITIAL_SIZE number of pages allocated and an
+ extra page is allocated for each of the indexes present. But in
+ the case of clust index 2 pages are allocated and as one is
+ covered in the calculation as part of table->indexes.count we
+ take care of the other page by adding 1. */
+ ulint space_size = table->indexes.count +
+ FIL_IBD_FILE_INITIAL_SIZE + 1;
+
+ if (has_internal_doc_id) {
+ /* Since aux tables are created for fts indexes and
+ they use seperate tablespaces. */
+ space_size -= ib_vector_size(table->fts->indexes);
+ }
+
+ fil_reinit_space_header(table->space, space_size, trx);
}
DBUG_EXECUTE_IF("ib_trunc_crash_with_intermediate_log_checkpoint",
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 25504e32087..9288adb21a4 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.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.
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
@@ -41,6 +41,7 @@ Created 2/25/1997 Heikki Tuuri
#include "que0que.h"
#include "ibuf0ibuf.h"
#include "log0log.h"
+#include "fil0fil.h"
/*************************************************************************
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -345,8 +346,20 @@ row_undo_ins_parse_undo_rec(
/* Skip the UNDO if we can't find the table or the .ibd file. */
if (UNIV_UNLIKELY(node->table == NULL)) {
- } else if (UNIV_UNLIKELY(node->table->ibd_file_missing)) {
+ return;
+ }
+
+ if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) {
close_table:
+ /* Normally, tables should not disappear or become
+ unaccessible during ROLLBACK, because they should be
+ protected by InnoDB table locks. TRUNCATE TABLE
+ or table corruption could be valid exceptions.
+
+ FIXME: When running out of temporary tablespace, it
+ would probably be better to just drop all temporary
+ tables (and temporary undo log records) of the current
+ connection, instead of doing this rollback. */
dict_table_close(node->table, dict_locked, FALSE);
node->table = NULL;
} else {
@@ -357,6 +370,9 @@ close_table:
ptr, clust_index, &node->ref, node->heap);
if (!row_undo_search_clust_to_pcur(node)) {
+ /* An error probably occurred during
+ an insert into the clustered index,
+ after we wrote the undo log record. */
goto close_table;
}
if (node->table->n_v_cols) {
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 378cad00b93..ba072a72aa1 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.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.
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
@@ -1139,12 +1139,19 @@ row_undo_mod_parse_undo_rec(
return;
}
- if (node->table->ibd_file_missing) {
+ if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) {
+close_table:
+ /* Normally, tables should not disappear or become
+ unaccessible during ROLLBACK, because they should be
+ protected by InnoDB table locks. TRUNCATE TABLE
+ or table corruption could be valid exceptions.
+
+ FIXME: When running out of temporary tablespace, it
+ would probably be better to just drop all temporary
+ tables (and temporary undo log records) of the current
+ connection, instead of doing this rollback. */
dict_table_close(node->table, dict_locked, FALSE);
-
- /* We skip undo operations to missing .ibd files */
node->table = NULL;
-
return;
}
@@ -1162,15 +1169,21 @@ row_undo_mod_parse_undo_rec(
node->new_trx_id = trx_id;
node->cmpl_info = cmpl_info;
- if (!row_undo_search_clust_to_pcur(node)) {
-
- dict_table_close(node->table, dict_locked, FALSE);
-
- node->table = NULL;
+ if (UNIV_UNLIKELY(!row_undo_search_clust_to_pcur(node))) {
+ /* This should never occur. As long as this
+ rolling-back transaction exists, the PRIMARY KEY value
+ pointed to by the undo log record must exist.
+ btr_cur_upd_lock_and_undo() only writes the undo log
+ record after successfully acquiring an exclusive lock
+ on the the clustered index record. That lock will not
+ be released before the transaction is committed or
+ fully rolled back. */
+ ut_ad(0);
+ goto close_table;
}
/* Extract indexed virtual columns from undo log */
- if (node->table && node->table->n_v_cols) {
+ if (node->table->n_v_cols) {
row_upd_replace_vcol(node->row, node->table,
node->update, false, node->undo_row,
(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 95f17fa68d0..f3595308363 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -87,7 +87,7 @@ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPH
/* How much data manipulation language (DML) statements need to be delayed,
in microseconds, in order to reduce the lagging of the purge thread. */
-ulint srv_dml_needed_delay = 0;
+ulint srv_dml_needed_delay;
bool srv_monitor_active;
bool srv_error_monitor_active;
@@ -107,34 +107,34 @@ const char srv_mysql50_table_name_prefix[10] = "#mysql50#";
/* The following three are dir paths which are catenated before file
names, where the file name itself may also contain a path */
-char* srv_data_home = NULL;
+char* srv_data_home;
/** Rollback files directory, can be absolute. */
-char* srv_undo_dir = NULL;
+char* srv_undo_dir;
/** The number of tablespaces to use for rollback segments. */
-ulong srv_undo_tablespaces = 0;
+ulong srv_undo_tablespaces;
/** The number of UNDO tablespaces that are open and ready to use. */
-ulint srv_undo_tablespaces_open = 0;
+ulint srv_undo_tablespaces_open;
/** The number of UNDO tablespaces that are active (hosting some rollback
segment). It is quite possible that some of the tablespaces doesn't host
any of the rollback-segment based on configuration used. */
-ulint srv_undo_tablespaces_active = 0;
+ulint srv_undo_tablespaces_active;
/* The number of rollback segments to use */
-ulong srv_undo_logs = 1;
+ulong srv_undo_logs;
/** Rate at which UNDO records should be purged. */
-ulong srv_purge_rseg_truncate_frequency = 128;
+ulong srv_purge_rseg_truncate_frequency;
/** Enable or Disable Truncate of UNDO tablespace.
Note: If enabled then UNDO tablespace will be selected for truncate.
While Server waits for undo-tablespace to truncate if user disables
it, truncate action is completed but no new tablespace is marked
for truncate (action is never aborted). */
-my_bool srv_undo_log_truncate = FALSE;
+my_bool srv_undo_log_truncate;
/** Maximum size of undo tablespace. */
unsigned long long srv_max_undo_log_size;
@@ -151,7 +151,7 @@ my_bool srv_read_only_mode;
dictionary tables are in the system tablespace 0 */
my_bool srv_file_per_table;
/** The file format to use on new *.ibd files. */
-ulint srv_file_format = 0;
+ulint srv_file_format;
/** Whether to check file format during startup. A value of
UNIV_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to
set it to the highest format we support. */
@@ -166,9 +166,9 @@ my_bool high_level_read_only;
/** Place locks to records only i.e. do not use next-key locking except
on duplicate key checking and foreign key checking */
-ibool srv_locks_unsafe_for_binlog = FALSE;
+ibool srv_locks_unsafe_for_binlog;
/** Sort buffer size in index creation */
-ulong srv_sort_buf_size = 1048576;
+ulong srv_sort_buf_size;
/** Maximum modification log file size for online index creation */
unsigned long long srv_online_max_size;
@@ -176,16 +176,16 @@ 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 */
-my_bool srv_use_native_aio = TRUE;
-my_bool srv_numa_interleave = FALSE;
-/* If this flag is TRUE, then we disable doublewrite buffer */
-UNIV_INTERN my_bool srv_use_atomic_writes = FALSE;
-/* If this flag IS TRUE, then we use this algorithm for page compressing the pages */
-UNIV_INTERN ulong innodb_compression_algorithm = PAGE_ZLIB_ALGORITHM;
-/* Number of threads used for multi-threaded flush */
-UNIV_INTERN long srv_mtflush_threads = MTFLUSH_DEFAULT_WORKER;
-/* If this flag is TRUE, then we will use multi threaded flush. */
-UNIV_INTERN my_bool srv_use_mtflush = FALSE;
+my_bool srv_use_native_aio;
+my_bool srv_numa_interleave;
+/** copy of innodb_use_atomic_writes; @see innobase_init() */
+my_bool srv_use_atomic_writes;
+/** innodb_compression_algorithm; used with page compression */
+ulong innodb_compression_algorithm;
+/** innodb_mtflush_threads; number of threads used for multi-threaded flush */
+long srv_mtflush_threads;
+/** innodb_use_mtflush; whether to use multi threaded flush. */
+my_bool srv_use_mtflush;
#ifdef UNIV_DEBUG
/** Used by SET GLOBAL innodb_master_thread_disabled_debug = X. */
@@ -212,22 +212,27 @@ During startup, this is in bytes, and later converted to pages. */
ib_uint64_t srv_log_file_size;
/** The value of the startup parameter innodb_log_file_size */
ib_uint64_t srv_log_file_size_requested;
-/* size in database pages */
-ulint srv_log_buffer_size = ULINT_MAX;
-ulong srv_flush_log_at_trx_commit = 1;
-uint srv_flush_log_at_timeout = 1;
-ulong srv_page_size = UNIV_PAGE_SIZE_DEF;
-ulong srv_page_size_shift = UNIV_PAGE_SIZE_SHIFT_DEF;
-ulong srv_log_write_ahead_size = 0;
+/** copy of innodb_log_buffer_size, but in database pages */
+ulint srv_log_buffer_size;
+/** innodb_flush_log_at_trx_commit */
+ulong srv_flush_log_at_trx_commit;
+/** innodb_flush_log_at_timeout */
+uint srv_flush_log_at_timeout;
+/** innodb_page_size */
+ulong srv_page_size;
+/** log2 of innodb_page_size; @see innobase_init() */
+ulong srv_page_size_shift;
+/** innodb_log_write_ahead_size */
+ulong srv_log_write_ahead_size;
page_size_t univ_page_size(0, 0, false);
-/* Try to flush dirty pages so as to avoid IO bursts at
-the checkpoints. */
-char srv_adaptive_flushing = TRUE;
+/** innodb_adaptive_flushing; try to flush dirty pages so as to avoid
+IO bursts at the checkpoints. */
+my_bool srv_adaptive_flushing;
-/* Allow IO bursts at the checkpoints ignoring io_capacity setting. */
-my_bool srv_flush_sync = TRUE;
+/** innodb_flush_sync; whether to ignore io_capacity at log checkpoints */
+my_bool srv_flush_sync;
/** Maximum number of times allowed to conditionally acquire
mutex before switching to blocking wait on the mutex */
@@ -243,93 +248,100 @@ with mutex_enter(), which will wait until it gets the mutex. */
UNIV_INTERN os_event_t srv_allow_writes_event;
#endif /* WITH_INNODB_DISALLOW_WRITES */
-/** Requested size in bytes */
-ulint srv_buf_pool_size = ULINT_MAX;
+/** copy of innodb_buffer_pool_size */
+ulint srv_buf_pool_size;
const ulint srv_buf_pool_min_size = 5 * 1024 * 1024;
/** Default pool size in bytes */
const ulint srv_buf_pool_def_size = 128 * 1024 * 1024;
/** Requested buffer pool chunk size. Each buffer pool instance consists
of one or more chunks. */
ulong srv_buf_pool_chunk_unit;
-/** Requested number of buffer pool instances */
+/** innodb_buffer_pool_instances (0 is interpreted as 1) */
ulong srv_buf_pool_instances;
-/** Default number of buffer pool instances */
+/** Default value of innodb_buffer_pool_instances */
const ulong srv_buf_pool_instances_default = 0;
-/** Number of locks to protect buf_pool->page_hash */
+/** innodb_page_hash_locks (a debug-only parameter);
+number of locks to protect buf_pool->page_hash */
ulong srv_n_page_hash_locks = 16;
-/** Scan depth for LRU flush batch i.e.: number of blocks scanned*/
-ulong srv_LRU_scan_depth = 1024;
-/** Whether or not to flush neighbors of a block */
-ulong srv_flush_neighbors = 1;
+/** innodb_lru_scan_depth; number of blocks scanned in LRU flush batch */
+ulong srv_LRU_scan_depth;
+/** innodb_flush_neighbors; whether or not to flush neighbors of a block */
+ulong srv_flush_neighbors;
/** Previously requested size */
-ulint srv_buf_pool_old_size = 0;
+ulint srv_buf_pool_old_size;
/** Current size as scaling factor for the other components */
-ulint srv_buf_pool_base_size = 0;
+ulint srv_buf_pool_base_size;
/** Current size in bytes */
-ulint srv_buf_pool_curr_size = 0;
+ulint srv_buf_pool_curr_size;
/** Dump this % of each buffer pool during BP dump */
ulong srv_buf_pool_dump_pct;
/** Lock table size in bytes */
ulint srv_lock_table_size = ULINT_MAX;
-UNIV_INTERN ulong srv_idle_flush_pct = 100;
+/** innodb_idle_flush_pct */
+ulong srv_idle_flush_pct;
-/* This parameter is deprecated. Use srv_n_io_[read|write]_threads
-instead. */
-ulint srv_n_read_io_threads = ULINT_MAX;
-ulint srv_n_write_io_threads = ULINT_MAX;
+/** copy of innodb_read_io_threads */
+ulint srv_n_read_io_threads;
+/** copy of innodb_write_io_threads */
+ulint srv_n_write_io_threads;
-/* Switch to enable random read ahead. */
-my_bool srv_random_read_ahead = FALSE;
-/* User settable value of the number of pages that must be present
+/** innodb_random_read_ahead */
+my_bool srv_random_read_ahead;
+/** innodb_read_ahead_threshold; the number of pages that must be present
in the buffer cache and accessed sequentially for InnoDB to trigger a
readahead request. */
-ulong srv_read_ahead_threshold = 56;
+ulong srv_read_ahead_threshold;
-/** Maximum on-disk size of change buffer in terms of percentage
-of the buffer pool. */
-uint srv_change_buffer_max_size = CHANGE_BUFFER_DEFAULT_SIZE;
+/** innodb_change_buffer_max_size; maximum on-disk size of change
+buffer in terms of percentage of the buffer pool. */
+uint srv_change_buffer_max_size;
-char* srv_file_flush_method_str = NULL;
+char* srv_file_flush_method_str;
enum srv_flush_t srv_file_flush_method = IF_WIN(SRV_ALL_O_DIRECT_FSYNC,SRV_FSYNC);
-ulint srv_max_n_open_files = 300;
+/** copy of innodb_open_files, initialized by innobase_init() */
+ulint srv_max_n_open_files;
-/* Number of IO operations per second the server can do */
-ulong srv_io_capacity = 200;
-ulong srv_max_io_capacity = 400;
+/** innodb_io_capacity */
+ulong srv_io_capacity;
+/** innodb_io_capacity_max */
+ulong srv_max_io_capacity;
-/* The number of page cleaner threads to use.*/
-ulong srv_n_page_cleaners = 4;
+/** innodb_page_cleaners; the number of page cleaner threads */
+ulong srv_n_page_cleaners;
/* The InnoDB main thread tries to keep the ratio of modified pages
in the buffer pool to all database pages in the buffer pool smaller than
the following number. But it is not guaranteed that the value stays below
that during a time of heavy update/insert activity. */
-double srv_max_buf_pool_modified_pct = 75.0;
-double srv_max_dirty_pages_pct_lwm = 0.0;
+/** innodb_max_dirty_pages_pct */
+double srv_max_buf_pool_modified_pct;
+/** innodb_max_dirty_pages_pct_lwm */
+double srv_max_dirty_pages_pct_lwm;
-/* This is the percentage of log capacity at which adaptive flushing,
-if enabled, will kick in. */
-UNIV_INTERN double srv_adaptive_flushing_lwm = 10.0;
+/** innodb_adaptive_flushing_lwm; the percentage of log capacity at
+which adaptive flushing, if enabled, will kick in. */
+double srv_adaptive_flushing_lwm;
-/* Number of iterations over which adaptive flushing is averaged. */
-ulong srv_flushing_avg_loops = 30;
+/** innodb_flushing_avg_loops; number of iterations over which
+adaptive flushing is averaged */
+ulong srv_flushing_avg_loops;
-/* The number of purge threads to use.*/
-ulong srv_n_purge_threads = 4;
+/** innodb_purge_threads; the number of purge threads to use */
+ulong srv_n_purge_threads;
-/* the number of pages to purge in one batch */
-ulong srv_purge_batch_size = 20;
+/** innodb_purge_batch_size, in pages */
+ulong srv_purge_batch_size;
-/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
+/** innodb_stats_method decides how InnoDB treats
NULL value when collecting statistics. By default, it is set to
SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
-ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
+ulong srv_innodb_stats_method;
srv_stats_t srv_stats;
@@ -342,59 +354,67 @@ by SELECT or mysqldump. When this is nonzero, we do not allow any user
modifications to the data. */
ulong srv_force_recovery;
-/** Print all user-level transactions deadlocks to mysqld stderr */
+/** innodb_print_all_deadlocks; whether to print all user-level
+transactions deadlocks to the error log */
+my_bool srv_print_all_deadlocks;
-my_bool srv_print_all_deadlocks = FALSE;
+/** innodb_cmp_per_index_enabled; enable
+INFORMATION_SCHEMA.innodb_cmp_per_index */
+my_bool srv_cmp_per_index_enabled;
-/** Enable INFORMATION_SCHEMA.innodb_cmp_per_index */
-my_bool srv_cmp_per_index_enabled = FALSE;
-
-/* If the following is set to 1 then we do not run purge and insert buffer
+/** innodb_fast_shutdown; if 1 then we do not run purge and insert buffer
merge to completion before shutdown. If it is set to 2, do not even flush the
buffer pool to data files at the shutdown: we effectively 'crash'
InnoDB (but lose no committed transactions). */
uint srv_fast_shutdown;
-/* Generate a innodb_status.<pid> file */
-ibool srv_innodb_status = FALSE;
+/** copy of innodb_status_file; generate a innodb_status.<pid> file */
+ibool srv_innodb_status;
-/* Optimize prefix index queries to skip cluster index lookup when possible */
-/* Enables or disables this prefix optimization. Disabled by default. */
-UNIV_INTERN my_bool srv_prefix_index_cluster_optimization = 0;
+/** innodb_prefix_index_cluster_optimization; whether to optimize
+prefix index queries to skip cluster index lookup when possible */
+my_bool srv_prefix_index_cluster_optimization;
-/* When estimating number of different key values in an index, sample
+/** innodb_stats_transient_sample_pages;
+When estimating number of different key values in an index, sample
this many index pages, there are 2 ways to calculate statistics:
* persistent stats that are calculated by ANALYZE TABLE and saved
in the innodb database.
* quick transient stats, that are used if persistent stats for the given
table/index are not found in the innodb database */
-unsigned long long srv_stats_transient_sample_pages = 8;
-my_bool srv_stats_persistent = TRUE;
-unsigned long long srv_stats_persistent_sample_pages = 20;
-my_bool srv_stats_auto_recalc = TRUE;
-
-/* The number of rows modified before we calculate new statistics (default 0
-= current limits) */
-UNIV_INTERN unsigned long long srv_stats_modified_counter = 0;
-
-/* Enable traditional statistic calculation based on number of configured
-pages default true. */
-UNIV_INTERN my_bool srv_stats_sample_traditional = TRUE;
-
-ibool srv_use_doublewrite_buf = TRUE;
-
-/** doublewrite buffer is 1MB is size i.e.: it can hold 128 16K pages.
-The following parameter is the size of the buffer that is used for
-batch flushing i.e.: LRU flushing and flush_list flushing. The rest
-of the pages are used for single page flushing. */
-ulong srv_doublewrite_batch_size = 120;
-
-ulong srv_replication_delay = 0;
-
-/*-------------------------------------------*/
-UNIV_INTERN ulong srv_n_spin_wait_rounds = 15;
+unsigned long long srv_stats_transient_sample_pages;
+/** innodb_stats_persistent */
+my_bool srv_stats_persistent;
+/** innodb_stats_include_delete_marked */
+my_bool srv_stats_include_delete_marked;
+/** innodb_stats_persistent_sample_pages */
+unsigned long long srv_stats_persistent_sample_pages;
+/** innodb_stats_auto_recalc */
+my_bool srv_stats_auto_recalc;
+
+/** innodb_stats_modified_counter; The number of rows modified before
+we calculate new statistics (default 0 = current limits) */
+unsigned long long srv_stats_modified_counter;
+
+/** innodb_stats_traditional; enable traditional statistic calculation
+based on number of configured pages */
+my_bool srv_stats_sample_traditional;
+
+/** copy of innodb_doublewrite */
+ibool srv_use_doublewrite_buf;
+
+/** innodb_doublewrite_batch_size (a debug parameter) specifies the
+number of pages to use in LRU and flush_list batch flushing.
+The rest of the doublewrite buffer is used for single-page flushing. */
+ulong srv_doublewrite_batch_size = 120;
+
+/** innodb_replication_delay */
+ulong srv_replication_delay;
+
+/** innodb_sync_spin_loops */
+ulong srv_n_spin_wait_rounds;
+/** innodb_spin_wait_delay */
uint srv_spin_wait_delay;
-ibool srv_priority_boost = TRUE;
static ulint srv_n_rows_inserted_old;
static ulint srv_n_rows_updated_old;
@@ -421,23 +441,29 @@ UNIV_INTERN ib_uint64_t srv_index_page_decompressed;
/* Defragmentation */
UNIV_INTERN my_bool srv_defragment;
-UNIV_INTERN uint srv_defragment_n_pages = 7;
+/** innodb_defragment_n_pages */
+UNIV_INTERN uint srv_defragment_n_pages;
UNIV_INTERN uint srv_defragment_stats_accuracy;
-UNIV_INTERN uint srv_defragment_fill_factor_n_recs = 20;
-UNIV_INTERN double srv_defragment_fill_factor = 0.9;
-UNIV_INTERN uint srv_defragment_frequency =
- SRV_DEFRAGMENT_FREQUENCY_DEFAULT;
+/** innodb_defragment_fill_factor_n_recs */
+UNIV_INTERN uint srv_defragment_fill_factor_n_recs;
+/** innodb_defragment_fill_factor */
+UNIV_INTERN double srv_defragment_fill_factor;
+/** innodb_defragment_frequency */
+UNIV_INTERN uint srv_defragment_frequency;
+/** derived from innodb_defragment_frequency;
+@see innodb_defragment_frequency_update() */
UNIV_INTERN ulonglong srv_defragment_interval;
/* Set the following to 0 if you want InnoDB to write messages on
-stderr on startup/shutdown. */
-ibool srv_print_verbose_log = TRUE;
-my_bool srv_print_innodb_monitor = FALSE;
-my_bool srv_print_innodb_lock_monitor = FALSE;
-my_bool srv_print_innodb_tablespace_monitor = FALSE;
-my_bool srv_print_innodb_table_monitor = FALSE;
-/** If this flag is set tables without primary key are not allowed */
-my_bool srv_force_primary_key = FALSE;
+stderr on startup/shutdown. Not enabled on the embedded server. */
+ibool srv_print_verbose_log;
+my_bool srv_print_innodb_monitor;
+my_bool srv_print_innodb_lock_monitor;
+my_bool srv_print_innodb_tablespace_monitor;
+my_bool srv_print_innodb_table_monitor;
+/** innodb_force_primary_key; whether to disallow CREATE TABLE without
+PRIMARY KEY */
+my_bool srv_force_primary_key;
/* Array of English strings describing the current state of an
i/o handler thread */
@@ -470,19 +496,19 @@ ib_mutex_t srv_misc_tmpfile_mutex;
/** Temporary file for miscellanous diagnostic output */
FILE* srv_misc_tmpfile;
-static ulint srv_main_thread_process_no = 0;
-static ulint srv_main_thread_id = 0;
+static ulint srv_main_thread_process_no;
+static ulint srv_main_thread_id;
/* The following counts are used by the srv_master_thread. */
/** Iterations of the loop bounded by 'srv_active' label. */
-static ulint srv_main_active_loops = 0;
+static ulint srv_main_active_loops;
/** Iterations of the loop bounded by the 'srv_idle' label. */
-static ulint srv_main_idle_loops = 0;
+static ulint srv_main_idle_loops;
/** Iterations of the loop bounded by the 'srv_shutdown' label. */
-static ulint srv_main_shutdown_loops = 0;
+static ulint srv_main_shutdown_loops;
/** Log writes involving flush. */
-static ulint srv_log_writes_and_flush = 0;
+static ulint srv_log_writes_and_flush;
/* This is only ever touched by the master thread. It records the
time when the last flush of log file has happened. The master
@@ -503,10 +529,10 @@ current_time % 5 != 0. */
# define SRV_MASTER_DICT_LRU_INTERVAL (47)
/** Simulate compression failures. */
-UNIV_INTERN uint srv_simulate_comp_failures = 0;
+UNIV_INTERN uint srv_simulate_comp_failures;
/** Buffer pool dump status frequence in percentages */
-UNIV_INTERN ulong srv_buf_dump_status_frequency = 0;
+UNIV_INTERN ulong srv_buf_dump_status_frequency;
/** Acquire the system_mutex. */
#define srv_sys_mutex_enter() do { \
@@ -614,14 +640,16 @@ struct srv_sys_t{
ulint n_threads_active[SRV_MASTER + 1];
/*!< number of threads active
- in a thread class */
+ in a thread class; protected
+ by both my_atomic_addlint()
+ and mutex */
srv_stats_t::ulint_ctr_1_t
activity_count; /*!< For tracking server
activity */
};
-static srv_sys_t* srv_sys = NULL;
+static srv_sys_t* srv_sys;
/** Event to signal srv_monitor_thread. Not protected by a mutex.
Set after setting srv_print_innodb_monitor. */
@@ -819,7 +847,7 @@ srv_reserve_slot(
ut_ad(srv_slot_get_type(slot) == type);
- ++srv_sys->n_threads_active[type];
+ my_atomic_addlint(&srv_sys->n_threads_active[type], 1);
srv_sys_mutex_exit();
@@ -860,16 +888,15 @@ srv_suspend_thread_low(
case SRV_WORKER:
ut_a(srv_n_purge_threads > 1);
- ut_a(srv_sys->n_threads_active[type] > 0);
break;
}
ut_a(!slot->suspended);
slot->suspended = TRUE;
- ut_a(srv_sys->n_threads_active[type] > 0);
-
- srv_sys->n_threads_active[type]--;
+ if (my_atomic_addlint(&srv_sys->n_threads_active[type], -1) < 0) {
+ ut_error;
+ }
return(os_event_reset(slot->event));
}
@@ -924,7 +951,7 @@ srv_resume_thread(srv_slot_t* slot, int64_t sig_count = 0, bool wait = true,
ut_ad(slot->suspended);
slot->suspended = FALSE;
- ++srv_sys->n_threads_active[slot->type];
+ my_atomic_addlint(&srv_sys->n_threads_active[slot->type], 1);
srv_sys_mutex_exit();
return(timeout);
}
@@ -1476,7 +1503,7 @@ srv_export_innodb_status(void)
ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS));
export_vars.innodb_data_pending_writes =
- ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS));
+ ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES));
export_vars.innodb_data_pending_fsyncs =
fil_n_pending_log_flushes
@@ -2032,22 +2059,16 @@ srv_get_active_thread_type(void)
return(ret);
}
-/*******************************************************************//**
-Tells the InnoDB server that there has been activity in the database
-and wakes up the master thread if it is suspended (not sleeping). Used
-in the MySQL interface. Note that there is a small chance that the master
-thread stays suspended (we do not protect our operation with the
-srv_sys_t->mutex, for performance reasons). */
+/** Wake up the InnoDB master thread if it was suspended (not sleeping). */
void
srv_active_wake_master_thread_low()
-/*===============================*/
{
ut_ad(!srv_read_only_mode);
ut_ad(!srv_sys_mutex_own());
srv_inc_activity_count();
- if (srv_sys->n_threads_active[SRV_MASTER] == 0) {
+ if (my_atomic_loadlint(&srv_sys->n_threads_active[SRV_MASTER]) == 0) {
srv_slot_t* slot;
srv_sys_mutex_enter();
@@ -2065,35 +2086,25 @@ srv_active_wake_master_thread_low()
}
}
-/*******************************************************************//**
-Tells the purge thread that there has been activity in the database
-and wakes up the purge thread if it is suspended (not sleeping). Note
-that there is a small chance that the purge thread stays suspended
-(we do not protect our check with the srv_sys_t:mutex and the
-purge_sys->latch, for performance reasons). */
+/** Wake up the purge threads if there is work to do. */
void
-srv_wake_purge_thread_if_not_active(void)
-/*=====================================*/
+srv_wake_purge_thread_if_not_active()
{
ut_ad(!srv_sys_mutex_own());
if (purge_sys->state == PURGE_STATE_RUN
- && srv_sys->n_threads_active[SRV_PURGE] == 0) {
+ && !my_atomic_loadlint(&srv_sys->n_threads_active[SRV_PURGE])
+ && my_atomic_loadlint(&trx_sys->rseg_history_len)) {
srv_release_threads(SRV_PURGE, 1);
}
}
-/*******************************************************************//**
-Wakes up the master thread if it is suspended or being suspended. */
+/** Wake up the master thread if it is suspended or being suspended. */
void
-srv_wake_master_thread(void)
-/*========================*/
+srv_wake_master_thread()
{
- ut_ad(!srv_sys_mutex_own());
-
srv_inc_activity_count();
-
srv_release_threads(SRV_MASTER, 1);
}
@@ -2679,12 +2690,8 @@ DECLARE_THREAD(srv_worker_thread)(
slot = srv_reserve_slot(SRV_WORKER);
ut_a(srv_n_purge_threads > 1);
-
- srv_sys_mutex_enter();
-
- ut_a(srv_sys->n_threads_active[SRV_WORKER] < srv_n_purge_threads);
-
- srv_sys_mutex_exit();
+ ut_a(my_atomic_loadlint(&srv_sys->n_threads_active[SRV_WORKER])
+ < static_cast<lint>(srv_n_purge_threads));
/* We need to ensure that the worker threads exit after the
purge coordinator thread. Otherwise the purge coordinator can
@@ -2957,14 +2964,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
ut_a(srv_purge_should_exit(thd, n_total_purged));
- ulint n_pages_purged = ULINT_MAX;
-
- /* Ensure that all records are purged if it is not a fast shutdown.
- This covers the case where a record can be added after we exit the
- loop above. */
- while (srv_fast_shutdown == 0 && n_pages_purged > 0) {
- n_pages_purged = trx_purge(1, srv_purge_batch_size, false);
- }
+ /* Ensure that all records are purged on slow shutdown. */
+ while (srv_fast_shutdown == 0
+ && trx_purge(1, srv_purge_batch_size, false));
#ifdef UNIV_DEBUG
if (srv_fast_shutdown == 0) {
@@ -2978,12 +2980,10 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
delay in shutdown ,so reducing the batch size to magic number 20
(which was default in 5.5), which we hope will be sufficient to
remove all the undo records */
- const uint temp_batch_size = 20;
- n_pages_purged = trx_purge(1, srv_purge_batch_size <= temp_batch_size
- ? srv_purge_batch_size : temp_batch_size,
- true);
- ut_a(n_pages_purged == 0 || srv_fast_shutdown != 0);
+ if (trx_purge(1, std::min(srv_purge_batch_size, 20UL), true)) {
+ ut_a(srv_fast_shutdown);
+ }
/* The task queue should always be empty, independent of fast
shutdown state. */
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 9e89dfda833..6d153ff1bc6 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -121,22 +121,22 @@ lsn_t srv_start_lsn;
lsn_t srv_shutdown_lsn;
/** TRUE if a raw partition is in use */
-ibool srv_start_raw_disk_in_use = FALSE;
+ibool srv_start_raw_disk_in_use;
/** Number of IO threads to use */
-ulint srv_n_file_io_threads = 0;
+ulint srv_n_file_io_threads;
/** TRUE if the server is being started, before rolling back any
incomplete transactions */
-bool srv_startup_is_before_trx_rollback_phase = false;
+bool srv_startup_is_before_trx_rollback_phase;
/** TRUE if the server is being started */
-bool srv_is_being_started = false;
+bool srv_is_being_started;
/** TRUE if SYS_TABLESPACES is available for lookups */
-bool srv_sys_tablespaces_open = false;
+bool srv_sys_tablespaces_open;
/** TRUE if the server was successfully started */
-ibool srv_was_started = FALSE;
+bool srv_was_started;
/** TRUE if innobase_start_or_create_for_mysql() has been called */
-static ibool srv_start_has_been_called = FALSE;
+static bool srv_start_has_been_called;
#ifdef UNIV_DEBUG
/** InnoDB system tablespace to set during recovery */
UNIV_INTERN uint srv_sys_space_size_debug;
@@ -894,6 +894,7 @@ srv_undo_tablespaces_init(bool create_new_db)
}
}
} else {
+ srv_undo_tablespaces_active = srv_undo_tablespaces;
n_undo_tablespaces = srv_undo_tablespaces;
for (i = 1; i <= n_undo_tablespaces; ++i) {
@@ -975,12 +976,10 @@ srv_undo_tablespaces_init(bool create_new_db)
return(err != DB_SUCCESS ? err : DB_ERROR);
- } else if (n_undo_tablespaces > 0) {
+ } else if (n_undo_tablespaces > 0) {
ib::info() << "Opened " << n_undo_tablespaces
- << " undo tablespaces ("
- << srv_undo_tablespaces_active
- << " active)";
+ << " undo tablespaces";
if (srv_undo_tablespaces == 0) {
ib::warn() << "innodb_undo_tablespaces=0 disables"
@@ -1443,6 +1442,10 @@ innobase_start_or_create_for_mysql(void)
size_t dirnamelen;
unsigned i = 0;
+ if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) {
+ srv_read_only_mode = true;
+ }
+
high_level_read_only = srv_read_only_mode
|| srv_force_recovery > SRV_FORCE_NO_TRX_UNDO;
@@ -1519,7 +1522,7 @@ innobase_start_or_create_for_mysql(void)
" once during the process lifetime.";
}
- srv_start_has_been_called = TRUE;
+ srv_start_has_been_called = true;
srv_is_being_started = true;
@@ -2889,8 +2892,8 @@ innodb_shutdown()
}
srv_start_state = SRV_START_STATE_NONE;
- srv_was_started = FALSE;
- srv_start_has_been_called = FALSE;
+ srv_was_started = false;
+ srv_start_has_been_called = false;
}
#if 0 // TODO: Enable this in WL#6608
diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc
index 956511a7f59..75919043731 100644
--- a/storage/innobase/sync/sync0arr.cc
+++ b/storage/innobase/sync/sync0arr.cc
@@ -514,17 +514,17 @@ sync_array_cell_print(
if (mutex) {
fprintf(file,
- "Mutex at %p, %s, lock var %lu\n"
+ "Mutex at %p, %s, lock var %x\n"
#ifdef UNIV_DEBUG
- "Last time reserved in file %s line %lu"
+ "Last time reserved in file %s line %u"
#endif /* UNIV_DEBUG */
"\n",
(void*) mutex,
policy.to_string().c_str(),
- (ulong) mutex->state()
+ mutex->state()
#ifdef UNIV_DEBUG
,name,
- (ulong) policy.get_enter_line()
+ policy.get_enter_line()
#endif /* UNIV_DEBUG */
);
}
@@ -569,18 +569,18 @@ sync_array_cell_print(
if (rwlock) {
fprintf(file,
- " RW-latch at %p created in file %s line %lu\n",
+ " RW-latch at %p created in file %s line %u\n",
(void*) rwlock, innobase_basename(rwlock->cfile_name),
- (ulong) rwlock->cline);
+ rwlock->cline);
writer = rw_lock_get_writer(rwlock);
if (writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
- "a writer (thread id %lu) has"
+ "a writer (thread id " ULINTPF ") has"
" reserved it in mode %s",
- (ulong) os_thread_pf(rwlock->writer_thread),
+ os_thread_pf(rwlock->writer_thread),
writer == RW_LOCK_X ? " exclusive\n"
: writer == RW_LOCK_SX ? " SX\n"
: " wait exclusive\n");
@@ -591,21 +591,25 @@ sync_array_cell_print(
", waiters flag %u, "
"lock_word: " ULINTPFx "\n"
"Last time read locked in file %s line %u\n"
- "Last time write locked in file %s line %u\n",
+ "Last time write locked in file %s line %u"
+#if 0 /* JAN: TODO: FIX LATER */
+ "\nHolder thread " ULINTPF
+ " file %s line " ULINTPF
+#endif
+ "\n",
rw_lock_get_reader_count(rwlock),
rwlock->waiters,
rwlock->lock_word,
innobase_basename(rwlock->last_s_file_name),
rwlock->last_s_line,
- rwlock->last_x_file_name,
- rwlock->last_x_line);
-
- /* JAN: TODO: FIX LATER
- fprintf(file,
- "Holder thread %lu file %s line %lu\n",
- rwlock->thread_id, rwlock->file_name,
- rwlock->line);
- */
+ innobase_basename(rwlock->last_x_file_name),
+ rwlock->last_x_line
+#if 0 /* JAN: TODO: FIX LATER */
+ , os_thread_pf(rwlock->thread_id),
+ innobase_basename(rwlock->file_name),
+ rwlock->line
+#endif
+ );
}
} else {
diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc
index 135c84ad0d8..4fff24a77f1 100644
--- a/storage/innobase/sync/sync0debug.cc
+++ b/storage/innobase/sync/sync0debug.cc
@@ -130,7 +130,7 @@ struct LatchDebug {
os_thread_id_t,
Latches*,
os_thread_id_less,
- ut_allocator<std::pair<const std::string, latch_meta_t> > >
+ ut_allocator<std::pair<const os_thread_id_t, Latches*> > >
ThreadMap;
/** Constructor */
@@ -425,7 +425,7 @@ private:
latch_level_t,
std::string,
latch_level_less,
- ut_allocator<std::pair<latch_level_t, std::string> > >
+ ut_allocator<std::pair<const latch_level_t, std::string> > >
Levels;
/** Mutex protecting the deadlock detector data structures. */
@@ -1342,219 +1342,249 @@ sync_latch_meta_init()
/* The latches should be ordered on latch_id_t. So that we can
index directly into the vector to update and fetch meta-data. */
- LATCH_ADD(AUTOINC, SYNC_DICT_AUTOINC_MUTEX, autoinc_mutex_key);
+ LATCH_ADD_MUTEX(AUTOINC, SYNC_DICT_AUTOINC_MUTEX, autoinc_mutex_key);
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
- LATCH_ADD(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK, PFS_NOT_INSTRUMENTED);
#else
- LATCH_ADD(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK, buffer_block_mutex_key);
+ LATCH_ADD_MUTEX(BUF_BLOCK_MUTEX, SYNC_BUF_BLOCK,
+ buffer_block_mutex_key);
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
- LATCH_ADD(BUF_POOL, SYNC_BUF_POOL, buf_pool_mutex_key);
+ LATCH_ADD_MUTEX(BUF_POOL, SYNC_BUF_POOL, buf_pool_mutex_key);
- LATCH_ADD(BUF_POOL_ZIP, SYNC_BUF_BLOCK, buf_pool_zip_mutex_key);
+ LATCH_ADD_MUTEX(BUF_POOL_ZIP, SYNC_BUF_BLOCK, buf_pool_zip_mutex_key);
- LATCH_ADD(CACHE_LAST_READ, SYNC_TRX_I_S_LAST_READ,
- cache_last_read_mutex_key);
+ LATCH_ADD_MUTEX(CACHE_LAST_READ, SYNC_TRX_I_S_LAST_READ,
+ cache_last_read_mutex_key);
- LATCH_ADD(DICT_FOREIGN_ERR, SYNC_NO_ORDER_CHECK,
- dict_foreign_err_mutex_key);
+ LATCH_ADD_MUTEX(DICT_FOREIGN_ERR, SYNC_NO_ORDER_CHECK,
+ dict_foreign_err_mutex_key);
- LATCH_ADD(DICT_SYS, SYNC_DICT, dict_sys_mutex_key);
+ LATCH_ADD_MUTEX(DICT_SYS, SYNC_DICT, dict_sys_mutex_key);
- LATCH_ADD(FILE_FORMAT_MAX, SYNC_FILE_FORMAT_TAG,
- file_format_max_mutex_key);
+ LATCH_ADD_MUTEX(FILE_FORMAT_MAX, SYNC_FILE_FORMAT_TAG,
+ file_format_max_mutex_key);
- LATCH_ADD(FIL_SYSTEM, SYNC_ANY_LATCH, fil_system_mutex_key);
+ LATCH_ADD_MUTEX(FIL_SYSTEM, SYNC_ANY_LATCH, fil_system_mutex_key);
- LATCH_ADD(FLUSH_LIST, SYNC_BUF_FLUSH_LIST, flush_list_mutex_key);
+ LATCH_ADD_MUTEX(FLUSH_LIST, SYNC_BUF_FLUSH_LIST, flush_list_mutex_key);
- LATCH_ADD(FTS_BG_THREADS, SYNC_FTS_BG_THREADS,
- fts_bg_threads_mutex_key);
+ LATCH_ADD_MUTEX(FTS_BG_THREADS, SYNC_FTS_BG_THREADS,
+ fts_bg_threads_mutex_key);
- LATCH_ADD(FTS_DELETE, SYNC_FTS_OPTIMIZE, fts_delete_mutex_key);
+ LATCH_ADD_MUTEX(FTS_DELETE, SYNC_FTS_OPTIMIZE, fts_delete_mutex_key);
- LATCH_ADD(FTS_OPTIMIZE, SYNC_FTS_OPTIMIZE, fts_optimize_mutex_key);
+ LATCH_ADD_MUTEX(FTS_OPTIMIZE, SYNC_FTS_OPTIMIZE,
+ fts_optimize_mutex_key);
- LATCH_ADD(FTS_DOC_ID, SYNC_FTS_OPTIMIZE, fts_doc_id_mutex_key);
+ LATCH_ADD_MUTEX(FTS_DOC_ID, SYNC_FTS_OPTIMIZE, fts_doc_id_mutex_key);
- LATCH_ADD(FTS_PLL_TOKENIZE, SYNC_FTS_TOKENIZE,
- fts_pll_tokenize_mutex_key);
+ LATCH_ADD_MUTEX(FTS_PLL_TOKENIZE, SYNC_FTS_TOKENIZE,
+ fts_pll_tokenize_mutex_key);
- LATCH_ADD(HASH_TABLE_MUTEX, SYNC_BUF_PAGE_HASH, hash_table_mutex_key);
+ LATCH_ADD_MUTEX(HASH_TABLE_MUTEX, SYNC_BUF_PAGE_HASH,
+ hash_table_mutex_key);
- LATCH_ADD(IBUF_BITMAP, SYNC_IBUF_BITMAP_MUTEX, ibuf_bitmap_mutex_key);
+ LATCH_ADD_MUTEX(IBUF_BITMAP, SYNC_IBUF_BITMAP_MUTEX,
+ ibuf_bitmap_mutex_key);
- LATCH_ADD(IBUF, SYNC_IBUF_MUTEX, ibuf_mutex_key);
+ LATCH_ADD_MUTEX(IBUF, SYNC_IBUF_MUTEX, ibuf_mutex_key);
- LATCH_ADD(IBUF_PESSIMISTIC_INSERT, SYNC_IBUF_PESS_INSERT_MUTEX,
- ibuf_pessimistic_insert_mutex_key);
+ LATCH_ADD_MUTEX(IBUF_PESSIMISTIC_INSERT, SYNC_IBUF_PESS_INSERT_MUTEX,
+ ibuf_pessimistic_insert_mutex_key);
- LATCH_ADD(LOG_SYS, SYNC_LOG, log_sys_mutex_key);
+ LATCH_ADD_MUTEX(LOG_SYS, SYNC_LOG, log_sys_mutex_key);
- LATCH_ADD(LOG_WRITE, SYNC_LOG_WRITE, log_sys_write_mutex_key);
+ LATCH_ADD_MUTEX(LOG_WRITE, SYNC_LOG_WRITE, log_sys_write_mutex_key);
- LATCH_ADD(LOG_FLUSH_ORDER, SYNC_LOG_FLUSH_ORDER,
- log_flush_order_mutex_key);
+ LATCH_ADD_MUTEX(LOG_FLUSH_ORDER, SYNC_LOG_FLUSH_ORDER,
+ log_flush_order_mutex_key);
- LATCH_ADD(MUTEX_LIST, SYNC_NO_ORDER_CHECK, mutex_list_mutex_key);
+ LATCH_ADD_MUTEX(MUTEX_LIST, SYNC_NO_ORDER_CHECK, mutex_list_mutex_key);
- LATCH_ADD(PAGE_CLEANER, SYNC_PAGE_CLEANER, page_cleaner_mutex_key);
+ LATCH_ADD_MUTEX(PAGE_CLEANER, SYNC_PAGE_CLEANER,
+ page_cleaner_mutex_key);
- LATCH_ADD(PURGE_SYS_PQ, SYNC_PURGE_QUEUE, purge_sys_pq_mutex_key);
+ LATCH_ADD_MUTEX(PURGE_SYS_PQ, SYNC_PURGE_QUEUE,
+ purge_sys_pq_mutex_key);
- LATCH_ADD(RECALC_POOL, SYNC_STATS_AUTO_RECALC,
- recalc_pool_mutex_key);
+ LATCH_ADD_MUTEX(RECALC_POOL, SYNC_STATS_AUTO_RECALC,
+ recalc_pool_mutex_key);
- LATCH_ADD(RECV_SYS, SYNC_RECV, recv_sys_mutex_key);
+ LATCH_ADD_MUTEX(RECV_SYS, SYNC_RECV, recv_sys_mutex_key);
- LATCH_ADD(RECV_WRITER, SYNC_RECV_WRITER, recv_writer_mutex_key);
+ LATCH_ADD_MUTEX(RECV_WRITER, SYNC_RECV_WRITER, recv_writer_mutex_key);
- LATCH_ADD(REDO_RSEG, SYNC_REDO_RSEG, redo_rseg_mutex_key);
+ LATCH_ADD_MUTEX(REDO_RSEG, SYNC_REDO_RSEG, redo_rseg_mutex_key);
- LATCH_ADD(NOREDO_RSEG, SYNC_NOREDO_RSEG, noredo_rseg_mutex_key);
+ LATCH_ADD_MUTEX(NOREDO_RSEG, SYNC_NOREDO_RSEG, noredo_rseg_mutex_key);
#ifdef UNIV_DEBUG
/* Mutex names starting with '.' are not tracked. They are assumed
to be diagnostic mutexes used in debugging. */
latch_meta[LATCH_ID_RW_LOCK_DEBUG] =
- LATCH_ADD(RW_LOCK_DEBUG,
+ LATCH_ADD_MUTEX(RW_LOCK_DEBUG,
SYNC_NO_ORDER_CHECK,
rw_lock_debug_mutex_key);
#endif /* UNIV_DEBUG */
- LATCH_ADD(RTR_SSN_MUTEX, SYNC_ANY_LATCH, rtr_ssn_mutex_key);
+ LATCH_ADD_MUTEX(RTR_SSN_MUTEX, SYNC_ANY_LATCH, rtr_ssn_mutex_key);
- LATCH_ADD(RTR_ACTIVE_MUTEX, SYNC_ANY_LATCH, rtr_active_mutex_key);
+ LATCH_ADD_MUTEX(RTR_ACTIVE_MUTEX, SYNC_ANY_LATCH,
+ rtr_active_mutex_key);
- LATCH_ADD(RTR_MATCH_MUTEX, SYNC_ANY_LATCH, rtr_match_mutex_key);
+ LATCH_ADD_MUTEX(RTR_MATCH_MUTEX, SYNC_ANY_LATCH, rtr_match_mutex_key);
- LATCH_ADD(RTR_PATH_MUTEX, SYNC_ANY_LATCH, rtr_path_mutex_key);
+ LATCH_ADD_MUTEX(RTR_PATH_MUTEX, SYNC_ANY_LATCH, rtr_path_mutex_key);
- LATCH_ADD(RW_LOCK_LIST, SYNC_NO_ORDER_CHECK, rw_lock_list_mutex_key);
+ LATCH_ADD_MUTEX(RW_LOCK_LIST, SYNC_NO_ORDER_CHECK,
+ rw_lock_list_mutex_key);
- LATCH_ADD(RW_LOCK_MUTEX, SYNC_NO_ORDER_CHECK, rw_lock_mutex_key);
+ LATCH_ADD_MUTEX(RW_LOCK_MUTEX, SYNC_NO_ORDER_CHECK, rw_lock_mutex_key);
- LATCH_ADD(SRV_DICT_TMPFILE, SYNC_DICT_OPERATION,
- srv_dict_tmpfile_mutex_key);
+ LATCH_ADD_MUTEX(SRV_DICT_TMPFILE, SYNC_DICT_OPERATION,
+ srv_dict_tmpfile_mutex_key);
- LATCH_ADD(SRV_INNODB_MONITOR, SYNC_NO_ORDER_CHECK,
- srv_innodb_monitor_mutex_key);
+ LATCH_ADD_MUTEX(SRV_INNODB_MONITOR, SYNC_NO_ORDER_CHECK,
+ srv_innodb_monitor_mutex_key);
- LATCH_ADD(SRV_MISC_TMPFILE, SYNC_ANY_LATCH,
- srv_misc_tmpfile_mutex_key);
+ LATCH_ADD_MUTEX(SRV_MISC_TMPFILE, SYNC_ANY_LATCH,
+ srv_misc_tmpfile_mutex_key);
- LATCH_ADD(SRV_MONITOR_FILE, SYNC_NO_ORDER_CHECK,
- srv_monitor_file_mutex_key);
+ LATCH_ADD_MUTEX(SRV_MONITOR_FILE, SYNC_NO_ORDER_CHECK,
+ srv_monitor_file_mutex_key);
#ifdef UNIV_DEBUG
- LATCH_ADD(SYNC_THREAD, SYNC_NO_ORDER_CHECK, sync_thread_mutex_key);
+ LATCH_ADD_MUTEX(SYNC_THREAD, SYNC_NO_ORDER_CHECK,
+ sync_thread_mutex_key);
#endif /* UNIV_DEBUG */
- LATCH_ADD(BUF_DBLWR, SYNC_DOUBLEWRITE, buf_dblwr_mutex_key);
+ LATCH_ADD_MUTEX(BUF_DBLWR, SYNC_DOUBLEWRITE, buf_dblwr_mutex_key);
- LATCH_ADD(TRX_UNDO, SYNC_TRX_UNDO, trx_undo_mutex_key);
+ LATCH_ADD_MUTEX(TRX_UNDO, SYNC_TRX_UNDO, trx_undo_mutex_key);
- LATCH_ADD(TRX_POOL, SYNC_POOL, trx_pool_mutex_key);
+ LATCH_ADD_MUTEX(TRX_POOL, SYNC_POOL, trx_pool_mutex_key);
- LATCH_ADD(TRX_POOL_MANAGER, SYNC_POOL_MANAGER,
- trx_pool_manager_mutex_key);
+ LATCH_ADD_MUTEX(TRX_POOL_MANAGER, SYNC_POOL_MANAGER,
+ trx_pool_manager_mutex_key);
- LATCH_ADD(TRX, SYNC_TRX, trx_mutex_key);
+ LATCH_ADD_MUTEX(TRX, SYNC_TRX, trx_mutex_key);
- LATCH_ADD(LOCK_SYS, SYNC_LOCK_SYS, lock_mutex_key);
+ LATCH_ADD_MUTEX(LOCK_SYS, SYNC_LOCK_SYS, lock_mutex_key);
- LATCH_ADD(LOCK_SYS_WAIT, SYNC_LOCK_WAIT_SYS, lock_wait_mutex_key);
+ LATCH_ADD_MUTEX(LOCK_SYS_WAIT, SYNC_LOCK_WAIT_SYS,
+ lock_wait_mutex_key);
- LATCH_ADD(TRX_SYS, SYNC_TRX_SYS, trx_sys_mutex_key);
+ LATCH_ADD_MUTEX(TRX_SYS, SYNC_TRX_SYS, trx_sys_mutex_key);
- LATCH_ADD(SRV_SYS, SYNC_THREADS, srv_sys_mutex_key);
+ LATCH_ADD_MUTEX(SRV_SYS, SYNC_THREADS, srv_sys_mutex_key);
- LATCH_ADD(SRV_SYS_TASKS, SYNC_ANY_LATCH, srv_threads_mutex_key);
+ LATCH_ADD_MUTEX(SRV_SYS_TASKS, SYNC_ANY_LATCH, srv_threads_mutex_key);
- LATCH_ADD(PAGE_ZIP_STAT_PER_INDEX, SYNC_ANY_LATCH,
- page_zip_stat_per_index_mutex_key);
+ LATCH_ADD_MUTEX(PAGE_ZIP_STAT_PER_INDEX, SYNC_ANY_LATCH,
+ page_zip_stat_per_index_mutex_key);
#ifndef PFS_SKIP_EVENT_MUTEX
- LATCH_ADD(EVENT_MANAGER, SYNC_NO_ORDER_CHECK, event_manager_mutex_key);
+ LATCH_ADD_MUTEX(EVENT_MANAGER, SYNC_NO_ORDER_CHECK,
+ event_manager_mutex_key);
#else
- LATCH_ADD(EVENT_MANAGER, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(EVENT_MANAGER, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
#endif /* !PFS_SKIP_EVENT_MUTEX */
- LATCH_ADD(EVENT_MUTEX, SYNC_NO_ORDER_CHECK, event_mutex_key);
+ LATCH_ADD_MUTEX(EVENT_MUTEX, SYNC_NO_ORDER_CHECK, event_mutex_key);
- LATCH_ADD(SYNC_ARRAY_MUTEX, SYNC_NO_ORDER_CHECK,
- sync_array_mutex_key);
+ LATCH_ADD_MUTEX(SYNC_ARRAY_MUTEX, SYNC_NO_ORDER_CHECK,
+ sync_array_mutex_key);
- LATCH_ADD(THREAD_MUTEX, SYNC_NO_ORDER_CHECK, thread_mutex_key);
+ LATCH_ADD_MUTEX(THREAD_MUTEX, SYNC_NO_ORDER_CHECK, thread_mutex_key);
- LATCH_ADD(ZIP_PAD_MUTEX, SYNC_NO_ORDER_CHECK, zip_pad_mutex_key);
+ LATCH_ADD_MUTEX(ZIP_PAD_MUTEX, SYNC_NO_ORDER_CHECK, zip_pad_mutex_key);
- LATCH_ADD(OS_AIO_READ_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(OS_AIO_READ_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
- LATCH_ADD(OS_AIO_WRITE_MUTEX, SYNC_NO_ORDER_CHECK,
- PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(OS_AIO_WRITE_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
- LATCH_ADD(OS_AIO_LOG_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(OS_AIO_LOG_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
- LATCH_ADD(OS_AIO_IBUF_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(OS_AIO_IBUF_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
- LATCH_ADD(OS_AIO_SYNC_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(OS_AIO_SYNC_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
- LATCH_ADD(ROW_DROP_LIST, SYNC_NO_ORDER_CHECK, row_drop_list_mutex_key);
+ LATCH_ADD_MUTEX(ROW_DROP_LIST, SYNC_NO_ORDER_CHECK,
+ row_drop_list_mutex_key);
- LATCH_ADD(INDEX_ONLINE_LOG, SYNC_INDEX_ONLINE_LOG,
- index_online_log_key);
+ LATCH_ADD_MUTEX(INDEX_ONLINE_LOG, SYNC_INDEX_ONLINE_LOG,
+ index_online_log_key);
- LATCH_ADD(WORK_QUEUE, SYNC_WORK_QUEUE, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(WORK_QUEUE, SYNC_WORK_QUEUE, PFS_NOT_INSTRUMENTED);
// Add the RW locks
- LATCH_ADD(BTR_SEARCH, SYNC_SEARCH_SYS, btr_search_latch_key);
+ LATCH_ADD_RWLOCK(BTR_SEARCH, SYNC_SEARCH_SYS, btr_search_latch_key);
- LATCH_ADD(BUF_BLOCK_LOCK, SYNC_LEVEL_VARYING, buf_block_lock_key);
+ LATCH_ADD_RWLOCK(BUF_BLOCK_LOCK, SYNC_LEVEL_VARYING,
+ buf_block_lock_key);
#ifdef UNIV_DEBUG
- LATCH_ADD(BUF_BLOCK_DEBUG, SYNC_NO_ORDER_CHECK,
- buf_block_debug_latch_key);
+ LATCH_ADD_RWLOCK(BUF_BLOCK_DEBUG, SYNC_NO_ORDER_CHECK,
+ buf_block_debug_latch_key);
#endif /* UNIV_DEBUG */
- LATCH_ADD(DICT_OPERATION, SYNC_DICT, dict_operation_lock_key);
+ LATCH_ADD_RWLOCK(DICT_OPERATION, SYNC_DICT, dict_operation_lock_key);
- LATCH_ADD(CHECKPOINT, SYNC_NO_ORDER_CHECK, checkpoint_lock_key);
+ LATCH_ADD_RWLOCK(CHECKPOINT, SYNC_NO_ORDER_CHECK, checkpoint_lock_key);
- LATCH_ADD(FIL_SPACE, SYNC_FSP, fil_space_latch_key);
+ LATCH_ADD_RWLOCK(FIL_SPACE, SYNC_FSP, fil_space_latch_key);
- LATCH_ADD(FTS_CACHE, SYNC_FTS_CACHE, fts_cache_rw_lock_key);
+ LATCH_ADD_RWLOCK(FTS_CACHE, SYNC_FTS_CACHE, fts_cache_rw_lock_key);
- LATCH_ADD(FTS_CACHE_INIT, SYNC_FTS_CACHE_INIT,
- fts_cache_init_rw_lock_key);
+ LATCH_ADD_RWLOCK(FTS_CACHE_INIT, SYNC_FTS_CACHE_INIT,
+ fts_cache_init_rw_lock_key);
- LATCH_ADD(TRX_I_S_CACHE, SYNC_TRX_I_S_RWLOCK, trx_i_s_cache_lock_key);
+ LATCH_ADD_RWLOCK(TRX_I_S_CACHE, SYNC_TRX_I_S_RWLOCK,
+ trx_i_s_cache_lock_key);
- LATCH_ADD(TRX_PURGE, SYNC_PURGE_LATCH, trx_purge_latch_key);
+ LATCH_ADD_RWLOCK(TRX_PURGE, SYNC_PURGE_LATCH, trx_purge_latch_key);
- LATCH_ADD(IBUF_INDEX_TREE, SYNC_IBUF_INDEX_TREE,
- index_tree_rw_lock_key);
+ LATCH_ADD_RWLOCK(IBUF_INDEX_TREE, SYNC_IBUF_INDEX_TREE,
+ index_tree_rw_lock_key);
- LATCH_ADD(INDEX_TREE, SYNC_INDEX_TREE, index_tree_rw_lock_key);
+ LATCH_ADD_RWLOCK(INDEX_TREE, SYNC_INDEX_TREE, index_tree_rw_lock_key);
- LATCH_ADD(DICT_TABLE_STATS, SYNC_INDEX_TREE, dict_table_stats_key);
+ LATCH_ADD_RWLOCK(DICT_TABLE_STATS, SYNC_INDEX_TREE,
+ dict_table_stats_key);
- LATCH_ADD(HASH_TABLE_RW_LOCK, SYNC_BUF_PAGE_HASH,
+ LATCH_ADD_RWLOCK(HASH_TABLE_RW_LOCK, SYNC_BUF_PAGE_HASH,
hash_table_locks_key);
- LATCH_ADD(SYNC_DEBUG_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(SYNC_DEBUG_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
/* JAN: TODO: Add PFS instrumentation */
- LATCH_ADD(SCRUB_STAT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(BTR_DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(MTFLUSH_THREAD_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(MTFLUSH_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(FIL_CRYPT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(FIL_CRYPT_STAT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(FIL_CRYPT_DATA_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
- LATCH_ADD(FIL_CRYPT_THREADS_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(SCRUB_STAT_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(BTR_DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(MTFLUSH_THREAD_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(MTFLUSH_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(FIL_CRYPT_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(FIL_CRYPT_STAT_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(FIL_CRYPT_DATA_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
+ LATCH_ADD_MUTEX(FIL_CRYPT_THREADS_MUTEX, SYNC_NO_ORDER_CHECK,
+ PFS_NOT_INSTRUMENTED);
latch_id_t id = LATCH_ID_NONE;
@@ -1717,7 +1747,7 @@ private:
const void*,
File,
std::less<const void*>,
- ut_allocator<std::pair<const void*, File> > >
+ ut_allocator<std::pair<const void* const, File> > >
Files;
typedef OSMutex Mutex;
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index f83d9377852..b21ec75c3a6 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2017, MariaDB Corporation.
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
@@ -291,7 +291,6 @@ trx_purge_add_update_undo_to_history(
undo_header + TRX_UNDO_HISTORY_NODE, mtr);
my_atomic_addlint(&trx_sys->rseg_history_len, 1);
- srv_wake_purge_thread_if_not_active();
/* Write the trx number to the undo log header */
mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
@@ -987,27 +986,20 @@ trx_purge_initiate_truncate(
initiate truncate.
d. Execute actual truncate
e. Remove the DDL log. */
- DBUG_EXECUTE_IF("ib_undo_trunc_before_checkpoint",
- ib::info() << "ib_undo_trunc_before_checkpoint";
- DBUG_SUICIDE(););
/* After truncate if server crashes then redo logging done for this
undo tablespace might not stand valid as tablespace has been
truncated. */
log_make_checkpoint_at(LSN_MAX, TRUE);
- ib::info() << "Truncating UNDO tablespace with space identifier "
- << undo_trunc->get_marked_space_id();
+ const ulint space_id = undo_trunc->get_marked_space_id();
- DBUG_EXECUTE_IF("ib_undo_trunc_before_ddl_log_start",
- ib::info() << "ib_undo_trunc_before_ddl_log_start";
- DBUG_SUICIDE(););
+ ib::info() << "Truncating UNDO tablespace " << space_id;
#ifdef UNIV_DEBUG
dberr_t err =
#endif /* UNIV_DEBUG */
- undo_trunc->start_logging(
- undo_trunc->get_marked_space_id());
+ undo_trunc->start_logging(space_id);
ut_ad(err == DB_SUCCESS);
DBUG_EXECUTE_IF("ib_undo_trunc_before_truncate",
@@ -1016,14 +1008,12 @@ trx_purge_initiate_truncate(
trx_purge_cleanse_purge_queue(undo_trunc);
- bool success = trx_undo_truncate_tablespace(undo_trunc);
- if (!success) {
+ if (!trx_undo_truncate_tablespace(undo_trunc)) {
/* Note: In case of error we don't enable the rsegs
and neither unmark the tablespace so the tablespace
continue to remain inactive. */
- ib::error() << "Failed to truncate UNDO tablespace with"
- " space identifier "
- << undo_trunc->get_marked_space_id();
+ ib::error() << "Failed to truncate UNDO tablespace "
+ << space_id;
return;
}
@@ -1046,7 +1036,7 @@ trx_purge_initiate_truncate(
log_make_checkpoint_at(LSN_MAX, TRUE);
- undo_trunc->done_logging(undo_trunc->get_marked_space_id());
+ undo_trunc->done_logging(space_id);
/* Completed truncate. Now it is safe to re-use the tablespace. */
for (ulint i = 0; i < undo_trunc->rsegs_size(); ++i) {
@@ -1054,8 +1044,7 @@ trx_purge_initiate_truncate(
rseg->skip_allocation = false;
}
- ib::info() << "Completed truncate of UNDO tablespace with space"
- " identifier " << undo_trunc->get_marked_space_id();
+ ib::info() << "Truncated UNDO tablespace " << space_id;
undo_trunc->reset();
undo::Truncate::clear_trunc_list();
@@ -1075,7 +1064,7 @@ trx_purge_truncate_history(
purge_iter_t* limit, /*!< in: truncate limit */
const ReadView* view) /*!< in: purge view */
{
- ulint i;
+ ut_ad(trx_purge_check_limit());
/* We play safe and set the truncate limit at most to the purge view
low_limit number, though this is not necessary */
@@ -1088,7 +1077,7 @@ trx_purge_truncate_history(
ut_ad(limit->trx_no <= purge_sys->view.low_limit_no());
- for (i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
trx_rseg_t* rseg = trx_sys->rseg_array[i];
if (rseg != NULL) {
@@ -1100,8 +1089,7 @@ trx_purge_truncate_history(
/* UNDO tablespace truncate. We will try to truncate as much as we
can (greedy approach). This will ensure when the server is idle we
try and truncate all the UNDO tablespaces. */
- ulint nchances = srv_undo_tablespaces_active;
- for (i = 0; i < nchances; i++) {
+ for (ulint i = srv_undo_tablespaces_active; i--; ) {
trx_purge_mark_undo_for_truncate(&purge_sys->undo_trunc);
trx_purge_initiate_truncate(limit, &purge_sys->undo_trunc);
}
@@ -1638,22 +1626,6 @@ trx_purge_wait_for_workers_to_complete(
ut_a(srv_get_task_queue_length() == 0);
}
-/******************************************************************//**
-Remove old historical changes from the rollback segments. */
-static
-void
-trx_purge_truncate(void)
-/*====================*/
-{
- ut_ad(trx_purge_check_limit());
-
- if (purge_sys->limit.trx_no == 0) {
- trx_purge_truncate_history(&purge_sys->iter, &purge_sys->view);
- } else {
- trx_purge_truncate_history(&purge_sys->limit, &purge_sys->view);
- }
-}
-
/*******************************************************************//**
This function runs a purge batch.
@return number of undo log pages handled in the batch */
@@ -1742,7 +1714,11 @@ run_synchronously:
#endif /* UNIV_DEBUG */
if (truncate) {
- trx_purge_truncate();
+ trx_purge_truncate_history(
+ purge_sys->limit.trx_no
+ ? &purge_sys->limit
+ : &purge_sys->iter,
+ &purge_sys->view);
}
MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index ec723375fe9..69f01e64b59 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/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
@@ -868,6 +868,8 @@ 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
@@ -878,6 +880,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/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 3393a0464a8..663566cf26f 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -204,7 +204,7 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
len = flst_get_len(rseg_header + TRX_RSEG_HISTORY);
if (len > 0) {
- trx_sys->rseg_history_len += len;
+ my_atomic_addlint(&trx_sys->rseg_history_len, len);
node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 19d4a228eda..47f30138ceb 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -446,7 +446,6 @@ trx_sysf_create(
page_t* page;
ulint page_no;
byte* ptr;
- ulint len;
ut_ad(mtr);
@@ -481,13 +480,12 @@ trx_sysf_create(
mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE, 1);
/* Reset the rollback segment slots. Old versions of InnoDB
- define TRX_SYS_N_RSEGS as 256 (TRX_SYS_OLD_N_RSEGS) and expect
+ (before MySQL 5.5) define TRX_SYS_N_RSEGS as 256 and expect
that the whole array is initialized. */
ptr = TRX_SYS_RSEGS + sys_header;
- len = ut_max(TRX_SYS_OLD_N_RSEGS, TRX_SYS_N_RSEGS)
- * TRX_SYS_RSEG_SLOT_SIZE;
- memset(ptr, 0xff, len);
- ptr += len;
+ compile_time_assert(256 >= TRX_SYS_N_RSEGS);
+ memset(ptr, 0xff, 256 * TRX_SYS_RSEG_SLOT_SIZE);
+ ptr += 256 * TRX_SYS_RSEG_SLOT_SIZE;
ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));
/* Initialize all of the page. This part used to be uninitialized. */
@@ -881,7 +879,7 @@ trx_sys_create_rsegs()
srv_undo_logs determines how many of the
srv_available_undo_logs rollback segments may be used for
logging new transactions. */
- ut_ad(srv_undo_tablespaces < TRX_SYS_N_RSEGS);
+ ut_ad(srv_undo_tablespaces <= TRX_SYS_MAX_UNDO_SPACES);
ut_ad(srv_undo_logs <= TRX_SYS_N_RSEGS);
if (srv_read_only_mode) {
@@ -923,13 +921,28 @@ trx_sys_create_rsegs()
" requested innodb_undo_logs";
return(false);
}
+
+ /* Increase the number of active undo
+ tablespace in case new rollback segment
+ assigned to new undo tablespace. */
+ if (space > srv_undo_tablespaces_active) {
+ srv_undo_tablespaces_active++;
+
+ ut_ad(srv_undo_tablespaces_active == space);
+ }
}
}
ut_ad(srv_undo_logs <= srv_available_undo_logs);
- ib::info() << srv_undo_logs << " out of " << srv_available_undo_logs
- << " rollback segments are active.";
+ ib::info info;
+ info << srv_undo_logs << " out of " << srv_available_undo_logs;
+ if (srv_undo_tablespaces_active) {
+ info << " rollback segments in " << srv_undo_tablespaces_active
+ << " undo tablespaces are active.";
+ } else {
+ info << " rollback segments are active.";
+ }
return(true);
}
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 36324c43970..a6cfcf0910b 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1908,6 +1908,7 @@ trx_commit_in_memory(
trx_mutex_exit(trx);
ut_a(trx->error_state == DB_SUCCESS);
+ srv_wake_purge_thread_if_not_active();
}
/****************************************************************//**
@@ -2455,6 +2456,121 @@ trx_print_latched(
mem_heap_get_size(trx->lock.lock_heap));
}
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+ FILE* f,
+ /*!< in: output stream */
+ const trx_t* trx,
+ /*!< in: transaction */
+ ulint max_query_len)
+ /*!< in: max query length to print,
+ or 0 to use the default max length */
+{
+ ibool newline;
+ const char* op_info;
+
+ ut_ad(lock_mutex_own());
+ ut_ad(trx->lock.trx_locks.count > 0);
+
+ fprintf(f, "TRANSACTION " TRX_ID_FMT, trx->id);
+
+ /* trx->state may change since trx_sys->mutex is not required */
+ switch (trx->state) {
+ case TRX_STATE_NOT_STARTED:
+ fputs(", not started", f);
+ goto state_ok;
+ case TRX_STATE_ACTIVE:
+ fprintf(f, ", ACTIVE %lu sec",
+ (ulong) difftime(time(NULL), trx->start_time));
+ goto state_ok;
+ case TRX_STATE_FORCED_ROLLBACK:
+ fprintf(f, ", FORCED ROLLBACK, %lu sec",
+ (ulong) difftime(time(NULL), trx->start_time));
+ goto state_ok;
+ case TRX_STATE_PREPARED:
+ fprintf(f, ", ACTIVE (PREPARED) %lu sec",
+ (ulong) difftime(time(NULL), trx->start_time));
+ goto state_ok;
+ case TRX_STATE_COMMITTED_IN_MEMORY:
+ fputs(", COMMITTED IN MEMORY", f);
+ goto state_ok;
+ }
+ fprintf(f, ", state %lu", (ulong) trx->state);
+ ut_ad(0);
+state_ok:
+
+ /* prevent a race condition */
+ op_info = trx->op_info;
+
+ if (*op_info) {
+ putc(' ', f);
+ fputs(op_info, f);
+ }
+
+ if (trx->is_recovered) {
+ fputs(" recovered trx", f);
+ }
+
+ if (trx->declared_to_be_inside_innodb) {
+ fprintf(f, ", thread declared inside InnoDB %lu",
+ (ulong) trx->n_tickets_to_enter_innodb);
+ }
+
+ putc('\n', f);
+
+ if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) {
+ fprintf(f, "mysql tables in use %lu, locked %lu\n",
+ (ulong) trx->n_mysql_tables_in_use,
+ (ulong) trx->mysql_n_tables_locked);
+ }
+
+ newline = TRUE;
+
+ /* trx->lock.que_state of an ACTIVE transaction may change
+ while we are not holding trx->mutex. We perform a dirty read
+ for performance reasons. */
+
+ switch (trx->lock.que_state) {
+ case TRX_QUE_RUNNING:
+ newline = FALSE; break;
+ case TRX_QUE_LOCK_WAIT:
+ fputs("LOCK WAIT ", f); break;
+ case TRX_QUE_ROLLING_BACK:
+ fputs("ROLLING BACK ", f); break;
+ case TRX_QUE_COMMITTING:
+ fputs("COMMITTING ", f); break;
+ default:
+ fprintf(f, "que state %lu ", (ulong) trx->lock.que_state);
+ }
+
+ if (trx->has_search_latch) {
+ newline = TRUE;
+ fputs(", holds adaptive hash latch", f);
+ }
+
+ if (trx->undo_no != 0) {
+ newline = TRUE;
+ fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no);
+ }
+
+ if (newline) {
+ putc('\n', f);
+ }
+
+ if (trx->mysql_thd != NULL) {
+ innobase_mysql_print_thd(
+ f, trx->mysql_thd, static_cast<uint>(max_query_len));
+ }
+}
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */
diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt
index 3223e084709..d72b4e54e43 100644
--- a/storage/rocksdb/CMakeLists.txt
+++ b/storage/rocksdb/CMakeLists.txt
@@ -22,6 +22,13 @@ IF(CMAKE_SYSTEM_PROCESSOR MATCHES "i[36]86")
SKIP_ROCKSDB_PLUGIN("Intel 32 bit not supported.")
ENDIF()
+# Due to retrieved data being incorrect endian
+include(TestBigEndian)
+test_big_endian(BIG_ENDIAN)
+if(BIG_ENDIAN)
+ SKIP_ROCKSDB_PLUGIN("Big Endian not supported.")
+endif()
+
#
# Also, disable building on 32-bit Windows
#
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index a87abfb8073..7ed8661cc74 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -2109,6 +2109,7 @@ int ha_spider::index_read_map_internal(
result_list.desc_flg = FALSE;
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -2624,6 +2625,7 @@ int ha_spider::index_read_last_map_internal(
result_list.desc_flg = TRUE;
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3089,6 +3091,7 @@ int ha_spider::index_first_internal(
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
result_list.key_order = 0;
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3472,6 +3475,7 @@ int ha_spider::index_last_internal(
result_list.sorted = TRUE;
result_list.key_info = &table->key_info[active_index];
result_list.key_order = 0;
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -3914,6 +3918,7 @@ int ha_spider::read_range_first_internal(
result_list.desc_flg = FALSE;
result_list.sorted = sorted;
result_list.key_info = &table->key_info[active_index];
+ check_distinct_key_query();
result_list.limit_num =
result_list.internal_limit >= result_list.split_read ?
result_list.split_read : result_list.internal_limit;
@@ -12078,6 +12083,81 @@ void ha_spider::check_direct_order_limit()
DBUG_VOID_RETURN;
}
+/********************************************************************
+ * Check whether the current query is a SELECT DISTINCT using an
+ * index in a non-partitioned Spider configuration, with a
+ * projection list that consists solely of the first key prefix
+ * column.
+ *
+ * For a SELECT DISTINCT query using an index in a non-partitioned
+ * Spider configuration, with a projection list that consists
+ * solely of the first key prefix, set the internal row retrieval
+ * limit to avoid visiting each row multiple times.
+ ********************************************************************/
+void ha_spider::check_distinct_key_query()
+{
+ DBUG_ENTER( "ha_spider::check_distinct_key_query" );
+
+ if ( result_list.direct_distinct && !partition_handler_share->handlers &&
+ result_list.keyread && result_list.check_direct_order_limit )
+ {
+ // SELECT DISTINCT query using an index in a non-partitioned configuration
+ KEY_PART_INFO* key_part = result_list.key_info->key_part;
+ Field* key_field = key_part->field;
+
+ if ( is_sole_projection_field( key_field->field_index ) )
+ {
+ // Projection list consists solely of the first key prefix column
+
+ // Set the internal row retrieval limit to avoid visiting each row
+ // multiple times. This fixes a Spider performance bug that
+ // caused each row to be visited multiple times.
+ result_list.internal_limit = 1;
+ }
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool ha_spider::is_sole_projection_field( uint16 field_index )
+{
+ // NOTE: It is assumed that spider_db_append_select_columns() has already been called
+ // to build the bitmap of projection fields
+ bool is_ha_sole_projection_field;
+ uint loop_index, dbton_id;
+ spider_db_handler* dbton_hdl;
+ DBUG_ENTER( "ha_spider::is_sole_projection_field" );
+
+ for ( loop_index = 0; loop_index < share->use_sql_dbton_count; loop_index++ )
+ {
+ dbton_id = share->use_sql_dbton_ids[ loop_index ];
+ dbton_hdl = dbton_handler[ dbton_id ];
+
+ if ( dbton_hdl->first_link_idx >= 0 )
+ {
+ is_ha_sole_projection_field = dbton_hdl->is_sole_projection_field( field_index );
+ if ( !is_ha_sole_projection_field )
+ {
+ DBUG_RETURN( FALSE );
+ }
+ }
+ }
+
+ DBUG_RETURN( TRUE );
+}
+
int ha_spider::check_ha_range_eof()
{
DBUG_ENTER("ha_spider::check_ha_range_eof");
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index bd02e34043d..87c6afaa89f 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -751,6 +751,8 @@ public:
);
uint check_partitioned();
void check_direct_order_limit();
+ void check_distinct_key_query();
+ bool is_sole_projection_field( uint16 field_index );
int check_ha_range_eof();
int drop_tmp_tables();
bool handler_opened(
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index 8f031acdbde..51b1d1f1752 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -4994,6 +4994,15 @@ int spider_handlersocket_handler::append_explain_select_part(
DBUG_RETURN(0);
}
+int spider_handlersocket_handler::is_sole_projection_field(
+ uint16 field_index
+) {
+ DBUG_ENTER("spider_handlersocket_handler::is_sole_projection_field");
+ DBUG_PRINT("info", ("spider this=%p", this));
+ DBUG_ASSERT(0);
+ DBUG_RETURN(0);
+}
+
bool spider_handlersocket_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h
index d3fdf5564b7..a3955aea044 100644
--- a/storage/spider/spd_db_handlersocket.h
+++ b/storage/spider/spd_db_handlersocket.h
@@ -776,6 +776,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index 936951d3860..56bc2ccad42 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -1279,6 +1279,9 @@ public:
ulong sql_type,
int link_idx
) = 0;
+ virtual bool is_sole_projection_field(
+ uint16 field_index
+ ) = 0;
virtual bool is_bulk_insert_exec_period(
bool bulk_end
) = 0;
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index f902508e9c4..385b122c274 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -9516,6 +9516,65 @@ int spider_mysql_handler::append_explain_select(
DBUG_RETURN(0);
}
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool spider_mysql_handler::is_sole_projection_field( uint16 field_index )
+{
+ // Determine whether the projection list consists solely of the field of interest
+ bool is_field_in_projection_list = FALSE;
+ TABLE* table = spider->get_table();
+ uint16 projection_field_count = 0;
+ uint16 projection_field_index;
+ Field** field;
+ DBUG_ENTER( "spider_mysql_handler::is_sole_projection_field" );
+
+ for ( field = table->field; *field ; field++ )
+ {
+ projection_field_index = ( *field )->field_index;
+
+ if ( !( minimum_select_bit_is_set( projection_field_index ) ) )
+ {
+ // Current field is not in the projection list
+ continue;
+ }
+
+ projection_field_count++;
+
+ if ( !is_field_in_projection_list )
+ {
+ if ( field_index == projection_field_index )
+ {
+ // Field of interest is in the projection list
+ is_field_in_projection_list = TRUE;
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count != 1 ) )
+ {
+ // Field of interest is not the sole column in the projection list
+ DBUG_RETURN( FALSE );
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count == 1 ) )
+ {
+ // Field of interest is the only column in the projection list
+ DBUG_RETURN( TRUE );
+ }
+
+ DBUG_RETURN( FALSE );
+}
+
bool spider_mysql_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
index 9a4f08ade98..482289d1d68 100644
--- a/storage/spider/spd_db_mysql.h
+++ b/storage/spider/spd_db_mysql.h
@@ -1128,6 +1128,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index 5e6c89b10d0..5b322b9c4d7 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -9571,6 +9571,65 @@ int spider_oracle_handler::append_explain_select(
DBUG_RETURN(0);
}
+/********************************************************************
+ * Determine whether the current query's projection list
+ * consists solely of the specified column.
+ *
+ * Params IN - field_index:
+ * Field index of the column of interest within
+ * its table.
+ *
+ * Returns TRUE - if the query's projection list consists
+ * solely of the specified column.
+ * FALSE - otherwise.
+ ********************************************************************/
+bool spider_oracle_handler::is_sole_projection_field( uint16 field_index )
+{
+ // Determine whether the projection list consists solely of the field of interest
+ bool is_field_in_projection_list = FALSE;
+ TABLE* table = spider->get_table();
+ uint16 projection_field_count = 0;
+ uint16 projection_field_index;
+ Field** field;
+ DBUG_ENTER( "spider_oracle_handler::is_sole_projection_field" );
+
+ for ( field = table->field; *field; field++ )
+ {
+ projection_field_index = ( *field )->field_index;
+
+ if ( !( minimum_select_bit_is_set( projection_field_index ) ) )
+ {
+ // Current field is not in the projection list
+ continue;
+ }
+
+ projection_field_count++;
+
+ if ( !is_field_in_projection_list )
+ {
+ if (field_index == projection_field_index)
+ {
+ // Field of interest is in the projection list
+ is_field_in_projection_list = TRUE;
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count != 1 ) )
+ {
+ // Field of interest is not the sole column in the projection list
+ DBUG_RETURN( FALSE );
+ }
+ }
+
+ if ( is_field_in_projection_list && ( projection_field_count == 1 ) )
+ {
+ // Field of interest is the only column in the projection list
+ DBUG_RETURN( TRUE );
+ }
+
+ DBUG_RETURN( FALSE );
+}
+
bool spider_oracle_handler::is_bulk_insert_exec_period(
bool bulk_end
) {
diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h
index 0e84435d9be..7a070f498da 100644
--- a/storage/spider/spd_db_oracle.h
+++ b/storage/spider/spd_db_oracle.h
@@ -1208,6 +1208,9 @@ public:
ulong sql_type,
int link_idx
);
+ bool is_sole_projection_field(
+ uint16 field_index
+ );
bool is_bulk_insert_exec_period(
bool bulk_end
);
diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc
index 417eeb2c367..48411b6ff6a 100644
--- a/storage/xtradb/btr/btr0btr.cc
+++ b/storage/xtradb/btr/btr0btr.cc
@@ -3277,7 +3277,7 @@ func_start:
btr_page_create(new_block, new_page_zip, cursor->index,
btr_page_get_level(page, mtr), mtr);
/* Only record the leaf level page splits. */
- if (btr_page_get_level(page, mtr) == 0) {
+ if (page_is_leaf(page)) {
cursor->index->stat_defrag_n_page_split ++;
cursor->index->stat_defrag_modified_counter ++;
btr_defragment_save_defrag_stats_if_needed(cursor->index);
diff --git a/storage/xtradb/btr/btr0defragment.cc b/storage/xtradb/btr/btr0defragment.cc
index 8de85e746ca..3f4185341a6 100644
--- a/storage/xtradb/btr/btr0defragment.cc
+++ b/storage/xtradb/btr/btr0defragment.cc
@@ -233,7 +233,7 @@ btr_defragment_add_index(
return NULL;
}
- if (btr_page_get_level(page, &mtr) == 0) {
+ if (page_is_leaf(page)) {
// Index root is a leaf page, no need to defragment.
mtr_commit(&mtr);
return NULL;
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 70cd9610b18..78ebbb7902b 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -5931,23 +5931,22 @@ buf_print_io_instance(
pool_info->pages_written_rate);
if (pool_info->n_page_get_delta) {
- double hit_rate = ((1000 * pool_info->page_read_delta)
- / pool_info->n_page_get_delta);
+ double hit_rate = double(pool_info->page_read_delta)
+ / pool_info->n_page_get_delta;
- if (hit_rate > 1000) {
- hit_rate = 1000;
+ if (hit_rate > 1) {
+ hit_rate = 1;
}
- hit_rate = 1000 - hit_rate;
-
fprintf(file,
- "Buffer pool hit rate %lu / 1000,"
- " young-making rate %lu / 1000 not %lu / 1000\n",
- (ulint) hit_rate,
- (ulint) (1000 * pool_info->young_making_delta
- / pool_info->n_page_get_delta),
- (ulint) (1000 * pool_info->not_young_making_delta
- / pool_info->n_page_get_delta));
+ "Buffer pool hit rate " ULINTPF " / 1000,"
+ " young-making rate " ULINTPF " / 1000 not "
+ ULINTPF " / 1000\n",
+ ulint(1000 * (1 - hit_rate)),
+ ulint(1000 * double(pool_info->young_making_delta)
+ / pool_info->n_page_get_delta),
+ ulint(1000 * double(pool_info->not_young_making_delta)
+ / pool_info->n_page_get_delta));
} else {
fputs("No buffer pool page gets since the last printout\n",
file);
@@ -6245,70 +6244,54 @@ buf_pool_reserve_tmp_slot(
return (free_slot);
}
-/********************************************************************//**
-Encrypts a buffer page right before it's flushed to disk
-@param[in,out] bpage Page control block
-@param[in,out] src_frame Source page
-@param[in] space_id Tablespace id
-@return either unencrypted source page or decrypted page.
-*/
+/** Encryption and page_compression hook that is called just before
+a page is written to disk.
+@param[in,out] space tablespace
+@param[in,out] bpage buffer page
+@param[in] src_frame physical page frame that is being encrypted
+@return page frame to be written to file
+(may be src_frame or an encrypted/compressed copy of it) */
+UNIV_INTERN
byte*
buf_page_encrypt_before_write(
+ fil_space_t* space,
buf_page_t* bpage,
- byte* src_frame,
- ulint space_id)
+ byte* src_frame)
{
+ ut_ad(space->id == bpage->space);
bpage->real_size = UNIV_PAGE_SIZE;
fil_page_type_validate(src_frame);
- if (bpage->offset == 0) {
+ switch (bpage->offset) {
+ case 0:
/* Page 0 of a tablespace is not encrypted/compressed */
ut_ad(bpage->key_version == 0);
return src_frame;
- }
-
- if (bpage->space == TRX_SYS_SPACE && bpage->offset == TRX_SYS_PAGE_NO) {
- /* don't encrypt/compress page as it contains address to dblwr buffer */
- bpage->key_version = 0;
- return src_frame;
- }
-
- fil_space_t* space = fil_space_acquire_silent(space_id);
-
- /* Tablespace must exist during write operation */
- if (!space) {
- /* This could be true on discard if we have injected a error
- case e.g. in innodb.innodb-wl5522-debug-zip so that space
- is already marked as stop_new_ops = true. */
- return src_frame;
+ case TRX_SYS_PAGE_NO:
+ if (bpage->space == TRX_SYS_SPACE) {
+ /* don't encrypt/compress page as it contains
+ address to dblwr buffer */
+ bpage->key_version = 0;
+ return src_frame;
+ }
}
fil_space_crypt_t* crypt_data = space->crypt_data;
- bool encrypted = true;
+ const bool encrypted = crypt_data
+ && !crypt_data->not_encrypted()
+ && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
+ && (!crypt_data->is_default_encryption()
+ || srv_encrypt_tables);
- if (space->crypt_data != NULL && space->crypt_data->not_encrypted()) {
- /* Encryption is disabled */
- encrypted = false;
- }
-
- if (!srv_encrypt_tables && (crypt_data == NULL || crypt_data->is_default_encryption())) {
- /* Encryption is disabled */
- encrypted = false;
- }
-
- /* Is encryption needed? */
- if (crypt_data == NULL || crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
- /* An unencrypted table */
+ if (!encrypted) {
bpage->key_version = 0;
- encrypted = false;
}
- bool page_compressed = fil_space_is_page_compressed(bpage->space);
+ bool page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
if (!encrypted && !page_compressed) {
/* No need to encrypt or page compress the page */
- fil_space_release(space);
return src_frame;
}
@@ -6336,25 +6319,21 @@ buf_page_encrypt_before_write(
bpage->real_size = page_size;
slot->out_buf = dst_frame = tmp;
-#ifdef UNIV_DEBUG
- fil_page_type_validate(tmp);
-#endif
-
+ ut_d(fil_page_type_validate(tmp));
} else {
/* First we compress the page content */
ulint out_len = 0;
- ulint block_size = fil_space_get_block_size(bpage->space, bpage->offset, page_size);
-
- byte *tmp = fil_compress_page(bpage->space,
- (byte *)src_frame,
- slot->comp_buf,
- page_size,
- fil_space_get_page_compression_level(bpage->space),
- block_size,
- encrypted,
- &out_len,
- IF_LZO(slot->lzo_mem, NULL)
- );
+
+ byte *tmp = fil_compress_page(
+ space,
+ (byte *)src_frame,
+ slot->comp_buf,
+ page_size,
+ fsp_flags_get_page_compression_level(space->flags),
+ fil_space_get_block_size(space, bpage->offset),
+ encrypted,
+ &out_len,
+ IF_LZO(slot->lzo_mem, NULL));
bpage->real_size = out_len;
@@ -6379,7 +6358,6 @@ buf_page_encrypt_before_write(
fil_page_type_validate(dst_frame);
#endif
- fil_space_release(space);
// return dst_frame which will be written
return dst_frame;
}
@@ -6433,9 +6411,9 @@ buf_page_decrypt_after_read(
/* decompress using comp_buf to dst_frame */
fil_decompress_page(slot->comp_buf,
- dst_frame,
- size,
- &bpage->write_size);
+ dst_frame,
+ ulong(size),
+ &bpage->write_size);
/* Mark this slot as free */
slot->reserved = false;
@@ -6487,13 +6465,10 @@ buf_page_decrypt_after_read(
#endif
/* decompress using comp_buf to dst_frame */
fil_decompress_page(slot->comp_buf,
- dst_frame,
- size,
- &bpage->write_size);
-
-#ifdef UNIV_DEBUG
- fil_page_type_validate(dst_frame);
-#endif
+ dst_frame,
+ ulong(size),
+ &bpage->write_size);
+ ut_d(fil_page_type_validate(dst_frame));
}
/* Mark this slot as free */
diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc
index b11c32064bf..55c5e4d543a 100644
--- a/storage/xtradb/buf/buf0dblwr.cc
+++ b/storage/xtradb/buf/buf0dblwr.cc
@@ -538,7 +538,7 @@ buf_dblwr_process()
/* Decompress the page before
validating the checksum. */
fil_decompress_page(
- NULL, read_buf, UNIV_PAGE_SIZE,
+ NULL, read_buf, srv_page_size,
NULL, true);
}
@@ -565,7 +565,7 @@ buf_dblwr_process()
/* Decompress the page before
validating the checksum. */
fil_decompress_page(
- NULL, page, UNIV_PAGE_SIZE, NULL, true);
+ NULL, page, srv_page_size, NULL, true);
}
if (!fil_space_verify_crypt_checksum(page, zip_size, NULL, page_no)
@@ -1001,7 +1001,7 @@ flush:
srv_stats.dblwr_writes.inc();
/* Now flush the doublewrite buffer data to disk */
- fil_flush(TRX_SYS_SPACE);
+ fil_flush(ulint(TRX_SYS_SPACE));
/* We know that the writes have been flushed to disk now
and in recovery we will find them in the doublewrite buffer
@@ -1249,7 +1249,7 @@ retry:
}
/* Now flush the doublewrite buffer data to disk */
- fil_flush(TRX_SYS_SPACE);
+ fil_flush(ulint(TRX_SYS_SPACE));
/* We know that the write has been flushed to disk now
and during recovery we will find it in the doublewrite buffer
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index e7ed7204920..ffd40157c30 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -873,11 +873,12 @@ buf_flush_write_block_low(
buf_flush_t flush_type, /*!< in: type of flush */
bool sync) /*!< in: true if sync IO request */
{
+ fil_space_t* space = fil_space_acquire(bpage->space, true);
+ if (!space) {
+ return;
+ }
ulint zip_size = buf_page_get_zip_size(bpage);
page_t* frame = NULL;
- ulint space_id = buf_page_get_space(bpage);
- atomic_writes_t awrites = fil_space_get_atomic_writes(space_id);
-
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(!mutex_own(&buf_pool->LRU_list_mutex));
@@ -947,7 +948,7 @@ buf_flush_write_block_low(
break;
}
- frame = buf_page_encrypt_before_write(bpage, frame, space_id);
+ frame = buf_page_encrypt_before_write(space, bpage, frame);
if (!srv_use_doublewrite_buf || !buf_dblwr) {
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
@@ -968,7 +969,8 @@ buf_flush_write_block_low(
atomic writes should be used, no doublewrite buffer
is used. */
- if (awrites == ATOMIC_WRITES_ON) {
+ if (fsp_flags_get_atomic_writes(space->flags)
+ == ATOMIC_WRITES_ON) {
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
FALSE,
buf_page_get_space(bpage),
@@ -991,10 +993,12 @@ buf_flush_write_block_low(
are working on. */
if (sync) {
ut_ad(flush_type == BUF_FLUSH_SINGLE_PAGE);
- fil_flush(buf_page_get_space(bpage));
+ fil_flush(space);
buf_page_io_complete(bpage);
}
+ fil_space_release(space);
+
/* Increment the counter of I/O operations used
for selecting LRU policy. */
buf_LRU_stat_inc_io();
diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc
index 15465699726..be2ee56504b 100644
--- a/storage/xtradb/buf/buf0rea.cc
+++ b/storage/xtradb/buf/buf0rea.cc
@@ -998,15 +998,11 @@ not_to_recover:
count++;
if (count > 1000) {
- fprintf(stderr,
- "InnoDB: Error: InnoDB has waited for"
- " 10 seconds for pending\n"
- "InnoDB: reads to the buffer pool to"
- " be finished.\n"
- "InnoDB: Number of pending reads %lu,"
- " pending pread calls %lu\n",
- (ulong) buf_pool->n_pend_reads,
- (ulong) os_file_n_pending_preads);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "waited for 10 seconds for " ULINTPF
+ " pending reads to the buffer pool to"
+ " be finished",
+ buf_pool->n_pend_reads);
os_aio_print_debug = TRUE;
}
diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc
index 6a28f3cdf8f..33b6c2e23e0 100644
--- a/storage/xtradb/dict/dict0stats.cc
+++ b/storage/xtradb/dict/dict0stats.cc
@@ -1576,7 +1576,7 @@ dict_stats_analyze_index_below_cur(
page = buf_block_get_frame(block);
- if (btr_page_get_level(page, mtr) == 0) {
+ if (page_is_leaf(page)) {
/* leaf level */
break;
}
@@ -1620,7 +1620,7 @@ dict_stats_analyze_index_below_cur(
}
/* make sure we got a leaf page as a result from the above loop */
- ut_ad(btr_page_get_level(page, &mtr) == 0);
+ ut_ad(page_is_leaf(page));
/* scan the leaf page and find the number of distinct keys,
when looking only at the first n_prefix columns; also estimate
diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc
index aa95de7efea..f37d5e19ad6 100644
--- a/storage/xtradb/fil/fil0crypt.cc
+++ b/storage/xtradb/fil/fil0crypt.cc
@@ -694,7 +694,8 @@ fil_space_encrypt(
comp_mem = (byte *)malloc(UNIV_PAGE_SIZE);
uncomp_mem = (byte *)malloc(UNIV_PAGE_SIZE);
memcpy(comp_mem, src_frame, UNIV_PAGE_SIZE);
- fil_decompress_page(uncomp_mem, comp_mem, UNIV_PAGE_SIZE, NULL);
+ fil_decompress_page(uncomp_mem, comp_mem,
+ srv_page_size, NULL);
src = uncomp_mem;
}
@@ -704,7 +705,8 @@ fil_space_encrypt(
/* Need to decompress the page if it was also compressed */
if (page_compressed_encrypted) {
memcpy(comp_mem, tmp_mem, UNIV_PAGE_SIZE);
- fil_decompress_page(tmp_mem, comp_mem, UNIV_PAGE_SIZE, NULL);
+ fil_decompress_page(tmp_mem, comp_mem,
+ srv_page_size, NULL);
}
bool corrupted = buf_page_is_corrupted(true, tmp_mem, zip_size, space);
@@ -1492,20 +1494,21 @@ fil_crypt_realloc_iops(
if (10 * state->cnt_waited > state->batch) {
/* if we waited more than 10% re-estimate max_iops */
- uint avg_wait_time_us =
+ ulint avg_wait_time_us =
state->sum_waited_us / state->cnt_waited;
+ if (avg_wait_time_us == 0) {
+ avg_wait_time_us = 1; // prevent division by zero
+ }
+
DBUG_PRINT("ib_crypt",
- ("thr_no: %u - update estimated_max_iops from %u to %u.",
+ ("thr_no: %u - update estimated_max_iops from %u to "
+ ULINTPF ".",
state->thread_no,
state->estimated_max_iops,
1000000 / avg_wait_time_us));
- if (avg_wait_time_us == 0) {
- avg_wait_time_us = 1; // prevent division by zero
- }
-
- state->estimated_max_iops = 1000000 / avg_wait_time_us;
+ state->estimated_max_iops = uint(1000000 / avg_wait_time_us);
state->cnt_waited = 0;
state->sum_waited_us = 0;
} else {
@@ -1739,33 +1742,27 @@ fil_crypt_find_page_to_rotate(
fil_space_crypt_t *crypt_data = space->crypt_data;
- /* Space might already be dropped */
- if (crypt_data) {
- mutex_enter(&crypt_data->mutex);
- ut_ad(key_state->key_id == crypt_data->key_id);
-
- if (crypt_data->rotate_state.next_offset <
- crypt_data->rotate_state.max_offset) {
+ mutex_enter(&crypt_data->mutex);
+ ut_ad(key_state->key_id == crypt_data->key_id);
- state->offset = crypt_data->rotate_state.next_offset;
- ulint remaining = crypt_data->rotate_state.max_offset -
- crypt_data->rotate_state.next_offset;
+ bool found = crypt_data->rotate_state.max_offset >=
+ crypt_data->rotate_state.next_offset;
- if (batch <= remaining) {
- state->batch = batch;
- } else {
- state->batch = remaining;
- }
+ if (found) {
+ state->offset = crypt_data->rotate_state.next_offset;
+ ulint remaining = crypt_data->rotate_state.max_offset -
+ crypt_data->rotate_state.next_offset;
- crypt_data->rotate_state.next_offset += batch;
- mutex_exit(&crypt_data->mutex);
- return true;
+ if (batch <= remaining) {
+ state->batch = batch;
+ } else {
+ state->batch = remaining;
}
-
- mutex_exit(&crypt_data->mutex);
}
- return false;
+ crypt_data->rotate_state.next_offset += batch;
+ mutex_exit(&crypt_data->mutex);
+ return found;
}
/***********************************************************************
@@ -2343,7 +2340,7 @@ DECLARE_THREAD(fil_crypt_thread)(
fil_crypt_start_rotate_space(&new_state, &thr);
/* iterate all pages (cooperativly with other threads) */
- while (!thr.should_shutdown() && thr.space &&
+ while (!thr.should_shutdown() &&
fil_crypt_find_page_to_rotate(&new_state, &thr)) {
/* rotate a (set) of pages */
@@ -2352,6 +2349,8 @@ DECLARE_THREAD(fil_crypt_thread)(
/* If space is marked as stopping, release
space and stop rotation. */
if (thr.space->is_stopping()) {
+ fil_crypt_complete_rotate_space(
+ &new_state, &thr);
fil_space_release(thr.space);
thr.space = NULL;
break;
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index e7244d719c8..e504ab3947e 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -5993,31 +5993,34 @@ fil_space_get_node(
return (node);
}
-/********************************************************************//**
-Return block size of node in file space
-@return file block size */
+
+/** Determine the block size of the data file.
+@param[in] space tablespace
+@param[in] offset page number
+@return block size */
UNIV_INTERN
ulint
-fil_space_get_block_size(
-/*=====================*/
- ulint space_id,
- ulint block_offset,
- ulint len)
+fil_space_get_block_size(const fil_space_t* space, unsigned offset)
{
- ulint block_size = 512;
- ut_ad(!mutex_own(&fil_system->mutex));
-
- mutex_enter(&fil_system->mutex);
- fil_space_t* space = fil_space_get_space(space_id);
+ ut_ad(space->n_pending_ops > 0);
- if (space) {
- fil_node_t* node = fil_space_get_node(space, space_id, &block_offset, 0, len);
+ ulint block_size = 512;
- if (node) {
- block_size = node->file_block_size;
+ for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
+ node != NULL;
+ node = UT_LIST_GET_NEXT(chain, node)) {
+ block_size = node->file_block_size;
+ if (node->size > offset) {
+ break;
}
+ offset -= node->size;
+ }
+
+ /* Currently supporting block size up to 4K,
+ fall back to default if bigger requested. */
+ if (block_size > 4096) {
+ block_size = 512;
}
- mutex_exit(&fil_system->mutex);
return block_size;
}
@@ -6398,14 +6401,29 @@ fil_flush(
mutex_exit(&fil_system->mutex);
}
-/**********************************************************************//**
-Flushes to disk the writes in file spaces of the given type possibly cached by
-the OS. */
+/** Flush a tablespace.
+@param[in,out] space tablespace to flush */
UNIV_INTERN
void
-fil_flush_file_spaces(
-/*==================*/
- ulint purpose) /*!< in: FIL_TABLESPACE, FIL_LOG */
+fil_flush(fil_space_t* space)
+{
+ ut_ad(space->n_pending_ops > 0);
+
+ if (!space->is_stopping()) {
+ mutex_enter(&fil_system->mutex);
+ if (!space->is_stopping()) {
+ fil_flush_low(space);
+ }
+ mutex_exit(&fil_system->mutex);
+ }
+}
+
+/** Flush to disk the writes in file spaces of the given type
+possibly cached by the OS.
+@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */
+UNIV_INTERN
+void
+fil_flush_file_spaces(ulint purpose)
{
fil_space_t* space;
ulint* space_ids;
@@ -6772,7 +6790,8 @@ fil_iterate(
/* If the original page is page_compressed, we need
to decompress page before we can update it. */
if (page_compressed) {
- fil_decompress_page(NULL, dst, size, NULL);
+ fil_decompress_page(NULL, dst, ulong(size),
+ NULL);
updated = true;
}
@@ -6832,12 +6851,14 @@ fil_iterate(
if (page_compressed) {
ulint len = 0;
- fil_compress_page(space_id,
+
+ fil_compress_page(
+ NULL,
src,
NULL,
size,
- fil_space_get_page_compression_level(space_id),
- fil_space_get_block_size(space_id, offset, size),
+ 0,/* FIXME: compression level */
+ 512,/* FIXME: use proper block size */
encrypted,
&len,
NULL);
@@ -6848,6 +6869,8 @@ fil_iterate(
/* If tablespace is encrypted, encrypt page before we
write it back. Note that we should not encrypt the
buffer that is in buffer pool. */
+ /* NOTE: At this stage of IMPORT the
+ buffer pool is not being used at all! */
if (decrypted && encrypted) {
byte *dest = writeptr + (i * size);
ulint space = mach_read_from_4(
@@ -7401,7 +7424,6 @@ fil_space_acquire_low(ulint id, bool silent, bool for_io = false)
if (!silent) {
ib_logf(IB_LOG_LEVEL_WARN, "Trying to access missing"
" tablespace " ULINTPF ".", id);
- ut_error;
}
} else if (!for_io && space->is_stopping()) {
space = NULL;
diff --git a/storage/xtradb/fil/fil0pagecompress.cc b/storage/xtradb/fil/fil0pagecompress.cc
index 303ab5102fb..8b2449983df 100644
--- a/storage/xtradb/fil/fil0pagecompress.cc
+++ b/storage/xtradb/fil/fil0pagecompress.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved.
+Copyright (C) 2013, 2017, MariaDB Corporation. 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
@@ -91,8 +91,7 @@ UNIV_INTERN
byte*
fil_compress_page(
/*==============*/
- ulint space_id, /*!< in: tablespace id of the
- table. */
+ fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */
byte* buf, /*!< in: buffer from which to write; in aio
this must be appropriately aligned */
byte* out_buf, /*!< out: compressed buffer */
@@ -110,9 +109,12 @@ fil_compress_page(
ulint write_size=0;
/* Cache to avoid change during function execution */
ulint comp_method = innodb_compression_algorithm;
- ulint orig_page_type;
bool allocated=false;
+ /* page_compression does not apply to tables or tablespaces
+ that use ROW_FORMAT=COMPRESSED */
+ ut_ad(!space || !FSP_FLAGS_GET_ZIP_SSIZE(space->flags));
+
if (encrypted) {
header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE;
}
@@ -133,21 +135,14 @@ fil_compress_page(
ut_ad(len);
ut_ad(out_len);
- /* read original page type */
- orig_page_type = mach_read_from_2(buf + FIL_PAGE_TYPE);
-
- fil_system_enter();
- fil_space_t* space = fil_space_get_by_id(space_id);
- fil_system_exit();
-
/* Let's not compress file space header or
extent descriptor */
- if (orig_page_type == 0 ||
- orig_page_type == FIL_PAGE_TYPE_FSP_HDR ||
- orig_page_type == FIL_PAGE_TYPE_XDES ||
- orig_page_type == FIL_PAGE_PAGE_COMPRESSED) {
+ switch (fil_page_get_type(buf)) {
+ case 0:
+ case FIL_PAGE_TYPE_FSP_HDR:
+ case FIL_PAGE_TYPE_XDES:
+ case FIL_PAGE_PAGE_COMPRESSED:
*out_len = len;
-
goto err_exit;
}
@@ -157,11 +152,11 @@ fil_compress_page(
comp_level = page_zip_level;
}
-#ifdef UNIV_PAGECOMPRESS_DEBUG
- ib_logf(IB_LOG_LEVEL_INFO,
- "Preparing for compress for space %lu name %s len %lu.",
- space_id, fil_space_name(space), len);
-#endif /* UNIV_PAGECOMPRESS_DEBUG */
+ DBUG_PRINT("compress",
+ ("Preparing for space " ULINTPF " '%s' len " ULINTPF,
+ space ? space->id : 0,
+ space ? space->name : "(import)",
+ len));
write_size = UNIV_PAGE_SIZE - header_len;
@@ -176,12 +171,15 @@ fil_compress_page(
/* If error we leave the actual page as it was */
#ifndef UNIV_PAGECOMPRESS_DEBUG
- if (space->printed_compression_failure == false) {
+ if (space && !space->printed_compression_failure) {
+ space->printed_compression_failure = true;
#endif
ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu rt %d write %lu.",
- space_id, fil_space_name(space), len, err, write_size);
- space->printed_compression_failure = true;
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " err %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ err, write_size);
#ifndef UNIV_PAGECOMPRESS_DEBUG
}
#endif
@@ -197,11 +195,14 @@ fil_compress_page(
buf, len, out_buf+header_len, &write_size, lzo_mem);
if (err != LZO_E_OK || write_size > UNIV_PAGE_SIZE-header_len) {
- if (space->printed_compression_failure == false) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu err %d write_size %lu.",
- space_id, fil_space_name(space), len, err, write_size);
+ if (space && !space->printed_compression_failure) {
space->printed_compression_failure = true;
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " err %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ err, write_size);
}
srv_stats.pages_page_compression_error.inc();
@@ -226,11 +227,14 @@ fil_compress_page(
(size_t)write_size);
if (err != LZMA_OK || out_pos > UNIV_PAGE_SIZE-header_len) {
- if (space->printed_compression_failure == false) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu err %d write_size %lu",
- space_id, fil_space_name(space), len, err, out_pos);
+ if (space && !space->printed_compression_failure) {
space->printed_compression_failure = true;
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " err %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ err, out_pos);
}
srv_stats.pages_page_compression_error.inc();
@@ -257,11 +261,14 @@ fil_compress_page(
0);
if (err != BZ_OK || write_size > UNIV_PAGE_SIZE-header_len) {
- if (space->printed_compression_failure == false) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu err %d write_size %lu.",
- space_id, fil_space_name(space), len, err, write_size);
+ if (space && !space->printed_compression_failure) {
space->printed_compression_failure = true;
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " err %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ err, write_size);
}
srv_stats.pages_page_compression_error.inc();
@@ -284,11 +291,14 @@ fil_compress_page(
(size_t*)&write_size);
if (cstatus != SNAPPY_OK || write_size > UNIV_PAGE_SIZE-header_len) {
- if (space->printed_compression_failure == false) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu err %d write_size %lu.",
- space_id, fil_space_name(space), len, (int)cstatus, write_size);
+ if (space && !space->printed_compression_failure) {
space->printed_compression_failure = true;
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " err %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ (int)cstatus, write_size);
}
srv_stats.pages_page_compression_error.inc();
@@ -300,16 +310,20 @@ fil_compress_page(
#endif /* HAVE_SNAPPY */
case PAGE_ZLIB_ALGORITHM:
- err = compress2(out_buf+header_len, (ulong*)&write_size, buf, len, comp_level);
+ err = compress2(out_buf+header_len, (ulong*)&write_size, buf,
+ uLong(len), comp_level);
if (err != Z_OK) {
/* If error we leave the actual page as it was */
- if (space->printed_compression_failure == false) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Compression failed for space %lu name %s len %lu rt %d write %lu.",
- space_id, fil_space_name(space), len, err, write_size);
+ if (space && !space->printed_compression_failure) {
space->printed_compression_failure = true;
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Compression failed for space " ULINTPF
+ " name %s len " ULINTPF
+ " rt %d write_size " ULINTPF ".",
+ space->id, space->name, len,
+ err, write_size);
}
srv_stats.pages_page_compression_error.inc();
@@ -364,11 +378,10 @@ fil_compress_page(
uncomp_page = static_cast<byte *>(ut_malloc(UNIV_PAGE_SIZE));
memcpy(comp_page, out_buf, UNIV_PAGE_SIZE);
- fil_decompress_page(uncomp_page, comp_page, len, NULL);
+ fil_decompress_page(uncomp_page, comp_page, ulong(len), NULL);
- if(buf_page_is_corrupted(false, uncomp_page, 0, space)) {
- buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
- ut_error;
+ if (buf_page_is_corrupted(false, uncomp_page, 0, space)) {
+ buf_page_print(uncomp_page, 0, 0);
}
ut_free(comp_page);
@@ -396,11 +409,12 @@ fil_compress_page(
#endif
}
-#ifdef UNIV_PAGECOMPRESS_DEBUG
- ib_logf(IB_LOG_LEVEL_INFO,
- "Compression succeeded for space %lu name %s len %lu out_len %lu.",
- space_id, fil_space_name(space), len, write_size);
-#endif /* UNIV_PAGECOMPRESS_DEBUG */
+ DBUG_PRINT("compress",
+ ("Succeeded for space " ULINTPF
+ " '%s' len " ULINTPF " out_len " ULINTPF,
+ space ? space->id : 0,
+ space ? space->name : "(import)",
+ len, write_size));
srv_stats.page_compression_saved.add((len - write_size));
srv_stats.pages_page_compressed.inc();
diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 1774d9445ff..4a632e2345f 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/include/buf0buf.h
@@ -1534,17 +1534,19 @@ buf_own_zip_mutex_for_page(
MY_ATTRIBUTE((nonnull,warn_unused_result));
#endif /* UNIV_DEBUG */
-/********************************************************************//**
-The hook that is called just before a page is written to disk.
-The function encrypts the content of the page and returns a pointer
-to a frame that will be written instead of the real frame. */
+/** Encryption and page_compression hook that is called just before
+a page is written to disk.
+@param[in,out] space tablespace
+@param[in,out] bpage buffer page
+@param[in] src_frame physical page frame that is being encrypted
+@return page frame to be written to file
+(may be src_frame or an encrypted/compressed copy of it) */
UNIV_INTERN
byte*
buf_page_encrypt_before_write(
-/*==========================*/
- buf_page_t* page, /*!< in/out: buffer page to be flushed */
- byte* frame, /*!< in: src frame */
- ulint space_id); /*!< in: space id */
+ fil_space_t* space,
+ buf_page_t* bpage,
+ byte* src_frame);
/**********************************************************************
The hook that is called after page is written to disk.
diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic
index 81da2fa5580..e3de7a33123 100644
--- a/storage/xtradb/include/dict0dict.ic
+++ b/storage/xtradb/include/dict0dict.ic
@@ -540,15 +540,16 @@ dict_tf_is_valid(
/* Make sure there are no bits that we do not know about. */
if (unused != 0) {
-
fprintf(stderr,
- "InnoDB: Error: table unused flags are %ld"
+ "InnoDB: Error: table unused flags are " ULINTPF
" in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF " atomic_blobs " ULINTPF
+ "\nInnoDB: unused " ULINTPF " data_dir " ULINTPF
+ " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
unused,
compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
@@ -564,17 +565,20 @@ dict_tf_is_valid(
if (!compact) {
fprintf(stderr,
- "InnoDB: Error: table compact flags are %ld"
+ "InnoDB: Error: table compact flags are "
+ ULINTPF
" in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF
+ " atomic_blobs " ULINTPF "\n"
+ "InnoDB: unused " ULINTPF
+ " data_dir " ULINTPF " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
compact, compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
);
-
return(false);
}
@@ -582,17 +586,18 @@ dict_tf_is_valid(
/* Antelope does not support COMPRESSED row format. */
fprintf(stderr,
- "InnoDB: Error: table flags are %ld"
+ "InnoDB: Error: table flags are " ULINTPF
" in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF " atomic_blobs " ULINTPF
+ "\nInnoDB: unused " ULINTPF " data_dir " ULINTPF
+ " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
);
-
return(false);
}
@@ -606,12 +611,17 @@ dict_tf_is_valid(
|| zip_ssize > PAGE_ZIP_SSIZE_MAX) {
fprintf(stderr,
- "InnoDB: Error: table compact flags are %ld in the data dictionary and are corrupted\n"
+ "InnoDB: Error: table compact flags are "
+ ULINTPF
+ " in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF
+ " atomic_blobs " ULINTPF "\n"
+ "InnoDB: unused " ULINTPF
+ " data_dir " ULINTPF " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
flags,
compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
@@ -630,16 +640,19 @@ dict_tf_is_valid(
|| !atomic_blobs) {
fprintf(stderr,
- "InnoDB: Error: table flags are %ld in the data dictionary and are corrupted\n"
+ "InnoDB: Error: table flags are " ULINTPF
+ " in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF
+ " atomic_blobs " ULINTPF "\n"
+ "InnoDB: unused " ULINTPF
+ " data_dir " ULINTPF " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
);
-
return(false);
}
}
@@ -649,12 +662,16 @@ dict_tf_is_valid(
if(atomic_writes > ATOMIC_WRITES_OFF) {
fprintf(stderr,
- "InnoDB: Error: table flags are %ld in the data dictionary and are corrupted\n"
+ "InnoDB: Error: table flags are " ULINTPF
+ " in the data dictionary and are corrupted\n"
"InnoDB: Error: data dictionary flags are\n"
- "InnoDB: compact %ld atomic_blobs %ld\n"
- "InnoDB: unused %ld data_dir %ld zip_ssize %ld\n"
- "InnoDB: page_compression %ld page_compression_level %ld\n"
- "InnoDB: atomic_writes %ld\n",
+ "InnoDB: compact " ULINTPF
+ " atomic_blobs " ULINTPF "\n"
+ "InnoDB: unused " ULINTPF
+ " data_dir " ULINTPF " zip_ssize " ULINTPF
+ "\nInnoDB: page_compression " ULINTPF
+ " page_compression_level " ULINTPF
+ "\nInnoDB: atomic_writes " ULINTPF "\n",
flags, compact, atomic_blobs, unused, data_dir, zip_ssize,
page_compression, page_compression_level, atomic_writes
);
@@ -699,7 +716,7 @@ dict_sys_tables_type_validate(
if (redundant) {
if (zip_ssize || atomic_blobs) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=Redundant, zip_ssize %lu atomic_blobs %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=Redundant, zip_ssize " ULINTPF " atomic_blobs " ULINTPF "\n",
zip_ssize, atomic_blobs);
return(ULINT_UNDEFINED);
}
@@ -707,7 +724,7 @@ dict_sys_tables_type_validate(
/* Make sure there are no bits that we do not know about. */
if (unused) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, unused %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", unused " ULINTPF "\n",
type, unused);
return(ULINT_UNDEFINED);
}
@@ -723,7 +740,7 @@ dict_sys_tables_type_validate(
} else if (zip_ssize) {
/* Antelope does not support COMPRESSED format. */
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, zip_ssize %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", zip_ssize " ULINTPF "\n",
type, zip_ssize);
return(ULINT_UNDEFINED);
}
@@ -734,14 +751,14 @@ dict_sys_tables_type_validate(
should be in N_COLS, but we already know about the
low_order_bit and DICT_N_COLS_COMPACT flags. */
if (!atomic_blobs) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, zip_ssize %lu atomic_blobs %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", zip_ssize " ULINTPF " atomic_blobs " ULINTPF "\n",
type, zip_ssize, atomic_blobs);
return(ULINT_UNDEFINED);
}
/* Validate that the number is within allowed range. */
if (zip_ssize > PAGE_ZIP_SSIZE_MAX) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, zip_ssize %lu max %d\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", zip_ssize " ULINTPF " max %d\n",
type, zip_ssize, PAGE_ZIP_SSIZE_MAX);
return(ULINT_UNDEFINED);
}
@@ -759,8 +776,8 @@ dict_sys_tables_type_validate(
low_order_bit and DICT_N_COLS_COMPACT flags. */
if (!atomic_blobs || !page_compression) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, page_compression %lu page_compression_level %lu\n"
- "InnoDB: Error: atomic_blobs %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", page_compression " ULINTPF " page_compression_level " ULINTPF "\n"
+ "InnoDB: Error: atomic_blobs " ULINTPF "\n",
type, page_compression, page_compression_level, atomic_blobs);
return(ULINT_UNDEFINED);
}
@@ -768,7 +785,7 @@ dict_sys_tables_type_validate(
/* Validate that the atomic writes number is within allowed range. */
if (atomic_writes > ATOMIC_WRITES_OFF) {
- fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=%lu, atomic_writes %lu\n",
+ fprintf(stderr, "InnoDB: Error: SYS_TABLES::TYPE=" ULINTPF ", atomic_writes " ULINTPF "\n",
type, atomic_writes);
return(ULINT_UNDEFINED);
}
diff --git a/storage/xtradb/include/fil0crypt.h b/storage/xtradb/include/fil0crypt.h
index cfc2d850883..e7e9676aa3a 100644
--- a/storage/xtradb/include/fil0crypt.h
+++ b/storage/xtradb/include/fil0crypt.h
@@ -109,7 +109,7 @@ struct fil_space_crypt_t : st_encryption_scheme
The object is expected to be placed in a buffer that
has been zero-initialized. */
fil_space_crypt_t(
- ulint new_type,
+ uint new_type,
uint new_min_key_version,
uint new_key_id,
fil_encryption_t new_encryption)
@@ -117,10 +117,10 @@ struct fil_space_crypt_t : st_encryption_scheme
min_key_version(new_min_key_version),
page0_offset(0),
encryption(new_encryption),
- key_found(),
+ mutex(),
+ key_found(new_min_key_version),
rotate_state()
{
- key_found = new_min_key_version;
key_id = new_key_id;
my_random_bytes(iv, sizeof(iv));
mutex_create(fil_crypt_data_mutex_key,
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 698039afede..d73a68d9d34 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -1120,16 +1120,13 @@ _fil_io(
#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size) \
_fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size, NULL)
-/*******************************************************************//**
-Returns the block size of the file space
+/** Determine the block size of the data file.
+@param[in] space tablespace
+@param[in] offset page number
@return block size */
UNIV_INTERN
ulint
-fil_space_get_block_size(
-/*=====================*/
- ulint id, /*!< in: space id */
- ulint offset, /*!< in: page offset */
- ulint len); /*!< in: page len */
+fil_space_get_block_size(const fil_space_t* space, unsigned offset);
/**********************************************************************//**
Waits for an aio operation to complete. This function is used to write the
@@ -1151,14 +1148,18 @@ fil_flush(
/*======*/
ulint space_id); /*!< in: file space id (this can be a group of
log files or a tablespace of the database) */
-/**********************************************************************//**
-Flushes to disk writes in file spaces of the given type possibly cached by
-the OS. */
+/** Flush a tablespace.
+@param[in,out] space tablespace to flush */
UNIV_INTERN
void
-fil_flush_file_spaces(
-/*==================*/
- ulint purpose); /*!< in: FIL_TABLESPACE, FIL_LOG */
+fil_flush(fil_space_t* space);
+
+/** Flush to disk the writes in file spaces of the given type
+possibly cached by the OS.
+@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */
+UNIV_INTERN
+void
+fil_flush_file_spaces(ulint purpose);
/******************************************************************//**
Checks the consistency of the tablespace cache.
@return TRUE if ok */
@@ -1459,14 +1460,6 @@ fil_get_next_space_safe(
#endif /* UNIV_INNOCHECKSUM */
-/*******************************************************************//**
-Return space flags */
-UNIV_INLINE
-ulint
-fil_space_flags(
-/*===========*/
- fil_space_t* space); /*!< in: space */
-
/****************************************************************//**
Does error handling when a file operation fails.
@return TRUE if we should retry the operation */
diff --git a/storage/xtradb/include/fil0fil.ic b/storage/xtradb/include/fil0fil.ic
index 1179eea8b8e..6c2504c9f8c 100644
--- a/storage/xtradb/include/fil0fil.ic
+++ b/storage/xtradb/include/fil0fil.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2015, MariaDB Corporation.
+Copyright (c) 2015, 2017, MariaDB Corporation.
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
@@ -27,28 +27,6 @@ Created 31/03/2015 Jan Lindström
#define fil0fil_ic
/*******************************************************************//**
-Return space name */
-UNIV_INLINE
-char*
-fil_space_name(
-/*===========*/
- fil_space_t* space) /*!< in: space */
-{
- return (space->name);
-}
-
-/*******************************************************************//**
-Return space flags */
-UNIV_INLINE
-ulint
-fil_space_flags(
-/*===========*/
- fil_space_t* space) /*!< in: space */
-{
- return (space->flags);
-}
-
-/*******************************************************************//**
Return page type name */
UNIV_INLINE
const char*
@@ -137,7 +115,7 @@ fil_page_type_validate(
page_type == FIL_PAGE_TYPE_ZBLOB2 ||
page_type == FIL_PAGE_TYPE_COMPRESSED))) {
- uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ ulint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED);
bool page_compressed_encrypted = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
@@ -148,30 +126,18 @@ fil_page_type_validate(
fil_space_t* rspace = fil_space_get_by_id(space);
fil_system_exit();
-
/* Dump out the page info */
- fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n"
- "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %llu compressed_len %lu\n",
- space, offset, rspace->name, page_type, fil_get_page_type_name(page_type),
- key_version, page_compressed, page_compressed_encrypted, (ulonglong)lsn, compressed_len);
- fflush(stderr);
-
- ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED ||
- page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ||
- page_type == FIL_PAGE_INDEX ||
- page_type == FIL_PAGE_UNDO_LOG ||
- page_type == FIL_PAGE_INODE ||
- page_type == FIL_PAGE_IBUF_FREE_LIST ||
- page_type == FIL_PAGE_TYPE_ALLOCATED ||
- page_type == FIL_PAGE_IBUF_BITMAP ||
- page_type == FIL_PAGE_TYPE_SYS ||
- page_type == FIL_PAGE_TYPE_TRX_SYS ||
- page_type == FIL_PAGE_TYPE_FSP_HDR ||
- page_type == FIL_PAGE_TYPE_XDES ||
- page_type == FIL_PAGE_TYPE_BLOB ||
- page_type == FIL_PAGE_TYPE_ZBLOB ||
- page_type == FIL_PAGE_TYPE_ZBLOB2 ||
- page_type == FIL_PAGE_TYPE_COMPRESSED);
+ fprintf(stderr, "InnoDB: Page " ULINTPF ":" ULINTPF
+ " name %s page_type " ULINTPF " page_type_name %s\n"
+ "InnoDB: key_version " ULINTPF
+ " page_compressed %d page_compressed_encrypted %d lsn "
+ LSN_PF " compressed_len " ULINTPF "\n",
+ space, offset, rspace->name, page_type,
+ fil_get_page_type_name(page_type),
+ key_version,
+ page_compressed, page_compressed_encrypted,
+ lsn, compressed_len);
+ ut_error;
return false;
}
diff --git a/storage/xtradb/include/fil0pagecompress.h b/storage/xtradb/include/fil0pagecompress.h
index 1fe5cb66bf6..73667c5420e 100644
--- a/storage/xtradb/include/fil0pagecompress.h
+++ b/storage/xtradb/include/fil0pagecompress.h
@@ -31,33 +31,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
***********************************************************************/
/*******************************************************************//**
-Returns the page compression level flag of the space, or 0 if the space
-is not compressed. The tablespace must be cached in the memory cache.
-@return page compression level if page compressed, ULINT_UNDEFINED if space not found */
-UNIV_INLINE
-ulint
-fil_space_get_page_compression_level(
-/*=================================*/
- ulint id); /*!< in: space id */
-/*******************************************************************//**
-Returns the page compression flag of the space, or false if the space
-is not compressed. The tablespace must be cached in the memory cache.
-@return true if page compressed, false if not or space not found */
-UNIV_INLINE
-bool
-fil_space_is_page_compressed(
-/*=========================*/
- ulint id); /*!< in: space id */
-/*******************************************************************//**
-Returns the atomic writes flag of the space, or false if the space
-is not using atomic writes. The tablespace must be cached in the memory cache.
-@return atomic write table option value */
-UNIV_INLINE
-atomic_writes_t
-fil_space_get_atomic_writes(
-/*=========================*/
- ulint id); /*!< in: space id */
-/*******************************************************************//**
Find out wheather the page is index page or not
@return true if page type index page, false if not */
UNIV_INLINE
@@ -84,8 +57,7 @@ UNIV_INTERN
byte*
fil_compress_page(
/*==============*/
- ulint space_id, /*!< in: tablespace id of the
- table. */
+ fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */
byte* buf, /*!< in: buffer from which to write; in aio
this must be appropriately aligned */
byte* out_buf, /*!< out: compressed buffer */
diff --git a/storage/xtradb/include/fsp0pagecompress.ic b/storage/xtradb/include/fsp0pagecompress.ic
index 48163277feb..14f968e319e 100644
--- a/storage/xtradb/include/fsp0pagecompress.ic
+++ b/storage/xtradb/include/fsp0pagecompress.ic
@@ -85,47 +85,6 @@ fil_page_is_compressed_encrypted(
return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
}
-#ifndef UNIV_INNOCHECKSUM
-/*******************************************************************//**
-Returns the page compression level of the space, or 0 if the space
-is not compressed. The tablespace must be cached in the memory cache.
-@return page compression level, 0 if space not found */
-UNIV_INLINE
-ulint
-fil_space_get_page_compression_level(
-/*=================================*/
- ulint id) /*!< in: space id */
-{
- ulint flags;
-
- flags = fil_space_get_flags(id);
-
- if (flags && flags != ULINT_UNDEFINED) {
-
- return(fsp_flags_get_page_compression_level(flags));
- }
-
- return(0);
-}
-
-/*******************************************************************//**
-Extract the page compression from space.
-@return true if space is page compressed, false if space is not found
-or space is not page compressed. */
-UNIV_INLINE
-bool
-fil_space_is_page_compressed(
-/*=========================*/
- ulint id) /*!< in: space id */
-{
- ulint flags = fil_space_get_flags(id);
-
- return(flags != ULINT_UNDEFINED
- && FSP_FLAGS_HAS_PAGE_COMPRESSION(flags));
-}
-
-#endif /* UNIV_INNOCHECKSUM */
-
/****************************************************************//**
Get the name of the compression algorithm used for page
compression.
@@ -166,28 +125,6 @@ fil_get_compression_alg_name(
#ifndef UNIV_INNOCHECKSUM
/*******************************************************************//**
-Returns the atomic writes flag of the space, or false if the space
-is not using atomic writes. The tablespace must be cached in the memory cache.
-@return atomic writes table option value */
-UNIV_INLINE
-atomic_writes_t
-fil_space_get_atomic_writes(
-/*========================*/
- ulint id) /*!< in: space id */
-{
- ulint flags;
-
- flags = fil_space_get_flags(id);
-
- if (flags && flags != ULINT_UNDEFINED) {
-
- return((atomic_writes_t)fsp_flags_get_atomic_writes(flags));
- }
-
- return((atomic_writes_t)0);
-}
-
-/*******************************************************************//**
Find out wheather the page is page compressed with lzo method
@return true if page is page compressed with lzo method, false if not */
UNIV_INLINE
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index d6f0ecfb69c..06bb6a6fbac 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
@@ -52,16 +52,6 @@ extern ibool os_has_said_disk_full;
/** Flag: enable debug printout for asynchronous i/o */
extern ibool os_aio_print_debug;
-/** Number of pending os_file_pread() operations */
-extern ulint os_file_n_pending_preads;
-/** Number of pending os_file_pwrite() operations */
-extern ulint os_file_n_pending_pwrites;
-
-/** Number of pending read operations */
-extern ulint os_n_pending_reads;
-/** Number of pending write operations */
-extern ulint os_n_pending_writes;
-
#ifdef __WIN__
/** We define always WIN_ASYNC_IO, and check at run-time whether
diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h
index f6207555f1a..48c56a73369 100644
--- a/storage/xtradb/include/os0sync.h
+++ b/storage/xtradb/include/os0sync.h
@@ -718,10 +718,7 @@ os_atomic_clear(volatile lock_word_t* ptr)
# define HAVE_ATOMIC_BUILTINS
# define HAVE_ATOMIC_BUILTINS_BYTE
-
-# ifndef _WIN32
-# define HAVE_ATOMIC_BUILTINS_64
-# endif
+# define HAVE_ATOMIC_BUILTINS_64
/**********************************************************//**
Atomic compare and exchange of signed integers (both 32 and 64 bit).
diff --git a/storage/xtradb/include/srv0mon.h b/storage/xtradb/include/srv0mon.h
index 3b030d56d29..63fd449ee18 100644
--- a/storage/xtradb/include/srv0mon.h
+++ b/storage/xtradb/include/srv0mon.h
@@ -2,7 +2,7 @@
Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2016, MariaDB Corporation.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -571,22 +571,30 @@ on the counters */
/** Increment a monitor counter under mutex protection.
Use MONITOR_INC if appropriate mutex protection already exists.
+@param mutex mutex to acquire and release
@param monitor monitor to be incremented by 1
-@param mutex mutex to acquire and relese */
-# define MONITOR_MUTEX_INC(mutex, monitor) \
+@param enabled whether the monitor is enabled */
+#define MONITOR_MUTEX_INC_LOW(mutex, monitor, enabled) \
ut_ad(!mutex_own(mutex)); \
- if (MONITOR_IS_ON(monitor)) { \
+ if (enabled) { \
mutex_enter(mutex); \
if (++MONITOR_VALUE(monitor) > MONITOR_MAX_VALUE(monitor)) { \
MONITOR_MAX_VALUE(monitor) = MONITOR_VALUE(monitor); \
} \
mutex_exit(mutex); \
}
+/** Increment a monitor counter under mutex protection.
+Use MONITOR_INC if appropriate mutex protection already exists.
+@param mutex mutex to acquire and release
+@param monitor monitor to be incremented by 1 */
+#define MONITOR_MUTEX_INC(mutex, monitor) \
+ MONITOR_MUTEX_INC_LOW(mutex, monitor, MONITOR_IS_ON(monitor))
/** Decrement a monitor counter under mutex protection.
Use MONITOR_DEC if appropriate mutex protection already exists.
+@param mutex mutex to acquire and release
@param monitor monitor to be decremented by 1
-@param mutex mutex to acquire and relese */
-# define MONITOR_MUTEX_DEC(mutex, monitor) \
+@param enabled whether the monitor is enabled */
+#define MONITOR_MUTEX_DEC_LOW(mutex, monitor, enabled) \
ut_ad(!mutex_own(mutex)); \
if (MONITOR_IS_ON(monitor)) { \
mutex_enter(mutex); \
@@ -595,13 +603,20 @@ Use MONITOR_DEC if appropriate mutex protection already exists.
} \
mutex_exit(mutex); \
}
+/** Decrement a monitor counter under mutex protection.
+Use MONITOR_DEC if appropriate mutex protection already exists.
+@param mutex mutex to acquire and release
+@param monitor monitor to be decremented by 1 */
+#define MONITOR_MUTEX_DEC(mutex, monitor) \
+ MONITOR_MUTEX_DEC_LOW(mutex, monitor, MONITOR_IS_ON(monitor))
#if defined HAVE_ATOMIC_BUILTINS_64
/** Atomically increment a monitor counter.
Use MONITOR_INC if appropriate mutex protection exists.
-@param monitor monitor to be incremented by 1 */
-# define MONITOR_ATOMIC_INC(monitor) \
- if (MONITOR_IS_ON(monitor)) { \
+@param monitor monitor to be incremented by 1
+@param enabled whether the monitor is enabled */
+# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \
+ if (enabled) { \
ib_uint64_t value; \
value = os_atomic_increment_uint64( \
(ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \
@@ -614,9 +629,10 @@ Use MONITOR_INC if appropriate mutex protection exists.
/** Atomically decrement a monitor counter.
Use MONITOR_DEC if appropriate mutex protection exists.
-@param monitor monitor to be decremented by 1 */
-# define MONITOR_ATOMIC_DEC(monitor) \
- if (MONITOR_IS_ON(monitor)) { \
+@param monitor monitor to be decremented by 1
+@param enabled whether the monitor is enabled */
+# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \
+ if (enabled) { \
ib_uint64_t value; \
value = os_atomic_decrement_uint64( \
(ib_uint64_t*) &MONITOR_VALUE(monitor), 1); \
@@ -647,14 +663,29 @@ srv_mon_free(void);
/** Atomically increment a monitor counter.
Use MONITOR_INC if appropriate mutex protection exists.
-@param monitor monitor to be incremented by 1 */
-# define MONITOR_ATOMIC_INC(monitor) MONITOR_MUTEX_INC(&monitor_mutex, monitor)
+@param monitor monitor to be incremented by 1
+@param enabled whether the monitor is enabled */
+# define MONITOR_ATOMIC_INC_LOW(monitor, enabled) \
+ MONITOR_MUTEX_INC_LOW(&monitor_mutex, monitor, enabled)
/** Atomically decrement a monitor counter.
Use MONITOR_DEC if appropriate mutex protection exists.
-@param monitor monitor to be decremented by 1 */
-# define MONITOR_ATOMIC_DEC(monitor) MONITOR_MUTEX_DEC(&monitor_mutex, monitor)
+@param monitor monitor to be decremented by 1
+@param enabled whether the monitor is enabled */
+# define MONITOR_ATOMIC_DEC_LOW(monitor, enabled) \
+ MONITOR_MUTEX_DEC_LOW(&monitor_mutex, monitor, enabled)
#endif /* HAVE_ATOMIC_BUILTINS_64 */
+/** Atomically increment a monitor counter if it is enabled.
+Use MONITOR_INC if appropriate mutex protection exists.
+@param monitor monitor to be incremented by 1 */
+#define MONITOR_ATOMIC_INC(monitor) \
+ MONITOR_ATOMIC_INC_LOW(monitor, MONITOR_IS_ON(monitor))
+/** Atomically decrement a monitor counter if it is enabled.
+Use MONITOR_DEC if appropriate mutex protection exists.
+@param monitor monitor to be decremented by 1 */
+#define MONITOR_ATOMIC_DEC(monitor) \
+ MONITOR_ATOMIC_DEC_LOW(monitor, MONITOR_IS_ON(monitor))
+
#define MONITOR_DEC(monitor) \
if (MONITOR_IS_ON(monitor)) { \
MONITOR_VALUE(monitor)--; \
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index e621d4226a7..766d61039b4 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -348,6 +348,23 @@ trx_print_latched(
or 0 to use the default max length */
MY_ATTRIBUTE((nonnull));
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+/*==============*/
+ FILE* f, /*!< in: output stream */
+ const trx_t* trx, /*!< in: transaction */
+ ulint max_query_len) /*!< in: max query length to print,
+ or 0 to use the default max length */
+ MY_ATTRIBUTE((nonnull));
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 1e375ba2c09..e698f08f15b 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -304,22 +304,12 @@ definitions: */
#endif /* !UNIV_MUST_NOT_INLINE */
-#ifdef _WIN32
-#define UNIV_WORD_SIZE 4
-#elif defined(_WIN64)
-#define UNIV_WORD_SIZE 8
-#else
-/** MySQL config.h generated by GNU autoconf will define SIZEOF_LONG in Posix */
-#define UNIV_WORD_SIZE SIZEOF_LONG
-#endif
+#define UNIV_WORD_SIZE SIZEOF_SIZE_T
/** The following alignment is used in memory allocations in memory heap
management to ensure correct alignment for doubles etc. */
#define UNIV_MEM_ALIGNMENT 8
-/** The following alignment is used in aligning lints etc. */
-#define UNIV_WORD_ALIGNMENT UNIV_WORD_SIZE
-
/*
DATABASE VERSION CONTROL
========================
@@ -478,13 +468,12 @@ the word size of the machine, that is on a 32-bit platform 32 bits, and on a
macro ULINTPF. */
-#ifdef __WIN__
+#ifdef _WIN32
/* Use the integer types and formatting strings defined in Visual Studio. */
-# define UINT32PF "%I32u"
-# define INT64PF "%I64d"
-# define UINT64PF "%I64u"
-# define UINT64PFx "%016I64x"
-# define DBUG_LSN_PF "%llu"
+# define UINT32PF "%u"
+# define INT64PF "%lld"
+# define UINT64PF "%llu"
+# define UINT64PFx "%016llx"
typedef __int64 ib_int64_t;
typedef unsigned __int64 ib_uint64_t;
typedef unsigned __int32 ib_uint32_t;
@@ -494,13 +483,12 @@ typedef unsigned __int32 ib_uint32_t;
# define INT64PF "%" PRId64
# define UINT64PF "%" PRIu64
# define UINT64PFx "%016" PRIx64
-# define DBUG_LSN_PF UINT64PF
typedef int64_t ib_int64_t;
typedef uint64_t ib_uint64_t;
typedef uint32_t ib_uint32_t;
-# endif /* __WIN__ */
+#endif
-# define IB_ID_FMT UINT64PF
+#define IB_ID_FMT UINT64PF
/* Type used for all log sequence number storage and arithmetics */
typedef ib_uint64_t lsn_t;
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index 0d555ed2dd7..717fbf02536 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -1762,7 +1762,6 @@ wsrep_kill_victim(
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
- mutex_enter(&trx_sys->mutex);
if (bf_this) {
fputs("\n*** Priority TRANSACTION:\n",
stderr);
@@ -1771,7 +1770,7 @@ wsrep_kill_victim(
stderr);
}
- trx_print_latched(stderr, trx, 3000);
+ wsrep_trx_print_locking(stderr, trx, 3000);
if (bf_other) {
fputs("\n*** Priority TRANSACTION:\n",
@@ -1780,10 +1779,7 @@ wsrep_kill_victim(
fputs("\n*** Victim TRANSACTION:\n",
stderr);
}
-
- trx_print_latched(stderr, lock->trx, 3000);
-
- mutex_exit(&trx_sys->mutex);
+ wsrep_trx_print_locking(stderr, lock->trx, 3000);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
stderr);
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index 6b7c8d77824..120f1432ccf 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -1728,7 +1728,7 @@ recv_recover_page_func(
}
DBUG_PRINT("ib_log",
- ("apply " DBUG_LSN_PF ": %u len %u "
+ ("apply " LSN_PF ": %u len %u "
"page %u:%u", recv->start_lsn,
(unsigned) recv->type,
(unsigned) recv->len,
@@ -2391,7 +2391,7 @@ loop:
recv_sys->recovered_lsn = new_recovered_lsn;
DBUG_PRINT("ib_log",
- ("scan " DBUG_LSN_PF ": log rec %u len %u "
+ ("scan " LSN_PF ": log rec %u len %u "
"page %u:%u", old_lsn,
(unsigned) type, (unsigned) len,
(unsigned) space, (unsigned) page_no));
@@ -2483,7 +2483,7 @@ loop:
#endif /* UNIV_LOG_DEBUG */
DBUG_PRINT("ib_log",
- ("scan " DBUG_LSN_PF ": multi-log rec %u "
+ ("scan " LSN_PF ": multi-log rec %u "
"len %u page %u:%u",
recv_sys->recovered_lsn,
(unsigned) type, (unsigned) len,
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index ed84834e6ea..03200fee80b 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
-Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2013, 2017, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
@@ -339,21 +339,6 @@ UNIV_INTERN time_t os_last_printout;
UNIV_INTERN ibool os_has_said_disk_full = FALSE;
-#if !defined(UNIV_HOTBACKUP) \
- && (!defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8)
-/** The mutex protecting the following counts of pending I/O operations */
-static os_ib_mutex_t os_file_count_mutex;
-#endif /* !UNIV_HOTBACKUP && (!HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8) */
-
-/** Number of pending os_file_pread() operations */
-UNIV_INTERN ulint os_file_n_pending_preads;
-/** Number of pending os_file_pwrite() operations */
-UNIV_INTERN ulint os_file_n_pending_pwrites;
-/** Number of pending write operations */
-UNIV_INTERN ulint os_n_pending_writes;
-/** Number of pending read operations */
-UNIV_INTERN ulint os_n_pending_reads;
-
#if defined(WIN_ASYNC_IO) || defined(LINUX_NATIVE_AIO)
/** After first fallocate failure we will disable os_file_trim */
static bool os_fallocate_failed;
@@ -1021,10 +1006,6 @@ void
os_io_init_simple(void)
/*===================*/
{
-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
- os_file_count_mutex = os_mutex_create();
-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8 */
-
for (ulint i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
os_file_seek_mutexes[i] = os_mutex_create();
}
@@ -2811,10 +2792,6 @@ os_file_pread(
trx_t* trx)
{
off_t offs;
-#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
- ssize_t n_bytes;
- ssize_t n_read;
-#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
ulint sec;
ulint ms;
ib_uint64_t start_time;
@@ -2844,22 +2821,16 @@ os_file_pread(
} else {
start_time = 0;
}
-#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
- (void) os_atomic_increment_ulint(&os_n_pending_reads, 1);
- (void) os_atomic_increment_ulint(&os_file_n_pending_preads, 1);
- MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS);
-#else
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_preads++;
- os_n_pending_reads++;
- MONITOR_INC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */
+
+ const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS);
+#ifdef HAVE_PREAD
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor);
+
+ ssize_t n_bytes;
/* Handle partial reads and signal interruptions correctly */
for (n_bytes = 0; n_bytes < (ssize_t) n; ) {
- n_read = pread(file, buf, (ssize_t)n - n_bytes, offs);
+ ssize_t n_read = pread(file, buf, (ssize_t)n - n_bytes, offs);
if (n_read > 0) {
n_bytes += n_read;
offs += n_read;
@@ -2871,17 +2842,7 @@ os_file_pread(
}
}
-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
- (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1);
- (void) os_atomic_decrement_ulint(&os_file_n_pending_preads, 1);
- MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_READS);
-#else
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_preads--;
- os_n_pending_reads--;
- MONITOR_DEC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD == 8 */
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor);
if (UNIV_UNLIKELY(start_time != 0))
{
@@ -2900,15 +2861,7 @@ os_file_pread(
ulint i;
#endif /* !UNIV_HOTBACKUP */
-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
- (void) os_atomic_increment_ulint(&os_n_pending_reads, 1);
- MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_READS);
-#else
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads++;
- MONITOR_INC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD == 8 */
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor);
#ifndef UNIV_HOTBACKUP
/* Protect the seek / read operation with a mutex */
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
@@ -2938,15 +2891,7 @@ os_file_pread(
os_mutex_exit(os_file_seek_mutexes[i]);
#endif /* !UNIV_HOTBACKUP */
-#if defined(HAVE_ATOMIC_BUILTINS) && UNIV_WORD_SIZE == 8
- (void) os_atomic_decrement_ulint(&os_n_pending_reads, 1);
- MONITOR_ATOIC_DEC(MONITOR_OS_PENDING_READS);
-#else
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads--;
- MONITOR_DEC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
-#endif /* HAVE_ATOMIC_BUILTINS && UNIV_WORD_SIZE == 8 */
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor);
if (UNIV_UNLIKELY(start_time != 0)
{
@@ -2992,18 +2937,9 @@ os_file_pwrite(
os_n_file_writes++;
-#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_pwrites++;
- os_n_pending_writes++;
- MONITOR_INC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
-#else
- (void) os_atomic_increment_ulint(&os_n_pending_writes, 1);
- (void) os_atomic_increment_ulint(&os_file_n_pending_pwrites, 1);
- MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES);
-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */
+ const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES);
+#ifdef HAVE_PWRITE
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
/* Handle partial writes and signal interruptions correctly */
for (ret = 0; ret < (ssize_t) n; ) {
@@ -3022,17 +2958,7 @@ os_file_pwrite(
}
}
-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
- os_mutex_enter(os_file_count_mutex);
- os_file_n_pending_pwrites--;
- os_n_pending_writes--;
- MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
-#else
- (void) os_atomic_decrement_ulint(&os_n_pending_writes, 1);
- (void) os_atomic_decrement_ulint(&os_file_n_pending_pwrites, 1);
- MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_WRITES);
-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD < 8 */
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
return(ret);
#else
@@ -3042,10 +2968,7 @@ os_file_pwrite(
ulint i;
# endif /* !UNIV_HOTBACKUP */
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_writes++;
- MONITOR_INC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
# ifndef UNIV_HOTBACKUP
/* Protect the seek / write operation with a mutex */
@@ -3079,14 +3002,10 @@ func_exit:
os_mutex_exit(os_file_seek_mutexes[i]);
# endif /* !UNIV_HOTBACKUP */
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_writes--;
- MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
-
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
return(ret);
}
-#endif /* !UNIV_HOTBACKUP */
+#endif /* HAVE_PWRITE */
}
#endif
@@ -3118,15 +3037,13 @@ os_file_read_func(
os_n_file_reads++;
os_bytes_read_since_printout += n;
+ const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS);
try_again:
ut_ad(buf);
ut_ad(n > 0);
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads++;
- MONITOR_INC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor);
memset (&overlapped, 0, sizeof (overlapped));
overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF);
@@ -3139,10 +3056,7 @@ try_again:
else if(GetLastError() == ERROR_IO_PENDING) {
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
}
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads--;
- MONITOR_DEC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor);
if (ret && len == n) {
return(TRUE);
@@ -3226,15 +3140,13 @@ os_file_read_no_error_handling_func(
os_n_file_reads++;
os_bytes_read_since_printout += n;
+ const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_READS);
try_again:
ut_ad(buf);
ut_ad(n > 0);
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads++;
- MONITOR_INC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_READS, monitor);
memset (&overlapped, 0, sizeof (overlapped));
overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF);
@@ -3247,10 +3159,7 @@ try_again:
else if(GetLastError() == ERROR_IO_PENDING) {
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
}
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_reads--;
- MONITOR_DEC(MONITOR_OS_PENDING_READS);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_READS, monitor);
if (ret && len == n) {
return(TRUE);
@@ -3344,13 +3253,10 @@ os_file_write_func(
ut_ad(buf);
ut_ad(n > 0);
-
+ const bool monitor = MONITOR_IS_ON(MONITOR_OS_PENDING_WRITES);
retry:
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_writes++;
- MONITOR_INC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_INC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
memset (&overlapped, 0, sizeof (overlapped));
overlapped.Offset = (DWORD)(offset & 0xFFFFFFFF);
@@ -3365,10 +3271,7 @@ retry:
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
}
- os_mutex_enter(os_file_count_mutex);
- os_n_pending_writes--;
- MONITOR_DEC(MONITOR_OS_PENDING_WRITES);
- os_mutex_exit(os_file_count_mutex);
+ MONITOR_ATOMIC_DEC_LOW(MONITOR_OS_PENDING_WRITES, monitor);
if (ret && len == n) {
@@ -4463,10 +4366,6 @@ os_aio_free(void)
}
}
-#if !defined(HAVE_ATOMIC_BUILTINS) || UNIV_WORD_SIZE < 8
- os_mutex_free(os_file_count_mutex);
-#endif /* !HAVE_ATOMIC_BUILTINS || UNIV_WORD_SIZE < 8 */
-
for (ulint i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
os_mutex_free(os_file_seek_mutexes[i]);
}
@@ -6192,19 +6091,24 @@ os_aio_print(
time_elapsed = 0.001 + difftime(current_time, os_last_printout);
fprintf(file,
- "Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
- "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
- (ulong) fil_n_pending_log_flushes,
- (ulong) fil_n_pending_tablespace_flushes,
- (ulong) os_n_file_reads,
- (ulong) os_n_file_writes,
- (ulong) os_n_fsyncs);
-
- if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) {
+ "Pending flushes (fsync) log: " ULINTPF
+ "; buffer pool: " ULINTPF "\n"
+ ULINTPF " OS file reads, "
+ ULINTPF " OS file writes, "
+ ULINTPF " OS fsyncs\n",
+ fil_n_pending_log_flushes,
+ fil_n_pending_tablespace_flushes,
+ os_n_file_reads,
+ os_n_file_writes,
+ os_n_fsyncs);
+
+ const ulint n_reads = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS));
+ const ulint n_writes = ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES));
+
+ if (n_reads != 0 || n_writes != 0) {
fprintf(file,
- "%lu pending preads, %lu pending pwrites\n",
- (ulong) os_file_n_pending_preads,
- (ulong) os_file_n_pending_pwrites);
+ ULINTPF " pending reads, " ULINTPF " pending writes\n",
+ n_reads, n_writes);
}
if (os_n_file_reads == os_n_file_reads_old) {
diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc
index 29ddffd2587..4542aa31a6c 100644
--- a/storage/xtradb/row/row0ftsort.cc
+++ b/storage/xtradb/row/row0ftsort.cc
@@ -1320,10 +1320,9 @@ row_fts_build_sel_tree_level(
int child_left;
int child_right;
ulint i;
- ulint num_item;
+ ulint num_item = ulint(1) << level;
- start = static_cast<ulint>((1 << level) - 1);
- num_item = static_cast<ulint>(1 << level);
+ start = num_item - 1;
for (i = 0; i < num_item; i++) {
child_left = sel_tree[(start + i) * 2 + 1];
@@ -1392,7 +1391,7 @@ row_fts_build_sel_tree(
treelevel++;
}
- start = (1 << treelevel) - 1;
+ start = (ulint(1) << treelevel) - 1;
for (i = 0; i < (int) fts_sort_pll_degree; i++) {
sel_tree[i + start] = i;
diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc
index 6dc01907710..baa7bcbea09 100644
--- a/storage/xtradb/row/row0import.cc
+++ b/storage/xtradb/row/row0import.cc
@@ -583,8 +583,8 @@ AbstractCallback::init(
} else if (!is_compressed_table() && m_page_size != UNIV_PAGE_SIZE) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Page size %lu of ibd file is not the same "
- "as the server page size %lu",
+ "Page size " ULINTPF " of ibd file is not the same "
+ "as the server page size " ULINTPF,
m_page_size, UNIV_PAGE_SIZE);
return(DB_CORRUPTION);
@@ -593,8 +593,8 @@ AbstractCallback::init(
ib_logf(IB_LOG_LEVEL_ERROR,
"File size " UINT64PF " is not a multiple "
- "of the page size %lu",
- (ib_uint64_t) file_size, (ulong) m_page_size);
+ "of the page size " ULINTPF,
+ (ib_uint64_t) file_size, m_page_size);
return(DB_CORRUPTION);
}
@@ -695,8 +695,8 @@ FetchIndexRootPages::operator() (
if (block->page.offset * m_page_size != offset) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Page offset doesn't match file offset: "
- "page offset: %lu, file offset: %lu",
- (ulint) block->page.offset,
+ "page offset: %u, file offset: " ULINTPF,
+ block->page.offset,
(ulint) (offset / m_page_size));
err = DB_CORRUPTION;
@@ -1134,10 +1134,9 @@ row_import::match_index_columns(
ib_errf(thd, IB_LOG_LEVEL_ERROR,
ER_TABLE_SCHEMA_MISMATCH,
- "Index field count %lu doesn't match"
- " tablespace metadata file value %lu",
- (ulong) index->n_fields,
- (ulong) cfg_index->m_n_fields);
+ "Index field count %u doesn't match"
+ " tablespace metadata file value " ULINTPF,
+ index->n_fields, cfg_index->m_n_fields);
return(DB_ERROR);
}
@@ -1154,34 +1153,31 @@ row_import::match_index_columns(
ER_TABLE_SCHEMA_MISMATCH,
"Index field name %s doesn't match"
" tablespace metadata field name %s"
- " for field position %lu",
- field->name, cfg_field->name, (ulong) i);
+ " for field position " ULINTPF,
+ field->name, cfg_field->name, i);
err = DB_ERROR;
}
if (cfg_field->prefix_len != field->prefix_len) {
ib_errf(thd, IB_LOG_LEVEL_ERROR,
- ER_TABLE_SCHEMA_MISMATCH,
- "Index %s field %s prefix len %lu"
- " doesn't match metadata file value"
- " %lu",
- index->name, field->name,
- (ulong) field->prefix_len,
- (ulong) cfg_field->prefix_len);
+ ER_TABLE_SCHEMA_MISMATCH,
+ "Index %s field %s prefix len %u"
+ " doesn't match metadata file value %u",
+ index->name, field->name,
+ field->prefix_len, cfg_field->prefix_len);
err = DB_ERROR;
}
if (cfg_field->fixed_len != field->fixed_len) {
ib_errf(thd, IB_LOG_LEVEL_ERROR,
- ER_TABLE_SCHEMA_MISMATCH,
- "Index %s field %s fixed len %lu"
- " doesn't match metadata file value"
- " %lu",
- index->name, field->name,
- (ulong) field->fixed_len,
- (ulong) cfg_field->fixed_len);
+ ER_TABLE_SCHEMA_MISMATCH,
+ "Index %s field %s fixed len %u"
+ " doesn't match metadata file value %u",
+ index->name, field->name,
+ field->fixed_len,
+ cfg_field->fixed_len);
err = DB_ERROR;
}
@@ -1223,12 +1219,11 @@ row_import::match_table_columns(
} else if (cfg_col_index != col->ind) {
ib_errf(thd, IB_LOG_LEVEL_ERROR,
- ER_TABLE_SCHEMA_MISMATCH,
- "Column %s ordinal value mismatch, it's at "
- "%lu in the table and %lu in the tablespace "
- "meta-data file",
- col_name,
- (ulong) col->ind, (ulong) cfg_col_index);
+ ER_TABLE_SCHEMA_MISMATCH,
+ "Column %s ordinal value mismatch, it's at %u"
+ " in the table and " ULINTPF
+ " in the tablespace meta-data file",
+ col_name, col->ind, cfg_col_index);
err = DB_ERROR;
} else {
@@ -1310,23 +1305,20 @@ row_import::match_schema(
THD* thd) UNIV_NOTHROW
{
/* Do some simple checks. */
- const unsigned relevant_flags = m_flags & ~DICT_TF_MASK_DATA_DIR;
- const unsigned relevant_table_flags
- = m_table->flags & ~DICT_TF_MASK_DATA_DIR;
- if (relevant_flags != relevant_table_flags) {
+ if ((m_table->flags ^ m_flags) & ~DICT_TF_MASK_DATA_DIR) {
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
- "Table flags don't match, server table has 0x%x "
- "and the meta-data file has 0x%x",
- relevant_table_flags, relevant_flags);
+ "Table flags don't match, server table has 0x%x"
+ " and the meta-data file has 0x%lx",
+ m_table->flags, ulong(m_flags));
return(DB_ERROR);
} else if (m_table->n_cols != m_n_cols) {
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
- "Number of columns don't match, table has %lu "
- "columns but the tablespace meta-data file has "
- "%lu columns",
- (ulong) m_table->n_cols, (ulong) m_n_cols);
+ "Number of columns don't match, table has %u "
+ "columns but the tablespace meta-data file has "
+ ULINTPF " columns",
+ m_table->n_cols, m_n_cols);
return(DB_ERROR);
} else if (UT_LIST_GET_LEN(m_table->indexes) != m_n_indexes) {
@@ -1336,11 +1328,10 @@ row_import::match_schema(
table matching the IMPORT definition. */
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
- "Number of indexes don't match, table has %lu "
- "indexes but the tablespace meta-data file has "
- "%lu indexes",
- (ulong) UT_LIST_GET_LEN(m_table->indexes),
- (ulong) m_n_indexes);
+ "Number of indexes don't match, table has " ULINTPF
+ " indexes but the tablespace meta-data file has "
+ ULINTPF " indexes",
+ UT_LIST_GET_LEN(m_table->indexes), m_n_indexes);
return(DB_ERROR);
}
@@ -1416,8 +1407,8 @@ row_import::set_root_by_heuristic() UNIV_NOTHROW
table_name, sizeof(table_name), m_table->name, FALSE);
ib_logf(IB_LOG_LEVEL_WARN,
- "Table %s should have %lu indexes but the tablespace "
- "has %lu indexes",
+ "Table %s should have " ULINTPF
+ " indexes but the tablespace has " ULINTPF " indexes",
table_name,
UT_LIST_GET_LEN(m_table->indexes),
m_n_indexes);
@@ -1655,9 +1646,10 @@ PageConverter::adjust_cluster_index_blob_column(
ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR,
ER_INNODB_INDEX_CORRUPT,
- "Externally stored column(%lu) has a reference "
- "length of %lu in the cluster index %s",
- (ulong) i, (ulong) len, index_name);
+ "Externally stored column(" ULINTPF
+ ") has a reference length of " ULINTPF
+ " in the cluster index %s",
+ i, len, index_name);
return(DB_CORRUPTION);
}
@@ -2021,7 +2013,8 @@ PageConverter::update_page(
return(err);
}
- ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (%lu)", page_type);
+ ib_logf(IB_LOG_LEVEL_WARN, "Unknown page type (" ULINTPF ")",
+ page_type);
return(DB_CORRUPTION);
}
@@ -2058,7 +2051,8 @@ PageConverter::validate(
if (checksum != 0) {
/* Checksum check passed in buf_page_is_corrupted(). */
ib_logf(IB_LOG_LEVEL_WARN,
- "%s: Page %lu checksum %lu should be zero.",
+ "%s: Page %lu checksum " ULINTPF
+ " should be zero.",
m_filepath, (ulong) (offset / m_page_size),
checksum);
}
@@ -2372,11 +2366,10 @@ row_import_adjust_root_pages_of_secondary_indexes(
ib_errf(trx->mysql_thd,
IB_LOG_LEVEL_WARN,
ER_INNODB_INDEX_CORRUPT,
- "Index '%s' contains %lu entries, "
- "should be %lu, you should recreate "
+ "Index '%s' contains " ULINTPF " entries, "
+ "should be " ULINTPF ", you should recreate "
"this index.", index_name,
- (ulong) purge.get_n_rows(),
- (ulong) n_rows_in_table);
+ purge.get_n_rows(), n_rows_in_table);
index->type |= DICT_CORRUPT;
@@ -2727,7 +2720,7 @@ row_import_read_index_data(
if (len > OS_FILE_MAX_PATH) {
ib_errf(thd, IB_LOG_LEVEL_ERROR,
ER_INNODB_INDEX_CORRUPT,
- "Index name length (%lu) is too long, "
+ "Index name length (" ULINTPF ") is too long, "
"the meta-data is corrupt", len);
return(DB_CORRUPTION);
@@ -2808,8 +2801,8 @@ row_import_read_indexes(
} else if (cfg->m_n_indexes > 1024) {
// FIXME: What is the upper limit? */
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
- "Number of indexes in meta-data file is too high: %lu",
- (ulong) cfg->m_n_indexes);
+ "Number of indexes in meta-data file is too high: "
+ ULINTPF, cfg->m_n_indexes);
cfg->m_n_indexes = 0;
return(DB_CORRUPTION);
@@ -2907,8 +2900,8 @@ row_import_read_columns(
if (len == 0 || len > 128) {
ib_errf(thd, IB_LOG_LEVEL_ERROR,
ER_IO_READ_ERROR,
- "Column name length %lu, is invalid",
- (ulong) len);
+ "Column name length " ULINTPF ", is invalid",
+ len);
return(DB_CORRUPTION);
}
@@ -3079,8 +3072,9 @@ row_import_read_v1(
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH,
"Tablespace to be imported has a different "
"page size than this server. Server page size "
- "is %lu, whereas tablespace page size is %lu",
- UNIV_PAGE_SIZE, (ulong) cfg->m_page_size);
+ "is " ULINTPF ", whereas tablespace page size is "
+ ULINTPF,
+ UNIV_PAGE_SIZE, cfg->m_page_size);
return(DB_ERROR);
}
@@ -3145,8 +3139,8 @@ row_import_read_meta_data(
return(row_import_read_v1(file, thd, &cfg));
default:
ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
- "Unsupported meta-data version number (%lu), "
- "file ignored", (ulong) cfg.m_version);
+ "Unsupported meta-data version number (" ULINTPF "), "
+ "file ignored", cfg.m_version);
}
return(DB_ERROR);
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index 72be305d481..24cd9687a47 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2014, 2017, MariaDB Corporation.
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
@@ -26,6 +26,7 @@ Completed by Sunny Bains and Marko Makela
*******************************************************/
#include <my_config.h>
#include <log.h>
+#include <sql_class.h>
#include "row0merge.h"
#include "row0ext.h"
@@ -188,7 +189,8 @@ row_merge_tuple_print(
}
ut_print_buf(f, dfield_get_data(field), len);
if (len != field_len) {
- fprintf(f, " (total %lu bytes)", field_len);
+ fprintf(f, " (total " ULINTPF " bytes)",
+ field_len);
}
}
}
@@ -881,9 +883,9 @@ row_merge_buf_write(
ut_ad(b < &block[srv_sort_buf_size]);
#ifdef UNIV_DEBUG
if (row_merge_print_write) {
- fprintf(stderr, "row_merge_buf_write %p,%d,%lu %lu",
- (void*) b, of->fd, (ulong) of->offset,
- (ulong) i);
+ fprintf(stderr, "row_merge_buf_write %p,%d,"
+ ULINTPF " " ULINTPF,
+ (void*) b, of->fd, of->offset, i);
row_merge_tuple_print(stderr, entry, n_fields);
}
#endif /* UNIV_DEBUG */
@@ -900,8 +902,8 @@ row_merge_buf_write(
#endif /* UNIV_DEBUG_VALGRIND */
#ifdef UNIV_DEBUG
if (row_merge_print_write) {
- fprintf(stderr, "row_merge_buf_write %p,%d,%lu EOF\n",
- (void*) b, of->fd, (ulong) of->offset);
+ fprintf(stderr, "row_merge_buf_write %p,%d," ULINTPF " EOF\n",
+ (void*) b, of->fd, of->offset);
}
#endif /* UNIV_DEBUG */
}
@@ -960,15 +962,8 @@ row_merge_read(
#ifdef UNIV_DEBUG
if (row_merge_print_block_read) {
- fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n",
- fd, (ulong) offset);
- }
-#endif /* UNIV_DEBUG */
-
-#ifdef UNIV_DEBUG
- if (row_merge_print_block_read) {
- fprintf(stderr, "row_merge_read fd=%d ofs=%lu\n",
- fd, (ulong) offset);
+ fprintf(stderr, "row_merge_read fd=%d ofs=" ULINTPF "\n",
+ fd, offset);
}
#endif /* UNIV_DEBUG */
@@ -1032,8 +1027,8 @@ row_merge_write(
#ifdef UNIV_DEBUG
if (row_merge_print_block_write) {
- fprintf(stderr, "row_merge_write fd=%d ofs=%lu\n",
- fd, (ulong) offset);
+ fprintf(stderr, "row_merge_write fd=%d ofs=" ULINTPF "\n",
+ fd, offset);
}
#endif /* UNIV_DEBUG */
@@ -1088,9 +1083,10 @@ row_merge_read_rec(
*mrec = NULL;
#ifdef UNIV_DEBUG
if (row_merge_print_read) {
- fprintf(stderr, "row_merge_read %p,%p,%d,%lu EOF\n",
+ fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF
+ " EOF\n",
(const void*) b, (const void*) block,
- fd, (ulong) *foffs);
+ fd, *foffs);
}
#endif /* UNIV_DEBUG */
return(NULL);
@@ -1208,9 +1204,9 @@ err_exit:
func_exit:
#ifdef UNIV_DEBUG
if (row_merge_print_read) {
- fprintf(stderr, "row_merge_read %p,%p,%d,%lu ",
+ fprintf(stderr, "row_merge_read %p,%p,%d," ULINTPF " ",
(const void*) b, (const void*) block,
- fd, (ulong) *foffs);
+ fd, *foffs);
rec_print_comp(stderr, *mrec, offsets);
putc('\n', stderr);
}
@@ -1244,8 +1240,8 @@ row_merge_write_rec_low(
ut_ad(e == rec_offs_extra_size(offsets) + 1);
if (row_merge_print_write) {
- fprintf(stderr, "row_merge_write %p,%d,%lu ",
- (void*) b, fd, (ulong) foffs);
+ fprintf(stderr, "row_merge_write %p,%d," ULINTPF " ",
+ (void*) b, fd, foffs);
rec_print_comp(stderr, mrec, offsets);
putc('\n', stderr);
}
@@ -1358,8 +1354,8 @@ row_merge_write_eof(
ut_ad(foffs);
#ifdef UNIV_DEBUG
if (row_merge_print_write) {
- fprintf(stderr, "row_merge_write %p,%p,%d,%lu EOF\n",
- (void*) b, (void*) block, fd, (ulong) *foffs);
+ fprintf(stderr, "row_merge_write %p,%p,%d," ULINTPF " EOF\n",
+ (void*) b, (void*) block, fd, *foffs);
}
#endif /* UNIV_DEBUG */
@@ -2258,11 +2254,12 @@ row_merge_blocks(
#ifdef UNIV_DEBUG
if (row_merge_print_block) {
fprintf(stderr,
- "row_merge_blocks fd=%d ofs=%lu + fd=%d ofs=%lu"
- " = fd=%d ofs=%lu\n",
- file->fd, (ulong) *foffs0,
- file->fd, (ulong) *foffs1,
- of->fd, (ulong) of->offset);
+ "row_merge_blocks fd=%d ofs=" ULINTPF
+ " + fd=%d ofs=" ULINTPF
+ " = fd=%d ofs=" ULINTPF "\n",
+ file->fd, *foffs0,
+ file->fd, *foffs1,
+ of->fd, of->offset);
}
#endif /* UNIV_DEBUG */
@@ -2373,10 +2370,10 @@ row_merge_blocks_copy(
#ifdef UNIV_DEBUG
if (row_merge_print_block) {
fprintf(stderr,
- "row_merge_blocks_copy fd=%d ofs=%lu"
- " = fd=%d ofs=%lu\n",
- file->fd, (ulong) foffs0,
- of->fd, (ulong) of->offset);
+ "row_merge_blocks_copy fd=%d ofs=" ULINTPF
+ " = fd=%d ofs=" ULINTPF "\n",
+ file->fd, *foffs0,
+ of->fd, of->offset);
}
#endif /* UNIV_DEBUG */
@@ -2635,7 +2632,11 @@ row_merge_sort(
thd_progress_init(trx->mysql_thd, 1);
}
- sql_print_information("InnoDB: Online DDL : merge-sorting has estimated %lu runs", num_runs);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : merge-sorting"
+ " has estimated " ULINTPF " runs",
+ num_runs);
+ }
/* Merge the runs until we have one big run */
do {
@@ -4060,9 +4061,11 @@ row_merge_build_indexes(
duplicate keys. */
innobase_rec_reset(table);
- sql_print_information("InnoDB: Online DDL : Start");
- sql_print_information("InnoDB: Online DDL : Start reading clustered "
- "index of the table and create temporary files");
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : Start reading"
+ " clustered index of the table"
+ " and create temporary files");
+ }
pct_cost = COST_READ_CLUSTERED_INDEX * 100 / (total_static_cost + total_dynamic_cost);
@@ -4089,8 +4092,11 @@ row_merge_build_indexes(
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : End of reading "
- "clustered index of the table and create temporary files");
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL : End of reading "
+ "clustered index of the table"
+ " and create temporary files");
+ }
for (i = 0; i < n_indexes; i++) {
total_index_blocks += merge_files[i].offset;
@@ -4186,8 +4192,7 @@ wait_again:
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
#endif
} else if (merge_files[i].fd != -1) {
- char buf[3 * NAME_LEN];
- char *bufend;
+ char buf[NAME_LEN + 1];
row_merge_dup_t dup = {
sort_idx, table, col_map, 0};
@@ -4196,18 +4201,25 @@ wait_again:
total_index_blocks)) /
(total_static_cost + total_dynamic_cost)
* PCT_COST_MERGESORT_INDEX * 100;
-
- bufend = innobase_convert_name(
+ char* bufend = innobase_convert_name(
buf, sizeof buf,
- indexes[i]->name, strlen(indexes[i]->name),
+ indexes[i]->name,
+ strlen(indexes[i]->name),
trx->mysql_thd,
FALSE);
-
buf[bufend - buf]='\0';
- sql_print_information("InnoDB: Online DDL : Start merge-sorting"
- " index %s (%lu / %lu), estimated cost : %2.4f",
- buf, (i+1), n_indexes, pct_cost);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL :"
+ " Start merge-sorting"
+ " index %s"
+ " (" ULINTPF
+ " / " ULINTPF "),"
+ " estimated cost :"
+ " %2.4f",
+ buf, i + 1, n_indexes,
+ pct_cost);
+ }
error = row_merge_sort(
trx, &dup, &merge_files[i],
@@ -4217,9 +4229,14 @@ wait_again:
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : End of "
- " merge-sorting index %s (%lu / %lu)",
- buf, (i+1), n_indexes);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information("InnoDB: Online DDL :"
+ " End of "
+ " merge-sorting index %s"
+ " (" ULINTPF
+ " / " ULINTPF ")",
+ buf, i + 1, n_indexes);
+ }
DBUG_EXECUTE_IF(
"ib_merge_wait_after_sort",
@@ -4232,10 +4249,15 @@ wait_again:
(total_static_cost + total_dynamic_cost) *
PCT_COST_INSERT_INDEX * 100;
- sql_print_information("InnoDB: Online DDL : Start "
- "building index %s (%lu / %lu), estimated "
- "cost : %2.4f", buf, (i+1),
- n_indexes, pct_cost);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : Start "
+ "building index %s"
+ " (" ULINTPF
+ " / " ULINTPF "), estimated "
+ "cost : %2.4f", buf, i + 1,
+ n_indexes, pct_cost);
+ }
error = row_merge_insert_index_tuples(
trx->id, sort_idx, old_table,
@@ -4244,9 +4266,13 @@ wait_again:
crypt_data, crypt_block, new_table->space);
pct_progress += pct_cost;
- sql_print_information("InnoDB: Online DDL : "
- "End of building index %s (%lu / %lu)",
- buf, (i+1), n_indexes);
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : "
+ "End of building index %s"
+ " (" ULINTPF " / " ULINTPF ")",
+ buf, i + 1, n_indexes);
+ }
}
}
@@ -4263,15 +4289,16 @@ wait_again:
ut_ad(sort_idx->online_status
== ONLINE_INDEX_COMPLETE);
} else {
- sql_print_information("InnoDB: Online DDL : Start applying row log");
+ if (global_system_variables.log_warnings > 2) {
+ sql_print_information(
+ "InnoDB: Online DDL : Applying"
+ " log to index");
+ }
DEBUG_SYNC_C("row_log_apply_before");
error = row_log_apply(trx, sort_idx, table);
DEBUG_SYNC_C("row_log_apply_after");
- sql_print_information("InnoDB: Online DDL : End of applying row log");
}
- sql_print_information("InnoDB: Online DDL : Completed");
-
if (error != DB_SUCCESS) {
trx->error_key_num = key_numbers[i];
goto func_exit;
diff --git a/storage/xtradb/srv/srv0mon.cc b/storage/xtradb/srv/srv0mon.cc
index 7c2e549e188..47abae66192 100644
--- a/storage/xtradb/srv/srv0mon.cc
+++ b/storage/xtradb/srv/srv0mon.cc
@@ -2,7 +2,7 @@
Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2016, MariaDB Corporation.
+Copyright (c) 2013, 2017, MariaDB Corporation.
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
@@ -690,11 +690,11 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_DEFAULT_START, MONITOR_OVLD_OS_FSYNC},
{"os_pending_reads", "os", "Number of reads pending",
- MONITOR_NONE,
+ MONITOR_DEFAULT_ON,
MONITOR_DEFAULT_START, MONITOR_OS_PENDING_READS},
{"os_pending_writes", "os", "Number of writes pending",
- MONITOR_NONE,
+ MONITOR_DEFAULT_ON,
MONITOR_DEFAULT_START, MONITOR_OS_PENDING_WRITES},
{"os_log_bytes_written", "os",
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index f8c8c330f0c..1c40baee04b 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1814,10 +1814,10 @@ srv_export_innodb_status(void)
mutex_enter(&srv_innodb_monitor_mutex);
export_vars.innodb_data_pending_reads =
- os_n_pending_reads;
+ ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS));
export_vars.innodb_data_pending_writes =
- os_n_pending_writes;
+ ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES));
export_vars.innodb_data_pending_fsyncs =
fil_n_pending_log_flushes
diff --git a/storage/xtradb/sync/sync0arr.cc b/storage/xtradb/sync/sync0arr.cc
index c311d2cbd7d..134d16ae58e 100644
--- a/storage/xtradb/sync/sync0arr.cc
+++ b/storage/xtradb/sync/sync0arr.cc
@@ -522,13 +522,14 @@ sync_array_cell_print(
if (mutex) {
fprintf(file,
"Mutex at %p '%s', lock var %lu\n"
- "Last time reserved by thread %lu in file %s line %lu, "
- "waiters flag %lu\n",
+ "Last time reserved by thread " ULINTPF
+ " in file %s line " ULINTPF ", "
+ "waiters flag " ULINTPF "\n",
(void*) mutex, mutex->cmutex_name,
(ulong) mutex->lock_word,
- mutex->thread_id,
- mutex->file_name, (ulong) mutex->line,
- (ulong) mutex->waiters);
+ os_thread_pf(mutex->thread_id),
+ mutex->file_name, mutex->line,
+ mutex->waiters);
}
/* If stacktrace feature is enabled we will send a SIGUSR2
@@ -582,9 +583,9 @@ sync_array_cell_print(
if (writer && writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
- "a writer (thread id %lu) has"
+ "a writer (thread id " ULINTPF ") has"
" reserved it in mode %s",
- (ulong) os_thread_pf(rwlock->writer_thread),
+ os_thread_pf(rwlock->writer_thread),
writer == RW_LOCK_EX
? " exclusive\n"
: " wait exclusive\n");
@@ -593,21 +594,23 @@ sync_array_cell_print(
}
fprintf(file,
- "number of readers %lu, waiters flag %lu, "
+ "number of readers " ULINTPF
+ ", waiters flag " ULINTPF ", "
"lock_word: %lx\n"
- "Last time read locked in file %s line %lu\n"
- "Last time write locked in file %s line %lu\n",
- (ulong) rw_lock_get_reader_count(rwlock),
- (ulong) rwlock->waiters,
+ "Last time read locked in file %s line %u\n"
+ "Last time write locked in file %s line %u\n"
+ "Holder thread " ULINTPF
+ " file %s line " ULINTPF "\n",
+ rw_lock_get_reader_count(rwlock),
+ rwlock->waiters,
rwlock->lock_word,
innobase_basename(rwlock->last_s_file_name),
- (ulong) rwlock->last_s_line,
- rwlock->last_x_file_name,
- (ulong) rwlock->last_x_line);
-
- fprintf(file,
- "Holder thread %lu file %s line %lu\n",
- rwlock->thread_id, rwlock->file_name, rwlock->line);
+ rwlock->last_s_line,
+ innobase_basename(rwlock->last_x_file_name),
+ rwlock->last_x_line,
+ os_thread_pf(rwlock->thread_id),
+ innobase_basename(rwlock->file_name),
+ rwlock->line);
/* If stacktrace feature is enabled we will send a SIGUSR2
signal to thread that has locked RW-latch with write mode.
@@ -1175,9 +1178,10 @@ sync_array_print_long_waits(
now the values of pending calls of these. */
fprintf(stderr,
- "InnoDB: Pending preads %lu, pwrites %lu\n",
- (ulong) os_file_n_pending_preads,
- (ulong) os_file_n_pending_pwrites);
+ "InnoDB: Pending reads " UINT64PF
+ ", writes " UINT64PF "\n",
+ MONITOR_VALUE(MONITOR_OS_PENDING_READS),
+ MONITOR_VALUE(MONITOR_OS_PENDING_WRITES));
srv_print_innodb_monitor = TRUE;
os_event_set(srv_monitor_event);
diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc
index 439897a5b96..92d7525ea84 100644
--- a/storage/xtradb/trx/trx0trx.cc
+++ b/storage/xtradb/trx/trx0trx.cc
@@ -2161,6 +2161,118 @@ trx_print_latched(
mem_heap_get_size(trx->lock.lock_heap));
}
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+/*==========*/
+ FILE* f,
+ /*!< in: output stream */
+ const trx_t* trx,
+ /*!< in: transaction */
+ ulint max_query_len)
+ /*!< in: max query length to print,
+ or 0 to use the default max length */
+{
+ ibool newline;
+ const char* op_info;
+
+ ut_ad(lock_mutex_own());
+ ut_ad(trx->lock.trx_locks.count > 0);
+
+ fprintf(f, "TRANSACTION " TRX_ID_FMT, trx->id);
+
+ /* trx->state may change since trx_sys->mutex is not required */
+ switch (trx->state) {
+ case TRX_STATE_NOT_STARTED:
+ fputs(", not started", f);
+ goto state_ok;
+ case TRX_STATE_ACTIVE:
+ fprintf(f, ", ACTIVE %lu sec",
+ (ulong) difftime(time(NULL), trx->start_time));
+ goto state_ok;
+ case TRX_STATE_PREPARED:
+ fprintf(f, ", ACTIVE (PREPARED) %lu sec",
+ (ulong) difftime(time(NULL), trx->start_time));
+ goto state_ok;
+ case TRX_STATE_COMMITTED_IN_MEMORY:
+ fputs(", COMMITTED IN MEMORY", f);
+ goto state_ok;
+ }
+ fprintf(f, ", state %lu", (ulong) trx->state);
+ ut_ad(0);
+state_ok:
+
+ /* prevent a race condition */
+ op_info = trx->op_info;
+
+ if (*op_info) {
+ putc(' ', f);
+ fputs(op_info, f);
+ }
+
+ if (trx->is_recovered) {
+ fputs(" recovered trx", f);
+ }
+
+ if (trx->declared_to_be_inside_innodb) {
+ fprintf(f, ", thread declared inside InnoDB %lu",
+ (ulong) trx->n_tickets_to_enter_innodb);
+ }
+
+ putc('\n', f);
+
+ if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) {
+ fprintf(f, "mysql tables in use %lu, locked %lu\n",
+ (ulong) trx->n_mysql_tables_in_use,
+ (ulong) trx->mysql_n_tables_locked);
+ }
+
+ newline = TRUE;
+
+ /* trx->lock.que_state of an ACTIVE transaction may change
+ while we are not holding trx->mutex. We perform a dirty read
+ for performance reasons. */
+
+ switch (trx->lock.que_state) {
+ case TRX_QUE_RUNNING:
+ newline = FALSE; break;
+ case TRX_QUE_LOCK_WAIT:
+ fputs("LOCK WAIT ", f); break;
+ case TRX_QUE_ROLLING_BACK:
+ fputs("ROLLING BACK ", f); break;
+ case TRX_QUE_COMMITTING:
+ fputs("COMMITTING ", f); break;
+ default:
+ fprintf(f, "que state %lu ", (ulong) trx->lock.que_state);
+ }
+
+ if (trx->has_search_latch) {
+ newline = TRUE;
+ fputs(", holds adaptive hash latch", f);
+ }
+
+ if (trx->undo_no != 0) {
+ newline = TRUE;
+ fprintf(f, ", undo log entries " TRX_ID_FMT, trx->undo_no);
+ }
+
+ if (newline) {
+ putc('\n', f);
+ }
+
+ if (trx->mysql_thd != NULL) {
+ innobase_mysql_print_thd(
+ f, trx->mysql_thd, static_cast<uint>(max_query_len));
+ }
+}
+#endif /* WITH_WSREP */
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */