From caf9356688a722c2246969e2f1421bf25c7c882e Mon Sep 17 00:00:00 2001
From: kommih <haribabuk@fast.au.fujitsu.com>
Date: Mon, 22 Oct 2018 17:58:27 +1100
Subject: [PATCH 2/3] New API's are added

1. init fork API
2. set New filenode
3. Estimate rel size

Set New filenode and estimate rel size are added as function hooks
and these not complusory for heap, when they exist, it take over
the control.
---
 src/backend/access/heap/heapam_handler.c | 27 +++++++++++++++++++++++-
 src/backend/catalog/heap.c               | 24 ++-------------------
 src/backend/commands/tablecmds.c         |  4 ++--
 src/backend/optimizer/util/plancat.c     | 12 +++++++++++
 src/backend/utils/cache/relcache.c       | 12 +++++++++++
 src/include/access/tableam.h             | 16 ++++++++++++++
 src/include/catalog/heap.h               |  2 --
 7 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 3254e30a45..ae832e1f71 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -30,6 +30,7 @@
 #include "catalog/catalog.h"
 #include "catalog/index.h"
 #include "catalog/pg_am_d.h"
+#include "catalog/storage_xlog.h"
 #include "executor/executor.h"
 #include "pgstat.h"
 #include "storage/lmgr.h"
@@ -2118,6 +2119,28 @@ heap_copy_for_cluster(Relation OldHeap, Relation NewHeap, Relation OldIndex,
 	pfree(isnull);
 }
 
+/*
+ * Set up an init fork for an unlogged table so that it can be correctly
+ * reinitialized on restart.  An immediate sync is required even if the
+ * page has been logged, because the write did not go through
+ * shared_buffers and therefore a concurrent checkpoint may have moved
+ * the redo pointer past our xlog record.  Recovery may as well remove it
+ * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
+ * record. Therefore, logging is necessary even if wal_level=minimal.
+ */
+static void
+heap_create_init_fork(Relation rel)
+{
+	Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
+		   rel->rd_rel->relkind == RELKIND_MATVIEW ||
+		   rel->rd_rel->relkind == RELKIND_TOASTVALUE);
+	RelationOpenSmgr(rel);
+	smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
+	log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
+	smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
+}
+
+
 static const TableAmRoutine heapam_methods = {
 	.type = T_TableAmRoutine,
 
@@ -2165,7 +2188,9 @@ static const TableAmRoutine heapam_methods = {
 
 	.index_build_range_scan = IndexBuildHeapRangeScan,
 
-	.index_validate_scan = validate_index_heapscan
+	.index_validate_scan = validate_index_heapscan,
+
+	.CreateInitFork = heap_create_init_fork
 };
 
 const TableAmRoutine *
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 38b368f916..8e7c8ce684 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -32,6 +32,7 @@
 #include "access/htup_details.h"
 #include "access/multixact.h"
 #include "access/sysattr.h"
+#include "access/tableam.h"
 #include "access/transam.h"
 #include "access/xact.h"
 #include "access/xlog.h"
@@ -1425,7 +1426,7 @@ heap_create_with_catalog(const char *relname,
 	 */
 	if (relpersistence == RELPERSISTENCE_UNLOGGED &&
 		relkind != RELKIND_PARTITIONED_TABLE)
-		heap_create_init_fork(new_rel_desc);
+		table_create_init_fork(new_rel_desc);
 
 	/*
 	 * ok, the relation has been cataloged, so close our relations and return
@@ -1437,27 +1438,6 @@ heap_create_with_catalog(const char *relname,
 	return relid;
 }
 
-/*
- * Set up an init fork for an unlogged table so that it can be correctly
- * reinitialized on restart.  An immediate sync is required even if the
- * page has been logged, because the write did not go through
- * shared_buffers and therefore a concurrent checkpoint may have moved
- * the redo pointer past our xlog record.  Recovery may as well remove it
- * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
- * record. Therefore, logging is necessary even if wal_level=minimal.
- */
-void
-heap_create_init_fork(Relation rel)
-{
-	Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
-		   rel->rd_rel->relkind == RELKIND_MATVIEW ||
-		   rel->rd_rel->relkind == RELKIND_TOASTVALUE);
-	RelationOpenSmgr(rel);
-	smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
-	log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
-	smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
-}
-
 /*
  *		RelationRemoveInheritance
  *
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f3526b267d..3c46a48882 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1649,7 +1649,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
 			RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
 									  RecentXmin, minmulti);
 			if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
-				heap_create_init_fork(rel);
+				table_create_init_fork(rel);
 
 			heap_relid = RelationGetRelid(rel);
 			toast_relid = rel->rd_rel->reltoastrelid;
@@ -1663,7 +1663,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
 				RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
 										  RecentXmin, minmulti);
 				if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
-					heap_create_init_fork(rel);
+					table_create_init_fork(rel);
 				heap_close(rel, NoLock);
 			}
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 8da468a86f..3355f8bff4 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -947,6 +947,18 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
 	BlockNumber relallvisible;
 	double		density;
 
+	/*
+	 * If the relation contains any specific EstimateRelSize
+	 * function, use that instead of the regular default heap method.
+	 */
+	if (rel->rd_tableamroutine &&
+			rel->rd_tableamroutine->EstimateRelSize)
+	{
+		rel->rd_tableamroutine->EstimateRelSize(rel, attr_widths, pages,
+												tuples, allvisfrac);
+		return;
+	}
+
 	switch (rel->rd_rel->relkind)
 	{
 		case RELKIND_RELATION:
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 0d6e5a189f..9cc8e98e40 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3424,6 +3424,18 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
 	HeapTuple	tuple;
 	Form_pg_class classform;
 
+	/*
+	 * If the relation contains any specific SetNewFilenode
+	 * function, use that instead of the regular default heap method.
+	 */
+	if (relation->rd_tableamroutine &&
+			relation->rd_tableamroutine->SetNewFileNode)
+	{
+		relation->rd_tableamroutine->SetNewFileNode(relation, persistence,
+													freezeXid, minmulti);
+		return;
+	}
+
 	/* Indexes, sequences must have Invalid frozenxid; other rels must not */
 	Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
 			relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 7fe6ff6c22..eb7c9b8007 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -194,6 +194,12 @@ struct SampleScanState;
 typedef bool (*SampleScanNextBlock_function)(TableScanDesc scan, struct SampleScanState *scanstate);
 typedef bool (*SampleScanNextTuple_function)(TableScanDesc scan, struct SampleScanState *scanstate, TupleTableSlot *slot);
 
+typedef void (*CreateInitFork_function)(Relation rel);
+typedef void (*EstimateRelSize_function)(Relation rel, int32 *attr_widths,
+				  BlockNumber *pages, double *tuples, double *allvisfrac);
+typedef void (*SetNewFileNode_function)(Relation relation, char persistence,
+										TransactionId freezeXid, MultiXactId minmulti);
+
 /*
  * API struct for a table AM.  Note this must be allocated in a
  * server-lifetime manner, typically as a static const struct.
@@ -250,6 +256,10 @@ typedef struct TableAmRoutine
 
 	IndexBuildRangeScan_function index_build_range_scan;
 	IndexValidateScan_function index_validate_scan;
+
+	CreateInitFork_function CreateInitFork;
+	EstimateRelSize_function EstimateRelSize;
+	SetNewFileNode_function	SetNewFileNode;
 }			TableAmRoutine;
 
 static inline const TupleTableSlotOps*
@@ -741,6 +751,12 @@ table_index_build_range_scan(Relation heapRelation,
 		scan);
 }
 
+static inline void
+table_create_init_fork(Relation relation)
+{
+	relation->rd_tableamroutine->CreateInitFork(relation);
+}
+
 extern BlockNumber table_parallelscan_nextpage(TableScanDesc scan);
 extern void table_parallelscan_startblock_init(TableScanDesc scan);
 extern Size table_parallelscan_estimate(Snapshot snapshot);
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 4584b3473c..c0e706ecc9 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -77,8 +77,6 @@ extern Oid heap_create_with_catalog(const char *relname,
 						 Oid relrewrite,
 						 ObjectAddress *typaddress);
 
-extern void heap_create_init_fork(Relation rel);
-
 extern void heap_drop_with_catalog(Oid relid);
 
 extern void heap_truncate(List *relids);
-- 
2.18.0.windows.1

