*** a/doc/src/sgml/ref/pg_basebackup.sgml --- b/doc/src/sgml/ref/pg_basebackup.sgml *************** *** 338,345 **** 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. --- 338,345 ---- 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. A value of zero disables ! the status updates completely. The default value is 10 seconds. *** a/doc/src/sgml/ref/pg_receivexlog.sgml --- b/doc/src/sgml/ref/pg_receivexlog.sgml *************** *** 129,136 **** 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. --- 129,136 ---- 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. A value of zero disables the ! status updates completely. The default value is 10 seconds. *** a/src/bin/pg_basebackup/pg_basebackup.c --- b/src/bin/pg_basebackup/pg_basebackup.c *************** *** 46,52 **** int compresslevel = 0; bool includewal = false; bool streamwal = false; bool fastcheckpoint = false; ! int standby_message_timeout = 10; /* 10 sec = default */ /* Progress counters */ static uint64 totalsize; --- 46,52 ---- bool includewal = false; bool streamwal = false; bool fastcheckpoint = false; ! int standby_message_timeout = 10 * 1000; /* 10 sec = default */ /* Progress counters */ static uint64 totalsize; *************** *** 1311,1317 **** main(int argc, char **argv) dbgetpassword = 1; break; case 's': ! standby_message_timeout = atoi(optarg); if (standby_message_timeout < 0) { fprintf(stderr, _("%s: invalid status interval \"%s\"\n"), --- 1311,1317 ---- dbgetpassword = 1; break; case 's': ! standby_message_timeout = atoi(optarg) * 1000; if (standby_message_timeout < 0) { fprintf(stderr, _("%s: invalid status interval \"%s\"\n"), *** a/src/bin/pg_basebackup/pg_receivexlog.c --- b/src/bin/pg_basebackup/pg_receivexlog.c *************** *** 40,46 **** char *basedir = NULL; int verbose = 0; int noloop = 0; ! int standby_message_timeout = 10; /* 10 sec = default */ volatile bool time_to_abort = false; --- 40,46 ---- char *basedir = NULL; int verbose = 0; int noloop = 0; ! int standby_message_timeout = 10 * 1000; /* 10 sec = default */ volatile bool time_to_abort = false; *************** *** 356,362 **** main(int argc, char **argv) dbgetpassword = 1; break; case 's': ! standby_message_timeout = atoi(optarg); if (standby_message_timeout < 0) { fprintf(stderr, _("%s: invalid status interval \"%s\"\n"), --- 356,362 ---- dbgetpassword = 1; break; case 's': ! standby_message_timeout = atoi(optarg) * 1000; if (standby_message_timeout < 0) { fprintf(stderr, _("%s: invalid status interval \"%s\"\n"), *** a/src/bin/pg_basebackup/receivelog.c --- b/src/bin/pg_basebackup/receivelog.c *************** *** 62,68 **** open_walfile(XLogRecPtr startpoint, uint32 timeline, char *basedir, char *namebu f = open(fn, O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR); if (f == -1) { ! fprintf(stderr, _("%s: Could not open WAL segment %s: %s\n"), progname, fn, strerror(errno)); return -1; } --- 62,68 ---- f = open(fn, O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR); if (f == -1) { ! fprintf(stderr, _("%s: could not open WAL segment %s: %s\n"), progname, fn, strerror(errno)); return -1; } *************** *** 196,201 **** localGetCurrentTimestamp(void) --- 196,256 ---- } /* + * 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 + } + + /* + * Local version of TimestampTzPlusMilliseconds(), since we are not + * linked with backend code. + */ + #ifdef HAVE_INT64_TIMESTAMP + #define localTimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000)) + #else + #define localTimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) / 1000.0)) + #endif + + /* * Receive a log stream starting at the specified position. * * If sysidentifier is specified, validate that both the system *************** *** 306,312 **** ReceiveXlogStream(PGconn *conn, XLogRecPtr startpos, uint32 timeline, char *sysi */ now = localGetCurrentTimestamp(); if (standby_message_timeout > 0 && ! last_status < now - standby_message_timeout * 1000000) { /* Time to send feedback! */ char replybuf[sizeof(StandbyReplyMessage) + 1]; --- 361,368 ---- */ now = localGetCurrentTimestamp(); if (standby_message_timeout > 0 && ! localTimestampDifferenceExceeds(last_status, now, ! standby_message_timeout)) { /* Time to send feedback! */ char replybuf[sizeof(StandbyReplyMessage) + 1]; *************** *** 345,354 **** 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; if (timeout.tv_sec <= 0) timeout.tv_sec = 1; /* Always sleep at least 1 sec */ - timeout.tv_usec = 0; timeoutptr = &timeout; } else --- 401,411 ---- FD_SET(PQsocket(conn), &input_mask); if (standby_message_timeout) { ! localTimestampDifference(now, localTimestampTzPlusMilliseconds(last_status, ! standby_message_timeout - 1), ! &timeout.tv_sec, (int *)&timeout.tv_usec); if (timeout.tv_sec <= 0) timeout.tv_sec = 1; /* Always sleep at least 1 sec */ timeoutptr = &timeout; } else