On Mon, Jul 26, 2021 at 10:13:09AM -0400, Robert Haas wrote:
> I don't think walkdir() has any business calling LogStartupProgress()
> at all. It's supposed to be a generic function, not one that is only
> available to be called from the startup process, or has different
> behavior there. From my point of view, the right thing is to put the
> logging calls into the particular callbacks that SyncDataDirectory()
> uses.

You're right - this is better.

On Wed, Jul 21, 2021 at 04:47:32PM +0530, Bharath Rupireddy wrote:
> > > 1) I still don't see the need for two functions LogStartupProgress and
> > > LogStartupProgressComplete. Most of the code is duplicate. I think we
> > > can just do it with a single function something like [1]:
> >
> > I agree that one function can do this more succinctly.  I think it's best to
> > use a separate enum value for START operations and END operations.
> 
> Maybe I'm missing something here, but I don't understand the purpose
> of this. You can always combine two functions into one, but it's only
> worth doing if you end up with less code, which doesn't seem to be the
> case here.

 4 files changed, 39 insertions(+), 71 deletions(-)

> ... but I'm not exactly sure how to get there from here. Having only
> LogStartupProgress() but having it do a giant if-statement to figure
> out whether we're mid-phase or end-of-phase does not seem like the
> right approach.

I used a bool arg and negation to handle within a single switch.  Maybe it's
cleaner to use a separate enum value for each DONE, and set a local done flag.

 startup[29675] LOG:  database system was interrupted; last known up at 
2021-07-26 10:23:04 CDT
 startup[29675] LOG:  syncing data directory (fsync), elapsed time: 1.38 s, 
current path: ./pg_ident.conf
 startup[29675] LOG:  data directory sync (fsync) complete after 1.72 s
 startup[29675] LOG:  database system was not properly shut down; automatic 
recovery in progress
 startup[29675] LOG:  resetting unlogged relations (cleanup) complete after 
0.00 s
 startup[29675] LOG:  redo starts at 0/17BE500
 startup[29675] LOG:  redo in progress, elapsed time: 1.00 s, current LSN: 
0/35D7CB8
 startup[29675] LOG:  redo in progress, elapsed time: 2.00 s, current LSN: 
0/54A6918
 startup[29675] LOG:  redo in progress, elapsed time: 3.00 s, current LSN: 
0/7370570
 startup[29675] LOG:  redo in progress, elapsed time: 4.00 s, current LSN: 
0/924D8A0
 startup[29675] LOG:  redo done at 0/9FFFFB8 system usage: CPU: user: 4.28 s, 
system: 0.15 s, elapsed: 4.44 s
 startup[29675] LOG:  resetting unlogged relations (init) complete after 0.03 s
 startup[29675] LOG:  checkpoint starting: end-of-recovery immediate
 startup[29675] LOG:  checkpoint complete: wrote 9872 buffers (60.3%); 0 WAL 
file(s) added, 0 removed, 8 recycled; write=0.136 s, sync=0.801 s, total=1.260 
s; sync files=21, longest=0.774 s, average=B

>From 9443005040be52225498d58678b5faa1668bd2ad Mon Sep 17 00:00:00 2001
From: Nitin <nitin.jad...@enterprisedb.com>
Date: Fri, 23 Jul 2021 15:46:56 +0530
Subject: [PATCH 1/2] Shows the progress of the operations performed during
 startup process. The interval between each progress update is configurable
 and it should be mentioned in seconds

---
 src/backend/access/transam/xlog.c             | 178 ++++++++++++++++++
 src/backend/postmaster/startup.c              |   1 +
 src/backend/storage/file/fd.c                 |  13 ++
 src/backend/storage/file/reinit.c             |  18 ++
 src/backend/utils/misc/guc.c                  |  13 +-
 src/backend/utils/misc/postgresql.conf.sample |   6 +
 src/include/access/xlog.h                     |  18 ++
 src/include/utils/timeout.h                   |   1 +
 8 files changed, 247 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3479402272..4f052050f3 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -79,6 +79,7 @@
 #include "utils/relmapper.h"
 #include "utils/pg_rusage.h"
 #include "utils/snapmgr.h"
+#include "utils/timeout.h"
 #include "utils/timestamp.h"
 
 extern uint32 bootstrap_data_checksum_version;
@@ -397,6 +398,23 @@ static bool doRequestWalReceiverReply;
  */
 static XLogRecPtr RedoStartLSN = InvalidXLogRecPtr;
 
+/*
+ * Start timestamp of the operation that occur during startup process.
+ */
+static TimestampTz startupProcessOpStartTime;
+
+/*
+ * Indicates whether the startup progress interval mentioned by the user is
+ * elapsed or not. TRUE if timeout occurred, FALSE otherwise.
+ */
+static bool logStartupProgressTimeout;
+
+/*
+ * The interval between each progress update of the operations that occur
+ * during startup process.
+ */
+int	log_startup_progress_interval;
+
 /*----------
  * Shared-memory data structures for XLOG control
  *
@@ -7351,6 +7369,8 @@ StartupXLOG(void)
 					(errmsg("redo starts at %X/%X",
 							LSN_FORMAT_ARGS(ReadRecPtr))));
 
+			InitStartupProgress();
+
 			/*
 			 * main redo apply loop
 			 */
@@ -7358,6 +7378,8 @@ StartupXLOG(void)
 			{
 				bool		switchedTLI = false;
 
+				LogStartupProgress(STARTUP_PROCESS_OP_REDO, NULL);
+
 #ifdef WAL_DEBUG
 				if (XLOG_DEBUG ||
 					(rmid == RM_XACT_ID && trace_recovery_messages <= DEBUG2) ||
@@ -13021,3 +13043,159 @@ XLogRequestWalReceiverReply(void)
 {
 	doRequestWalReceiverReply = true;
 }
+
+/*
+ * Schedule a wakeup call for logging the progress of startup process.
+ */
+void
+LogStartupProgressTimeoutHandler(void)
+{
+	logStartupProgressTimeout = true;
+}
+
+/*
+ * Sets the start timestamp of the current operation and also enables the
+ * timeout for logging the progress of startup process.
+ */
+void
+InitStartupProgress(void)
+{
+	/*
+	 * If not called from startup process then just return without
+	 * initialization.
+	 */
+	if (!AmStartupProcess())
+		return;
+
+	startupProcessOpStartTime = GetCurrentTimestamp();
+	enable_timeout_after(LOG_STARTUP_PROGRESS_TIMEOUT,
+						 (log_startup_progress_interval * 1000));
+}
+
+/*
+ * Logs the progress of the operations performed during startup process.
+ */
+void
+LogStartupProgress(StartupProcessOp operation, const char *path)
+{
+	long        secs;
+	int         usecs;
+	int			elapsed_ms;
+	int			interval_in_ms;
+
+	/* If not called from startup process then this feature is of no use. */
+	if (!AmStartupProcess())
+		return;
+
+	/* If the feature is disabled, then no need to proceed further. */
+	if (log_startup_progress_interval < 0)
+		return;
+
+	/* If the timeout has not occurred, then no need to log the details. */
+	if (!logStartupProgressTimeout)
+		return;
+
+	/* Timeout has occurred. */
+	TimestampDifference(startupProcessOpStartTime,
+						GetCurrentTimestamp(),
+						&secs, &usecs);
+
+	/*
+	 * Enable the timer for the next log message based on the time that current
+	 * log message timer was supposed to fire.
+	 */
+	elapsed_ms = (secs * 1000) + (usecs / 1000);
+	interval_in_ms = log_startup_progress_interval * 1000;
+	enable_timeout_after(LOG_STARTUP_PROGRESS_TIMEOUT,
+						 (interval_in_ms - (elapsed_ms % interval_in_ms)));
+
+	switch(operation)
+	{
+		case STARTUP_PROCESS_OP_SYNCFS:
+			ereport(LOG,
+					(errmsg("syncing data directory (syncfs), elapsed time: %ld.%02d s, current path: %s",
+							secs, (usecs / 10000), path)));
+			break;
+		case STARTUP_PROCESS_OP_FSYNC:
+			ereport(LOG,
+					(errmsg("syncing data directory (fsync), elapsed time: %ld.%02d s, current path: %s",
+							secs, (usecs / 10000), path)));
+			break;
+		case STARTUP_PROCESS_OP_REDO:
+			ereport(LOG,
+					(errmsg("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
+							secs, (usecs / 10000), LSN_FORMAT_ARGS(ReadRecPtr))));
+			break;
+		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT:
+			ereport(LOG,
+					(errmsg("resetting unlogged relations (init), elapsed time: %ld.%02d s, current path: %s",
+							secs, (usecs / 10000), path)));
+			break;
+		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP:
+			ereport(LOG,
+					(errmsg("resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s",
+							secs, (usecs / 10000), path)));
+			break;
+		default:
+			ereport(ERROR,
+					(errmsg("unrecognized operation (%d) in startup progress update",
+							operation)));
+			break;
+	}
+
+	logStartupProgressTimeout = false;
+}
+
+/*
+ * Logs the completion of the operation performed during startup process and
+ * disables the timeout used for logging the progress.
+ */
+void
+LogStartupProgressComplete(StartupProcessOp operation)
+{
+	long        secs;
+	int         usecs;
+
+	/* If not called from startup process then this feature is of no use. */
+	if (!AmStartupProcess())
+		return;
+
+	/* If the feature is disabled, then no need to proceed further. */
+	if (log_startup_progress_interval < 0)
+		return;
+
+	TimestampDifference(startupProcessOpStartTime,
+						GetCurrentTimestamp(),
+						&secs, &usecs);
+
+	switch(operation)
+	{
+		case STARTUP_PROCESS_OP_SYNCFS:
+			ereport(LOG,
+					(errmsg("data directory sync (syncfs) complete after %ld.%02d s",
+							secs, (usecs / 10000))));
+			break;
+		case STARTUP_PROCESS_OP_FSYNC:
+			ereport(LOG,
+					(errmsg("data directory sync (fsync) complete after %ld.%02d s",
+							secs, (usecs / 10000))));
+			break;
+		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT:
+			ereport(LOG,
+					(errmsg("resetting unlogged relations (init) complete after %ld.%02d s",
+							secs, (usecs / 10000))));
+			break;
+		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP:
+			ereport(LOG,
+					(errmsg("resetting unlogged relations (cleanup) complete after %ld.%02d s",
+							secs, (usecs / 10000))));
+			break;
+		default:
+			ereport(ERROR,
+					(errmsg("unrecognized operation (%d) in startup progress update",
+							operation)));
+			break;
+	}
+
+	disable_timeout(LOG_STARTUP_PROGRESS_TIMEOUT, false);
+}
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
index 69077bd207..08c271cad6 100644
--- a/src/backend/postmaster/startup.c
+++ b/src/backend/postmaster/startup.c
@@ -232,6 +232,7 @@ StartupProcessMain(void)
 	RegisterTimeout(STANDBY_DEADLOCK_TIMEOUT, StandbyDeadLockHandler);
 	RegisterTimeout(STANDBY_TIMEOUT, StandbyTimeoutHandler);
 	RegisterTimeout(STANDBY_LOCK_TIMEOUT, StandbyLockTimeoutHandler);
+	RegisterTimeout(LOG_STARTUP_PROGRESS_TIMEOUT, LogStartupProgressTimeoutHandler);
 
 	/*
 	 * Unblock signals (they were blocked when the postmaster forked us)
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 5d5e8ae94e..49ecbbd3b9 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -100,6 +100,7 @@
 #include "storage/ipc.h"
 #include "utils/guc.h"
 #include "utils/resowner_private.h"
+#include "utils/timeout.h"
 
 /* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
 #if defined(HAVE_SYNC_FILE_RANGE)
@@ -3334,6 +3335,8 @@ do_syncfs(const char *path)
 {
 	int			fd;
 
+	LogStartupProgress(STARTUP_PROCESS_OP_SYNCFS, path);
+
 	fd = OpenTransientFile(path, O_RDONLY);
 	if (fd < 0)
 	{
@@ -3410,6 +3413,8 @@ SyncDataDirectory(void)
 		DIR		   *dir;
 		struct dirent *de;
 
+		InitStartupProgress();
+
 		/*
 		 * On Linux, we don't have to open every single file one by one.  We
 		 * can use syncfs() to sync whole filesystems.  We only expect
@@ -3436,6 +3441,8 @@ SyncDataDirectory(void)
 		/* If pg_wal is a symlink, process that too. */
 		if (xlog_is_symlink)
 			do_syncfs("pg_wal");
+
+		LogStartupProgressComplete(STARTUP_PROCESS_OP_SYNCFS);
 		return;
 	}
 #endif							/* !HAVE_SYNCFS */
@@ -3452,6 +3459,8 @@ SyncDataDirectory(void)
 	walkdir("pg_tblspc", pre_sync_fname, true, DEBUG1);
 #endif
 
+	InitStartupProgress();
+
 	/*
 	 * Now we do the fsync()s in the same order.
 	 *
@@ -3465,6 +3474,8 @@ SyncDataDirectory(void)
 	if (xlog_is_symlink)
 		walkdir("pg_wal", datadir_fsync_fname, false, LOG);
 	walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
+
+	LogStartupProgressComplete(STARTUP_PROCESS_OP_FSYNC);
 }
 
 /*
@@ -3505,6 +3516,8 @@ walkdir(const char *path,
 
 		snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
 
+		LogStartupProgress(STARTUP_PROCESS_OP_FSYNC, path);
+
 		switch (get_dirent_type(subpath, de, process_symlinks, elevel))
 		{
 			case PGFILETYPE_REG:
diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c
index 40c758d789..ba18996d98 100644
--- a/src/backend/storage/file/reinit.c
+++ b/src/backend/storage/file/reinit.c
@@ -16,12 +16,14 @@
 
 #include <unistd.h>
 
+#include "access/xlog.h"
 #include "common/relpath.h"
 #include "storage/copydir.h"
 #include "storage/fd.h"
 #include "storage/reinit.h"
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
+#include "utils/timeout.h"
 
 static void ResetUnloggedRelationsInTablespaceDir(const char *tsdirname,
 												  int op);
@@ -65,6 +67,8 @@ ResetUnloggedRelations(int op)
 								   ALLOCSET_DEFAULT_SIZES);
 	oldctx = MemoryContextSwitchTo(tmpctx);
 
+	InitStartupProgress();
+
 	/*
 	 * First process unlogged files in pg_default ($PGDATA/base)
 	 */
@@ -75,6 +79,7 @@ ResetUnloggedRelations(int op)
 	 */
 	spc_dir = AllocateDir("pg_tblspc");
 
+
 	while ((spc_de = ReadDir(spc_dir, "pg_tblspc")) != NULL)
 	{
 		if (strcmp(spc_de->d_name, ".") == 0 ||
@@ -86,6 +91,11 @@ ResetUnloggedRelations(int op)
 		ResetUnloggedRelationsInTablespaceDir(temp_path, op);
 	}
 
+	if (op & UNLOGGED_RELATION_INIT)
+		LogStartupProgressComplete(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT);
+	else if (op & UNLOGGED_RELATION_CLEANUP)
+		LogStartupProgressComplete(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP);
+
 	FreeDir(spc_dir);
 
 	/*
@@ -136,6 +146,14 @@ ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op)
 
 		snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
 				 tsdirname, de->d_name);
+
+		if (op & UNLOGGED_RELATION_INIT)
+			LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT,
+							   dbspace_path);
+		else if (op & UNLOGGED_RELATION_CLEANUP)
+			LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP,
+							   dbspace_path);
+
 		ResetUnloggedRelationsInDbspaceDir(dbspace_path, op);
 	}
 
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a2e0f8de7e..d0ea7de8ff 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -679,7 +679,6 @@ static char *recovery_target_lsn_string;
 /* should be static, but commands/variable.c needs to get at this */
 char	   *role_string;
 
-
 /*
  * Displayable names for context types (enum GucContext)
  *
@@ -3546,6 +3545,18 @@ static struct config_int ConfigureNamesInt[] =
 		check_client_connection_check_interval, NULL, NULL
 	},
 
+	{
+		{"log_startup_progress_interval", PGC_SIGHUP, LOGGING_WHEN,
+			gettext_noop("Sets the time interval between each progress update "
+						 "of the startup process."),
+			gettext_noop("0 logs all messages. -1 turns this feature off."),
+			GUC_UNIT_S,
+		},
+		&log_startup_progress_interval,
+		-1, -1, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index b242a7fc8b..901e4ba461 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -523,6 +523,12 @@
 					# are logged regardless of their duration; 1.0 logs all
 					# statements from all transactions, 0.0 never logs
 
+log_startup_progress_interval = 10	# Sets the time interval between each
+									# progress update of the startup process.
+									# -1 disables the feature, 0 logs all
+									# messages, > 0 indicates the interval in
+									# seconds.
+
 # - What to Log -
 
 #debug_print_parse = off
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index ccfcf43d62..f17d91bf9c 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -132,6 +132,7 @@ extern char *PrimaryConnInfo;
 extern char *PrimarySlotName;
 extern bool wal_receiver_create_temp_slot;
 extern bool track_wal_io_timing;
+extern int  log_startup_progress_interval;
 
 /* indirectly set via GUC system */
 extern TransactionId recoveryTargetXid;
@@ -295,6 +296,18 @@ typedef enum WALAvailability
 	WALAVAIL_REMOVED			/* WAL segment has been removed */
 } WALAvailability;
 
+/*
+ * Codes of the operations performed during startup process
+ */
+typedef enum StartupProcessOp
+{
+	STARTUP_PROCESS_OP_SYNCFS,
+	STARTUP_PROCESS_OP_FSYNC,
+	STARTUP_PROCESS_OP_REDO,
+	STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT,
+	STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP
+} StartupProcessOp;
+
 struct XLogRecData;
 
 extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
@@ -399,6 +412,11 @@ extern void do_pg_abort_backup(int code, Datum arg);
 extern void register_persistent_abort_backup_handler(void);
 extern SessionBackupState get_backup_status(void);
 
+extern void InitStartupProgress(void);
+extern void LogStartupProgress(StartupProcessOp operation, const char *path);
+extern void LogStartupProgressComplete(StartupProcessOp operation);
+extern void LogStartupProgressTimeoutHandler(void);
+
 /* File path names (all relative to $PGDATA) */
 #define RECOVERY_SIGNAL_FILE	"recovery.signal"
 #define STANDBY_SIGNAL_FILE		"standby.signal"
diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h
index 93e6a691b3..ef892dd647 100644
--- a/src/include/utils/timeout.h
+++ b/src/include/utils/timeout.h
@@ -33,6 +33,7 @@ typedef enum TimeoutId
 	IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
 	IDLE_SESSION_TIMEOUT,
 	CLIENT_CONNECTION_CHECK_TIMEOUT,
+	LOG_STARTUP_PROGRESS_TIMEOUT,
 	/* First user-definable timeout reason */
 	USER_TIMEOUT,
 	/* Maximum number of timeout reasons */
-- 
2.17.0

>From 0119274e7a05da4e31b1f7cfeccd14b90363829d Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryz...@telsasoft.com>
Date: Mon, 26 Jul 2021 10:10:21 -0500
Subject: [PATCH 2/2] justins changes

---
 src/backend/access/transam/xlog.c | 83 ++++++++++---------------------
 src/backend/storage/file/fd.c     | 12 ++---
 src/backend/storage/file/reinit.c |  9 ++--
 src/backend/utils/misc/guc.c      |  1 +
 src/include/access/xlog.h         |  7 ++-
 5 files changed, 40 insertions(+), 72 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 4f052050f3..6b6619a143 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7378,7 +7378,7 @@ StartupXLOG(void)
 			{
 				bool		switchedTLI = false;
 
-				LogStartupProgress(STARTUP_PROCESS_OP_REDO, NULL);
+				LogStartupProgress(STARTUP_PROCESS_OP_REDO, NULL, false);
 
 #ifdef WAL_DEBUG
 				if (XLOG_DEBUG ||
@@ -13073,15 +13073,18 @@ InitStartupProgress(void)
 }
 
 /*
- * Logs the progress of the operations performed during startup process.
+ * Logs the status of operations performed during startup process.
  */
 void
-LogStartupProgress(StartupProcessOp operation, const char *path)
+LogStartupProgress(StartupProcessOp operation, const char *path, bool done)
 {
 	long        secs;
 	int         usecs;
 	int			elapsed_ms;
 	int			interval_in_ms;
+	int			swval = done ? -operation : operation;
+
+	Assert(operation != 0);
 
 	/* If not called from startup process then this feature is of no use. */
 	if (!AmStartupProcess())
@@ -13092,7 +13095,7 @@ LogStartupProgress(StartupProcessOp operation, const char *path)
 		return;
 
 	/* If the timeout has not occurred, then no need to log the details. */
-	if (!logStartupProgressTimeout)
+	if (!logStartupProgressTimeout && !done)
 		return;
 
 	/* Timeout has occurred. */
@@ -13100,16 +13103,7 @@ LogStartupProgress(StartupProcessOp operation, const char *path)
 						GetCurrentTimestamp(),
 						&secs, &usecs);
 
-	/*
-	 * Enable the timer for the next log message based on the time that current
-	 * log message timer was supposed to fire.
-	 */
-	elapsed_ms = (secs * 1000) + (usecs / 1000);
-	interval_in_ms = log_startup_progress_interval * 1000;
-	enable_timeout_after(LOG_STARTUP_PROGRESS_TIMEOUT,
-						 (interval_in_ms - (elapsed_ms % interval_in_ms)));
-
-	switch(operation)
+	switch (swval)
 	{
 		case STARTUP_PROCESS_OP_SYNCFS:
 			ereport(LOG,
@@ -13136,66 +13130,41 @@ LogStartupProgress(StartupProcessOp operation, const char *path)
 					(errmsg("resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s",
 							secs, (usecs / 10000), path)));
 			break;
-		default:
-			ereport(ERROR,
-					(errmsg("unrecognized operation (%d) in startup progress update",
-							operation)));
-			break;
-	}
-
-	logStartupProgressTimeout = false;
-}
-
-/*
- * Logs the completion of the operation performed during startup process and
- * disables the timeout used for logging the progress.
- */
-void
-LogStartupProgressComplete(StartupProcessOp operation)
-{
-	long        secs;
-	int         usecs;
-
-	/* If not called from startup process then this feature is of no use. */
-	if (!AmStartupProcess())
-		return;
 
-	/* If the feature is disabled, then no need to proceed further. */
-	if (log_startup_progress_interval < 0)
-		return;
-
-	TimestampDifference(startupProcessOpStartTime,
-						GetCurrentTimestamp(),
-						&secs, &usecs);
-
-	switch(operation)
-	{
-		case STARTUP_PROCESS_OP_SYNCFS:
+		case -STARTUP_PROCESS_OP_SYNCFS:
 			ereport(LOG,
 					(errmsg("data directory sync (syncfs) complete after %ld.%02d s",
 							secs, (usecs / 10000))));
 			break;
-		case STARTUP_PROCESS_OP_FSYNC:
+		case -STARTUP_PROCESS_OP_FSYNC:
 			ereport(LOG,
 					(errmsg("data directory sync (fsync) complete after %ld.%02d s",
 							secs, (usecs / 10000))));
 			break;
-		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT:
+		case -STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT:
 			ereport(LOG,
 					(errmsg("resetting unlogged relations (init) complete after %ld.%02d s",
 							secs, (usecs / 10000))));
 			break;
-		case STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP:
+		case -STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP:
 			ereport(LOG,
 					(errmsg("resetting unlogged relations (cleanup) complete after %ld.%02d s",
 							secs, (usecs / 10000))));
 			break;
-		default:
-			ereport(ERROR,
-					(errmsg("unrecognized operation (%d) in startup progress update",
-							operation)));
-			break;
 	}
 
-	disable_timeout(LOG_STARTUP_PROGRESS_TIMEOUT, false);
+	if (!done)
+	{
+		/*
+		 * Enable the timer for the next log message based on the time that
+		 * the current log message timer was supposed to fire.
+		 */
+		logStartupProgressTimeout = false;
+		elapsed_ms = (secs * 1000) + (usecs / 1000);
+		interval_in_ms = log_startup_progress_interval * 1000;
+		enable_timeout_after(LOG_STARTUP_PROGRESS_TIMEOUT,
+							 (interval_in_ms - (elapsed_ms % interval_in_ms)));
+	}
+	else
+		disable_timeout(LOG_STARTUP_PROGRESS_TIMEOUT, false);
 }
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 49ecbbd3b9..65e7de200e 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -3335,7 +3335,7 @@ do_syncfs(const char *path)
 {
 	int			fd;
 
-	LogStartupProgress(STARTUP_PROCESS_OP_SYNCFS, path);
+	LogStartupProgress(STARTUP_PROCESS_OP_SYNCFS, path, false);
 
 	fd = OpenTransientFile(path, O_RDONLY);
 	if (fd < 0)
@@ -3442,7 +3442,7 @@ SyncDataDirectory(void)
 		if (xlog_is_symlink)
 			do_syncfs("pg_wal");
 
-		LogStartupProgressComplete(STARTUP_PROCESS_OP_SYNCFS);
+		LogStartupProgress(STARTUP_PROCESS_OP_SYNCFS, NULL, true);
 		return;
 	}
 #endif							/* !HAVE_SYNCFS */
@@ -3475,7 +3475,7 @@ SyncDataDirectory(void)
 		walkdir("pg_wal", datadir_fsync_fname, false, LOG);
 	walkdir("pg_tblspc", datadir_fsync_fname, true, LOG);
 
-	LogStartupProgressComplete(STARTUP_PROCESS_OP_FSYNC);
+	LogStartupProgress(STARTUP_PROCESS_OP_FSYNC, NULL, true);
 }
 
 /*
@@ -3516,8 +3516,6 @@ walkdir(const char *path,
 
 		snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name);
 
-		LogStartupProgress(STARTUP_PROCESS_OP_FSYNC, path);
-
 		switch (get_dirent_type(subpath, de, process_symlinks, elevel))
 		{
 			case PGFILETYPE_REG:
@@ -3596,8 +3594,10 @@ pre_sync_fname(const char *fname, bool isdir, int elevel)
 static void
 datadir_fsync_fname(const char *fname, bool isdir, int elevel)
 {
+	LogStartupProgress(STARTUP_PROCESS_OP_FSYNC, fname, false);
+
 	/*
-	 * We want to silently ignoring errors about unreadable files.  Pass that
+	 * We want to silently ignore errors about unreadable files.  Pass that
 	 * desire on to fsync_fname_ext().
 	 */
 	fsync_fname_ext(fname, isdir, true, elevel);
diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c
index ba18996d98..21a414d434 100644
--- a/src/backend/storage/file/reinit.c
+++ b/src/backend/storage/file/reinit.c
@@ -79,7 +79,6 @@ ResetUnloggedRelations(int op)
 	 */
 	spc_dir = AllocateDir("pg_tblspc");
 
-
 	while ((spc_de = ReadDir(spc_dir, "pg_tblspc")) != NULL)
 	{
 		if (strcmp(spc_de->d_name, ".") == 0 ||
@@ -92,9 +91,9 @@ ResetUnloggedRelations(int op)
 	}
 
 	if (op & UNLOGGED_RELATION_INIT)
-		LogStartupProgressComplete(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT);
+		LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT, NULL, true);
 	else if (op & UNLOGGED_RELATION_CLEANUP)
-		LogStartupProgressComplete(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP);
+		LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP, NULL, true);
 
 	FreeDir(spc_dir);
 
@@ -149,10 +148,10 @@ ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op)
 
 		if (op & UNLOGGED_RELATION_INIT)
 			LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT,
-							   dbspace_path);
+							   dbspace_path, false);
 		else if (op & UNLOGGED_RELATION_CLEANUP)
 			LogStartupProgress(STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP,
-							   dbspace_path);
+							   dbspace_path, false);
 
 		ResetUnloggedRelationsInDbspaceDir(dbspace_path, op);
 	}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d0ea7de8ff..82bbc880d8 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -679,6 +679,7 @@ static char *recovery_target_lsn_string;
 /* should be static, but commands/variable.c needs to get at this */
 char	   *role_string;
 
+
 /*
  * Displayable names for context types (enum GucContext)
  *
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index f17d91bf9c..22ede3baa9 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -301,11 +301,11 @@ typedef enum WALAvailability
  */
 typedef enum StartupProcessOp
 {
-	STARTUP_PROCESS_OP_SYNCFS,
+	STARTUP_PROCESS_OP_SYNCFS = 1,
 	STARTUP_PROCESS_OP_FSYNC,
 	STARTUP_PROCESS_OP_REDO,
 	STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_INIT,
-	STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP
+	STARTUP_PROCESS_OP_RESET_UNLOGGED_REL_CLEANUP,
 } StartupProcessOp;
 
 struct XLogRecData;
@@ -413,8 +413,7 @@ extern void register_persistent_abort_backup_handler(void);
 extern SessionBackupState get_backup_status(void);
 
 extern void InitStartupProgress(void);
-extern void LogStartupProgress(StartupProcessOp operation, const char *path);
-extern void LogStartupProgressComplete(StartupProcessOp operation);
+extern void LogStartupProgress(StartupProcessOp operation, const char *path, bool done);
 extern void LogStartupProgressTimeoutHandler(void);
 
 /* File path names (all relative to $PGDATA) */
-- 
2.17.0

Reply via email to