From a6f261d8454e61184142af91b0bf2a4811d78182 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 5 Sep 2019 21:29:32 +0900
Subject: [PATCH v6 4/4] Change policy of XLog read-buffer allocation

Page buffer in XLogReaderState was allocated by XLogReaderAllcoate but
actually it'd be the responsibility to the callers of XLogReadRecord,
which now actually reads in pages. This patch does that.
---
 src/backend/access/transam/twophase.c     |  2 ++
 src/backend/access/transam/xlog.c         |  2 ++
 src/backend/access/transam/xlogreader.c   | 18 ------------------
 src/backend/replication/logical/logical.c |  2 ++
 src/bin/pg_rewind/parsexlog.c             |  6 ++++++
 src/bin/pg_waldump/pg_waldump.c           |  2 ++
 6 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index a736504d62..358951c232 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1392,6 +1392,7 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of memory"),
 				 errdetail("Failed while allocating a WAL reading processor.")));
+	xlogreader->readBuf = palloc(XLOG_BLCKSZ);
 
 	while (XLogReadRecord(xlogreader, lsn, &record, &errormsg) ==
 		   XLREAD_NEED_DATA)
@@ -1421,6 +1422,7 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
 	*buf = palloc(sizeof(char) * XLogRecGetDataLen(xlogreader));
 	memcpy(*buf, XLogRecGetData(xlogreader), sizeof(char) * XLogRecGetDataLen(xlogreader));
 
+	pfree(xlogreader->readBuf);
 	XLogReaderFree(xlogreader);
 }
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c20d3b1418..a199600399 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6349,6 +6349,7 @@ StartupXLOG(void)
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of memory"),
 				 errdetail("Failed while allocating a WAL reading processor.")));
+	xlogreader->readBuf = palloc(XLOG_BLCKSZ);
 	xlogreader->system_identifier = ControlFile->system_identifier;
 
 	/*
@@ -7721,6 +7722,7 @@ StartupXLOG(void)
 		close(readFile);
 		readFile = -1;
 	}
+	pfree(xlogreader->readBuf);
 	XLogReaderFree(xlogreader);
 
 	/*
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index e00fa270ae..1f98dd0168 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -80,27 +80,11 @@ XLogReaderAllocate(int wal_segment_size)
 
 	state->max_block_id = -1;
 
-	/*
-	 * Permanently allocate readBuf.  We do it this way, rather than just
-	 * making a static array, for two reasons: (1) no need to waste the
-	 * storage in most instantiations of the backend; (2) a static char array
-	 * isn't guaranteed to have any particular alignment, whereas
-	 * palloc_extended() will provide MAXALIGN'd storage.
-	 */
-	state->readBuf = (char *) palloc_extended(XLOG_BLCKSZ,
-											  MCXT_ALLOC_NO_OOM);
-	if (!state->readBuf)
-	{
-		pfree(state);
-		return NULL;
-	}
-
 	state->wal_segment_size = wal_segment_size;
 	state->errormsg_buf = palloc_extended(MAX_ERRORMSG_LEN + 1,
 										  MCXT_ALLOC_NO_OOM);
 	if (!state->errormsg_buf)
 	{
-		pfree(state->readBuf);
 		pfree(state);
 		return NULL;
 	}
@@ -113,7 +97,6 @@ XLogReaderAllocate(int wal_segment_size)
 	if (!allocate_recordbuf(state, 0))
 	{
 		pfree(state->errormsg_buf);
-		pfree(state->readBuf);
 		pfree(state);
 		return NULL;
 	}
@@ -137,7 +120,6 @@ XLogReaderFree(XLogReaderState *state)
 	pfree(state->errormsg_buf);
 	if (state->readRecordBuf)
 		pfree(state->readRecordBuf);
-	pfree(state->readBuf);
 	pfree(state);
 }
 
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 11e52e4c01..ea027caa69 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -178,6 +178,7 @@ StartupDecodingContext(List *output_plugin_options,
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of memory")));
+	ctx->reader->readBuf = palloc(XLOG_BLCKSZ);
 	ctx->read_page = read_page;
 
 	ctx->reorder = ReorderBufferAllocate();
@@ -523,6 +524,7 @@ FreeDecodingContext(LogicalDecodingContext *ctx)
 
 	ReorderBufferFree(ctx->reorder);
 	FreeSnapshotBuilder(ctx->snapshot_builder);
+	pfree(ctx->reader->readBuf);
 	XLogReaderFree(ctx->reader);
 	MemoryContextDelete(ctx->context);
 }
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
index ff26b30f82..c60267e87e 100644
--- a/src/bin/pg_rewind/parsexlog.c
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -60,6 +60,7 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
 	xlogreader = XLogReaderAllocate(WalSegSz);
 	if (xlogreader == NULL)
 		pg_fatal("out of memory");
+	xlogreader->readBuf = pg_malloc(XLOG_BLCKSZ);
 
 	do
 	{
@@ -92,6 +93,7 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
 
 	} while (xlogreader->ReadRecPtr != endpoint);
 
+	pg_free(xlogreader->readBuf);
 	XLogReaderFree(xlogreader);
 	if (xlogreadfd != -1)
 	{
@@ -115,6 +117,7 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex)
 	xlogreader = XLogReaderAllocate(WalSegSz);
 	if (xlogreader == NULL)
 		pg_fatal("out of memory");
+	xlogreader->readBuf = pg_malloc(XLOG_BLCKSZ);
 
 	while (XLogReadRecord(xlogreader, ptr, &record, &errormsg) ==
 		   XLREAD_NEED_DATA)
@@ -133,6 +136,7 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex)
 	}
 	endptr = xlogreader->EndRecPtr;
 
+	pg_free(xlogreader->readBuf);
 	XLogReaderFree(xlogreader);
 	if (xlogreadfd != -1)
 	{
@@ -174,6 +178,7 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
 	xlogreader = XLogReaderAllocate(WalSegSz);
 	if (xlogreader == NULL)
 		pg_fatal("out of memory");
+	xlogreader->readBuf = pg_malloc(XLOG_BLCKSZ);
 
 	searchptr = forkptr;
 	for (;;)
@@ -222,6 +227,7 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
 		searchptr = record->xl_prev;
 	}
 
+	pg_free(xlogreader->readBuf);
 	XLogReaderFree(xlogreader);
 	if (xlogreadfd != -1)
 	{
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index a61a5a91cb..5eba802720 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -1108,6 +1108,7 @@ main(int argc, char **argv)
 	xlogreader_state = XLogReaderAllocate(WalSegSz);
 	if (!xlogreader_state)
 		fatal_error("out of memory");
+	xlogreader_state->readBuf = palloc(XLOG_BLCKSZ);
 
 	/* first find a valid recptr to start from */
 	first_record = XLogFindNextRecord(xlogreader_state, private.startptr,
@@ -1188,6 +1189,7 @@ main(int argc, char **argv)
 					(uint32) xlogreader_state->ReadRecPtr,
 					errormsg);
 
+	pfree(xlogreader_state->readBuf);
 	XLogReaderFree(xlogreader_state);
 
 	return EXIT_SUCCESS;
-- 
2.16.3

