From 64dbbd49719656eb3fbeb7fd8582a0fb952d54e9 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 17 Feb 2015 19:00:07 +0900
Subject: [PATCH] Make walreceiver to keep regular reply message even on heavy
 load v2.

Wal receiver cannot send receiver reply message while it is receiving
continuous WAL stream caused by heavy load or something else. This
patch makes wal receiver to send reply message even on such a
situation.
---
 src/backend/replication/walreceiver.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 3dfc3d6..a3e1fd9 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -67,6 +67,10 @@ walrcv_send_type walrcv_send = NULL;
 walrcv_disconnect_type walrcv_disconnect = NULL;
 
 #define NAPTIME_PER_CYCLE 100	/* max sleep time between cycles (100ms) */
+#define WAL_PROCESS_WORST_DURATION 1 /* Anticipated worst duration to process
+									  * wal record in seconds. This is used to
+									  * calculate how often to check the time
+									  * to send reply message */
 
 /*
  * These variables are used similarly to openLogFile/Id/Seg/Off,
@@ -316,13 +320,34 @@ WalReceiverMain(void)
 		/* Wait a while for data to arrive */
 		if (walrcv_receive(NAPTIME_PER_CYCLE, &type, &buf, &len))
 		{
-			/* Accept the received data, and process it */
-			XLogWalRcvProcessMsg(type, buf, len);
+			/*
+			 * Check timeout once per several loops in order to avoid exccess
+			 * calling of gettimeofday().
+			 */
+			int check_interval = 
+				wal_receiver_status_interval / WAL_PROCESS_WORST_DURATION;
+			int count = 0;
 
 			/* Receive any more data we can without sleeping */
-			while (walrcv_receive(0, &type, &buf, &len))
+			do
+			{
+				/* Accept the received data, and process it */
 				XLogWalRcvProcessMsg(type, buf, len);
 
+				/*
+				 * walrecv->lastMsgReceiptTime has the time as of
+				 * XLogWalRcvProcessMsg just above.
+				 */
+				if (count++ >= check_interval)
+				{
+					if (TimestampDifferenceExceeds(reply_message.sendTime,
+										GetCurrentTimestamp(),
+										wal_receiver_status_interval * 1000))
+						XLogWalRcvSendReply();
+					count = 0;
+				}
+			} while (walrcv_receive(0, &type, &buf, &len));
+
 			/* Let the master know that we received some data. */
 			XLogWalRcvSendReply();
 
-- 
2.1.0.GIT

