From 940342d009a753251d2c94ed5e594062b5cd925e Mon Sep 17 00:00:00 2001
From: Hari Babu <kommi.haribabu@gmail.com>
Date: Wed, 3 Jan 2018 17:34:59 +1100
Subject: [PATCH 10/12] storage rewrite functionality

All the heap rewrite functionality is moved into heap storage
and exposed them with storage API. Currenlty these API's are used
only by the cluster command operation.

The logical rewrite mapping code is currently left as it is,
this needs to be handled seperately.
---
 src/backend/access/heap/heapam_storage.c |  6 ++++++
 src/backend/access/storage/storageam.c   | 33 ++++++++++++++++++++++++++++++++
 src/backend/commands/cluster.c           | 32 +++++++++++++++----------------
 src/include/access/heapam.h              |  9 +++++++++
 src/include/access/rewriteheap.h         | 11 -----------
 src/include/access/storage_common.h      |  2 ++
 src/include/access/storageam.h           |  8 ++++++++
 src/include/access/storageamapi.h        | 13 +++++++++++++
 8 files changed, 86 insertions(+), 28 deletions(-)

diff --git a/src/backend/access/heap/heapam_storage.c b/src/backend/access/heap/heapam_storage.c
index e914088be0..8621015846 100644
--- a/src/backend/access/heap/heapam_storage.c
+++ b/src/backend/access/heap/heapam_storage.c
@@ -22,6 +22,7 @@
 
 #include "access/heapam.h"
 #include "access/relscan.h"
+#include "access/rewriteheap.h"
 #include "access/storageamapi.h"
 #include "pgstat.h"
 #include "utils/builtins.h"
@@ -336,5 +337,10 @@ heapam_storage_handler(PG_FUNCTION_ARGS)
 	amroutine->freebulkinsertstate = FreeBulkInsertState;
 	amroutine->releasebulkinsertstate = ReleaseBulkInsertStatePin;
 
+	amroutine->begin_heap_rewrite = begin_heap_rewrite;
+	amroutine->end_heap_rewrite = end_heap_rewrite;
+	amroutine->rewrite_heap_tuple = rewrite_heap_tuple;
+	amroutine->rewrite_heap_dead_tuple = rewrite_heap_dead_tuple;
+
 	PG_RETURN_POINTER(amroutine);
 }
diff --git a/src/backend/access/storage/storageam.c b/src/backend/access/storage/storageam.c
index 9554e9a902..239339c033 100644
--- a/src/backend/access/storage/storageam.c
+++ b/src/backend/access/storage/storageam.c
@@ -401,3 +401,36 @@ storage_releasebulkinsertstate(Relation rel, BulkInsertState bistate)
 {
 	rel->rd_stamroutine->releasebulkinsertstate(bistate);
 }
+
+/*
+ * -------------------
+ * storage tuple rewrite functions
+ * -------------------
+ */
+RewriteState
+storage_begin_rewrite(Relation OldHeap, Relation NewHeap,
+				   TransactionId OldestXmin, TransactionId FreezeXid,
+				   MultiXactId MultiXactCutoff, bool use_wal)
+{
+	return NewHeap->rd_stamroutine->begin_heap_rewrite(OldHeap, NewHeap,
+			OldestXmin, FreezeXid, MultiXactCutoff, use_wal);
+}
+
+void
+storage_end_rewrite(Relation rel, RewriteState state)
+{
+	rel->rd_stamroutine->end_heap_rewrite(state);
+}
+
+void
+storage_rewrite_tuple(Relation rel, RewriteState state, HeapTuple oldTuple,
+				   HeapTuple newTuple)
+{
+	rel->rd_stamroutine->rewrite_heap_tuple(state, oldTuple, newTuple);
+}
+
+bool
+storage_rewrite_dead_tuple(Relation rel, RewriteState state, HeapTuple oldTuple)
+{
+	return rel->rd_stamroutine->rewrite_heap_dead_tuple(state, oldTuple);
+}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index d6b01da629..9b286e932d 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -75,9 +75,8 @@ static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
 			   TransactionId *pFreezeXid, MultiXactId *pCutoffMulti);
 static List *get_tables_to_cluster(MemoryContext cluster_context);
 static void reform_and_rewrite_tuple(HeapTuple tuple,
-						 TupleDesc oldTupDesc, TupleDesc newTupDesc,
-						 Datum *values, bool *isnull,
-						 bool newRelHasOids, RewriteState rwstate);
+						 Relation OldHeap, Relation NewHeap,
+						 Datum *values, bool *isnull, RewriteState rwstate);
 
 
 /*---------------------------------------------------------------------------
@@ -879,7 +878,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 	is_system_catalog = IsSystemRelation(OldHeap);
 
 	/* Initialize the rewrite operation */
-	rwstate = begin_heap_rewrite(OldHeap, NewHeap, OldestXmin, FreezeXid,
+	rwstate = storage_begin_rewrite(OldHeap, NewHeap, OldestXmin, FreezeXid,
 								 MultiXactCutoff, use_wal);
 
 	/*
@@ -1028,7 +1027,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 		{
 			tups_vacuumed += 1;
 			/* heap rewrite module still needs to see it... */
-			if (rewrite_heap_dead_tuple(rwstate, tuple))
+			if (storage_rewrite_dead_tuple(NewHeap, rwstate, tuple))
 			{
 				/* A previous recently-dead tuple is now known dead */
 				tups_vacuumed += 1;
@@ -1042,9 +1041,8 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 			tuplesort_putheaptuple(tuplesort, tuple);
 		else
 			reform_and_rewrite_tuple(tuple,
-									 oldTupDesc, newTupDesc,
-									 values, isnull,
-									 NewHeap->rd_rel->relhasoids, rwstate);
+									 OldHeap, NewHeap,
+									 values, isnull, rwstate);
 	}
 
 	if (indexScan != NULL)
@@ -1071,16 +1069,15 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 				break;
 
 			reform_and_rewrite_tuple(tuple,
-									 oldTupDesc, newTupDesc,
-									 values, isnull,
-									 NewHeap->rd_rel->relhasoids, rwstate);
+									 OldHeap, NewHeap,
+									 values, isnull, rwstate);
 		}
 
 		tuplesort_end(tuplesort);
 	}
 
 	/* Write out any remaining tuples, and fsync if needed */
-	end_heap_rewrite(rwstate);
+	storage_end_rewrite(NewHeap, rwstate);
 
 	/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
 	NewHeap->rd_toastoid = InvalidOid;
@@ -1734,10 +1731,11 @@ get_tables_to_cluster(MemoryContext cluster_context)
  */
 static void
 reform_and_rewrite_tuple(HeapTuple tuple,
-						 TupleDesc oldTupDesc, TupleDesc newTupDesc,
-						 Datum *values, bool *isnull,
-						 bool newRelHasOids, RewriteState rwstate)
+						 Relation OldHeap, Relation NewHeap,
+						 Datum *values, bool *isnull, RewriteState rwstate)
 {
+	TupleDesc oldTupDesc = RelationGetDescr(OldHeap);
+	TupleDesc newTupDesc = RelationGetDescr(NewHeap);
 	HeapTuple	copiedTuple;
 	int			i;
 
@@ -1753,11 +1751,11 @@ reform_and_rewrite_tuple(HeapTuple tuple,
 	copiedTuple = heap_form_tuple(newTupDesc, values, isnull);
 
 	/* Preserve OID, if any */
-	if (newRelHasOids)
+	if (NewHeap->rd_rel->relhasoids)
 		HeapTupleSetOid(copiedTuple, HeapTupleGetOid(tuple));
 
 	/* The heap rewrite module does the rest */
-	rewrite_heap_tuple(rwstate, tuple, copiedTuple);
+	storage_rewrite_tuple(NewHeap, rwstate, tuple, copiedTuple);
 
 	heap_freetuple(copiedTuple);
 }
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index abc36fb554..58a955be4f 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -216,4 +216,13 @@ extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
 extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
 extern bool HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin);
 
+/* in heap/rewriteheap.c */
+extern RewriteState begin_heap_rewrite(Relation OldHeap, Relation NewHeap,
+				   TransactionId OldestXmin, TransactionId FreezeXid,
+				   MultiXactId MultiXactCutoff, bool use_wal);
+extern void end_heap_rewrite(RewriteState state);
+extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
+				   HeapTuple newTuple);
+extern bool rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
+
 #endif							/* HEAPAM_H */
diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h
index 6d7f669cbc..c610914133 100644
--- a/src/include/access/rewriteheap.h
+++ b/src/include/access/rewriteheap.h
@@ -18,17 +18,6 @@
 #include "storage/relfilenode.h"
 #include "utils/relcache.h"
 
-/* struct definition is private to rewriteheap.c */
-typedef struct RewriteStateData *RewriteState;
-
-extern RewriteState begin_heap_rewrite(Relation OldHeap, Relation NewHeap,
-				   TransactionId OldestXmin, TransactionId FreezeXid,
-				   MultiXactId MultiXactCutoff, bool use_wal);
-extern void end_heap_rewrite(RewriteState state);
-extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
-				   HeapTuple newTuple);
-extern bool rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
-
 /*
  * On-Disk data format for an individual logical rewrite mapping.
  */
diff --git a/src/include/access/storage_common.h b/src/include/access/storage_common.h
index 0487758665..04280a7380 100644
--- a/src/include/access/storage_common.h
+++ b/src/include/access/storage_common.h
@@ -40,6 +40,8 @@ typedef enum
 
 typedef struct BulkInsertStateData *BulkInsertState;
 
+/* struct definition is private to rewriteheap.c */
+typedef struct RewriteStateData *RewriteState;
 
 /*
  * slot storage routine functions
diff --git a/src/include/access/storageam.h b/src/include/access/storageam.h
index a0d588c7b0..c7cd01cd10 100644
--- a/src/include/access/storageam.h
+++ b/src/include/access/storageam.h
@@ -122,4 +122,12 @@ extern BulkInsertState storage_getbulkinsertstate(Relation rel);
 extern void storage_freebulkinsertstate(Relation rel, BulkInsertState bistate);
 extern void storage_releasebulkinsertstate(Relation rel, BulkInsertState bistate);
 
+extern RewriteState storage_begin_rewrite(Relation OldHeap, Relation NewHeap,
+				   TransactionId OldestXmin, TransactionId FreezeXid,
+				   MultiXactId MultiXactCutoff, bool use_wal);
+extern void storage_end_rewrite(Relation rel, RewriteState state);
+extern void storage_rewrite_tuple(Relation rel, RewriteState state, HeapTuple oldTuple,
+				   HeapTuple newTuple);
+extern bool storage_rewrite_dead_tuple(Relation rel, RewriteState state, HeapTuple oldTuple);
+
 #endif
diff --git a/src/include/access/storageamapi.h b/src/include/access/storageamapi.h
index d5eb893341..b7a0d5fb07 100644
--- a/src/include/access/storageamapi.h
+++ b/src/include/access/storageamapi.h
@@ -86,6 +86,14 @@ typedef BulkInsertState (*GetBulkInsertState_function) (void);
 typedef void (*FreeBulkInsertState_function) (BulkInsertState bistate);
 typedef void (*ReleaseBulkInsertState_function) (BulkInsertState bistate);
 
+typedef RewriteState (*BeginHeapRewrite_function) (Relation OldHeap, Relation NewHeap,
+				   TransactionId OldestXmin, TransactionId FreezeXid,
+				   MultiXactId MultiXactCutoff, bool use_wal);
+typedef void (*EndHeapRewrite_function) (RewriteState state);
+typedef void (*RewriteHeapTuple_function) (RewriteState state, HeapTuple oldTuple,
+				   HeapTuple newTuple);
+typedef bool (*RewriteHeapDeadTuple_function) (RewriteState state, HeapTuple oldTuple);
+
 typedef StorageScanDesc(*ScanBegin_function) (Relation relation,
 											  Snapshot snapshot,
 											  int nkeys, ScanKey key,
@@ -160,6 +168,11 @@ typedef struct StorageAmRoutine
 	FreeBulkInsertState_function freebulkinsertstate;
 	ReleaseBulkInsertState_function releasebulkinsertstate;
 
+	BeginHeapRewrite_function begin_heap_rewrite;
+	EndHeapRewrite_function end_heap_rewrite;
+	RewriteHeapTuple_function rewrite_heap_tuple;
+	RewriteHeapDeadTuple_function rewrite_heap_dead_tuple;
+
 	/* Operations on relation scans */
 	ScanBegin_function scan_begin;
 	ScanGetParallelheapscandesc_function scan_get_parallelheapscandesc;
-- 
2.15.0.windows.1

