v4-0003-Address-some-comments-proposed-on-hackers.patch
application/octet-stream
Filename: v4-0003-Address-some-comments-proposed-on-hackers.patch
Type: application/octet-stream
Part: 2
Message:
RE: speed up a logical replica setup
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v4-0003
Subject: Address some comments proposed on -hackers
| File | + | − |
|---|---|---|
| src/bin/pg_basebackup/pg_subscriber.c | 98 | 12 |
From efae01bbbf8f26ad09273562261d93bd57f485fe Mon Sep 17 00:00:00 2001
From: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Date: Wed, 10 Jan 2024 05:53:56 +0000
Subject: [PATCH v4 3/3] Address some comments proposed on -hackers
This patch contains below changes.
* Add --port option
* Restrict --subscriber-conninfo not to specify external server
* Allow to specify publication/subscription options
* Remove unecessary Assert
* Save logs in Standby logfile
---
src/bin/pg_basebackup/pg_subscriber.c | 110 +++++++++++++++++++++++---
1 file changed, 98 insertions(+), 12 deletions(-)
diff --git a/src/bin/pg_basebackup/pg_subscriber.c b/src/bin/pg_basebackup/pg_subscriber.c
index c2d17dcda3..d502230b28 100644
--- a/src/bin/pg_basebackup/pg_subscriber.c
+++ b/src/bin/pg_basebackup/pg_subscriber.c
@@ -27,6 +27,7 @@
#include "fe_utils/recovery_gen.h"
#include "fe_utils/simple_list.h"
#include "getopt_long.h"
+#include "libpq/pqcomm.h"
#include "utils/pidfile.h"
typedef struct LogicalRepInfo
@@ -52,7 +53,7 @@ static char *get_base_conninfo(char *conninfo, char *dbname,
const char *noderole);
static bool get_exec_path(const char *path);
static bool check_data_directory(const char *datadir);
-static char *concat_conninfo_dbname(const char *conninfo, const char *dbname);
+static char *concat_conninfo(const char *conninfo, const char *dbname, unsigned short port);
static LogicalRepInfo *store_pub_sub_info(const char *pub_base_conninfo, const char *sub_base_conninfo);
static PGconn *connect_database(const char *conninfo);
static void disconnect_database(PGconn *conn);
@@ -74,6 +75,7 @@ static void enable_subscription(PGconn *conn, LogicalRepInfo *dbinfo);
#define USEC_PER_SEC 1000000
#define WAIT_INTERVAL 1 /* 1 second */
+#define DEF_PGSPORT 50111
/* Options */
static const char *progname;
@@ -95,6 +97,11 @@ static int num_dbs = 0;
static char temp_replslot[NAMEDATALEN] = {0};
static bool made_transient_replslot = false;
+static unsigned short subport;
+
+static char *pubopts;
+static char *subopts;
+
enum WaitPMResult
{
POSTMASTER_READY,
@@ -120,6 +127,9 @@ cleanup_objects_atexit(void)
if (success)
return;
+ if (!dbinfo)
+ return;
+
for (i = 0; i < num_dbs; i++)
{
if (dbinfo[i].made_subscription)
@@ -149,7 +159,8 @@ cleanup_objects_atexit(void)
if (made_transient_replslot)
{
conn = connect_database(dbinfo[0].pubconninfo);
- drop_replication_slot(conn, &dbinfo[0], temp_replslot);
+ if (conn != NULL)
+ drop_replication_slot(conn, &dbinfo[0], temp_replslot);
disconnect_database(conn);
}
}
@@ -214,6 +225,26 @@ get_base_conninfo(char *conninfo, char *dbname, const char *noderole)
continue;
}
+ /*
+ * If the dbname is NULL (this means the conninfo is for the
+ * subscriber), we also check that the connection string does not
+ * specify the non-local server.
+ */
+ if (!dbname &&
+ (strcmp(conn_opt->keyword, "host") == 0 ||
+ strcmp(conn_opt->keyword, "hostaddr") == 0) &&
+ conn_opt->val != NULL)
+ {
+ const char *value = conn_opt->val;
+
+ if (value && strlen(value) > 0 &&
+ /* check for 'local' host values */
+ (strcmp(value, "localhost") != 0 && strcmp(value, "127.0.0.1") != 0 &&
+ strcmp(value, "::1") != 0 && !is_unixsock_path(value)))
+ pg_fatal("--subscriber-conninfo must not be non-local connection: %s",
+ value);
+ }
+
if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
{
if (i > 0)
@@ -332,14 +363,14 @@ check_data_directory(const char *datadir)
}
/*
- * Append database name into a base connection string.
+ * Append database name and/or port number into a base connection string.
*
* dbname is the only parameter that changes so it is not included in the base
* connection string. This function concatenates dbname to build a "real"
* connection string.
*/
static char *
-concat_conninfo_dbname(const char *conninfo, const char *dbname)
+concat_conninfo(const char *conninfo, const char *dbname, unsigned short port)
{
PQExpBuffer buf = createPQExpBuffer();
char *ret;
@@ -349,6 +380,9 @@ concat_conninfo_dbname(const char *conninfo, const char *dbname)
appendPQExpBufferStr(buf, conninfo);
appendPQExpBuffer(buf, " dbname=%s", dbname);
+ if (port)
+ appendPQExpBuffer(buf, " port=%d", port);
+
ret = pg_strdup(buf->data);
destroyPQExpBuffer(buf);
@@ -372,7 +406,7 @@ store_pub_sub_info(const char *pub_base_conninfo, const char *sub_base_conninfo)
char *conninfo;
/* Publisher. */
- conninfo = concat_conninfo_dbname(pub_base_conninfo, cell->val);
+ conninfo = concat_conninfo(pub_base_conninfo, cell->val, 0);
dbinfo[i].pubconninfo = conninfo;
dbinfo[i].dbname = cell->val;
dbinfo[i].made_replslot = false;
@@ -381,7 +415,7 @@ store_pub_sub_info(const char *pub_base_conninfo, const char *sub_base_conninfo)
/* other struct fields will be filled later. */
/* Subscriber. */
- conninfo = concat_conninfo_dbname(sub_base_conninfo, cell->val);
+ conninfo = concat_conninfo(sub_base_conninfo, cell->val, subport);
dbinfo[i].subconninfo = conninfo;
i++;
@@ -689,8 +723,6 @@ drop_replication_slot(PGconn *conn, LogicalRepInfo *dbinfo, const char *slot_nam
PQExpBuffer str = createPQExpBuffer();
PGresult *res;
- Assert(conn != NULL);
-
pg_log_info("dropping the replication slot \"%s\" on database \"%s\"", slot_name, dbinfo->dbname);
appendPQExpBuffer(str, "DROP_REPLICATION_SLOT \"%s\"", slot_name);
@@ -872,6 +904,9 @@ create_publication(PGconn *conn, LogicalRepInfo *dbinfo)
appendPQExpBuffer(str, "CREATE PUBLICATION %s FOR ALL TABLES", dbinfo->pubname);
+ if (pubopts)
+ appendPQExpBuffer(str, " WITH (%s)", pubopts);
+
pg_log_debug("command is: %s", str->data);
if (!dry_run)
@@ -948,9 +983,14 @@ create_subscription(PGconn *conn, LogicalRepInfo *dbinfo)
appendPQExpBuffer(str,
"CREATE SUBSCRIPTION %s CONNECTION '%s' PUBLICATION %s "
- "WITH (create_slot = false, copy_data = false, enabled = false)",
+ "WITH (create_slot = false, copy_data = false, enabled = false",
dbinfo->subname, dbinfo->pubconninfo, dbinfo->pubname);
+ if (subopts)
+ appendPQExpBuffer(str, ", %s)", subopts);
+ else
+ appendPQExpBufferStr(str, ")");
+
pg_log_debug("command is: %s", str->data);
if (!dry_run)
@@ -1142,6 +1182,9 @@ main(int argc, char **argv)
{"database", required_argument, NULL, 'd'},
{"dry-run", no_argument, NULL, 'n'},
{"verbose", no_argument, NULL, 'v'},
+ {"port", required_argument, NULL, 'p'},
+ {"pubopts", required_argument, NULL, 'o'},
+ {"subopts", required_argument, NULL, 'O'},
{NULL, 0, NULL, 0}
};
@@ -1168,11 +1211,17 @@ main(int argc, char **argv)
int i;
+ char timebuf[128];
+ struct timeval time;
+ time_t tt;
+
pg_logging_init(argv[0]);
pg_logging_set_level(PG_LOG_WARNING);
progname = get_progname(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_subscriber"));
+ subport = getenv("PGSUBPORT") ? atoi(getenv("PGSUBPORT")) : DEF_PGSPORT;
+
if (argc > 1)
{
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
@@ -1204,7 +1253,7 @@ main(int argc, char **argv)
}
#endif
- while ((c = getopt_long(argc, argv, "D:P:S:d:nv",
+ while ((c = getopt_long(argc, argv, "D:P:S:d:nvp:o:O:",
long_options, &option_index)) != -1)
{
switch (c)
@@ -1228,6 +1277,36 @@ main(int argc, char **argv)
case 'v':
pg_logging_increase_verbosity();
break;
+ case 'p':
+ if ((subport = atoi(optarg)) < 0)
+ pg_fatal("invalid port number");
+ break;
+ case 'o':
+ /* append option? */
+ if (!pubopts)
+ pubopts = pg_strdup(optarg);
+ else
+ {
+ char *old_pubopts = pubopts;
+
+ pubopts = psprintf("%s %s", old_pubopts, optarg);
+ free(old_pubopts);
+ }
+ break;
+
+ case 'O':
+ /* append option? */
+ if (!subopts)
+ subopts = pg_strdup(optarg);
+ else
+ {
+ char *old_subopts = subopts;
+
+ subopts = psprintf("%s %s", old_subopts, optarg);
+ free(old_subopts);
+ }
+ break;
+
default:
/* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
@@ -1418,9 +1497,16 @@ main(int argc, char **argv)
/*
* Start subscriber and wait until accepting connections.
*/
- pg_log_info("starting the subscriber");
+ gettimeofday(&time, NULL);
+ tt = (time_t) time.tv_sec;
+ strftime(timebuf, sizeof(timebuf), "%Y%m%dT%H%M%S", localtime(&tt));
+ /* append milliseconds */
+ snprintf(timebuf + strlen(timebuf), sizeof(timebuf) - strlen(timebuf),
+ ".%03d", (int) (time.tv_usec / 1000));
- pg_ctl_cmd = psprintf("\"%s\" start -D \"%s\" -s", pg_ctl_path, subscriber_dir);
+ pg_log_info("starting the subscriber");
+ pg_ctl_cmd = psprintf("\"%s\" start -D \"%s\" -s -o \"-p %d\" -l \"%sstandby_%s.log\"",
+ pg_ctl_path, subscriber_dir, subport, subscriber_dir, timebuf);
rc = system(pg_ctl_cmd);
pg_ctl_status(pg_ctl_cmd, rc, 1);
--
2.43.0