#include "storage/bufmgr.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
-#include "storage/procarray.h"
#include "utils/snapmgr.h"
SpGistState spgstate; /* for SPGiST operations that need one */
spgVacPendingItem *pendingList; /* TIDs we need to (re)visit */
TransactionId myXmin; /* for detecting newly-added redirects */
- TransactionId OldestXmin; /* for deciding a redirect is obsolete */
BlockNumber lastFilledBlock; /* last non-deletable block */
} spgBulkDeleteState;
* Unlike the routines above, this works on both leaf and inner pages.
*/
static void
-vacuumRedirectAndPlaceholder(Relation index, Buffer buffer,
- TransactionId OldestXmin)
+vacuumRedirectAndPlaceholder(Relation index, Buffer buffer)
{
Page page = BufferGetPage(buffer);
SpGistPageOpaque opaque = SpGistPageGetOpaque(page);
xlrec.node = index->rd_node;
xlrec.blkno = BufferGetBlockNumber(buffer);
xlrec.nToPlaceholder = 0;
+ xlrec.newestRedirectXid = InvalidTransactionId;
START_CRIT_SECTION();
dt = (SpGistDeadTuple) PageGetItem(page, PageGetItemId(page, i));
if (dt->tupstate == SPGIST_REDIRECT &&
- TransactionIdPrecedes(dt->xid, OldestXmin))
+ TransactionIdPrecedes(dt->xid, RecentGlobalXmin))
{
dt->tupstate = SPGIST_PLACEHOLDER;
Assert(opaque->nRedirection > 0);
opaque->nRedirection--;
opaque->nPlaceholder++;
+ /* remember newest XID among the removed redirects */
+ if (!TransactionIdIsValid(xlrec.newestRedirectXid) ||
+ TransactionIdPrecedes(xlrec.newestRedirectXid, dt->xid))
+ xlrec.newestRedirectXid = dt->xid;
+
ItemPointerSetInvalid(&dt->pointer);
itemToPlaceholder[xlrec.nToPlaceholder] = i;
else
{
vacuumLeafPage(bds, index, buffer, false);
- vacuumRedirectAndPlaceholder(index, buffer, bds->OldestXmin);
+ vacuumRedirectAndPlaceholder(index, buffer);
}
}
else
{
/* inner page */
- vacuumRedirectAndPlaceholder(index, buffer, bds->OldestXmin);
+ vacuumRedirectAndPlaceholder(index, buffer);
}
/*
/* deal with any deletable tuples */
vacuumLeafPage(bds, index, buffer, true);
/* might as well do this while we are here */
- vacuumRedirectAndPlaceholder(index, buffer, bds->OldestXmin);
+ vacuumRedirectAndPlaceholder(index, buffer);
SpGistSetLastUsedPage(index, buffer);
initSpGistState(&bds->spgstate, index);
bds->pendingList = NULL;
bds->myXmin = GetActiveSnapshot()->xmin;
- bds->OldestXmin = GetOldestXmin(true, false);
bds->lastFilledBlock = SPGIST_LAST_FIXED_BLKNO;
/*
#include "postgres.h"
#include "access/spgist_private.h"
+#include "access/transam.h"
#include "access/xlogutils.h"
-#include "storage/bufmgr.h"
+#include "storage/standby.h"
#include "utils/memutils.h"
ptr += sizeof(spgxlogVacuumRedirect);
itemToPlaceholder = (OffsetNumber *) ptr;
+ /*
+ * If any redirection tuples are being removed, make sure there are no
+ * live Hot Standby transactions that might need to see them. This code
+ * behaves similarly to btree's XLOG_BTREE_REUSE_PAGE case.
+ */
+ if (InHotStandby && TransactionIdIsValid(xldata->newestRedirectXid))
+ ResolveRecoveryConflictWithSnapshot(xldata->newestRedirectXid,
+ xldata->node);
+
if (!(record->xl_info & XLR_BKP_BLOCK_1))
{
buffer = XLogReadBuffer(xldata->node, xldata->blkno, false);
break;
case XLOG_SPGIST_VACUUM_REDIRECT:
out_target(buf, ((spgxlogVacuumRedirect *) rec)->node);
- appendStringInfo(buf, "vacuum redirect tuples on page %u",
- ((spgxlogVacuumRedirect *) rec)->blkno);
+ appendStringInfo(buf, "vacuum redirect tuples on page %u, newest XID %u",
+ ((spgxlogVacuumRedirect *) rec)->blkno,
+ ((spgxlogVacuumRedirect *) rec)->newestRedirectXid);
break;
default:
appendStringInfo(buf, "unknown spgist op code %u", info);