4747#include <unistd.h>
4848
4949#include "access/timeline.h"
50+ #include "access/transam.h"
5051#include "access/xlog_internal.h"
5152#include "libpq/pqformat.h"
5253#include "libpq/pqsignal.h"
@@ -138,7 +139,7 @@ static void XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len);
138139static void XLogWalRcvWrite (char * buf , Size nbytes , XLogRecPtr recptr );
139140static void XLogWalRcvFlush (bool dying );
140141static void XLogWalRcvSendReply (bool force , bool requestReply );
141- static void XLogWalRcvSendHSFeedback (void );
142+ static void XLogWalRcvSendHSFeedback (bool immed );
142143static void ProcessWalSndrMessage (XLogRecPtr walEnd , TimestampTz sendTime );
143144
144145/* Signal handlers */
@@ -406,6 +407,7 @@ WalReceiverMain(void)
406407 {
407408 got_SIGHUP = false;
408409 ProcessConfigFile (PGC_SIGHUP );
410+ XLogWalRcvSendHSFeedback (true);
409411 }
410412
411413 /* Wait a while for data to arrive */
@@ -496,7 +498,7 @@ WalReceiverMain(void)
496498 }
497499
498500 XLogWalRcvSendReply (requestReply , requestReply );
499- XLogWalRcvSendHSFeedback ();
501+ XLogWalRcvSendHSFeedback (false );
500502 }
501503 }
502504
@@ -1059,46 +1061,60 @@ XLogWalRcvSendReply(bool force, bool requestReply)
10591061/*
10601062 * Send hot standby feedback message to primary, plus the current time,
10611063 * in case they don't have a watch.
1064+ *
1065+ * If the user disables feedback, send one final message to tell sender
1066+ * to forget about the xmin on this standby.
10621067 */
10631068static void
1064- XLogWalRcvSendHSFeedback (void )
1069+ XLogWalRcvSendHSFeedback (bool immed )
10651070{
10661071 TimestampTz now ;
10671072 TransactionId nextXid ;
10681073 uint32 nextEpoch ;
10691074 TransactionId xmin ;
10701075 static TimestampTz sendTime = 0 ;
1076+ static bool master_has_standby_xmin = false;
10711077
10721078 /*
10731079 * If the user doesn't want status to be reported to the master, be sure
10741080 * to exit before doing anything at all.
10751081 */
1076- if (wal_receiver_status_interval <= 0 || !hot_standby_feedback )
1082+ if ((wal_receiver_status_interval <= 0 || !hot_standby_feedback ) &&
1083+ !master_has_standby_xmin )
10771084 return ;
10781085
10791086 /* Get current timestamp. */
10801087 now = GetCurrentTimestamp ();
10811088
1082- /*
1083- * Send feedback at most once per wal_receiver_status_interval.
1084- */
1085- if (!TimestampDifferenceExceeds (sendTime , now ,
1089+ if (!immed )
1090+ {
1091+ /*
1092+ * Send feedback at most once per wal_receiver_status_interval.
1093+ */
1094+ if (!TimestampDifferenceExceeds (sendTime , now ,
10861095 wal_receiver_status_interval * 1000 ))
1087- return ;
1088- sendTime = now ;
1096+ return ;
1097+ sendTime = now ;
1098+ }
10891099
10901100 /*
10911101 * If Hot Standby is not yet active there is nothing to send. Check this
10921102 * after the interval has expired to reduce number of calls.
10931103 */
10941104 if (!HotStandbyActive ())
1105+ {
1106+ Assert (!master_has_standby_xmin );
10951107 return ;
1108+ }
10961109
10971110 /*
10981111 * Make the expensive call to get the oldest xmin once we are certain
10991112 * everything else has been checked.
11001113 */
1101- xmin = GetOldestXmin (true, false);
1114+ if (hot_standby_feedback )
1115+ xmin = GetOldestXmin (true, false);
1116+ else
1117+ xmin = InvalidTransactionId ;
11021118
11031119 /*
11041120 * Get epoch and adjust if nextXid and oldestXmin are different sides of
@@ -1118,6 +1134,10 @@ XLogWalRcvSendHSFeedback(void)
11181134 pq_sendint (& reply_message , xmin , 4 );
11191135 pq_sendint (& reply_message , nextEpoch , 4 );
11201136 walrcv_send (reply_message .data , reply_message .len );
1137+ if (TransactionIdIsValid (xmin ))
1138+ master_has_standby_xmin = true;
1139+ else
1140+ master_has_standby_xmin = false;
11211141}
11221142
11231143/*
0 commit comments