From 2caf22da57885cdd96929cfa02b5c8910c58baad Mon Sep 17 00:00:00 2001
From: Hari Babu <kommi.haribabu@gmail.com>
Date: Wed, 27 Dec 2017 13:04:24 +1100
Subject: [PATCH 10/11] 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 b89069bf74..2a39e0cc1e 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"
@@ -331,5 +332,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 d884b3633c..014dc6d265 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 ccdbe70ff6..1f9cfe9908 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);
 
 
 /*---------------------------------------------------------------------------
@@ -875,7 +874,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);
 
 	/*
@@ -1024,7 +1023,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;
@@ -1038,9 +1037,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)
@@ -1067,16 +1065,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;
@@ -1704,10 +1701,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;
 
@@ -1723,11 +1721,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 99b8cf67d8..9d54515c1e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -211,4 +211,13 @@ extern HTSU_Result HeapTupleSatisfiesUpdate(StorageTuple stup, CommandId curcid,
 extern HTSV_Result HeapTupleSatisfiesVacuum(StorageTuple stup, TransactionId OldestXmin,
 						 Buffer buffer);
 
+/* 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 91ff36707a..8b1ee7a5a7 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 2d0b1a3ccd..2676fc53e2 100644
--- a/src/include/access/storage_common.h
+++ b/src/include/access/storage_common.h
@@ -30,6 +30,8 @@ typedef void *StorageTuple;
 
 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 8ced6c6a1f..1ee2d2ee66 100644
--- a/src/include/access/storageam.h
+++ b/src/include/access/storageam.h
@@ -120,4 +120,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 d79aad71df..c112a97c03 100644
--- a/src/include/access/storageamapi.h
+++ b/src/include/access/storageamapi.h
@@ -84,6 +84,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,
@@ -158,6 +166,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

