aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gistutil.c')
-rw-r--r--src/backend/access/gist/gistutil.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index f32e16eed58..2163cc482d8 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -23,6 +23,7 @@
#include "storage/lmgr.h"
#include "utils/float.h"
#include "utils/syscache.h"
+#include "utils/snapmgr.h"
#include "utils/lsyscache.h"
@@ -829,13 +830,31 @@ gistNewBuffer(Relation r)
{
Page page = BufferGetPage(buffer);
+ /*
+ * If the page was never initialized, it's OK to use.
+ */
if (PageIsNew(page))
- return buffer; /* OK to use, if never initialized */
+ return buffer;
gistcheckpage(r, buffer);
- if (GistPageIsDeleted(page))
- return buffer; /* OK to use */
+ /*
+ * Otherwise, recycle it if deleted, and too old to have any processes
+ * interested in it.
+ */
+ if (gistPageRecyclable(page))
+ {
+ /*
+ * If we are generating WAL for Hot Standby then create a
+ * WAL record that will allow us to conflict with queries
+ * running on standby, in case they have snapshots older
+ * than the page's deleteXid.
+ */
+ if (XLogStandbyInfoActive() && RelationNeedsWAL(r))
+ gistXLogPageReuse(r, blkno, GistPageGetDeleteXid(page));
+
+ return buffer;
+ }
LockBuffer(buffer, GIST_UNLOCK);
}
@@ -859,6 +878,15 @@ gistNewBuffer(Relation r)
return buffer;
}
+/* Can this page be recycled yet? */
+bool
+gistPageRecyclable(Page page)
+{
+ return PageIsNew(page) ||
+ (GistPageIsDeleted(page) &&
+ TransactionIdPrecedes(GistPageGetDeleteXid(page), RecentGlobalXmin));
+}
+
bytea *
gistoptions(Datum reloptions, bool validate)
{