v65-66-InvalidateObsoleteReplicationSlots_API.patch

text/plain

Filename: v65-66-InvalidateObsoleteReplicationSlots_API.patch
Type: text/plain
Part: 0
Message: Re: Minimal logical decoding on standbys

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v65
File+
src/backend/access/transam/xlog.c 4 3
src/backend/replication/slot.c 32 17
src/backend/storage/ipc/standby.c 1 1
src/include/replication/slot.h 2 1
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a4153518fd..8dd8d40c07 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6818,7 +6818,7 @@ CreateCheckPoint(int flags)
 	XLByteToSeg(RedoRecPtr, _logSegNo, wal_segment_size);
 	KeepLogSeg(recptr, &_logSegNo);
 	if (InvalidateObsoleteReplicationSlots(_logSegNo, InvalidOid,
-										   InvalidTransactionId))
+										   InvalidTransactionId, RS_INVAL_WAL))
 	{
 		/*
 		 * Some slots have been invalidated; recalculate the old-segment
@@ -7263,7 +7263,7 @@ CreateRestartPoint(int flags)
 	endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
 	KeepLogSeg(endptr, &_logSegNo);
 	if (InvalidateObsoleteReplicationSlots(_logSegNo, InvalidOid,
-										   InvalidTransactionId))
+										   InvalidTransactionId, RS_INVAL_WAL))
 	{
 		/*
 		 * Some slots have been invalidated; recalculate the old-segment
@@ -7988,7 +7988,8 @@ xlog_redo(XLogReaderState *record)
 			xlrec.wal_level < WAL_LEVEL_LOGICAL &&
 			wal_level >= WAL_LEVEL_LOGICAL)
 			InvalidateObsoleteReplicationSlots(0, InvalidOid,
-											   InvalidTransactionId);
+											   InvalidTransactionId,
+											   RS_INVAL_WAL_LEVEL);
 
 		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 		ControlFile->MaxConnections = xlrec.MaxConnections;
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 411f6c0149..3c527742de 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1322,12 +1322,13 @@ LogicalReplicationSlotXidsConflict(ReplicationSlot *s, Oid dboid, TransactionId
  */
 static bool
 InvalidatePossiblyObsoleteSlot(ReplicationSlot *s, XLogRecPtr oldestLSN,
-							   Oid dboid, TransactionId xid, bool *invalidated)
+							   Oid dboid, TransactionId xid, bool *invalidated,
+							   ReplicationSlotInvalidationCause cause)
 {
 	int			last_signaled_pid = 0;
 	bool		released_lock = false;
 	bool		invalidate_all_logical = !TransactionIdIsValid(xid) &&
-		oldestLSN == InvalidXLogRecPtr;
+	oldestLSN == InvalidXLogRecPtr;
 
 
 	for (;;)
@@ -1363,14 +1364,30 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlot *s, XLogRecPtr oldestLSN,
 		 */
 		if (s->data.invalidated == RS_INVAL_NONE)
 		{
-			if (oldestLSN != InvalidXLogRecPtr && s->data.restart_lsn != InvalidXLogRecPtr &&
-				s->data.restart_lsn < oldestLSN)
-				conflict = RS_INVAL_WAL;
-			if (TransactionIdIsValid(xid) && SlotIsLogical(s) &&
-				LogicalReplicationSlotXidsConflict(s, dboid, xid))
-				conflict = RS_INVAL_XID;
-			else if (invalidate_all_logical && SlotIsLogical(s))
-				conflict = RS_INVAL_WAL_LEVEL;
+			switch (cause)
+			{
+				case RS_INVAL_WAL:
+					if (oldestLSN != InvalidXLogRecPtr && s->data.restart_lsn != InvalidXLogRecPtr &&
+						s->data.restart_lsn < oldestLSN)
+						conflict = cause;
+					break;
+				case RS_INVAL_XID:
+					if (TransactionIdIsValid(xid) && SlotIsLogical(s) &&
+						LogicalReplicationSlotXidsConflict(s, dboid, xid))
+						conflict = cause;
+					break;
+				case RS_INVAL_WAL_LEVEL:
+					if (invalidate_all_logical && SlotIsLogical(s))
+						conflict = cause;
+					break;
+				default:
+					break;
+
+					/*
+					 * this runs as part of checkpoint, so avoid raising
+					 * errors if possible
+					 */
+			}
 		}
 
 		/* if there's no conflict, we're done */
@@ -1511,16 +1528,12 @@ InvalidatePossiblyObsoleteSlot(ReplicationSlot *s, XLogRecPtr oldestLSN,
  *	 be invalidated. Note that WaitExceedsMaxStandbyDelay() is not taken into
  *	 account here (as opposed to ResolveRecoveryConflictWithVirtualXIDs()): XXXX
  *
- *
- * XXX: Should we have the caller pass in a specific
- * ReplicationSlotInvalidationCause that we should search for? That'd likely
- * make some things a bit neater.
- *
  * NB - this runs as part of checkpoint, so avoid raising errors if possible.
  */
 bool
 InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno, Oid dboid,
-								   TransactionId xid)
+								   TransactionId snapshotConflictHorizon,
+								   ReplicationSlotInvalidationCause cause)
 {
 	XLogRecPtr	oldestLSN;
 	bool		invalidated = false;
@@ -1539,7 +1552,9 @@ restart:
 		if (!s->in_use)
 			continue;
 
-		if (InvalidatePossiblyObsoleteSlot(s, oldestLSN, dboid, xid, &invalidated))
+		if (InvalidatePossiblyObsoleteSlot(s, oldestLSN, dboid,
+										   snapshotConflictHorizon, &invalidated,
+										   cause))
 		{
 			/* if the lock was released, start from scratch */
 			goto restart;
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index ce5842b0db..77166127f2 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -496,7 +496,7 @@ ResolveRecoveryConflictWithSnapshot(TransactionId snapshotConflictHorizon,
 
 	if (wal_level >= WAL_LEVEL_LOGICAL && isCatalogRel)
 		InvalidateObsoleteReplicationSlots(0, locator.dbOid,
-										   snapshotConflictHorizon);
+										   snapshotConflictHorizon, RS_INVAL_XID);
 }
 
 /*
diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h
index 35cafe94bc..1430c7e908 100644
--- a/src/include/replication/slot.h
+++ b/src/include/replication/slot.h
@@ -231,7 +231,8 @@ extern XLogRecPtr ReplicationSlotsComputeLogicalRestartLSN(void);
 extern bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive);
 extern void ReplicationSlotsDropDBSlots(Oid dboid);
 extern bool InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno, Oid dboid,
-											   TransactionId xid);
+											   TransactionId snapshotConflictHorizon,
+											   ReplicationSlotInvalidationCause cause);
 extern ReplicationSlot *SearchNamedReplicationSlot(const char *name, bool need_lock);
 extern int	ReplicationSlotIndex(ReplicationSlot *slot);
 extern bool ReplicationSlotName(int index, Name name);