diff --git a/doc/src/sgml/ref/pg_basebackup.sgml b/doc/src/sgml/ref/pg_basebackup.sgml
index 76bfcf1cbb..102d649f4e 100644
--- a/doc/src/sgml/ref/pg_basebackup.sgml
+++ b/doc/src/sgml/ref/pg_basebackup.sgml
@@ -338,8 +338,8 @@ PostgreSQL documentation
Specifies the number of seconds between status packets sent back to the
server. This is required when streaming the transaction log (using
--xlog=stream) if replication timeout is configured
- on the server, and allows for easier monitoring. The default value is
- 10 seconds.
+ on the server, and allows for easier monitoring. A value of zero disables
+ the status updates completely. The default value is 10 seconds.
diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml
index f829170da2..b1eee1f20b 100644
--- a/doc/src/sgml/ref/pg_receivexlog.sgml
+++ b/doc/src/sgml/ref/pg_receivexlog.sgml
@@ -129,8 +129,8 @@ PostgreSQL documentation
Specifies the number of seconds between status packets sent back to the
server. This is required if replication timeout is configured on the
- server, and allows for easier monitoring. The default value is
- 10 seconds.
+ server, and allows for easier monitoring. A value of zero disables the
+ status updates completely. The default value is 10 seconds.
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index d7466168d7..c3a0d89897 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -46,7 +46,7 @@ int compresslevel = 0;
bool includewal = false;
bool streamwal = false;
bool fastcheckpoint = false;
-int standby_message_timeout = 10; /* 10 sec = default */
+int standby_message_timeout = 10 * 1000; /* 10 sec = default */
/* Progress counters */
static uint64 totalsize;
@@ -1311,7 +1311,7 @@ main(int argc, char **argv)
dbgetpassword = 1;
break;
case 's':
- standby_message_timeout = atoi(optarg);
+ standby_message_timeout = atoi(optarg) * 1000;
if (standby_message_timeout < 0)
{
fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c
index 084ddc4a8c..67a70bcf71 100644
--- a/src/bin/pg_basebackup/pg_receivexlog.c
+++ b/src/bin/pg_basebackup/pg_receivexlog.c
@@ -40,7 +40,7 @@
char *basedir = NULL;
int verbose = 0;
int noloop = 0;
-int standby_message_timeout = 10; /* 10 sec = default */
+int standby_message_timeout = 10 * 1000; /* 10 sec = default */
volatile bool time_to_abort = false;
@@ -356,7 +356,7 @@ main(int argc, char **argv)
dbgetpassword = 1;
break;
case 's':
- standby_message_timeout = atoi(optarg);
+ standby_message_timeout = atoi(optarg) * 1000;
if (standby_message_timeout < 0)
{
fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 6639771852..a51a40edfd 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -23,6 +23,7 @@
#include "access/xlog_internal.h"
#include "replication/walprotocol.h"
#include "utils/datetime.h"
+#include "utils/timestamp.h"
#include "receivelog.h"
#include "streamutil.h"
@@ -195,6 +196,51 @@ localGetCurrentTimestamp(void)
return result;
}
+/*
+ * Local version of TimestampDifference(), since we are not
+ * linked with backend code.
+ */
+static void
+localTimestampDifference(TimestampTz start_time, TimestampTz stop_time,
+ long *secs, int *microsecs)
+{
+ TimestampTz diff = stop_time - start_time;
+
+ if (diff <= 0)
+ {
+ *secs = 0;
+ *microsecs = 0;
+ }
+ else
+ {
+#ifdef HAVE_INT64_TIMESTAMP
+ *secs = (long) (diff / USECS_PER_SEC);
+ *microsecs = (int) (diff % USECS_PER_SEC);
+#else
+ *secs = (long) diff;
+ *microsecs = (int) ((diff - *secs) * 1000000.0);
+#endif
+ }
+}
+
+/*
+ * Local version of TimestampDifferenceExceeds(), since we are not
+ * linked with backend code.
+ */
+static bool
+localTimestampDifferenceExceeds(TimestampTz start_time,
+ TimestampTz stop_time,
+ int msec)
+{
+ TimestampTz diff = stop_time - start_time;
+
+#ifdef HAVE_INT64_TIMESTAMP
+ return (diff >= msec * INT64CONST(1000));
+#else
+ return (diff * 1000.0 >= msec);
+#endif
+}
+
/*
* Receive a log stream starting at the specified position.
*
@@ -306,7 +352,8 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
*/
now = localGetCurrentTimestamp();
if (standby_message_timeout > 0 &&
- last_status < now - standby_message_timeout * 1000000)
+ localTimestampDifferenceExceeds(last_status, now,
+ standby_message_timeout))
{
/* Time to send feedback! */
char replybuf[sizeof(StandbyReplyMessage) + 1];
@@ -345,10 +392,16 @@ ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi
FD_SET(PQsocket(conn), &input_mask);
if (standby_message_timeout)
{
- timeout.tv_sec = last_status + standby_message_timeout - now - 1;
+ TimestampTz targettime;
+
+ targettime = TimestampTzPlusMilliseconds(last_status,
+ standby_message_timeout - 1);
+ localTimestampDifference(now,
+ targettime,
+ &timeout.tv_sec,
+ (int *)&timeout.tv_usec);
if (timeout.tv_sec <= 0)
timeout.tv_sec = 1; /* Always sleep at least 1 sec */
- timeout.tv_usec = 0;
timeoutptr = &timeout;
}
else