From 221eb38fa5e8a29d4b05dabee7a435298089d2bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Mon, 10 Jun 2019 15:37:35 +0300
Subject: [PATCH 1/2] WIP: Remove mlog_init. Does not work!

mlog_init.ibuf_merge() would be removed in MDEV-19514.

FIXME: Keep pseudo-records in recv_sys.pages similar to mlog_init,
and preserve them across recv_sys.pages.clear().
---
 storage/innobase/include/log0recv.h |   2 +
 storage/innobase/log/log0recv.cc    | 153 +++++-----------------------
 2 files changed, 26 insertions(+), 129 deletions(-)

diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index f7b7a39133f..71d75104d22 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -243,6 +243,8 @@ struct recv_sys_t{
 			RECV_NOT_PROCESSED,
 			/** not processed; the page will be reinitialized */
 			RECV_WILL_NOT_READ,
+			/** created based on redo log */
+			RECV_DID_NOT_READ,
 			/** page is being read */
 			RECV_BEING_READ,
 			/** log records are being applied on the page */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 319432e955b..08a28013dc4 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -195,116 +195,6 @@ void (*log_file_op)(ulint space_id, const byte* flags,
 		    const byte* name, ulint len,
 		    const byte* new_name, ulint new_len);
 
-/** Information about initializing page contents during redo log processing */
-class mlog_init_t
-{
-public:
-	/** A page initialization operation that was parsed from
-	the redo log */
-	struct init {
-		/** log sequence number of the page initialization */
-		lsn_t lsn;
-		/** Whether btr_page_create() avoided a read of the page.
-
-		At the end of the last recovery batch, ibuf_merge()
-		will invoke change buffer merge for pages that reside
-		in the buffer pool. (In the last batch, loading pages
-		would trigger change buffer merge.) */
-		bool created;
-	};
-
-private:
-	typedef std::map<const page_id_t, init,
-			 std::less<const page_id_t>,
-			 ut_allocator<std::pair<const page_id_t, init> > >
-		map;
-	/** Map of page initialization operations.
-	FIXME: Merge this to recv_sys.pages! */
-	map inits;
-public:
-	/** Record that a page will be initialized by the redo log.
-	@param[in]	page_id		page identifier
-	@param[in]	lsn		log sequence number */
-	void add(const page_id_t page_id, lsn_t lsn)
-	{
-		ut_ad(mutex_own(&recv_sys.mutex));
-		const init init = { lsn, false };
-		std::pair<map::iterator, bool> p = inits.insert(
-			map::value_type(page_id, init));
-		ut_ad(!p.first->second.created);
-		if (!p.second && p.first->second.lsn < init.lsn) {
-			p.first->second = init;
-		}
-	}
-
-	/** Get the last stored lsn of the page id and its respective
-	init/load operation.
-	@param[in]	page_id	page id
-	@param[in,out]	init	initialize log or load log
-	@return the latest page initialization;
-	not valid after releasing recv_sys.mutex. */
-	init& last(page_id_t page_id)
-	{
-		ut_ad(mutex_own(&recv_sys.mutex));
-		return inits.find(page_id)->second;
-	}
-
-	/** At the end of each recovery batch, reset the 'created' flags. */
-	void reset()
-	{
-		ut_ad(mutex_own(&recv_sys.mutex));
-		ut_ad(recv_no_ibuf_operations);
-		for (map::iterator i= inits.begin(); i != inits.end(); i++) {
-			i->second.created = false;
-		}
-	}
-
-	/** On the last recovery batch, merge buffered changes to those
-	pages that were initialized by buf_page_create() and still reside
-	in the buffer pool. Stale pages are not allowed in the buffer pool.
-
-	Note: When MDEV-14481 implements redo log apply in the
-	background, we will have to ensure that buf_page_get_gen()
-	will not deliver stale pages to users (pages on which the
-	change buffer was not merged yet).  Normally, the change
-	buffer merge is performed on I/O completion. Maybe, add a
-	flag to buf_page_t and perform the change buffer merge on
-	the first actual access?
-	@param[in,out]	mtr	dummy mini-transaction */
-	void ibuf_merge(mtr_t& mtr)
-	{
-		ut_ad(mutex_own(&recv_sys.mutex));
-		ut_ad(!recv_no_ibuf_operations);
-		mtr.start();
-
-		for (map::const_iterator i= inits.begin(); i != inits.end();
-		     i++) {
-			if (!i->second.created) {
-				continue;
-			}
-			if (buf_block_t* block = buf_page_get_gen(
-				    i->first, 0, RW_X_LATCH, NULL,
-				    BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
-				    &mtr, NULL)) {
-				mutex_exit(&recv_sys.mutex);
-				ibuf_merge_or_delete_for_page(
-					block, i->first,
-					block->zip_size(), true);
-				mtr.commit();
-				mtr.start();
-				mutex_enter(&recv_sys.mutex);
-			}
-		}
-
-		mtr.commit();
-	}
-
-	/** Clear the data structure */
-	void clear() { inits.clear(); }
-};
-
-static mlog_init_t mlog_init;
-
 /** Process a record that indicates that a tablespace is
 being shrunk in size.
 @param page_id	first page identifier that is not in the file
@@ -698,7 +588,6 @@ void recv_sys_t::close()
 	}
 
 	recv_spaces.clear();
-	mlog_init.clear();
 }
 
 /************************************************************
@@ -1737,7 +1626,6 @@ inline void recv_sys_t::add(mlog_id_t type, const page_id_t page_id,
 		ut_ad(recs.state == recs_t::RECV_NOT_PROCESSED
 		      || recs.state == recs_t::RECV_WILL_NOT_READ);
 		recs.state = recs_t::RECV_WILL_NOT_READ;
-		mlog_init.add(page_id, lsn); // FIXME: remove this
 		recs.log = NULL;
 		break;
 	default:
@@ -1808,10 +1696,10 @@ lsn of a log record.
 @param[in,out]	block		buffer pool page
 @param[in,out]	mtr		mini-transaction
 @param[in,out]	p		recovery address
-@param[in,out]	init		page initialization operation, or NULL */
+@param[in]	init_lsn	LSN of page initialization */
 static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
 			      recv_sys_t::map::iterator p,
-			      mlog_init_t::init* init = NULL)
+			      lsn_t init_lsn = 0)
 {
 	page_t*		page;
 	page_zip_des_t*	page_zip;
@@ -1819,10 +1707,13 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
 	ut_ad(mutex_own(&recv_sys.mutex));
 	ut_ad(recv_sys.apply_log_recs);
 	ut_ad(recv_needed_recovery);
-	ut_ad(!init || init->created);
-	ut_ad(!init || init->lsn);
 	ut_ad(block->page.id == p->first);
+	ut_ad(p->second.log);
 	ut_ad(p->second.state != recv_sys_t::recs_t::RECV_BEING_PROCESSED);
+	ut_ad(p->second.state != recv_sys_t::recs_t::RECV_DID_NOT_READ);
+	ut_ad(!init_lsn || p->second.state
+	      == recv_sys_t::recs_t::RECV_WILL_NOT_READ);
+	ut_ad(!init_lsn || init_lsn == p->second.log->start_lsn);
 
 	if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) {
 		ib::info() << "Applying log to page " << block->page.id;
@@ -1846,7 +1737,6 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
 	bool free_page = false;
 	lsn_t start_lsn = 0, end_lsn = 0;
 	ut_d(lsn_t recv_start_lsn = 0);
-	const lsn_t init_lsn = init ? init->lsn : 0;
 
 	for (const recv_t* recv = p->second.log; recv; recv = recv->next) {
 		ut_ad(recv->start_lsn);
@@ -1935,12 +1825,12 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
 		log_flush_order_mutex_enter();
 		buf_flush_note_modification(block, start_lsn, end_lsn, NULL);
 		log_flush_order_mutex_exit();
-	} else if (free_page && init) {
+	} else if (free_page && init_lsn) {
 		/* There have been no operations than MLOG_INIT_FREE_PAGE.
 		Any buffered changes must not be merged. A subsequent
 		buf_page_create() from a user thread should discard
 		any buffered changes. */
-		init->created = false;
+		init_lsn = 0;
 		ut_ad(!mtr.has_modifications());
 	}
 
@@ -1960,7 +1850,11 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
 
 	ut_ad(p->second.state == recv_sys_t::recs_t::RECV_BEING_PROCESSED);
 	ut_ad(!recv_sys.pages.empty());
-	recv_sys.pages.erase(p);
+	if (UNIV_UNLIKELY(init_lsn)) {
+		p->second.state = recv_sys_t::recs_t::RECV_DID_NOT_READ;
+	} else {
+		recv_sys.pages.erase(p);
+	}
 
 	if (recv_sys.report(time)) {
 		const ulint n = recv_sys.pages.size();
@@ -2126,6 +2020,7 @@ void recv_apply_hashed_log_recs(bool last_batch)
 		switch (recs.state) {
 		case recv_sys_t::recs_t::RECV_BEING_READ:
 		case recv_sys_t::recs_t::RECV_BEING_PROCESSED:
+		case recv_sys_t::recs_t::RECV_DID_NOT_READ:
 			p++;
 			continue;
 		case recv_sys_t::recs_t::RECV_NOT_PROCESSED:
@@ -2146,6 +2041,7 @@ void recv_apply_hashed_log_recs(bool last_batch)
 			}
 			break;
 		case recv_sys_t::recs_t::RECV_WILL_NOT_READ:
+#if 0
 			mlog_init_t::init& i = mlog_init.last(page_id);
 			lsn_t end_lsn = 0;
 			for (const recv_t* r = recs.log; r; r = r->next) {
@@ -2158,16 +2054,14 @@ void recv_apply_hashed_log_recs(bool last_batch)
 					 << page_id
 					 << " LSN " << end_lsn
 					 << " < " << i.lsn);
-ignore:
-				recv_sys_t::map::iterator r = p++;
-				recv_sys.pages.erase(r);
-				continue;
 			}
-
+#endif
 			fil_space_t* space = fil_space_acquire_for_io(
 				page_id.space());
 			if (!space) {
-				goto ignore;
+				recv_sys_t::map::iterator r = p++;
+				recv_sys.pages.erase(r);
+				continue;
 			}
 
 			if (space->enable_lsn) {
@@ -2215,11 +2109,11 @@ void recv_apply_hashed_log_recs(bool last_batch)
 				mtr.commit();
 			} else {
 				ut_ad(&recs == &p->second);
-				i.created = true;
 				buf_block_dbg_add_level(
 					block, SYNC_NO_ORDER_CHECK);
 				mtr.x_latch_at_savepoint(0, block);
-				recv_recover_page(block, mtr, p, &i);
+				recv_recover_page(block, mtr, p,
+						  p->second.log->start_lsn);
 				ut_ad(mtr.has_committed());
 			}
 
@@ -2278,10 +2172,11 @@ void recv_apply_hashed_log_recs(bool last_batch)
 
 		log_mutex_enter();
 		mutex_enter(&(recv_sys.mutex));
-		mlog_init.reset();
+#if 0 // FIXME: Implement MDEV-19514 and remove this logic
 	} else if (!recv_no_ibuf_operations) {
 		/* We skipped this in buf_page_create(). */
 		mlog_init.ibuf_merge(mtr);
+#endif
 	}
 
 	recv_sys.apply_log_recs = false;
-- 
2.20.1

