From 0560b46f96e82c7082b8fcf434a3c6c9f46a94b8 Mon Sep 17 00:00:00 2001
From: Andrey <amborodin@acm.org>
Date: Mon, 10 Dec 2018 18:49:47 +0500
Subject: [PATCH] Stamp deleted GIN page with xid v3

---
 src/backend/access/gin/ginutil.c   | 7 ++++++-
 src/backend/access/gin/ginvacuum.c | 7 ++++++-
 src/backend/access/gin/ginxlog.c   | 1 +
 src/include/access/gin_private.h   | 3 +++
 src/include/access/ginxlog.h       | 1 +
 5 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index d7696a1ad0..5ce39d821b 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -314,7 +314,12 @@ GinNewBuffer(Relation index)
 			if (PageIsNew(page))
 				return buffer;	/* OK to use, if never initialized */
 
-			if (GinPageIsDeleted(page))
+			/*
+			 * We should not reuse page until every transaction started before
+			 * deletion is over
+			 */
+			if (GinPageIsDeleted(page)
+				&& TransactionIdPrecedes(GinPageGetDeleteXid(page), RecentGlobalXmin))
 				return buffer;	/* OK to use */
 
 			LockBuffer(buffer, GIN_UNLOCK);
diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 3104bc12b6..75dc03f495 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -16,6 +16,7 @@
 
 #include "access/gin_private.h"
 #include "access/ginxlog.h"
+#include "access/transam.h"
 #include "access/xloginsert.h"
 #include "commands/vacuum.h"
 #include "miscadmin.h"
@@ -157,6 +158,9 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
 	page = BufferGetPage(dBuffer);
 	rightlink = GinPageGetOpaque(page)->rightlink;
 
+	/* for each deleted page we remember last xid which could knew it's address */
+	GinPageSetDeleteXid(page, ReadNewTransactionId());
+
 	/*
 	 * Any insert which would have gone on the leaf block will now go to its
 	 * right sibling.
@@ -213,6 +217,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
 
 		data.parentOffset = myoff;
 		data.rightLink = GinPageGetOpaque(page)->rightlink;
+		data.deleteXid = GinPageGetDeleteXid(page);
 
 		XLogRegisterData((char *) &data, sizeof(ginxlogDeletePage));
 
@@ -742,7 +747,7 @@ ginvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
 		LockBuffer(buffer, GIN_SHARE);
 		page = (Page) BufferGetPage(buffer);
 
-		if (PageIsNew(page) || GinPageIsDeleted(page))
+		if (PageIsNew(page) || (GinPageIsDeleted(page) && TransactionIdPrecedes(GinPageGetDeleteXid(page), RecentGlobalXmin)))
 		{
 			Assert(blkno != GIN_ROOT_BLKNO);
 			RecordFreeIndexPage(index, blkno);
diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c
index 7701a2d6bf..7821f69077 100644
--- a/src/backend/access/gin/ginxlog.c
+++ b/src/backend/access/gin/ginxlog.c
@@ -518,6 +518,7 @@ ginRedoDeletePage(XLogReaderState *record)
 		page = BufferGetPage(dbuffer);
 		Assert(GinPageIsData(page));
 		GinPageGetOpaque(page)->flags = GIN_DELETED;
+		GinPageSetDeleteXid(page, data->deleteXid);
 		PageSetLSN(page, lsn);
 		MarkBufferDirty(dbuffer);
 	}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 81bf8734ce..83d2621488 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -44,6 +44,9 @@ typedef struct GinOptions
 #define GIN_SHARE	BUFFER_LOCK_SHARE
 #define GIN_EXCLUSIVE  BUFFER_LOCK_EXCLUSIVE
 
+#define GinPageGetDeleteXid(page) ( ((PageHeader) (page))->pd_prune_xid )
+#define GinPageSetDeleteXid(page, val) ( ((PageHeader) (page))->pd_prune_xid = val)
+
 
 /*
  * GinState: working data structure describing the index being worked on
diff --git a/src/include/access/ginxlog.h b/src/include/access/ginxlog.h
index 64a3c9e18b..d7f44d6b83 100644
--- a/src/include/access/ginxlog.h
+++ b/src/include/access/ginxlog.h
@@ -158,6 +158,7 @@ typedef struct ginxlogDeletePage
 {
 	OffsetNumber parentOffset;
 	BlockNumber rightLink;
+	TransactionId deleteXid; /* last Xid which could see page in scan */
 } ginxlogDeletePage;
 
 #define XLOG_GIN_UPDATE_META_PAGE 0x60
-- 
2.17.2 (Apple Git-113)

