]> granicus.if.org Git - postgresql/commitdiff
Reset master xmin when hot_standby_feedback disabled.
authorSimon Riggs <simon@2ndQuadrant.com>
Tue, 15 Jul 2014 13:45:44 +0000 (14:45 +0100)
committerSimon Riggs <simon@2ndQuadrant.com>
Tue, 15 Jul 2014 13:45:44 +0000 (14:45 +0100)
If walsender has xmin of standby then ensure we
reset the value to 0 when we change from hot_standby_feedback=on
to hot_standby_feedback=off.

doc/src/sgml/protocol.sgml
src/backend/replication/walreceiver.c
src/backend/replication/walsender.c

index e7438809309d7d35f7f1a2e5b8e761b410df4f05..8a0755eea989259a0fe5e5895213213d35df46db 100644 (file)
@@ -1584,7 +1584,10 @@ The commands accepted in walsender mode are:
       </term>
       <listitem>
       <para>
-          The standby's current xmin.
+          The standby's current xmin. This may be 0, if the standby is
+          sending notification that Hot Standby feedback will no
+          longer be sent on this connection. Later non-zero messages may
+          reinitiate the feedback mechanism.
       </para>
       </listitem>
       </varlistentry>
index d2ac547602bed3b65fad79510dd5301fc4750314..3dfc3d64576727ddc50090fbb39954238642d93d 100644 (file)
@@ -124,7 +124,7 @@ static void XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len);
 static void XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr);
 static void XLogWalRcvFlush(bool dying);
 static void XLogWalRcvSendReply(void);
-static void XLogWalRcvSendHSFeedback(void);
+static void XLogWalRcvSendHSFeedback(bool immed);
 
 /* Signal handlers */
 static void WalRcvSigHupHandler(SIGNAL_ARGS);
@@ -310,6 +310,7 @@ WalReceiverMain(void)
                {
                        got_SIGHUP = false;
                        ProcessConfigFile(PGC_SIGHUP);
+                       XLogWalRcvSendHSFeedback(true);
                }
 
                /* Wait a while for data to arrive */
@@ -338,7 +339,7 @@ WalReceiverMain(void)
                         * master anyway, to report any progress in applying WAL.
                         */
                        XLogWalRcvSendReply();
-                       XLogWalRcvSendHSFeedback();
+                       XLogWalRcvSendHSFeedback(false);
                }
        }
 }
@@ -591,7 +592,7 @@ XLogWalRcvFlush(bool dying)
                if (!dying)
                {
                        XLogWalRcvSendReply();
-                       XLogWalRcvSendHSFeedback();
+                       XLogWalRcvSendHSFeedback(false);
                }
        }
 }
@@ -651,45 +652,62 @@ XLogWalRcvSendReply(void)
 /*
  * Send hot standby feedback message to primary, plus the current time,
  * in case they don't have a watch.
+ *
+ * If the user disables feedback, send one final message to tell sender
+ * to forget about the xmin on this standby.
  */
 static void
-XLogWalRcvSendHSFeedback(void)
+XLogWalRcvSendHSFeedback(bool immed)
 {
        char            buf[sizeof(StandbyHSFeedbackMessage) + 1];
        TimestampTz now;
        TransactionId nextXid;
        uint32          nextEpoch;
        TransactionId xmin;
+       static TimestampTz sendTime = 0;
+       static bool master_has_standby_xmin = false;
 
        /*
         * If the user doesn't want status to be reported to the master, be sure
         * to exit before doing anything at all.
         */
-       if (wal_receiver_status_interval <= 0 || !hot_standby_feedback)
+       if ((wal_receiver_status_interval <= 0 || !hot_standby_feedback) &&
+               !master_has_standby_xmin)
                return;
 
        /* Get current timestamp. */
        now = GetCurrentTimestamp();
 
-       /*
-        * Send feedback at most once per wal_receiver_status_interval.
-        */
-       if (!TimestampDifferenceExceeds(feedback_message.sendTime, now,
+       if (!immed)
+       {
+               /*
+                * Send feedback at most once per wal_receiver_status_interval.
+                */
+               if (!TimestampDifferenceExceeds(sendTime, now,
                                                                        wal_receiver_status_interval * 1000))
-               return;
+                       return;
+       }
+
+       sendTime = now;
 
        /*
         * If Hot Standby is not yet active there is nothing to send. Check this
         * after the interval has expired to reduce number of calls.
         */
        if (!HotStandbyActive())
+       {
+               Assert(!master_has_standby_xmin);
                return;
+       }
 
        /*
         * Make the expensive call to get the oldest xmin once we are certain
         * everything else has been checked.
         */
-       xmin = GetOldestXmin(true, false);
+       if (hot_standby_feedback)
+               xmin = GetOldestXmin(true, false);
+       else
+               xmin = InvalidTransactionId;
 
        /*
         * Get epoch and adjust if nextXid and oldestXmin are different sides of
@@ -714,4 +732,8 @@ XLogWalRcvSendHSFeedback(void)
        buf[0] = 'h';
        memcpy(&buf[1], &feedback_message, sizeof(StandbyHSFeedbackMessage));
        walrcv_send(buf, sizeof(StandbyHSFeedbackMessage) + 1);
+       if (TransactionIdIsValid(xmin))
+               master_has_standby_xmin = true;
+       else
+               master_has_standby_xmin = false;
 }
index a5683302d56a453b2ece263c7b08969f63ec96f1..4a5f01d8bed4376a8dd43874417ac3fbdca888d0 100644 (file)
@@ -623,9 +623,12 @@ ProcessStandbyHSFeedbackMessage(void)
                 reply.xmin,
                 reply.epoch);
 
-       /* Ignore invalid xmin (can't actually happen with current walreceiver) */
+       /* Unset WalSender's xmin if the feedback message value is invalid */
        if (!TransactionIdIsNormal(reply.xmin))
+       {
+               MyProc->xmin = InvalidTransactionId;
                return;
+       }
 
        /*
         * Check that the provided xmin/epoch are sane, that is, not in the future