From db400ce9532536da36812dbf0456e756a0ea4724 Mon Sep 17 00:00:00 2001
From: "Andrey V. Lepikhov" <a.lepikhov@postgrespro.ru>
Date: Tue, 31 Jul 2018 07:22:17 +0500
Subject: [PATCH 1/4] Relation-into-WAL-function

---
 src/backend/access/transam/generic_xlog.c | 62 +++++++++++++++++++++++
 src/include/access/generic_xlog.h         |  3 ++
 2 files changed, 65 insertions(+)

diff --git a/src/backend/access/transam/generic_xlog.c b/src/backend/access/transam/generic_xlog.c
index ce023548ae..8397b58ee7 100644
--- a/src/backend/access/transam/generic_xlog.c
+++ b/src/backend/access/transam/generic_xlog.c
@@ -80,6 +80,7 @@ static void computeRegionDelta(PageData *pageData,
 static void computeDelta(PageData *pageData, Page curpage, Page targetpage);
 static void applyPageRedo(Page page, const char *delta, Size deltaSize);
 
+static void standard_page_layout_check(Buffer buf);
 
 /*
  * Write next fragment into pageData's delta.
@@ -545,3 +546,64 @@ generic_mask(char *page, BlockNumber blkno)
 
 	mask_unused_space(page);
 }
+
+/*
+ * Check page layout.
+ * Caller must lock the buffer
+ */
+static void
+standard_page_layout_check(Buffer buf)
+{
+	PageHeader ph = (PageHeader) BufferGetPage(buf);
+
+	Assert((ph->pd_lower >= SizeOfPageHeaderData) &&
+		   (ph->pd_lower <= ph->pd_upper) &&
+		   (ph->pd_upper <= ph->pd_special) &&
+		   (ph->pd_special <= BLCKSZ) &&
+		   (ph->pd_special == MAXALIGN(ph->pd_special)));
+}
+
+/*
+ * Function to write generic xlog for every existing block of a relation.
+ * Caller is responsible for locking the relation exclusively.
+ */
+void
+generic_log_relation(Relation rel)
+{
+	BlockNumber blkno;
+	BlockNumber nblocks;
+
+	nblocks = RelationGetNumberOfBlocks(rel);
+
+	elog(DEBUG2, "generic_log_relation '%s', nblocks %u BEGIN.",
+		 RelationGetRelationName(rel), nblocks);
+
+	for (blkno = 0; blkno < nblocks; )
+	{
+		GenericXLogState	*state;
+		Buffer				buffer[MAX_GENERIC_XLOG_PAGES];
+		int					counter,
+							blocks_pack;
+
+		CHECK_FOR_INTERRUPTS();
+
+		blocks_pack = ((nblocks-blkno) < MAX_GENERIC_XLOG_PAGES) ?
+						(nblocks-blkno) : MAX_GENERIC_XLOG_PAGES;
+
+		state = GenericXLogStart(rel);
+
+		for (counter = 0 ; counter < blocks_pack; counter++)
+		{
+			buffer[counter] = ReadBuffer(rel, blkno++);
+			standard_page_layout_check(buffer[counter]);
+			LockBuffer(buffer[counter], BUFFER_LOCK_EXCLUSIVE);
+			GenericXLogRegisterBuffer(state, buffer[counter], GENERIC_XLOG_FULL_IMAGE);
+		}
+
+		GenericXLogFinish(state);
+
+		for (counter = 0 ; counter < blocks_pack; counter++)
+			UnlockReleaseBuffer(buffer[counter]);
+	}
+	elog(DEBUG2, "generic_log_relation '%s' END.", RelationGetRelationName(rel));
+}
diff --git a/src/include/access/generic_xlog.h b/src/include/access/generic_xlog.h
index b23e1f684b..1f4b3b7030 100644
--- a/src/include/access/generic_xlog.h
+++ b/src/include/access/generic_xlog.h
@@ -42,4 +42,7 @@ extern const char *generic_identify(uint8 info);
 extern void generic_desc(StringInfo buf, XLogReaderState *record);
 extern void generic_mask(char *pagedata, BlockNumber blkno);
 
+/* other utils */
+extern void generic_log_relation(Relation rel);
+
 #endif							/* GENERIC_XLOG_H */
-- 
2.17.1

