Reset master xmin when hot_standby_feedback disabled.
authorSimon Riggs <simon@2ndQuadrant.com>
Mon, 4 Feb 2013 10:29:22 +0000 (10:29 +0000)
committerSimon Riggs <simon@2ndQuadrant.com>
Mon, 4 Feb 2013 10:29:22 +0000 (10:29 +0000)
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 1a750593707130ec1504d09e58ecf627f98cf922..d32626677d17a01f4c16a8d5eb92c6c727eeff9f 100644 (file)
@@ -1682,8 +1682,10 @@ The commands accepted in walsender mode are:
       </term>
       <listitem>
       <para>
-          The standby's current xmin. This may be 0, if the standby does not
-          support feedback, or is not yet in Hot Standby state.
+          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 73592973ac6218c936b0f12abf5f337106dcb4d2..37d5e0821edaed476272d44fe96caf88bd613e33 100644 (file)
@@ -47,6 +47,7 @@
 #include <unistd.h>
 
 #include "access/timeline.h"
+#include "access/transam.h"
 #include "access/xlog_internal.h"
 #include "libpq/pqformat.h"
 #include "libpq/pqsignal.h"
@@ -138,7 +139,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(bool force, bool requestReply);
-static void XLogWalRcvSendHSFeedback(void);
+static void XLogWalRcvSendHSFeedback(bool immed);
 static void ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime);
 
 /* Signal handlers */
@@ -406,6 +407,7 @@ WalReceiverMain(void)
                {
                    got_SIGHUP = false;
                    ProcessConfigFile(PGC_SIGHUP);
+                   XLogWalRcvSendHSFeedback(true);
                }
 
                /* Wait a while for data to arrive */
@@ -496,7 +498,7 @@ WalReceiverMain(void)
                    }
 
                    XLogWalRcvSendReply(requestReply, requestReply);
-                   XLogWalRcvSendHSFeedback();
+                   XLogWalRcvSendHSFeedback(false);
                }
            }
 
@@ -1059,46 +1061,60 @@ XLogWalRcvSendReply(bool force, bool requestReply)
 /*
  * 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)
 {
    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(sendTime, now,
+   if (!immed)
+   {
+       /*
+        * Send feedback at most once per wal_receiver_status_interval.
+        */
+       if (!TimestampDifferenceExceeds(sendTime, now,
                                    wal_receiver_status_interval * 1000))
-       return;
-   sendTime = now;
+           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
@@ -1118,6 +1134,10 @@ XLogWalRcvSendHSFeedback(void)
    pq_sendint(&reply_message, xmin, 4);
    pq_sendint(&reply_message, nextEpoch, 4);
    walrcv_send(reply_message.data, reply_message.len);
+   if (TransactionIdIsValid(xmin))
+       master_has_standby_xmin = true;
+   else
+       master_has_standby_xmin = false;
 }
 
 /*
index 10e40506965fef3a9b2208b00fbbda26c2fd2e64..490b121362f30f0f8d5100adcf436ebde6ff6837 100644 (file)
@@ -870,9 +870,12 @@ ProcessStandbyHSFeedbackMessage(void)
         feedbackXmin,
         feedbackEpoch);
 
-   /* Ignore invalid xmin (can't actually happen with current walreceiver) */
+   /* Unset WalSender's xmin if the feedback message value is invalid */
    if (!TransactionIdIsNormal(feedbackXmin))
+   {
+       MyPgXact->xmin = InvalidTransactionId;
        return;
+   }
 
    /*
     * Check that the provided xmin/epoch are sane, that is, not in the future