From c1aa11c772925044318fc0288e5a16e6bc66f977 Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Wed, 31 Jan 2024 10:45:21 +0000
Subject: [PATCH v12 4/5] Exit earlier when we are in the dry_run mode

---
 src/bin/pg_basebackup/pg_createsubscriber.c | 198 ++++++++------------
 1 file changed, 75 insertions(+), 123 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c
index f0e9db7793..6f832f7551 100644
--- a/src/bin/pg_basebackup/pg_createsubscriber.c
+++ b/src/bin/pg_basebackup/pg_createsubscriber.c
@@ -584,8 +584,7 @@ modify_sysid(const char *pg_resetwal_path, const char *datadir)
 	cf->system_identifier |= ((uint64) tv.tv_usec) << 12;
 	cf->system_identifier |= getpid() & 0xFFF;
 
-	if (!dry_run)
-		update_controlfile(datadir, cf, true);
+	update_controlfile(datadir, cf, true);
 
 	pg_log_info("system identifier is %llu on subscriber", (unsigned long long) cf->system_identifier);
 
@@ -595,14 +594,12 @@ modify_sysid(const char *pg_resetwal_path, const char *datadir)
 
 	pg_log_debug("command is: %s", cmd_str);
 
-	if (!dry_run)
-	{
-		rc = system(cmd_str);
-		if (rc == 0)
-			pg_log_info("subscriber successfully changed the system identifier");
-		else
-			pg_log_error("subscriber failed to change system identifier: exit code: %d", rc);
-	}
+	rc = system(cmd_str);
+
+	if (rc == 0)
+		pg_log_info("subscriber successfully changed the system identifier");
+	else
+		pg_log_error("subscriber failed to change system identifier: exit code: %d", rc);
 
 	pfree(cf);
 }
@@ -676,7 +673,7 @@ setup_publisher(LogicalRepInfo *dbinfo)
 		dbinfo[i].subname = pg_strdup(replslotname);
 
 		/* Create replication slot on publisher. */
-		if (create_logical_replication_slot(conn, &dbinfo[i], replslotname) != NULL || dry_run)
+		if (create_logical_replication_slot(conn, &dbinfo[i], replslotname) != NULL)
 			pg_log_info("create replication slot \"%s\" on publisher", replslotname);
 		else
 			return false;
@@ -956,26 +953,20 @@ create_logical_replication_slot(PGconn *conn, LogicalRepInfo *dbinfo,
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_TUPLES_OK)
-		{
-			pg_log_error("could not create replication slot \"%s\" on database \"%s\": %s", slot_name, dbinfo->dbname,
-						 PQresultErrorMessage(res));
-			return lsn;
-		}
+		pg_log_error("could not create replication slot \"%s\" on database \"%s\": %s", slot_name, dbinfo->dbname,
+						PQresultErrorMessage(res));
+		return lsn;
 	}
 
 	/* for cleanup purposes */
 	if (!transient_replslot)
 		dbinfo->made_replslot = true;
 
-	if (!dry_run)
-	{
-		lsn = pg_strdup(PQgetvalue(res, 0, 1));
-		PQclear(res);
-	}
+	lsn = pg_strdup(PQgetvalue(res, 0, 1));
+	PQclear(res);
 
 	destroyPQExpBuffer(str);
 
@@ -997,15 +988,12 @@ drop_replication_slot(PGconn *conn, LogicalRepInfo *dbinfo, const char *slot_nam
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
-	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-			pg_log_error("could not drop replication slot \"%s\" on database \"%s\": %s", slot_name, dbinfo->dbname,
-						 PQerrorMessage(conn));
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		pg_log_error("could not drop replication slot \"%s\" on database \"%s\": %s", slot_name, dbinfo->dbname,
+						PQerrorMessage(conn));
 
-		PQclear(res);
-	}
+	PQclear(res);
 
 	destroyPQExpBuffer(str);
 }
@@ -1138,11 +1126,8 @@ wait_for_end_recovery(const char *conninfo)
 
 		PQclear(res);
 
-		/*
-		 * Does the recovery process finish? In dry run mode, there is no
-		 * recovery mode. Bail out as the recovery process has ended.
-		 */
-		if (!in_recovery || dry_run)
+		/* Does the recovery process finish? */
+		if (!in_recovery)
 		{
 			status = POSTMASTER_READY;
 			break;
@@ -1239,24 +1224,19 @@ create_publication(PGconn *conn, LogicalRepInfo *dbinfo)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-		{
-			pg_log_error("could not create publication \"%s\" on database \"%s\": %s",
-						 dbinfo->pubname, dbinfo->dbname, PQerrorMessage(conn));
-			PQfinish(conn);
-			exit(1);
-		}
+		pg_log_error("could not create publication \"%s\" on database \"%s\": %s",
+						dbinfo->pubname, dbinfo->dbname, PQerrorMessage(conn));
+		PQfinish(conn);
+		exit(1);
 	}
 
 	/* for cleanup purposes */
 	dbinfo->made_publication = true;
 
-	if (!dry_run)
-		PQclear(res);
-
+	PQclear(res);
 	destroyPQExpBuffer(str);
 }
 
@@ -1277,14 +1257,11 @@ drop_publication(PGconn *conn, LogicalRepInfo *dbinfo)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
-	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-			pg_log_error("could not drop publication \"%s\" on database \"%s\": %s", dbinfo->pubname, dbinfo->dbname, PQerrorMessage(conn));
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		pg_log_error("could not drop publication \"%s\" on database \"%s\": %s", dbinfo->pubname, dbinfo->dbname, PQerrorMessage(conn));
 
-		PQclear(res);
-	}
+	PQclear(res);
 
 	destroyPQExpBuffer(str);
 }
@@ -1318,24 +1295,19 @@ create_subscription(PGconn *conn, LogicalRepInfo *dbinfo)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-		{
-			pg_log_error("could not create subscription \"%s\" on database \"%s\": %s",
-						 dbinfo->subname, dbinfo->dbname, PQerrorMessage(conn));
-			PQfinish(conn);
-			exit(1);
-		}
+		pg_log_error("could not create subscription \"%s\" on database \"%s\": %s",
+						dbinfo->subname, dbinfo->dbname, PQerrorMessage(conn));
+		PQfinish(conn);
+		exit(1);
 	}
 
 	/* for cleanup purposes */
 	dbinfo->made_subscription = true;
 
-	if (!dry_run)
-		PQclear(res);
-
+	PQclear(res);
 	destroyPQExpBuffer(str);
 }
 
@@ -1356,14 +1328,11 @@ drop_subscription(PGconn *conn, LogicalRepInfo *dbinfo)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
-	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-			pg_log_error("could not drop subscription \"%s\" on database \"%s\": %s", dbinfo->subname, dbinfo->dbname, PQerrorMessage(conn));
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
+		pg_log_error("could not drop subscription \"%s\" on database \"%s\": %s", dbinfo->subname, dbinfo->dbname, PQerrorMessage(conn));
 
-		PQclear(res);
-	}
+	PQclear(res);
 
 	destroyPQExpBuffer(str);
 }
@@ -1402,7 +1371,7 @@ set_replication_progress(PGconn *conn, LogicalRepInfo *dbinfo, const char *lsn)
 		exit(1);
 	}
 
-	if (PQntuples(res) != 1 && !dry_run)
+	if (PQntuples(res) != 1)
 	{
 		pg_log_error("could not obtain subscription OID: got %d rows, expected %d rows",
 					 PQntuples(res), 1);
@@ -1411,16 +1380,8 @@ set_replication_progress(PGconn *conn, LogicalRepInfo *dbinfo, const char *lsn)
 		exit(1);
 	}
 
-	if (dry_run)
-	{
-		suboid = InvalidOid;
-		snprintf(lsnstr, sizeof(lsnstr), "%X/%X", LSN_FORMAT_ARGS((XLogRecPtr) InvalidXLogRecPtr));
-	}
-	else
-	{
-		suboid = strtoul(PQgetvalue(res, 0, 0), NULL, 10);
-		snprintf(lsnstr, sizeof(lsnstr), "%s", lsn);
-	}
+	suboid = strtoul(PQgetvalue(res, 0, 0), NULL, 10);
+	snprintf(lsnstr, sizeof(lsnstr), "%s", lsn);
 
 	/*
 	 * The origin name is defined as pg_%u. %u is the subscription OID. See
@@ -1439,20 +1400,16 @@ set_replication_progress(PGconn *conn, LogicalRepInfo *dbinfo, const char *lsn)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_TUPLES_OK)
-		{
-			pg_log_error("could not set replication progress for the subscription \"%s\": %s",
-						 dbinfo->subname, PQresultErrorMessage(res));
-			PQfinish(conn);
-			exit(1);
-		}
-
-		PQclear(res);
+		pg_log_error("could not set replication progress for the subscription \"%s\": %s",
+						dbinfo->subname, PQresultErrorMessage(res));
+		PQfinish(conn);
+		exit(1);
 	}
 
+	PQclear(res);
 	destroyPQExpBuffer(str);
 }
 
@@ -1477,20 +1434,16 @@ enable_subscription(PGconn *conn, LogicalRepInfo *dbinfo)
 
 	pg_log_debug("command is: %s", str->data);
 
-	if (!dry_run)
+	res = PQexec(conn, str->data);
+	if (PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		res = PQexec(conn, str->data);
-		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-		{
-			pg_log_error("could not enable subscription \"%s\": %s", dbinfo->subname,
-						 PQerrorMessage(conn));
-			PQfinish(conn);
-			exit(1);
-		}
-
-		PQclear(res);
+		pg_log_error("could not enable subscription \"%s\": %s", dbinfo->subname,
+						PQerrorMessage(conn));
+		PQfinish(conn);
+		exit(1);
 	}
 
+	PQclear(res);
 	destroyPQExpBuffer(str);
 }
 
@@ -1759,6 +1712,14 @@ main(int argc, char **argv)
 		exit(1);
 	}
 
+	/*
+	 * Exit earlier when we are in the dry_run mode.
+	 *
+	 * XXX: Should we keep turning on the standby server in case of dry_run?
+	 */
+	if (dry_run)
+		goto cleanup;
+
 	/*
 	 * Create a temporary logical replication slot to get a consistent LSN.
 	 *
@@ -1783,26 +1744,16 @@ main(int argc, char **argv)
 	 * Despite of the recovery parameters will be written to the subscriber,
 	 * use a publisher connection for the follwing recovery functions. The
 	 * connection is only used to check the current server version (physical
-	 * replica, same server version). The subscriber is not running yet. In
-	 * dry run mode, the recovery parameters *won't* be written. An invalid
-	 * LSN is used for printing purposes.
+	 * replica, same server version). The subscriber is not running yet.
 	 */
 	recoveryconfcontents = GenerateRecoveryConfig(conn, NULL);
 	appendPQExpBuffer(recoveryconfcontents, "recovery_target_inclusive = true\n");
 	appendPQExpBuffer(recoveryconfcontents, "recovery_target_action = promote\n");
 
-	if (dry_run)
-	{
-		appendPQExpBuffer(recoveryconfcontents, "# dry run mode");
-		appendPQExpBuffer(recoveryconfcontents, "recovery_target_lsn = '%X/%X'\n",
-						  LSN_FORMAT_ARGS((XLogRecPtr) InvalidXLogRecPtr));
-	}
-	else
-	{
-		appendPQExpBuffer(recoveryconfcontents, "recovery_target_lsn = '%s'\n",
-						  consistent_lsn);
-		WriteRecoveryConfig(conn, subscriber_dir, recoveryconfcontents);
-	}
+	appendPQExpBuffer(recoveryconfcontents, "recovery_target_lsn = '%s'\n",
+						consistent_lsn);
+	WriteRecoveryConfig(conn, subscriber_dir, recoveryconfcontents);
+
 	disconnect_database(conn);
 
 	pg_log_debug("recovery parameters:\n%s", recoveryconfcontents->data);
@@ -1860,6 +1811,7 @@ main(int argc, char **argv)
 	 */
 	modify_sysid(pg_resetwal_path, subscriber_dir);
 
+cleanup:
 	/*
 	 * The log file is kept if retain option is specified or this tool does
 	 * not run successfully. Otherwise, log file is removed.
-- 
2.43.0

