Save slot's restart_lsn when invalidated due to size
authorAlvaro Herrera
Wed, 24 Jun 2020 18:15:17 +0000 (14:15 -0400)
committerAlvaro Herrera
Wed, 24 Jun 2020 18:15:17 +0000 (14:15 -0400)
We put it aside as invalidated_at, which let us show "lost" in
pg_replication slot.  Prior to this change, the state value was reported
as NULL.

Backpatch to 13.

Author: Kyotaro Horiguchi 
Reviewed-by: Álvaro Herrera
Discussion: https://postgr.es/m/20200617.101707.1735599255100002667[email protected]
Discussion: https://postgr.es/m/20200407.120905.1507671100168805403[email protected]

src/backend/replication/slot.c
src/backend/replication/slotfuncs.c
src/include/access/xlog.h
src/include/replication/slot.h
src/test/recovery/t/019_replslot_limit.pl

index a7bbcf34991ad53cc927f331ae5f02cb3dedf725..e8761f3a180974126b147e4830653db96d16e602 100644 (file)
@@ -1226,6 +1226,7 @@ restart:
                        (uint32) restart_lsn)));
 
        SpinLockAcquire(&s->mutex);
+       s->data.invalidated_at = s->data.restart_lsn;
        s->data.restart_lsn = InvalidXLogRecPtr;
        SpinLockRelease(&s->mutex);
        ReplicationSlotRelease();
index 06e4955de73b9aeb8808de7f02c6f4a50edb860f..3fc54cb9bab1288d0e23e67276ae06604b5b312e 100644 (file)
@@ -283,6 +283,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
        bool        nulls[PG_GET_REPLICATION_SLOTS_COLS];
        WALAvailability walstate;
        XLogSegNo   last_removed_seg;
+       XLogRecPtr  targetLSN;
        int         i;
 
        if (!slot->in_use)
@@ -342,7 +343,15 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
        else
            nulls[i++] = true;
 
-       walstate = GetWALAvailability(slot_contents.data.restart_lsn);
+       /*
+        * Report availability from invalidated_at when the slot has been
+        * invalidated; otherwise slots would appear as invalid without any
+        * more clues as to what happened.
+        */
+       targetLSN = XLogRecPtrIsInvalid(slot_contents.data.restart_lsn) ?
+           slot_contents.data.invalidated_at :
+           slot_contents.data.restart_lsn;
+       walstate = GetWALAvailability(targetLSN);
 
        switch (walstate)
        {
index 347a38f57cf4c5fc29d6cc3ebae7b8363ab70d35..9702dce98aa2afa98525fa1f1753a9cd0cf5d01a 100644 (file)
@@ -326,7 +326,7 @@ extern void ShutdownXLOG(int code, Datum arg);
 extern void InitXLOGAccess(void);
 extern void CreateCheckPoint(int flags);
 extern bool CreateRestartPoint(int flags);
-extern WALAvailability GetWALAvailability(XLogRecPtr restart_lsn);
+extern WALAvailability GetWALAvailability(XLogRecPtr targetLSN);
 extern XLogRecPtr CalculateMaxmumSafeLSN(void);
 extern void XLogPutNextOid(Oid nextOid);
 extern XLogRecPtr XLogRestorePoint(const char *rpName);
index 917876010eb8e6301d02fd9fb47a455a012e284e..31362585ecb1e2d0c3eabf25f6043cceb534b6af 100644 (file)
@@ -79,6 +79,9 @@ typedef struct ReplicationSlotPersistentData
    /* oldest LSN that might be required by this replication slot */
    XLogRecPtr  restart_lsn;
 
+   /* restart_lsn is copied here when the slot is invalidated */
+   XLogRecPtr  invalidated_at;
+
    /*
     * Oldest LSN that the client has acked receipt for.  This is used as the
     * start_lsn point in case the client doesn't specify one, and also as a
index cba7df920c0c048b3ccb1c5900a00198d9995bc9..f1be984cc9a6cb058b09a5cb8165213f51e1ac99 100644 (file)
@@ -186,7 +186,7 @@ ok( find_in_log(
 $result = $node_master->safe_psql('postgres',
    "SELECT slot_name, active, restart_lsn IS NULL, wal_status, min_safe_lsn FROM pg_replication_slots WHERE slot_name = 'rep1'"
 );
-is($result, "rep1|f|t||", 'check that the slot became inactive');
+is($result, "rep1|f|t|lost|", 'check that the slot became inactive');
 
 # The standby no longer can connect to the master
 $logstart = get_log_size($node_standby);