From 97190fc844c4402e5ce26e2d332c41c5b470e91e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Fri, 16 Dec 2016 16:36:54 +0200
Subject: [PATCH] MySQL 5.7.17 port of MDEV-11585 Hard-code the shared InnoDB
 temporary tablespace ID

MySQL 5.7 supports only one shared temporary tablespace.
Hard-code its ID at ~1UL.

InnoDB is unnecessarily allocating a tablespace ID for the predefined
temporary tablespace on every startup, and it is in several places
testing whether a tablespace ID matches this dynamically generated ID.

We should use a compile-time constant to reduce code size.
---
 storage/innobase/btr/btr0btr.cc         |  2 +-
 storage/innobase/buf/buf0buf.cc         | 11 +++----
 storage/innobase/dict/dict0crea.cc      |  3 +-
 storage/innobase/fil/fil0fil.cc         | 11 ++++---
 storage/innobase/fsp/fsp0fsp.cc         | 53 +++++++++++++--------------------
 storage/innobase/fsp/fsp0space.cc       | 11 -------
 storage/innobase/ibuf/ibuf0ibuf.cc      |  3 +-
 storage/innobase/include/fsp0space.h    |  4 ---
 storage/innobase/include/fsp0sysspace.h | 11 +++----
 storage/innobase/include/fsp0types.h    | 13 ++++++--
 storage/innobase/include/srv0start.h    |  3 --
 storage/innobase/row/row0trunc.cc       |  2 +-
 storage/innobase/srv/srv0start.cc       | 41 ++++++++++---------------
 storage/innobase/trx/trx0sys.cc         |  3 +-
 14 files changed, 71 insertions(+), 100 deletions(-)

diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index a7bc8a21f86..2c6a13da7a6 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -919,7 +919,7 @@ btr_free_root_check(
 	index_id_t		index_id,
 	mtr_t*			mtr)
 {
-	ut_ad(page_id.space() != srv_tmp_space.space_id());
+	ut_ad(page_id.space() != SRV_TMP_SPACE_ID);
 	ut_ad(index_id != BTR_FREED_INDEX_ID);
 
 	buf_block_t*	block = buf_page_get(
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index a5c28f3b948..8bc9d0183a9 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -5729,9 +5729,9 @@ buf_page_io_complete(
 			error injection */
 			DBUG_EXECUTE_IF(
 				"buf_page_import_corrupt_failure",
-				if (bpage->id.space() > TRX_SYS_SPACE
-				    && !Tablespace::is_undo_tablespace(
-					    bpage->id.space())
+				if (bpage->id.space()
+				    > srv_undo_tablespaces_open
+				    && bpage->id.space() != SRV_TMP_SPACE_ID
 				    && buf_mark_space_corrupt(bpage)) {
 					ib::info() << "Simulated IMPORT "
 						"corruption";
@@ -5805,8 +5805,9 @@ corrupt:
 		if (uncompressed
 		    && !Compression::is_compressed_page(frame)
 		    && !recv_no_ibuf_operations
-		    && !Tablespace::is_undo_tablespace(bpage->id.space())
-		    && bpage->id.space() != srv_tmp_space.space_id()
+		    && (bpage->id.space() == 0
+			|| (bpage->id.space() > srv_undo_tablespaces_open
+			    && bpage->id.space() != SRV_TMP_SPACE_ID))
 		    && !srv_is_tablespace_truncated(bpage->id.space())
 		    && fil_page_get_type(frame) == FIL_PAGE_INDEX
 		    && page_is_leaf(frame)) {
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 63e44366fe1..c901a894ea9 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -566,8 +566,7 @@ dict_build_tablespace_for_table(
 			supports Redundant and Compact */
 			ut_ad(dict_tf_get_rec_format(table->flags)
 				!= REC_FORMAT_COMPRESSED);
-			table->space = static_cast<uint32_t>(
-				srv_tmp_space.space_id());
+			table->space = SRV_TMP_SPACE_ID;
 		} else {
 			/* Create in the system tablespace. */
 			ut_ad(table->space == srv_sys_space.space_id());
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index e3de757abeb..2ed23c2fb4f 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -231,7 +231,7 @@ fil_is_user_tablespace_id(
 	ulint	space_id)
 {
 	return(space_id > srv_undo_tablespaces_open
-	       && space_id != srv_tmp_space.space_id());
+	       && space_id != SRV_TMP_SPACE_ID);
 }
 
 #ifdef UNIV_DEBUG
@@ -1356,7 +1356,7 @@ fil_space_create(
 
 	/* This warning is not applicable while MEB scanning the redo logs */
 #ifndef UNIV_HOTBACKUP
-	if (fil_type_is_data(purpose)
+	if ((purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT)
 	    && !recv_recovery_on
 	    && id > fil_system->max_assigned_id) {
 
@@ -5125,10 +5125,13 @@ retry:
 	ulint	pages_per_mb = (1024 * 1024) / page_size;
 	ulint	size_in_pages = ((node->size / pages_per_mb) * pages_per_mb);
 
-	if (space->id == srv_sys_space.space_id()) {
+	switch (space->id) {
+	case TRX_SYS_SPACE:
 		srv_sys_space.set_last_file_size(size_in_pages);
-	} else if (space->id == srv_tmp_space.space_id()) {
+		break;
+	case SRV_TMP_SPACE_ID:
 		srv_tmp_space.set_last_file_size(size_in_pages);
+		break;
 	}
 #else
 	ib::trace() << "extended space : " << space->name << " from "
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 011a786844c..4ca287c65af 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -291,16 +291,6 @@ fsp_flags_is_valid(
 	return(true);
 }
 
-/** Check if tablespace is system temporary.
-@param[in]	space_id	tablespace ID
-@return true if tablespace is system temporary. */
-bool
-fsp_is_system_temporary(
-	ulint	space_id)
-{
-	return(space_id == srv_tmp_space.space_id());
-}
-
 /** Check if checksum is disabled for the given space.
 @param[in]	space_id	tablespace ID
 @return true if checksum is disabled for given space. */
@@ -755,8 +745,7 @@ fsp_space_modify_check(
 #ifdef UNIV_DEBUG
 		{
 			const fil_type_t	type = fil_space_get_type(id);
-			ut_a(id == srv_tmp_space.space_id()
-			     || srv_is_tablespace_truncated(id)
+			ut_a(srv_is_tablespace_truncated(id)
 			     || fil_space_is_being_truncated(id)
 			     || fil_space_get_flags(id) == ULINT_UNDEFINED
 			     || type == FIL_TYPE_TEMPORARY
@@ -766,10 +755,7 @@ fsp_space_modify_check(
 #endif /* UNIV_DEBUG */
 		return;
 	case MTR_LOG_ALL:
-		/* We must not write redo log for the shared temporary
-		tablespace. */
-		ut_ad(id != srv_tmp_space.space_id());
-		/* If we write redo log, the tablespace must exist. */
+		/* We may only write redo log for a persistent tablespace. */
 		ut_ad(fil_space_get_type(id) == FIL_TYPE_TABLESPACE);
 		ut_ad(mtr->is_named_space(id));
 		return;
@@ -1488,15 +1474,14 @@ fsp_try_extend_data_file(
 	const page_size_t	page_size(
 		mach_read_from_4(header + FSP_SPACE_FLAGS));
 
-	if (space->id == srv_sys_space.space_id()) {
-
+	switch (space->id) {
+	case TRX_SYS_SPACE:
 		size_increase = srv_sys_space.get_increment();
-
-	} else if (space->id == srv_tmp_space.space_id()) {
-
+		break;
+	case SRV_TMP_SPACE_ID:
 		size_increase = srv_tmp_space.get_increment();
-
-	} else {
+		break;
+	default:
 		ulint	extent_pages
 			= fsp_get_extent_size_in_pages(page_size);
 		if (size < extent_pages) {
@@ -1614,11 +1599,17 @@ fsp_fill_free_list(
 	const page_size_t	page_size(flags);
 
 	if (size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
-		if ((!init_space && !is_system_tablespace(space->id))
-		    || (space->id == srv_sys_space.space_id()
-			&& srv_sys_space.can_auto_extend_last_file())
-		    || (space->id == srv_tmp_space.space_id()
-			&& srv_tmp_space.can_auto_extend_last_file())) {
+		bool	skip_resize	= init_space;
+		switch (space->id) {
+		case TRX_SYS_SPACE:
+			skip_resize = !srv_sys_space.can_auto_extend_last_file();
+			break;
+		case SRV_TMP_SPACE_ID:
+			skip_resize = srv_tmp_space.can_auto_extend_last_file();
+			break;
+		}
+
+		if (!skip_resize) {
 			fsp_try_extend_data_file(space, header, mtr);
 			size = space->size_in_header;
 		}
@@ -1667,7 +1658,7 @@ fsp_fill_free_list(
 			order, and we must be able to release its latch.
 			Note: Insert-Buffering is disabled for tables that
 			reside in the temp-tablespace. */
-			if (space->id != srv_tmp_space.space_id()) {
+			if (space->purpose != FIL_TYPE_TEMPORARY) {
 				mtr_t	ibuf_mtr;
 
 				mtr_start(&ibuf_mtr);
@@ -1675,9 +1666,7 @@ fsp_fill_free_list(
 
 				/* Avoid logging while truncate table
 				fix-up is active. */
-				if (space->purpose == FIL_TYPE_TEMPORARY
-				    || srv_is_tablespace_truncated(
-					    space->id)) {
+				if (srv_is_tablespace_truncated(space->id)) {
 					mtr_set_log_mode(
 						&ibuf_mtr, MTR_LOG_NO_REDO);
 				}
diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc
index afdcbf7b6b7..9e2f39a9b07 100644
--- a/storage/innobase/fsp/fsp0space.cc
+++ b/storage/innobase/fsp/fsp0space.cc
@@ -207,17 +207,6 @@ Tablespace::delete_files()
 	}
 }
 
-/** Check if undo tablespace.
-@return true if undo tablespace */
-bool
-Tablespace::is_undo_tablespace(
-	ulint	id)
-{
-	return(id <= srv_undo_tablespaces_open
-	       && id != srv_sys_space.space_id()
-	       && id != srv_tmp_space.space_id());
-}
-
 /** Use the ADD DATAFILE path to create a Datafile object and add it to the
 front of m_files.
 Parse the datafile path into a path and a filename with extension 'ibd'.
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 07c698e4f4c..ddcb2829acb 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -3695,9 +3695,10 @@ ibuf_insert(
 			    op, page_id.space(), page_id.page_no()));
 
 	ut_ad(dtuple_check_typed(entry));
-	ut_ad(page_id.space() != srv_tmp_space.space_id());
+	ut_ad(page_id.space() != SRV_TMP_SPACE_ID);
 
 	ut_a(!dict_index_is_clust(index));
+	ut_ad(!dict_table_is_temporary(index->table));
 
 	no_counter = use <= IBUF_USE_INSERT;
 
diff --git a/storage/innobase/include/fsp0space.h b/storage/innobase/include/fsp0space.h
index 1c75d3426be..3aef206f22e 100644
--- a/storage/innobase/include/fsp0space.h
+++ b/storage/innobase/include/fsp0space.h
@@ -202,10 +202,6 @@ public:
 		ut_a(!m_files.empty());
 		return(&m_files.front());
 	}
-
-	/** Check if undo tablespace.
-	@return true if undo tablespace */
-	static bool is_undo_tablespace(ulint id);
 private:
 	/**
 	@param[in]	filename	Name to lookup in the data files.
diff --git a/storage/innobase/include/fsp0sysspace.h b/storage/innobase/include/fsp0sysspace.h
index 8d1bef0a940..f04f6e99f27 100644
--- a/storage/innobase/include/fsp0sysspace.h
+++ b/storage/innobase/include/fsp0sysspace.h
@@ -287,11 +287,9 @@ extern SysTablespace srv_tmp_space;
 @return true if id is a system tablespace, false if not. */
 UNIV_INLINE
 bool
-is_system_tablespace(
-	ulint	id)
+is_system_tablespace(ulint	id)
 {
-	return(id == srv_sys_space.space_id()
-	       || id == srv_tmp_space.space_id());
+	return(id == TRX_SYS_SPACE || id == SRV_TMP_SPACE_ID);
 }
 
 /** Check if shared-system or undo tablespace.
@@ -301,8 +299,7 @@ bool
 is_system_or_undo_tablespace(
 	ulint   id)
 {
-	return(id == srv_sys_space.space_id()
-	       || id <= srv_undo_tablespaces_open);
+	return(id <= srv_undo_tablespaces_open);
 }
 
 /** Check if predefined shared tablespace.
@@ -315,6 +312,6 @@ is_predefined_tablespace(
 	ut_ad(srv_sys_space.space_id() == TRX_SYS_SPACE);
 	ut_ad(TRX_SYS_SPACE == 0);
 	return(id <= srv_undo_tablespaces_open
-	       || id == srv_tmp_space.space_id());
+	       || id == SRV_TMP_SPACE_ID);
 }
 #endif /* fsp0sysspace_h */
diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h
index 912459f0f36..a8553bd5ab6 100644
--- a/storage/innobase/include/fsp0types.h
+++ b/storage/innobase/include/fsp0types.h
@@ -28,6 +28,12 @@ Created May 26, 2009 Vasil Dimov
 
 #ifndef UNIV_INNOCHECKSUM
 
+/** The fil_space_t::id of the redo log. All persistent tablespaces
+have a smaller fil_space_t::id. */
+#define SRV_LOG_SPACE_FIRST_ID		0xFFFFFFF0U
+/** The fil_space_t::id of the innodb_temporary tablespace. */
+#define SRV_TMP_SPACE_ID		0xFFFFFFFEU
+
 #include "univ.i"
 
 /** @name Flags for inserting records in order
@@ -194,9 +200,12 @@ fsp_flags_is_valid(
 /** Check if tablespace is system temporary.
 @param[in]      space_id        verify is checksum is enabled for given space.
 @return true if tablespace is system temporary. */
+inline
 bool
-fsp_is_system_temporary(
-	ulint	space_id);
+fsp_is_system_temporary(ulint	space_id)
+{
+	return(space_id == SRV_TMP_SPACE_ID);
+}
 
 /** Check if checksum is disabled for the given space.
 @param[in]	space_id	verify is checksum is enabled for given space.
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index 0dd98e5b19b..c10d481de01 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -46,9 +46,6 @@ struct dict_table_t;
 } while (0)
 #endif /* DBUG_OFF */
 
-/** Log 'spaces' have id's >= this */
-#define SRV_LOG_SPACE_FIRST_ID		0xFFFFFFF0UL
-
 /** If buffer pool is less than the size,
 only one buffer pool instance is used. */
 #define BUF_POOL_SIZE_THRESHOLD		(1024 * 1024 * 1024)
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc
index fe62642dcca..49106986ef3 100644
--- a/storage/innobase/row/row0trunc.cc
+++ b/storage/innobase/row/row0trunc.cc
@@ -2273,7 +2273,7 @@ truncate_t::fixup_tables_in_non_system_tablespace()
 				"id (" << (*it)->m_space_id << ")";
 
 			/* Temp-tables in temp-tablespace are never restored.*/
-			ut_ad((*it)->m_space_id != srv_tmp_space.space_id());
+			ut_ad((*it)->m_space_id != SRV_TMP_SPACE_ID);
 
 			err = fil_recreate_table(
 				(*it)->m_space_id,
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index d673a7a8b75..5f73da2d41e 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1092,76 +1092,67 @@ srv_start_wait_for_purge_to_start()
 
 /** Create the temporary file tablespace.
 @param[in]	create_new_db	whether we are creating a new database
-@param[in,out]	tmp_space	Shared Temporary SysTablespace
 @return DB_SUCCESS or error code. */
 static
 dberr_t
-srv_open_tmp_tablespace(
-	bool		create_new_db,
-	SysTablespace*	tmp_space)
+srv_open_tmp_tablespace(bool create_new_db)
 {
 	ulint	sum_of_new_sizes;
 
 	/* Will try to remove if there is existing file left-over by last
 	unclean shutdown */
-	tmp_space->set_sanity_check_status(true);
-	tmp_space->delete_files();
-	tmp_space->set_ignore_read_only(true);
+	srv_tmp_space.set_sanity_check_status(true);
+	srv_tmp_space.delete_files();
+	srv_tmp_space.set_ignore_read_only(true);
 
 	ib::info() << "Creating shared tablespace for temporary tables";
 
 	bool	create_new_temp_space;
-	ulint	temp_space_id = ULINT_UNDEFINED;
-
-	dict_hdr_get_new_id(NULL, NULL, &temp_space_id, NULL, true);
 
-	tmp_space->set_space_id(temp_space_id);
+	srv_tmp_space.set_space_id(SRV_TMP_SPACE_ID);
 
 	RECOVERY_CRASH(100);
 
-	dberr_t	err = tmp_space->check_file_spec(
-			&create_new_temp_space, 12 * 1024 * 1024);
+	dberr_t	err = srv_tmp_space.check_file_spec(
+		&create_new_temp_space, 12 * 1024 * 1024);
 
 	if (err == DB_FAIL) {
 
-		ib::error() << "The " << tmp_space->name()
+		ib::error() << "The " << srv_tmp_space.name()
 			<< " data file must be writable!";
 
 		err = DB_ERROR;
 
 	} else if (err != DB_SUCCESS) {
 		ib::error() << "Could not create the shared "
-			<< tmp_space->name() << ".";
+			<< srv_tmp_space.name() << ".";
 
-	} else if ((err = tmp_space->open_or_create(
+	} else if ((err = srv_tmp_space.open_or_create(
 			    true, create_new_db, &sum_of_new_sizes, NULL))
 		   != DB_SUCCESS) {
 
 		ib::error() << "Unable to create the shared "
-			<< tmp_space->name();
+			<< srv_tmp_space.name();
 
 	} else {
 
 		mtr_t	mtr;
-		ulint	size = tmp_space->get_sum_of_sizes();
-
-		ut_a(temp_space_id != ULINT_UNDEFINED);
-		ut_a(tmp_space->space_id() == temp_space_id);
+		ulint	size = srv_tmp_space.get_sum_of_sizes();
 
 		/* Open this shared temp tablespace in the fil_system so that
 		it stays open until shutdown. */
-		if (fil_space_open(tmp_space->name())) {
+		if (fil_space_open(srv_tmp_space.name())) {
 
 			/* Initialize the header page */
 			mtr_start(&mtr);
 			mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
 
-			fsp_header_init(tmp_space->space_id(), size, &mtr);
+			fsp_header_init(SRV_TMP_SPACE_ID, size, &mtr);
 
 			mtr_commit(&mtr);
 		} else {
 			/* This file was just opened in the code above! */
-			ib::error() << "The " << tmp_space->name()
+			ib::error() << "The " << srv_tmp_space.name()
 				<< " data file cannot be re-opened"
 				" after check_file_spec() succeeded!";
 
@@ -2389,7 +2380,7 @@ files_checked:
 
 	/* Open temp-tablespace and keep it open until shutdown. */
 
-	err = srv_open_tmp_tablespace(create_new_db, &srv_tmp_space);
+	err = srv_open_tmp_tablespace(create_new_db);
 
 	if (err != DB_SUCCESS) {
 		return(srv_init_abort(err));
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 7cd18750945..0cc3844cec3 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -845,8 +845,7 @@ trx_sys_create_noredo_rsegs(
 	Slot-1....Slot-N: reserved for temp-tablespace.
 	Slot-N+1....Slot-127: reserved for system/undo-tablespace. */
 	for (ulint i = 0; i < n_nonredo_rseg; i++) {
-		ulint space = srv_tmp_space.space_id();
-		if (trx_rseg_create(space, i) == NULL) {
+		if (trx_rseg_create(SRV_TMP_SPACE_ID, i) == NULL) {
 			break;
 		}
 		++n_created;
-- 
2.11.0

