From a62ecb48a6abd1a005aa27107741d0409588b3cb Mon Sep 17 00:00:00 2001 From: Shlok Kyal Date: Tue, 6 Feb 2024 14:45:03 +0530 Subject: [PATCH v24 04/18] Remove -S option to force unix domain connection With this patch removed -S option and added option for username(-U), port(-p) and socket directory(-s) for standby. This helps to force standby to use unix domain connection. --- doc/src/sgml/ref/pg_createsubscriber.sgml | 36 ++++++-- src/bin/pg_basebackup/pg_createsubscriber.c | 91 ++++++++++++++----- .../t/041_pg_createsubscriber_standby.pl | 33 ++++--- 3 files changed, 115 insertions(+), 45 deletions(-) diff --git a/doc/src/sgml/ref/pg_createsubscriber.sgml b/doc/src/sgml/ref/pg_createsubscriber.sgml index 9d0c6c764c..579e50a0a0 100644 --- a/doc/src/sgml/ref/pg_createsubscriber.sgml +++ b/doc/src/sgml/ref/pg_createsubscriber.sgml @@ -34,11 +34,6 @@ PostgreSQL documentation connstr - - - - - connstr @@ -179,11 +174,36 @@ PostgreSQL documentation - - + + + + + A port number on which the target server is listening for connections. + Defaults to the PGPORT environment variable, if set, or + a compiled-in default. + + + + + + + + + + Target's user name. Defaults to the PGUSER environment + variable. + + + + + + dir + dir - The connection string to the subscriber. For details see . + A directory which locales a temporary Unix socket files. If not + specified, pg_createsubscriber tries to + connect via TCP/IP to localhost. diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c index b15769c75b..1ad7de9190 100644 --- a/src/bin/pg_basebackup/pg_createsubscriber.c +++ b/src/bin/pg_basebackup/pg_createsubscriber.c @@ -35,7 +35,9 @@ typedef struct CreateSubscriberOptions { char *subscriber_dir; /* standby/subscriber data directory */ char *pub_conninfo_str; /* publisher connection string */ - char *sub_conninfo_str; /* subscriber connection string */ + unsigned short subport; /* port number listen()'d by the standby */ + char *subuser; /* database user of the standby */ + char *socketdir; /* socket directory */ SimpleStringList database_names; /* list of database names */ bool retain; /* retain log file? */ int recovery_timeout; /* stop recovery after this time */ @@ -57,7 +59,9 @@ typedef struct LogicalRepInfo static void cleanup_objects_atexit(void); static void usage(); -static char *get_base_conninfo(char *conninfo, char **dbname); +static char *get_pub_base_conninfo(char *conninfo, char **dbname); +static char *construct_sub_conninfo(char *username, unsigned short subport, + char *socketdir); static char *get_exec_path(const char *argv0, const char *progname); static bool check_data_directory(const char *datadir); static char *concat_conninfo_dbname(const char *conninfo, const char *dbname); @@ -180,7 +184,10 @@ usage(void) printf(_("\nOptions:\n")); printf(_(" -D, --pgdata=DATADIR location for the subscriber data directory\n")); printf(_(" -P, --publisher-server=CONNSTR publisher connection string\n")); - printf(_(" -S, --subscriber-server=CONNSTR subscriber connection string\n")); + printf(_(" -p, --port=PORT subscriber port number\n")); + printf(_(" -U, --username=NAME subscriber user\n")); + printf(_(" -s, --socketdir=DIR socket directory to use\n")); + printf(_(" If not specified, localhost would be used\n")); printf(_(" -d, --database=DBNAME database to create a subscription\n")); printf(_(" -n, --dry-run dry run, just show what would be done\n")); printf(_(" -t, --recovery-timeout=SECS seconds to wait for recovery to end\n")); @@ -193,8 +200,8 @@ usage(void) } /* - * Validate a connection string. Returns a base connection string that is a - * connection string without a database name. + * Validate a connection string for the publisher. Returns a base connection + * string that is a connection string without a database name. * * Since we might process multiple databases, each database name will be * appended to this base connection string to provide a final connection @@ -206,7 +213,7 @@ usage(void) * dbname. */ static char * -get_base_conninfo(char *conninfo, char **dbname) +get_pub_base_conninfo(char *conninfo, char **dbname) { PQExpBuffer buf = createPQExpBuffer(); PQconninfoOption *conn_opts = NULL; @@ -1593,6 +1600,40 @@ enable_subscription(PGconn *conn, LogicalRepInfo *dbinfo) destroyPQExpBuffer(str); } +/* + * Construct a connection string toward a target server, from argument options. + * + * If inputs are the zero, default value would be used. + * - username: PGUSER environment value (it would not be parsed) + * - port: PGPORT environment value (it would not be parsed) + * - socketdir: localhost connection (unix-domain would not be used) + */ +static char * +construct_sub_conninfo(char *username, unsigned short subport, char *sockdir) +{ + PQExpBuffer buf = createPQExpBuffer(); + char *ret; + + if (username) + appendPQExpBuffer(buf, "user=%s ", username); + + if (subport != 0) + appendPQExpBuffer(buf, "port=%u ", subport); + + if (sockdir) + appendPQExpBuffer(buf, "host=%s ", sockdir); + else + appendPQExpBuffer(buf, "host=localhost "); + + appendPQExpBuffer(buf, "fallback_application_name=%s", progname); + + ret = pg_strdup(buf->data); + + destroyPQExpBuffer(buf); + + return ret; +} + int main(int argc, char **argv) { @@ -1602,7 +1643,9 @@ main(int argc, char **argv) {"version", no_argument, NULL, 'V'}, {"pgdata", required_argument, NULL, 'D'}, {"publisher-server", required_argument, NULL, 'P'}, - {"subscriber-server", required_argument, NULL, 'S'}, + {"port", required_argument, NULL, 'p'}, + {"username", required_argument, NULL, 'U'}, + {"socketdir", required_argument, NULL, 's'}, {"database", required_argument, NULL, 'd'}, {"dry-run", no_argument, NULL, 'n'}, {"recovery-timeout", required_argument, NULL, 't'}, @@ -1659,7 +1702,9 @@ main(int argc, char **argv) /* Default settings */ opt.subscriber_dir = NULL; opt.pub_conninfo_str = NULL; - opt.sub_conninfo_str = NULL; + opt.subport = 0; + opt.subuser = NULL; + opt.socketdir = NULL; opt.database_names = (SimpleStringList) { NULL, NULL @@ -1683,7 +1728,7 @@ main(int argc, char **argv) get_restricted_token(); - while ((c = getopt_long(argc, argv, "D:P:S:d:nrt:v", + while ((c = getopt_long(argc, argv, "D:P:p:U:s:S:d:nrt:v", long_options, &option_index)) != -1) { switch (c) @@ -1695,8 +1740,17 @@ main(int argc, char **argv) case 'P': opt.pub_conninfo_str = pg_strdup(optarg); break; - case 'S': - opt.sub_conninfo_str = pg_strdup(optarg); + case 'p': + if ((opt.subport = atoi(optarg)) <= 0) + pg_fatal("invalid old port number"); + break; + case 'U': + pfree(opt.subuser); + opt.subuser = pg_strdup(optarg); + break; + case 's': + pfree(opt.socketdir); + opt.socketdir = pg_strdup(optarg); break; case 'd': /* Ignore duplicated database names */ @@ -1763,21 +1817,12 @@ main(int argc, char **argv) exit(1); } pg_log_info("validating connection string on publisher"); - pub_base_conninfo = get_base_conninfo(opt.pub_conninfo_str, - &dbname_conninfo); + pub_base_conninfo = get_pub_base_conninfo(opt.pub_conninfo_str, + &dbname_conninfo); if (pub_base_conninfo == NULL) exit(1); - if (opt.sub_conninfo_str == NULL) - { - pg_log_error("no subscriber connection string specified"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit(1); - } - pg_log_info("validating connection string on subscriber"); - sub_base_conninfo = get_base_conninfo(opt.sub_conninfo_str, NULL); - if (sub_base_conninfo == NULL) - exit(1); + sub_base_conninfo = construct_sub_conninfo(opt.subuser, opt.subport, opt.socketdir); if (opt.database_names.head == NULL) { diff --git a/src/bin/pg_basebackup/t/041_pg_createsubscriber_standby.pl b/src/bin/pg_basebackup/t/041_pg_createsubscriber_standby.pl index e2807d3fac..93148417db 100644 --- a/src/bin/pg_basebackup/t/041_pg_createsubscriber_standby.pl +++ b/src/bin/pg_basebackup/t/041_pg_createsubscriber_standby.pl @@ -66,7 +66,8 @@ command_fails( 'pg_createsubscriber', '--verbose', '--pgdata', $node_f->data_dir, '--publisher-server', $node_p->connstr('pg1'), - '--subscriber-server', $node_f->connstr('pg1'), + '--port', $node_f->port, + '--host', $node_f->host, '--database', 'pg1', '--database', 'pg2' ], @@ -78,8 +79,9 @@ command_fails( 'pg_createsubscriber', '--verbose', '--dry-run', '--pgdata', $node_s->data_dir, '--publisher-server', - $node_p->connstr('pg1'), '--subscriber-server', - $node_s->connstr('pg1'), '--database', + $node_p->connstr('pg1'), '--port', + $node_s->port, '--host', + $node_s->host, '--database', 'pg1', '--database', 'pg2' ], @@ -104,10 +106,11 @@ command_fails( 'pg_createsubscriber', '--verbose', '--dry-run', '--pgdata', $node_c->data_dir, '--publisher-server', - $node_s->connstr('pg1'), '--subscriber-server', - $node_c->connstr('pg1'), '--database', - 'pg1', '--database', - 'pg2' + $node_s->connstr('pg1'), + '--port', $node_c->port, + '--socketdir', $node_c->host, + '--database', 'pg1', + '--database', 'pg2' ], 'primary server is in recovery'); @@ -124,8 +127,9 @@ command_ok( 'pg_createsubscriber', '--verbose', '--dry-run', '--pgdata', $node_s->data_dir, '--publisher-server', - $node_p->connstr('pg1'), '--subscriber-server', - $node_s->connstr('pg1'), '--database', + $node_p->connstr('pg1'), '--port', + $node_s->port, '--socketdir', + $node_s->host, '--database', 'pg1', '--database', 'pg2' ], @@ -141,8 +145,9 @@ command_ok( 'pg_createsubscriber', '--verbose', '--dry-run', '--pgdata', $node_s->data_dir, '--publisher-server', - $node_p->connstr('pg1'), '--subscriber-server', - $node_s->connstr('pg1') + $node_p->connstr('pg1'), '--port', + $node_s->port, '--socketdir', + $node_s->host, ], 'run pg_createsubscriber without --databases'); @@ -152,9 +157,9 @@ command_ok( 'pg_createsubscriber', '--verbose', '--verbose', '--pgdata', $node_s->data_dir, '--publisher-server', - $node_p->connstr('pg1'), '--subscriber-server', - $node_s->connstr('pg1'), '--database', - 'pg1', '--database', + $node_p->connstr('pg1'), '--port', $node_s->port, + '--socketdir', $node_s->host, + '--database', 'pg1', '--database', 'pg2' ], 'run pg_createsubscriber on node S'); -- 2.43.0