[PATCH] pg_isready (was: [WIP] pg_ping utility)

Started by Phil Sorberalmost 13 years ago52 messages
#1Phil Sorber
phil@omniti.com
2 attachment(s)

Changing up the subject line because this is no longer a work in
progress nor is it pg_ping anymore.

On Sun, Jan 20, 2013 at 10:36 PM, Craig Ringer <craig@2ndquadrant.com> wrote:

On 01/21/2013 11:26 AM, Robert Haas wrote:

On Sun, Jan 20, 2013 at 2:59 PM, Phil Sorber <phil@omniti.com> wrote:

Ok. I can add something to the notes section of the docs. I can also
add some code comments for this and for grabbing the default params.

Sounds good.

I added the code comments, but realized it was already in the docs. I
will provide a separate patch for the PQping docs.

I also added the handling of extra params as Robert suggested.

Oh, I see. Is it really important to have the host and port in the
output, or should we trim that down to just e.g. "accepting
connections"? It seems useful to have that if a human is looking at
the output, but maybe not if a machine is looking at the output. And
if somebody doesn't want it, getting rid of it with sed or awk is
nontrivial - imagine:

pg_isready -d "/tmp:5432 - accepting connections"

If you are scripting I'd assume you would use the return code value.
It might be reasonable to make adding the host and port the verbose
method and have just "accepting connections" as the default output,
but my concern there is a misdiagnosis because someone doesn't realize
what server they are connecting to. This way they can't miss it and
they don't have to add another command line option to get that output.

It's a fair concern. Does anyone else have an opinion on this?

I have a strong view that the host and port *should* be printed in output.

One of the most common issues on Stack Overflow questions from new users
is with "I can't connect" problems that turn out to be them connecting
to the wrong host, port, or socket path.

It is absolutely vital that the unix socket path being used be printed
if unix socket connections are tested, as Mac OS X's insane setup means
that PostgreSQL tool builds on that platform regularly use the system
libpq not the user-installed PostgreSQL's libpq, and it defaults to a
different socket path. If users use pg_ping to verify that their
PostgreSQL instance is running it'll use the user-installed libpq -
fine, that's what we want. But the user will then wonder why the heck
Ruby on Rails's `pg' gem reports it can't connect to the unix socket.
They can't compare the unix socket paths printed in the error message if
pg_ping doesn't show it.

I would like to see pg_ping produce a similar error to psql on
connection failure.

As stated above this is no longer called pg_ping. Probably should have
switched the subject line a while ago.

I've left it outputting the host and port as default.

Also, we went over a lot of iterations on how the errors should look.
I am hesitant to change that now. I think the current errors are good
because not being able to connect isn't necessarily an unexpected
outcome like it is for psql.

Show quoted text

$ psql -p 9999
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.9999"?

$ psql -h localhost -p 9999
psql: could not connect to server: Connection refused
Is the server running on host "localhost" (::1) and accepting
TCP/IP connections on port 9999?
could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 9999?

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

pg_isready_bin_v11.diffapplication/octet-stream; name=pg_isready_bin_v11.diffDownload
diff --git a/src/bin/scripts/.gitignore b/src/bin/scripts/.gitignore
new file mode 100644
index e62f4b0..0b9b786
*** a/src/bin/scripts/.gitignore
--- b/src/bin/scripts/.gitignore
***************
*** 7,12 ****
--- 7,13 ----
  /dropuser
  /reindexdb
  /vacuumdb
+ /pg_isready
  
  /dumputils.c
  /keywords.c
diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile
new file mode 100644
index ea48411..26f6f8b
*** a/src/bin/scripts/Makefile
--- b/src/bin/scripts/Makefile
*************** subdir = src/bin/scripts
*** 16,22 ****
  top_builddir = ../../..
  include $(top_builddir)/src/Makefile.global
  
! PROGRAMS = createdb createlang createuser dropdb droplang dropuser clusterdb vacuumdb reindexdb
  
  override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS)
  
--- 16,22 ----
  top_builddir = ../../..
  include $(top_builddir)/src/Makefile.global
  
! PROGRAMS = createdb createlang createuser dropdb droplang dropuser clusterdb vacuumdb reindexdb pg_isready
  
  override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS)
  
*************** dropuser: dropuser.o common.o dumputils.
*** 34,39 ****
--- 34,40 ----
  clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  vacuumdb: vacuumdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
  reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+ pg_isready: pg_isready.o common.o | submake-libpq submake-libpgport
  
  dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
  	rm -f $@ && $(LN_S) $< .
*************** install: all installdirs
*** 54,59 ****
--- 55,61 ----
  	$(INSTALL_PROGRAM) clusterdb$(X)  '$(DESTDIR)$(bindir)'/clusterdb$(X)
  	$(INSTALL_PROGRAM) vacuumdb$(X)   '$(DESTDIR)$(bindir)'/vacuumdb$(X)
  	$(INSTALL_PROGRAM) reindexdb$(X)  '$(DESTDIR)$(bindir)'/reindexdb$(X)
+ 	$(INSTALL_PROGRAM) pg_isready$(X) '$(DESTDIR)$(bindir)'/pg_isready$(X)
  
  installdirs:
  	$(MKDIR_P) '$(DESTDIR)$(bindir)'
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index ...feee1a7
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 0 ****
--- 1,202 ----
+ /*-------------------------------------------------------------------------
+  *
+  * pg_isready --- checks the status of the PostgreSQL server
+  *
+  * Copyright (c) 2013, PostgreSQL Global Development Group
+  *
+  * src/bin/scripts/pg_isready.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "postgres_fe.h"
+ #include "common.h"
+ 
+ static void
+ help(const char *progname);
+ 
+ int
+ main(int argc, char **argv)
+ {
+ 	int c,optindex,opt_index = 0;
+ 
+ 	const char *progname;
+ 
+ 	const char *pghost = NULL;
+ 	const char *pgport = NULL;
+ 	const char *pguser = NULL;
+ 	const char *pgdbname = NULL;
+ 
+ 	const char *keywords[4], *values[4];
+ 
+ 	bool quiet = false;
+ 
+ 	PGPing rv;
+ 	PQconninfoOption *connect_options, *conn_opt_ptr;
+ 
+ 	/*
+ 	 * We accept user and database as options to avoid
+ 	 * useless errors from connecting with invalid params
+ 	 */
+ 
+ 	static struct option long_options[] = {
+ 			{"dbname", required_argument, NULL, 'd'},
+ 			{"host", required_argument, NULL, 'h'},
+ 			{"port", required_argument, NULL, 'p'},
+ 			{"quiet", no_argument, NULL, 'q'},
+ 			{"username", required_argument, NULL, 'U'},
+ 			{NULL, 0, NULL, 0}
+ 		};
+ 
+ 	progname = get_progname(argv[0]);
+ 	handle_help_version_opts(argc, argv, progname, help);
+ 
+ 	while ((c = getopt_long(argc, argv, "d:h:p:qU:V", long_options, &optindex)) != -1)
+ 	{
+ 		switch (c)
+ 		{
+ 			case 'd':
+ 				pgdbname = pg_strdup(optarg);
+ 				break;
+ 			case 'h':
+ 				pghost = pg_strdup(optarg);
+ 				break;
+ 			case 'p':
+ 				pgport = pg_strdup(optarg);
+ 				break;
+ 			case 'q':
+ 				quiet = true;
+ 				break;
+ 			case 'U':
+ 				pguser = pg_strdup(optarg);
+ 				break;
+ 			default:
+ 				/*
+ 				 * We need to make sure we don't return 1 here because someone
+ 				 * checking the return code might infer unintended meaning
+ 				 */
+ 				exit(PQPING_NO_ATTEMPT);
+ 		}
+ 	}
+ 
+ 	if (optind < argc)
+ 	{
+ 		fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
+ 				progname, argv[optind]);
+ 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ 		/*
+ 		 * We need to make sure we don't return 1 here because someone
+ 		 * checking the return code might infer unintended meaning
+ 		 */
+ 		exit(PQPING_NO_ATTEMPT);
+ 	}
+ 
+ 	/*
+ 	 * Get the default options so we can display them in our output
+ 	 */
+ 
+ 	connect_options = PQconndefaults();
+ 	conn_opt_ptr = connect_options;
+ 
+ 	while (conn_opt_ptr->keyword)
+ 	{
+ 		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
+ 		{
+ 			if (pghost)
+ 			{
+ 				keywords[opt_index] = conn_opt_ptr->keyword;
+ 				values[opt_index] = pghost;
+ 				opt_index++;
+ 			}
+ 			else if (conn_opt_ptr->val)
+ 				pghost = conn_opt_ptr->val;
+ 			else
+ 				pghost = DEFAULT_PGSOCKET_DIR;
+ 		}
+ 		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
+ 		{
+ 			if (pgport)
+ 			{
+ 				keywords[opt_index] = conn_opt_ptr->keyword;
+ 				values[opt_index] = pgport;
+ 				opt_index++;
+ 			}
+ 			else if (conn_opt_ptr->val)
+ 				pgport = conn_opt_ptr->val;
+ 		}
+ 		else if (strncmp(conn_opt_ptr->keyword, "user", 5) == 0)
+ 		{
+ 			if (pguser)
+ 			{
+ 				keywords[opt_index] = conn_opt_ptr->keyword;
+ 				values[opt_index] = pguser;
+ 				opt_index++;
+ 			}
+ 			else if (conn_opt_ptr->val)
+ 				pguser = conn_opt_ptr->val;
+ 		}
+ 		else if (strncmp(conn_opt_ptr->keyword, "dbname", 7) == 0)
+ 		{
+ 			if (pgdbname)
+ 			{
+ 				keywords[opt_index] = conn_opt_ptr->keyword;
+ 				values[opt_index] = pgdbname;
+ 				opt_index++;
+ 			}
+ 			else if (conn_opt_ptr->val)
+ 				pgdbname = conn_opt_ptr->val;
+ 		}
+ 		conn_opt_ptr++;
+ 	}
+ 
+ 	keywords[opt_index] = NULL;
+ 	values[opt_index] = NULL;
+ 
+ 	rv = PQpingParams(keywords, values, 1);
+ 
+ 	if (!quiet)
+ 	{
+ 		printf("%s:%s - ", pghost, pgport);
+ 
+ 		switch (rv)
+ 		{
+ 			case PQPING_OK:
+ 				printf("accepting connections\n");
+ 				break;
+ 			case PQPING_REJECT:
+ 				printf("rejecting connections\n");
+ 				break;
+ 			case PQPING_NO_RESPONSE:
+ 				printf("no response\n");
+ 				break;
+ 			case PQPING_NO_ATTEMPT:
+ 				printf("no attempt\n");
+ 				break;
+ 			default:
+ 				printf("unknown\n");
+ 		}
+ 	}
+ 
+ 	PQconninfoFree(connect_options);
+ 
+ 	exit(rv);
+ }
+ 
+ static void
+ help(const char *progname)
+ {
+ 	printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
+ 	printf(_("Usage:\n"));
+ 	printf(_("  %s [OPTION]...\n"), progname);
+ 
+ 	printf(_("\nOptions:\n"));
+ 	printf(_("  -d, --dbname=DBNAME      database name\n"));
+ 	printf(_("  -q, --quiet              run quietly\n"));
+ 	printf(_("  -V, --version            output version information, then exit\n"));
+ 	printf(_("  -?, --help               show this help, then exit\n"));
+ 
+ 	printf(_("\nConnection options:\n"));
+ 	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
+ 	printf(_("  -p, --port=PORT          database server port\n"));
+ 	printf(_("  -U, --username=USERNAME  database username\n"));
+ }
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
new file mode 100644
index 895afbc..e0f4bc7
*** a/src/interfaces/libpq/libpq-fe.h
--- b/src/interfaces/libpq/libpq-fe.h
*************** typedef enum
*** 110,115 ****
--- 110,120 ----
  	PQERRORS_VERBOSE			/* all the facts, ma'am */
  } PGVerbosity;
  
+ /*
+  * PGPing - The ordering of this enum should not be altered because the
+  * values are exposed externally via pg_isready.
+  */
+ 
  typedef enum
  {
  	PQPING_OK,					/* server is accepting connections */
pg_isready_docs_v11.diffapplication/octet-stream; name=pg_isready_docs_v11.diffDownload
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
new file mode 100644
index df84054..b3fc57d
*** a/doc/src/sgml/ref/allfiles.sgml
--- b/doc/src/sgml/ref/allfiles.sgml
*************** Complete list of usable sgml source file
*** 175,180 ****
--- 175,181 ----
  <!ENTITY pgCtl              SYSTEM "pg_ctl-ref.sgml">
  <!ENTITY pgDump             SYSTEM "pg_dump.sgml">
  <!ENTITY pgDumpall          SYSTEM "pg_dumpall.sgml">
+ <!ENTITY pgIsready          SYSTEM "pg_isready.sgml">
  <!ENTITY pgReceivexlog      SYSTEM "pg_receivexlog.sgml">
  <!ENTITY pgResetxlog        SYSTEM "pg_resetxlog.sgml">
  <!ENTITY pgRestore          SYSTEM "pg_restore.sgml">
diff --git a/doc/src/sgml/ref/pg_isready.sgml b/doc/src/sgml/ref/pg_isready.sgml
new file mode 100644
index ...ea0d3a7
*** a/doc/src/sgml/ref/pg_isready.sgml
--- b/doc/src/sgml/ref/pg_isready.sgml
***************
*** 0 ****
--- 1,200 ----
+ <!--
+ doc/src/sgml/ref/pg_isready.sgml
+ PostgreSQL documentation
+ -->
+ 
+ <refentry id="app-pg-isready">
+  <refmeta>
+   <refentrytitle><application>pg_isready</application></refentrytitle>
+   <manvolnum>1</manvolnum>
+   <refmiscinfo>Application</refmiscinfo>
+  </refmeta>
+ 
+  <refnamediv>
+   <refname>pg_isready</refname>
+   <refpurpose>checks the connection status of a <productname>PostgreSQL</productname> server</refpurpose>
+  </refnamediv>
+ 
+  <indexterm zone="app-pg-isready">
+   <primary>pg_isready</primary>
+  </indexterm>
+ 
+  <refsynopsisdiv>
+   <cmdsynopsis>
+    <command>pg_isready</command>
+    <arg rep="repeat"><replaceable>connection-option</replaceable></arg>
+    <arg rep="repeat"><replaceable>option</replaceable></arg>
+   </cmdsynopsis>
+  </refsynopsisdiv>
+ 
+ 
+  <refsect1 id="app-pg-isready-description">
+   <title>Description</title>
+   <para>
+    <application>pg_isready</application> is a utility for checking the connection
+    status of a <productname>PostgreSQL</productname> database server. The exit
+    status specifies the result of the connection check.
+   </para>
+  </refsect1>
+ 
+  <refsect1 id="app-pg-isready-options">
+   <title>Options</title>
+ 
+     <variablelist>
+ 
+     <varlistentry>
+       <term><option>-d <replaceable class="parameter">dbname</replaceable></></term>
+       <term><option>--dbname=<replaceable class="parameter">dbname</replaceable></></term>
+       <listitem>
+       <para>
+        Specifies the name of the database to connect to.
+       </para>
+       <para>
+        If this parameter contains an <symbol>=</symbol> sign or starts
+        with a valid <acronym>URI</acronym> prefix
+        (<literal>postgresql://</literal>
+        or <literal>postgres://</literal>), it is treated as a
+        <parameter>conninfo</parameter> string. See <xref linkend="libpq-connect"> for more information.
+       </para>
+       </listitem>
+     </varlistentry>
+ 
+      <varlistentry>
+        <term><option>-h <replaceable class="parameter">hostname</replaceable></></term>
+        <term><option>--host=<replaceable class="parameter">hostname</replaceable></></term>
+        <listitem>
+        <para>
+        Specifies the host name of the machine on which the
+        server is running. If the value begins
+        with a slash, it is used as the directory for the Unix-domain
+        socket.
+        </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+        <term><option>-p <replaceable class="parameter">port</replaceable></></term>
+        <term><option>--port=<replaceable class="parameter">port</replaceable></></term>
+        <listitem>
+        <para>
+        Specifies the TCP port or the local Unix-domain
+        socket file extension on which the server is listening for
+        connections. Defaults to the value of the <envar>PGPORT</envar>
+        environment variable or, if not set, to the port specified at
+        compile time, usually 5432.
+        </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-q</option></term>
+       <term><option>--quiet</option></term>
+       <listitem>
+        <para>
+         Do not display status message. This is useful when scripting.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+        <term><option>-U <replaceable class="parameter">username</replaceable></></term>
+        <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
+        <listitem>
+        <para>
+        Connect to the database as the user <replaceable
+        class="parameter">username</replaceable> instead of the default.
+        </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-V</></term>
+       <term><option>--version</></term>
+        <listitem>
+         <para>
+          Print the <application>pg_isready</application> version and exit.
+         </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
+       <term><option>-?</></term>
+       <term><option>--help</></term>
+       <listitem>
+        <para>
+         Show help about <application>pg_isready</application> command line
+         arguments, and exit.
+        </para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+ 
+  <refsect1>
+   <title>Exit Status</title>
+ 
+   <para>
+    <application>pg_isready</application> returns <literal>0</literal> to the shell if the server
+    is accepting connections normally, <literal>1</literal> if the server is rejecting
+    connections (for example during startup), <literal>2</literal> if there was no response to the
+    connection attempt, and <literal>3</literal> if no attempt was made (for example due to invalid
+    parameters).
+   </para>
+  </refsect1>
+ 
+  <refsect1>
+   <title>Environment</title>
+ 
+   <para>
+    <command>pg_isready</command>, like most other <productname>PostgreSQL</>
+    utilities,
+    also uses the environment variables supported by <application>libpq</>
+    (see <xref linkend="libpq-envars">).
+   </para>
+  </refsect1>
+ 
+  <refsect1 id="app-pg-isready-notes">
+   <title>Notes</title>
+ 
+   <para>
+    The options <option>--dbname</> and <option>--username</> can be used to avoid gratuitous
+    error messages in the logs, but are not necessary for proper functionality.
+   </para>
+  </refsect1>
+ 
+  <refsect1 id="app-pg-isready-examples">
+   <title>Examples</title>
+ 
+   <para>
+    Standard Usage:
+    <screen>
+     <prompt>$</prompt> <userinput>pg_isready</userinput>
+     <computeroutput>/tmp:5432 - accepting connections</computeroutput>
+     <prompt>$</prompt> <userinput>echo $?</userinput>
+     <computeroutput>0</computeroutput>
+    </screen>
+   </para>
+ 
+   <para>
+    Running with connection parameters to a <productname>PostgreSQL</productname> cluster in startup:
+    <screen>
+     <prompt>$ </prompt><userinput>pg_isready -h localhost -p 5433</userinput>
+     <computeroutput>localhost:5433 - rejecting connections</computeroutput>
+     <prompt>$</prompt> <userinput>echo $?</userinput>
+     <computeroutput>1</computeroutput>
+    </screen>
+   </para>
+ 
+   <para>
+    Running with connection parameters to a non-responsive <productname>PostgreSQL</productname> cluster:
+    <screen>
+     <prompt>$ </prompt><userinput>pg_isready -h someremotehost</userinput>
+     <computeroutput>someremotehost:5432 - no response</computeroutput>
+     <prompt>$</prompt> <userinput>echo $?</userinput>
+     <computeroutput>2</computeroutput>
+    </screen>
+   </para>
+ 
+  </refsect1>
+ 
+ </refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
new file mode 100644
index 0872168..fe90227
*** a/doc/src/sgml/reference.sgml
--- b/doc/src/sgml/reference.sgml
***************
*** 223,228 ****
--- 223,229 ----
     &pgConfig;
     &pgDump;
     &pgDumpall;
+    &pgIsready;
     &pgReceivexlog;
     &pgRestore;
     &psqlRef;
#2Robert Haas
robertmhaas@gmail.com
In reply to: Phil Sorber (#1)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Mon, Jan 21, 2013 at 12:23 PM, Phil Sorber <phil@omniti.com> wrote:

Changing up the subject line because this is no longer a work in
progress nor is it pg_ping anymore.

OK, I committed this. However, I have one suggestion. Maybe it would
be a good idea to add a -c or -t option that sets the connect_timeout
parameter. Because:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Phil Sorber
phil@omniti.com
In reply to: Robert Haas (#2)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Jan 21, 2013 at 12:23 PM, Phil Sorber <phil@omniti.com> wrote:

Changing up the subject line because this is no longer a work in
progress nor is it pg_ping anymore.

OK, I committed this. However, I have one suggestion. Maybe it would
be a good idea to add a -c or -t option that sets the connect_timeout
parameter. Because:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Oh, hrmm. Yes, I will address that with a follow up patch. I guess in
my testing I was using a host that responded properly with port
unreachable or TCP RST or something.

Do you think we should have a default timeout, or only have one if
specified at the command line?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Phil Sorber (#3)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Do you think we should have a default timeout, or only have one if
specified at the command line?

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#4)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Do you think we should have a default timeout, or only have one if
specified at the command line?

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

from pg_ctl.c:

#define DEFAULT_WAIT 60

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Phil Sorber
phil@omniti.com
In reply to: Bruce Momjian (#5)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Do you think we should have a default timeout, or only have one if
specified at the command line?

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

from pg_ctl.c:

#define DEFAULT_WAIT 60

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Bruce Momjian
bruce@momjian.us
In reply to: Phil Sorber (#6)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 02:50:01PM -0500, Phil Sorber wrote:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Do you think we should have a default timeout, or only have one if
specified at the command line?

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

from pg_ctl.c:

#define DEFAULT_WAIT 60

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

Yeah, being able to point to precedent is always helpful.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#8Phil Sorber
phil@omniti.com
In reply to: Bruce Momjian (#7)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 2:51 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 02:50:01PM -0500, Phil Sorber wrote:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 11:07 AM, Robert Haas <robertmhaas@gmail.com> wrote:

[rhaas pgsql]$ pg_isready -h www.google.com
<grows old, dies>

Do you think we should have a default timeout, or only have one if
specified at the command line?

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

from pg_ctl.c:

#define DEFAULT_WAIT 60

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

Yeah, being able to point to precedent is always helpful.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

Attached is the patch to add a connect_timeout.

I also factored out the setting of user and dbname from the default
gathering loop as we only need host and port defaults and made more
sense to handle user/dbname in the same area of the code as
connect_timeout. This was something mentioned by Robert upthread.

This also coincidentally fixes a bug in the size of the keywords and
values arrays. Must have added an option during review and not
extended that array. Is there a best practice to making sure that
doesn't happen in the future? I was thinking define MAX_PARAMS and
then setting the array size to MAX_PARAMS+1 and then checking in the
getopt loop to see how many params we expect to process and erroring
if we are doing to many, but that only works at runtime.

One other thing I noticed while refactoring the defaults gathering
code. If someone passes in a connect string for dbname, we output the
wrong info at the end. This is not addressed in this patch because I
wanted to get some feedback before fixing and make a separate patch. I
see the only real option being to use PQconninfoParse to get the
params from the connect string. If someone passes in a connect string
via dbname should that have precedence over other values passed in via
individual command line options? Should ordering of the command line
options matter?

For example if someone did: pg_isready -h foo -d "host=bar port=4321" -p 1234

What should the connection parameters be?

Attachments:

pg_isready_timeout.diffapplication/octet-stream; name=pg_isready_timeout.diffDownload
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index feee1a7..0e44dd2
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 12,17 ****
--- 12,19 ----
  #include "postgres_fe.h"
  #include "common.h"
  
+ #define	DEFAULT_CONNECT_TIMEOUT "60"
+ 
  static void
  help(const char *progname);
  
*************** main(int argc, char **argv)
*** 26,33 ****
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
  
! 	const char *keywords[4], *values[4];
  
  	bool quiet = false;
  
--- 28,37 ----
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
+ 	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
  
! 	const char *keywords[6] = { NULL };
! 	const char *values[6] = { NULL };
  
  	bool quiet = false;
  
*************** main(int argc, char **argv)
*** 44,49 ****
--- 48,54 ----
  			{"host", required_argument, NULL, 'h'},
  			{"port", required_argument, NULL, 'p'},
  			{"quiet", no_argument, NULL, 'q'},
+ 			{"timeout", required_argument, NULL, 't'},
  			{"username", required_argument, NULL, 'U'},
  			{NULL, 0, NULL, 0}
  		};
*************** main(int argc, char **argv)
*** 51,57 ****
  	progname = get_progname(argv[0]);
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qU:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 56,62 ----
  	progname = get_progname(argv[0]);
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 67,72 ****
--- 72,80 ----
  			case 'q':
  				quiet = true;
  				break;
+ 			case 't':
+ 				connect_timeout = pg_strdup(optarg);
+ 				break;
  			case 'U':
  				pguser = pg_strdup(optarg);
  				break;
*************** main(int argc, char **argv)
*** 92,98 ****
  	}
  
  	/*
! 	 * Get the default options so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
--- 100,126 ----
  	}
  
  	/*
! 	 * Set connection options
! 	 */
! 
! 	keywords[opt_index] = "connect_timeout";
! 	values[opt_index] = connect_timeout;
! 	opt_index++;
! 	if (pguser)
! 	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
! 	}
! 	if (pgdbname)
! 	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
! 	}
! 
! 	/*
! 	 * Get the default host and port so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
*************** main(int argc, char **argv)
*** 124,157 ****
  			else if (conn_opt_ptr->val)
  				pgport = conn_opt_ptr->val;
  		}
- 		else if (strncmp(conn_opt_ptr->keyword, "user", 5) == 0)
- 		{
- 			if (pguser)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pguser;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pguser = conn_opt_ptr->val;
- 		}
- 		else if (strncmp(conn_opt_ptr->keyword, "dbname", 7) == 0)
- 		{
- 			if (pgdbname)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pgdbname;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pgdbname = conn_opt_ptr->val;
- 		}
  		conn_opt_ptr++;
  	}
  
- 	keywords[opt_index] = NULL;
- 	values[opt_index] = NULL;
- 
  	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
--- 152,160 ----
*************** help(const char *progname)
*** 198,202 ****
--- 201,206 ----
  	printf(_("\nConnection options:\n"));
  	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
  	printf(_("  -p, --port=PORT          database server port\n"));
+ 	printf(_("  -t, --timeout=SECS       seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
  	printf(_("  -U, --username=USERNAME  database username\n"));
  }
#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Phil Sorber (#6)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

I'm not sure that's a relevant precedent at all. What that number is
is the time that pg_ctl will wait around for the postmaster to start or
stop before reporting a problem --- and in either case, a significant
delay (multiple seconds) is not surprising, because of crash-recovery
work, shutdown checkpointing, etc. For pg_isready, you'd expect to get
a response more or less instantly, wouldn't you? Personally, I'd decide
that pg_isready is broken if it didn't give me an answer in a couple of
seconds, much less a minute.

What I had in mind was a default timeout of maybe 3 or 4 seconds...

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#10Phil Sorber
phil@omniti.com
In reply to: Tom Lane (#9)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 6:07 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

I'm not sure that's a relevant precedent at all. What that number is
is the time that pg_ctl will wait around for the postmaster to start or
stop before reporting a problem --- and in either case, a significant
delay (multiple seconds) is not surprising, because of crash-recovery
work, shutdown checkpointing, etc. For pg_isready, you'd expect to get
a response more or less instantly, wouldn't you? Personally, I'd decide
that pg_isready is broken if it didn't give me an answer in a couple of
seconds, much less a minute.

What I had in mind was a default timeout of maybe 3 or 4 seconds...

I was thinking that if it was in a script you wouldn't care if it was
60 seconds. If it was at the command line you would ^C it much
earlier. I think the default linux TCP connection timeout is around 20
seconds. My feeling is everyone is going to have a differing opinion
on this, which is why I was hoping that some good precedent existed.
I'm fine with 3 or 4, whatever can be agreed upon.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#11Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#10)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Thu, Jan 24, 2013 at 8:47 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Jan 23, 2013 at 6:07 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

I'm not sure that's a relevant precedent at all. What that number is
is the time that pg_ctl will wait around for the postmaster to start or
stop before reporting a problem --- and in either case, a significant
delay (multiple seconds) is not surprising, because of crash-recovery
work, shutdown checkpointing, etc. For pg_isready, you'd expect to get
a response more or less instantly, wouldn't you? Personally, I'd decide
that pg_isready is broken if it didn't give me an answer in a couple of
seconds, much less a minute.

What I had in mind was a default timeout of maybe 3 or 4 seconds...

I was thinking that if it was in a script you wouldn't care if it was
60 seconds. If it was at the command line you would ^C it much
earlier. I think the default linux TCP connection timeout is around 20
seconds. My feeling is everyone is going to have a differing opinion
on this, which is why I was hoping that some good precedent existed.
I'm fine with 3 or 4, whatever can be agreed upon.

+1 with 3 or 4 secounds.

Aside from this issue, I have one minor comment. ISTM you need to
add the following line to the end of the help message. This line has
been included in the help message of all the other client commands.

Report bugs to <pgsql-bugs@postgresql.org>.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#12Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#11)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Jan 23, 2013 at 8:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Jan 24, 2013 at 8:47 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Jan 23, 2013 at 6:07 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

I'm not sure that's a relevant precedent at all. What that number is
is the time that pg_ctl will wait around for the postmaster to start or
stop before reporting a problem --- and in either case, a significant
delay (multiple seconds) is not surprising, because of crash-recovery
work, shutdown checkpointing, etc. For pg_isready, you'd expect to get
a response more or less instantly, wouldn't you? Personally, I'd decide
that pg_isready is broken if it didn't give me an answer in a couple of
seconds, much less a minute.

What I had in mind was a default timeout of maybe 3 or 4 seconds...

I was thinking that if it was in a script you wouldn't care if it was
60 seconds. If it was at the command line you would ^C it much
earlier. I think the default linux TCP connection timeout is around 20
seconds. My feeling is everyone is going to have a differing opinion
on this, which is why I was hoping that some good precedent existed.
I'm fine with 3 or 4, whatever can be agreed upon.

+1 with 3 or 4 secounds.

Aside from this issue, I have one minor comment. ISTM you need to
add the following line to the end of the help message. This line has
been included in the help message of all the other client commands.

Report bugs to <pgsql-bugs@postgresql.org>.

Ok, I set the default timeout to 3 seconds, added the bugs email to
the help, and also added docs that I forgot last time.

Also, still hoping to get some feedback on my other issues.

Thanks.

Show quoted text

Regards,

--
Fujii Masao

Attachments:

pg_isready_timeout_v2.diffapplication/octet-stream; name=pg_isready_timeout_v2.diffDownload
diff --git a/doc/src/sgml/ref/pg_isready.sgml b/doc/src/sgml/ref/pg_isready.sgml
new file mode 100644
index ea0d3a7..ff80a78
*** a/doc/src/sgml/ref/pg_isready.sgml
--- b/doc/src/sgml/ref/pg_isready.sgml
*************** PostgreSQL documentation
*** 97,102 ****
--- 97,114 ----
       </varlistentry>
  
       <varlistentry>
+        <term><option>-t <replaceable class="parameter">seconds</replaceable></></term>
+        <term><option>--timeout=<replaceable class="parameter">seconds</replaceable></></term>
+        <listitem>
+        <para>
+         The maximum number of seconds to wait when attempting connection before
+         returning that the server is not responding. Setting to 0 disables. The
+         default is 3 seconds.
+        </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
         <term><option>-U <replaceable class="parameter">username</replaceable></></term>
         <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
         <listitem>
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index feee1a7..56d1ddd
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 12,17 ****
--- 12,19 ----
  #include "postgres_fe.h"
  #include "common.h"
  
+ #define	DEFAULT_CONNECT_TIMEOUT "3"
+ 
  static void
  help(const char *progname);
  
*************** main(int argc, char **argv)
*** 26,33 ****
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
  
! 	const char *keywords[4], *values[4];
  
  	bool quiet = false;
  
--- 28,37 ----
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
+ 	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
  
! 	const char *keywords[6] = { NULL };
! 	const char *values[6] = { NULL };
  
  	bool quiet = false;
  
*************** main(int argc, char **argv)
*** 44,49 ****
--- 48,54 ----
  			{"host", required_argument, NULL, 'h'},
  			{"port", required_argument, NULL, 'p'},
  			{"quiet", no_argument, NULL, 'q'},
+ 			{"timeout", required_argument, NULL, 't'},
  			{"username", required_argument, NULL, 'U'},
  			{NULL, 0, NULL, 0}
  		};
*************** main(int argc, char **argv)
*** 51,57 ****
  	progname = get_progname(argv[0]);
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qU:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 56,62 ----
  	progname = get_progname(argv[0]);
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 67,72 ****
--- 72,80 ----
  			case 'q':
  				quiet = true;
  				break;
+ 			case 't':
+ 				connect_timeout = pg_strdup(optarg);
+ 				break;
  			case 'U':
  				pguser = pg_strdup(optarg);
  				break;
*************** main(int argc, char **argv)
*** 92,98 ****
  	}
  
  	/*
! 	 * Get the default options so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
--- 100,126 ----
  	}
  
  	/*
! 	 * Set connection options
! 	 */
! 
! 	keywords[opt_index] = "connect_timeout";
! 	values[opt_index] = connect_timeout;
! 	opt_index++;
! 	if (pguser)
! 	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
! 	}
! 	if (pgdbname)
! 	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
! 	}
! 
! 	/*
! 	 * Get the default host and port so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
*************** main(int argc, char **argv)
*** 124,157 ****
  			else if (conn_opt_ptr->val)
  				pgport = conn_opt_ptr->val;
  		}
- 		else if (strncmp(conn_opt_ptr->keyword, "user", 5) == 0)
- 		{
- 			if (pguser)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pguser;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pguser = conn_opt_ptr->val;
- 		}
- 		else if (strncmp(conn_opt_ptr->keyword, "dbname", 7) == 0)
- 		{
- 			if (pgdbname)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pgdbname;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pgdbname = conn_opt_ptr->val;
- 		}
  		conn_opt_ptr++;
  	}
  
- 	keywords[opt_index] = NULL;
- 	values[opt_index] = NULL;
- 
  	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
--- 152,160 ----
*************** help(const char *progname)
*** 198,202 ****
--- 201,207 ----
  	printf(_("\nConnection options:\n"));
  	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
  	printf(_("  -p, --port=PORT          database server port\n"));
+ 	printf(_("  -t, --timeout=SECS       seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
  	printf(_("  -U, --username=USERNAME  database username\n"));
+ 	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
#13Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#12)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Fri, Jan 25, 2013 at 1:45 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Jan 23, 2013 at 8:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Jan 24, 2013 at 8:47 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Jan 23, 2013 at 6:07 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Phil Sorber <phil@omniti.com> writes:

On Wed, Jan 23, 2013 at 1:58 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Wed, Jan 23, 2013 at 12:27:45PM -0500, Tom Lane wrote:

+1 for default timeout --- if this isn't like "ping" where you are
expecting to run indefinitely, I can't see that it's a good idea for it
to sit very long by default, in any circumstance.

FYI, the pg_ctl -w (wait) default is 60 seconds:

Great. That is what I came to on my own as well. Figured that might be
a sticking point, but as there is precedent, I'm happy with it.

I'm not sure that's a relevant precedent at all. What that number is
is the time that pg_ctl will wait around for the postmaster to start or
stop before reporting a problem --- and in either case, a significant
delay (multiple seconds) is not surprising, because of crash-recovery
work, shutdown checkpointing, etc. For pg_isready, you'd expect to get
a response more or less instantly, wouldn't you? Personally, I'd decide
that pg_isready is broken if it didn't give me an answer in a couple of
seconds, much less a minute.

What I had in mind was a default timeout of maybe 3 or 4 seconds...

I was thinking that if it was in a script you wouldn't care if it was
60 seconds. If it was at the command line you would ^C it much
earlier. I think the default linux TCP connection timeout is around 20
seconds. My feeling is everyone is going to have a differing opinion
on this, which is why I was hoping that some good precedent existed.
I'm fine with 3 or 4, whatever can be agreed upon.

+1 with 3 or 4 secounds.

Aside from this issue, I have one minor comment. ISTM you need to
add the following line to the end of the help message. This line has
been included in the help message of all the other client commands.

Report bugs to <pgsql-bugs@postgresql.org>.

Ok, I set the default timeout to 3 seconds, added the bugs email to
the help, and also added docs that I forgot last time.

Thanks!

Also, still hoping to get some feedback on my other issues.

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#14Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#13)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Thu, Jan 24, 2013 at 1:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

I've updated the patch to address these three issues. Attached.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

For example if someone did: pg_isready -h foo -d "host=bar port=4321" -p 1234

What should the connection parameters be?

Show quoted text

Regards,

--
Fujii Masao

Attachments:

pg_isready_timeout_v3.diffapplication/octet-stream; name=pg_isready_timeout_v3.diffDownload
diff --git a/doc/src/sgml/ref/pg_isready.sgml b/doc/src/sgml/ref/pg_isready.sgml
new file mode 100644
index ea0d3a7..ff80a78
*** a/doc/src/sgml/ref/pg_isready.sgml
--- b/doc/src/sgml/ref/pg_isready.sgml
*************** PostgreSQL documentation
*** 97,102 ****
--- 97,114 ----
       </varlistentry>
  
       <varlistentry>
+        <term><option>-t <replaceable class="parameter">seconds</replaceable></></term>
+        <term><option>--timeout=<replaceable class="parameter">seconds</replaceable></></term>
+        <listitem>
+        <para>
+         The maximum number of seconds to wait when attempting connection before
+         returning that the server is not responding. Setting to 0 disables. The
+         default is 3 seconds.
+        </para>
+        </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
         <term><option>-U <replaceable class="parameter">username</replaceable></></term>
         <term><option>--username=<replaceable class="parameter">username</replaceable></></term>
         <listitem>
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index feee1a7..a18d8cf
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 12,24 ****
  #include "postgres_fe.h"
  #include "common.h"
  
  static void
  help(const char *progname);
  
  int
  main(int argc, char **argv)
  {
! 	int c,optindex,opt_index = 0;
  
  	const char *progname;
  
--- 12,26 ----
  #include "postgres_fe.h"
  #include "common.h"
  
+ #define	DEFAULT_CONNECT_TIMEOUT "3"
+ 
  static void
  help(const char *progname);
  
  int
  main(int argc, char **argv)
  {
! 	int c,optindex,opt_index = 2;
  
  	const char *progname;
  
*************** main(int argc, char **argv)
*** 26,33 ****
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
  
! 	const char *keywords[4], *values[4];
  
  	bool quiet = false;
  
--- 28,37 ----
  	const char *pgport = NULL;
  	const char *pguser = NULL;
  	const char *pgdbname = NULL;
+ 	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
  
! 	const char *keywords[7] = { NULL };
! 	const char *values[7] = { NULL };
  
  	bool quiet = false;
  
*************** main(int argc, char **argv)
*** 44,57 ****
  			{"host", required_argument, NULL, 'h'},
  			{"port", required_argument, NULL, 'p'},
  			{"quiet", no_argument, NULL, 'q'},
  			{"username", required_argument, NULL, 'U'},
  			{NULL, 0, NULL, 0}
  		};
  
  	progname = get_progname(argv[0]);
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qU:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 48,63 ----
  			{"host", required_argument, NULL, 'h'},
  			{"port", required_argument, NULL, 'p'},
  			{"quiet", no_argument, NULL, 'q'},
+ 			{"timeout", required_argument, NULL, 't'},
  			{"username", required_argument, NULL, 'U'},
  			{NULL, 0, NULL, 0}
  		};
  
  	progname = get_progname(argv[0]);
+ 	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 67,76 ****
--- 73,86 ----
  			case 'q':
  				quiet = true;
  				break;
+ 			case 't':
+ 				connect_timeout = pg_strdup(optarg);
+ 				break;
  			case 'U':
  				pguser = pg_strdup(optarg);
  				break;
  			default:
+ 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  				/*
  				 * We need to make sure we don't return 1 here because someone
  				 * checking the return code might infer unintended meaning
*************** main(int argc, char **argv)
*** 92,98 ****
  	}
  
  	/*
! 	 * Get the default options so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
--- 102,129 ----
  	}
  
  	/*
! 	 * Set connection options
! 	 */
! 
! 	keywords[0] = "connect_timeout";
! 	values[0] = connect_timeout;
! 	keywords[1] = "fallback_application_name";
! 	values[1] = progname;
! 	if (pguser)
! 	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
! 	}
! 	if (pgdbname)
! 	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
! 	}
! 
! 	/*
! 	 * Get the default host and port so we can display them in our output
  	 */
  
  	connect_options = PQconndefaults();
*************** main(int argc, char **argv)
*** 124,157 ****
  			else if (conn_opt_ptr->val)
  				pgport = conn_opt_ptr->val;
  		}
- 		else if (strncmp(conn_opt_ptr->keyword, "user", 5) == 0)
- 		{
- 			if (pguser)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pguser;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pguser = conn_opt_ptr->val;
- 		}
- 		else if (strncmp(conn_opt_ptr->keyword, "dbname", 7) == 0)
- 		{
- 			if (pgdbname)
- 			{
- 				keywords[opt_index] = conn_opt_ptr->keyword;
- 				values[opt_index] = pgdbname;
- 				opt_index++;
- 			}
- 			else if (conn_opt_ptr->val)
- 				pgdbname = conn_opt_ptr->val;
- 		}
  		conn_opt_ptr++;
  	}
  
- 	keywords[opt_index] = NULL;
- 	values[opt_index] = NULL;
- 
  	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
--- 155,163 ----
*************** help(const char *progname)
*** 198,202 ****
--- 204,210 ----
  	printf(_("\nConnection options:\n"));
  	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
  	printf(_("  -p, --port=PORT          database server port\n"));
+ 	printf(_("  -t, --timeout=SECS       seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
  	printf(_("  -U, --username=USERNAME  database username\n"));
+ 	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
#15Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#14)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Fri, Jan 25, 2013 at 4:10 AM, Phil Sorber <phil@omniti.com> wrote:

On Thu, Jan 24, 2013 at 1:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

I've updated the patch to address these three issues. Attached.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

If I read conninfo_array_parse() correctly, PQpingParams() prefer the
option which is set to its keyword array later.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#16Pavel Stehule
pavel.stehule@gmail.com
In reply to: Fujii Masao (#15)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

Regards

Pavel

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

If I read conninfo_array_parse() correctly, PQpingParams() prefer the
option which is set to its keyword array later.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#17Phil Sorber
phil@omniti.com
In reply to: Pavel Stehule (#16)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#18Pavel Stehule
pavel.stehule@gmail.com
In reply to: Phil Sorber (#17)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#19Phil Sorber
phil@omniti.com
In reply to: Pavel Stehule (#18)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#20Pavel Stehule
pavel.stehule@gmail.com
In reply to: Phil Sorber (#19)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough intelligence
to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

Regards

Pavel

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#21Phil Sorber
phil@omniti.com
In reply to: Pavel Stehule (#20)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Jan 26, 2013 at 12:39 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough intelligence
to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

I guess I am still not clear why you can't do:

stop_pg_via_puppet
pg_isready
while [ $? -ne 2 ]
do
sleep 1
pg_isready
done
do_post_stop_things
start_pg_via_puppet

Regards

Pavel

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#22Pavel Stehule
pavel.stehule@gmail.com
In reply to: Phil Sorber (#21)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 12:39 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough intelligence
to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

I guess I am still not clear why you can't do:

stop_pg_via_puppet
pg_isready
while [ $? -ne 2 ]
do
sleep 1
pg_isready
done
do_post_stop_things
start_pg_via_puppet

because ! pg_isready <> pg_isdone

Regards

Pavel

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#23Phil Sorber
phil@omniti.com
In reply to: Pavel Stehule (#22)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Jan 26, 2013 at 4:37 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 12:39 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough intelligence
to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

I guess I am still not clear why you can't do:

stop_pg_via_puppet
pg_isready
while [ $? -ne 2 ]
do
sleep 1
pg_isready
done
do_post_stop_things
start_pg_via_puppet

because ! pg_isready <> pg_isdone

So you are proposing a different utility? Sorry, I thought you were
proposing a new option to pg_isready. What would pg_isdone be testing
for specifically? Is this something that would block until it has
confirmed a shutdown?

Regards

Pavel

Regards

Pavel

Perhaps with a counter to break out of the loop after some number of attempts.

Regards

Pavel

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#24Craig Ringer
craig@2ndQuadrant.com
In reply to: Phil Sorber (#23)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On 01/27/2013 06:20 AM, Phil Sorber wrote:

On Sat, Jan 26, 2013 at 4:37 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 12:39 PM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try to
start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough intelligence
to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

I guess I am still not clear why you can't do:

stop_pg_via_puppet
pg_isready
while [ $? -ne 2 ]
do
sleep 1
pg_isready
done
do_post_stop_things
start_pg_via_puppet

because ! pg_isready <> pg_isdone

So you are proposing a different utility? Sorry, I thought you were
proposing a new option to pg_isready. What would pg_isdone be testing
for specifically? Is this something that would block until it has
confirmed a shutdown?

That's what it sounds like - confirming that PostgreSQL is really fully
shut down.

I'm not sure how you could do that over a protocol connection, myself.
I'd just read the postmaster pid from the pidfile on disk and then `kill
-0` it in a delay loop until the `kill` command returns failure. This
could be a useful convenience utility but I'm not convinced it should be
added to pg_isready because it requires local and possibly privileged
execution, unlike pg_isready's network based operation. Privileges could
be avoided by using an aliveness test other than `kill -0`, but you
absolutely have to be local to verify that the postmaster has fully
terminated - and it wouldn't make sense for a non-local process to care
about this anyway.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#25Phil Sorber
phil@omniti.com
In reply to: Craig Ringer (#24)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Jan 26, 2013 6:56 PM, "Craig Ringer" <craig@2ndquadrant.com> wrote:

On 01/27/2013 06:20 AM, Phil Sorber wrote:

On Sat, Jan 26, 2013 at 4:37 PM, Pavel Stehule <pavel.stehule@gmail.com>

wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 12:39 PM, Pavel Stehule <

pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 11:53 AM, Pavel Stehule <

pavel.stehule@gmail.com> wrote:

2013/1/26 Phil Sorber <phil@omniti.com>:

On Sat, Jan 26, 2013 at 4:02 AM, Pavel Stehule <

pavel.stehule@gmail.com> wrote:

Hello

We now haw to solve small puppet issue, because our puppets try

to

start server too early, when old instance live still.

Maybe some new parameter - is_done can be useful.

What about something like:
pg_isready; while [ $? -ne 2 ]; do sleep 1; pg_isready; done

it is not enough - server is done in a moment, where can be started
again - or when we can do safe copy of database data directory.

I guess i am not completely understanding the case you are trying to
solve. Can you explain a bit further?

We use puppets and due some simplification we cannot to use reload
when configuration is changed. Our puppets has not enough

intelligence

to understand when is reload enough and when is restart necessary. So
any change to configuration require restarting postgres. I don't know
why "service restart" are not used. I believe so our puppet guru know
it. It just do sequence STOP:START Now puppets are "smart" and able
to wait for time, when server is ready. But there are missing simple
test if server is really done and I see a error messages related to
too early try to start. So some important feature can be verification
so server is really done.

We can do it with test on pid file now - and probably we will use it.
But I see so this is similar use case (in opposite direction)

I guess I am still not clear why you can't do:

stop_pg_via_puppet
pg_isready
while [ $? -ne 2 ]
do
sleep 1
pg_isready
done
do_post_stop_things
start_pg_via_puppet

because ! pg_isready <> pg_isdone

So you are proposing a different utility? Sorry, I thought you were
proposing a new option to pg_isready. What would pg_isdone be testing
for specifically? Is this something that would block until it has
confirmed a shutdown?

That's what it sounds like - confirming that PostgreSQL is really fully
shut down.

I'm not sure how you could do that over a protocol connection, myself.
I'd just read the postmaster pid from the pidfile on disk and then `kill
-0` it in a delay loop until the `kill` command returns failure. This
could be a useful convenience utility but I'm not convinced it should be
added to pg_isready because it requires local and possibly privileged
execution, unlike pg_isready's network based operation. Privileges could
be avoided by using an aliveness test other than `kill -0`, but you
absolutely have to be local to verify that the postmaster has fully
terminated - and it wouldn't make sense for a non-local process to care
about this anyway.

Maybe something to add to pg_ctl?

Show quoted text

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#26Craig Ringer
craig@2ndQuadrant.com
In reply to: Phil Sorber (#25)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On 01/27/2013 08:16 AM, Phil Sorber wrote:

Craig Ringer wrote:

That's what it sounds like - confirming that PostgreSQL is really fully
shut down.

I'm not sure how you could do that over a protocol connection, myself.
I'd just read the postmaster pid from the pidfile on disk and then `kill
-0` it in a delay loop until the `kill` command returns failure. This
could be a useful convenience utility but I'm not convinced it should be
added to pg_isready because it requires local and possibly privileged
execution, unlike pg_isready's network based operation. Privileges could
be avoided by using an aliveness test other than `kill -0`, but you
absolutely have to be local to verify that the postmaster has fully
terminated - and it wouldn't make sense for a non-local process to care
about this anyway.

Maybe something to add to pg_ctl?

That'd make a lot more sense than to pg_isready, yeah.

--
Craig Ringer http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#27Tom Lane
tgl@sss.pgh.pa.us
In reply to: Craig Ringer (#24)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Craig Ringer <craig@2ndQuadrant.com> writes:

That's what it sounds like - confirming that PostgreSQL is really fully
shut down.

I'm not sure how you could do that over a protocol connection, myself.
I'd just read the postmaster pid from the pidfile on disk and then `kill
-0` it in a delay loop until the `kill` command returns failure. This
could be a useful convenience utility but I'm not convinced it should be
added to pg_isready because it requires local and possibly privileged
execution, unlike pg_isready's network based operation. Privileges could
be avoided by using an aliveness test other than `kill -0`, but you
absolutely have to be local to verify that the postmaster has fully
terminated - and it wouldn't make sense for a non-local process to care
about this anyway.

This problem is actually quite a bit more difficult than it looks.
In particular, the mere fact that the postmaster process is gone does
not prove that the cluster is idle: it's possible that the postmaster
crashed leaving orphan backends behind, and the orphans are still busily
modifying on-disk state. A real postmaster knows how to check for that
(by looking at the nattch count of the shmem segment cited in the old
lockfile) but I can't see any shell script getting it right.

So ATM I wouldn't trust any method short of "try to start a new
postmaster and see if it works", which of course is not terribly helpful
if your objective is to get to a stopped state.

We could consider transposing the shmem logic into a new pg_ctl command.
It might be better though to have a new switch in the postgres
executable that just runs postmaster startup as far as detecting
lockfile conflicts, and reports what it found (without ever launching
any child processes that could confuse matters). Then "pg_ctl isdone"
could be a frontend for that, instead of duplicating logic.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#28Pavel Stehule
pavel.stehule@gmail.com
In reply to: Tom Lane (#27)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

2013/1/27 Tom Lane <tgl@sss.pgh.pa.us>:

Craig Ringer <craig@2ndQuadrant.com> writes:

That's what it sounds like - confirming that PostgreSQL is really fully
shut down.

I'm not sure how you could do that over a protocol connection, myself.
I'd just read the postmaster pid from the pidfile on disk and then `kill
-0` it in a delay loop until the `kill` command returns failure. This
could be a useful convenience utility but I'm not convinced it should be
added to pg_isready because it requires local and possibly privileged
execution, unlike pg_isready's network based operation. Privileges could
be avoided by using an aliveness test other than `kill -0`, but you
absolutely have to be local to verify that the postmaster has fully
terminated - and it wouldn't make sense for a non-local process to care
about this anyway.

This problem is actually quite a bit more difficult than it looks.
In particular, the mere fact that the postmaster process is gone does
not prove that the cluster is idle: it's possible that the postmaster
crashed leaving orphan backends behind, and the orphans are still busily
modifying on-disk state. A real postmaster knows how to check for that
(by looking at the nattch count of the shmem segment cited in the old
lockfile) but I can't see any shell script getting it right.

So ATM I wouldn't trust any method short of "try to start a new
postmaster and see if it works", which of course is not terribly helpful
if your objective is to get to a stopped state.

We could consider transposing the shmem logic into a new pg_ctl command.
It might be better though to have a new switch in the postgres
executable that just runs postmaster startup as far as detecting
lockfile conflicts, and reports what it found (without ever launching
any child processes that could confuse matters). Then "pg_ctl isdone"
could be a frontend for that, instead of duplicating logic.

+1

Pavel

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#29Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#15)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Fri, Jan 25, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Fri, Jan 25, 2013 at 4:10 AM, Phil Sorber <phil@omniti.com> wrote:

On Thu, Jan 24, 2013 at 1:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

I've updated the patch to address these three issues. Attached.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

If I read conninfo_array_parse() correctly, PQpingParams() prefer the
option which is set to its keyword array later.

It would be really nice to expose conninfo_array_parse() or some
wrapped version directly to a libpq consumer. Otherwise, I need to
recreate this behavior in pg_isready.c.

Thoughts on adding:
PQconninfoOption *PQparamsParse(const char **keywords, const char
**values, char **errmsg, bool use_defaults, int expand_dbname)
or similar?

Or perhaps there is a better way to accomplish this that I am not aware of?

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#30Phil Sorber
phil@omniti.com
In reply to: Phil Sorber (#29)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sun, Jan 27, 2013 at 2:38 PM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Jan 25, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Fri, Jan 25, 2013 at 4:10 AM, Phil Sorber <phil@omniti.com> wrote:

On Thu, Jan 24, 2013 at 1:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

I've updated the patch to address these three issues. Attached.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

If I read conninfo_array_parse() correctly, PQpingParams() prefer the
option which is set to its keyword array later.

It would be really nice to expose conninfo_array_parse() or some
wrapped version directly to a libpq consumer. Otherwise, I need to
recreate this behavior in pg_isready.c.

Thoughts on adding:
PQconninfoOption *PQparamsParse(const char **keywords, const char
**values, char **errmsg, bool use_defaults, int expand_dbname)
or similar?

Or perhaps there is a better way to accomplish this that I am not aware of?

It would also be nice to be able to pass user_defaults to PQconninfoParse().

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#31Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#30)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Mon, Jan 28, 2013 at 4:47 AM, Phil Sorber <phil@omniti.com> wrote:

On Sun, Jan 27, 2013 at 2:38 PM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Jan 25, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Fri, Jan 25, 2013 at 4:10 AM, Phil Sorber <phil@omniti.com> wrote:

On Thu, Jan 24, 2013 at 1:12 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

set_pglocale_pgservice() should be called?

I think that the command name (i.e., pg_isready) should be given to
PQpingParams() as fallback_application_name. Otherwise, the server
by default uses "unknown" as the application name of pg_isready.
It's undesirable.

Why isn't the following message output only when invalid option is
specified?

Try \"%s --help\" for more information.

I've updated the patch to address these three issues. Attached.

When the conninfo string including the hostname or port number is
specified in -d option, pg_isready displays the wrong information
as follows.

$ pg_isready -d "port=9999"
/tmp:5432 - no response

This is what i asked about in my previous email about precedence of
the parameters. I can parse that with PQconninfoParse, but what are
the rules for merging both individual and conninfo params together?

If I read conninfo_array_parse() correctly, PQpingParams() prefer the
option which is set to its keyword array later.

It would be really nice to expose conninfo_array_parse() or some
wrapped version directly to a libpq consumer. Otherwise, I need to
recreate this behavior in pg_isready.c.

Thoughts on adding:
PQconninfoOption *PQparamsParse(const char **keywords, const char
**values, char **errmsg, bool use_defaults, int expand_dbname)
or similar?

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#32Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#31)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Mon, Jan 28, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#33Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Phil Sorber (#32)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Phil Sorber escribió:

On Mon, Jan 28, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

I suggest duplicate the code for 9.3, and submit a patch to refactor
into a new libpq function for CF2013-next. If the patch is simple
enough, we can consider putting it into 9.3.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#34Phil Sorber
phil@omniti.com
In reply to: Alvaro Herrera (#33)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Mon, Jan 28, 2013 at 1:12 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Mon, Jan 28, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

I suggest duplicate the code for 9.3, and submit a patch to refactor
into a new libpq function for CF2013-next. If the patch is simple
enough, we can consider putting it into 9.3.

Ok, sounds good to me.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#35Fujii Masao
masao.fujii@gmail.com
In reply to: Alvaro Herrera (#33)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Jan 29, 2013 at 3:12 AM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Mon, Jan 28, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

I suggest duplicate the code for 9.3, and submit a patch to refactor
into a new libpq function for CF2013-next. If the patch is simple
enough, we can consider putting it into 9.3.

Agreed.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#36Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#35)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Jan 29, 2013 at 11:43 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Tue, Jan 29, 2013 at 3:12 AM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Mon, Jan 28, 2013 at 11:20 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Maybe. But I'm not inclined to add new libpq interface at this stage.
Because we are in the last CommitFest and I'm not sure whether
we have enough time to implement that. Instead, how about using
both PQconninfoParse() and PQconndefaults() like uri-regress.c does?
Or just remove that output message? At least I don't think that the
information about host and port needs to be output. Which would make
the code very simpler.

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

I suggest duplicate the code for 9.3, and submit a patch to refactor
into a new libpq function for CF2013-next. If the patch is simple
enough, we can consider putting it into 9.3.

Agreed.

Regards,

--
Fujii Masao

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

Attachments:

pg_isready_con_str.diffapplication/octet-stream; name=pg_isready_con_str.diffDownload
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index 4ba257d..f316a36
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 17,22 ****
--- 17,27 ----
  static void
  help(const char *progname);
  
+ static void
+ set_connect_options(PQconninfoOption *conninfo, const char **dbname,
+ 				const char **host, const char **port,
+ 				const char **conn_to, const char **user);
+ 
  int
  main(int argc, char **argv)
  {
*************** main(int argc, char **argv)
*** 62,68 ****
  		switch (c)
  		{
  			case 'd':
! 				pgdbname = pg_strdup(optarg);
  				break;
  			case 'h':
  				pghost = pg_strdup(optarg);
--- 67,77 ----
  		switch (c)
  		{
  			case 'd':
! 				connect_options = PQconninfoParse(optarg, NULL);
! 				if (connect_options)
! 					set_connect_options(connect_options, &pgdbname, &pghost, &pgport, &connect_timeout, &pguser);
! 				else
! 					pgdbname = pg_strdup(optarg);
  				break;
  			case 'h':
  				pghost = pg_strdup(optarg);
*************** help(const char *progname)
*** 206,208 ****
--- 215,244 ----
  	printf(_("  -U, --username=USERNAME  database username\n"));
  	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
+ 
+ static void
+ set_connect_options(PQconninfoOption *conninfo, const char **dbname,
+ 				const char **host, const char **port,
+ 				const char **conn_to, const char **user)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 	{
+ 		if (opts->val)
+ 		{
+ 			if (strcmp(opts->keyword, "dbname") == 0)
+ 				*dbname = pg_strdup(opts->val);
+ 			else if (strcmp(opts->keyword, "host") == 0)
+ 				*host = pg_strdup(opts->val);
+ 			else if (strcmp(opts->keyword, "port") == 0)
+ 				*port = pg_strdup(opts->val);
+ 			else if (strcmp(opts->keyword, "connect_timeout") == 0)
+ 				*conn_to = pg_strdup(opts->val);
+ 			else if (strcmp(opts->keyword, "user") == 0)
+ 				*user = pg_strdup(opts->val);
+ 		}
+ 	}
+ 
+ 	PQconninfoFree(conninfo);
+ }
#37Bruce Momjian
bruce@momjian.us
In reply to: Phil Sorber (#36)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Feb 2, 2013 at 09:55:29PM -0500, Phil Sorber wrote:

I think that output is important as do others up thread. I think it'd
be simpler to just disable dbname's ability to double as conninfo. If
we are looking for easy, that is.

I don't mind duplicating the behavior from conninfo_array_parse() or
uri-regress.c either. I can just put a comment that at some point in
the future we should add a libpq interface for it.

I suggest duplicate the code for 9.3, and submit a patch to refactor
into a new libpq function for CF2013-next. If the patch is simple
enough, we can consider putting it into 9.3.

Agreed.

Regards,

--
Fujii Masao

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

If we could run pg_isready on the patch, it would tell us if the patch
is ready. Consider this a feature request. ;-)

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#38Robert Haas
robertmhaas@gmail.com
In reply to: Phil Sorber (#36)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#39Phil Sorber
phil@omniti.com
In reply to: Robert Haas (#38)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port. It works, but I don't
really like it all that much, honestly. I also submitted a patch to
add on to libpq to handle this, but Alvaro posed some questions I
don't have good answers for. So I actually have another patch brewing
that I actually like, but I need to put the finishing touches on. I
plan on submitting that later this morning.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#40Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Phil Sorber (#39)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#41Phil Sorber
phil@omniti.com
In reply to: Alvaro Herrera (#40)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#42Phil Sorber
phil@omniti.com
In reply to: Phil Sorber (#41)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

There still seems to be a bit of a disconnect in libpq in my opinion.
Taking options as a string (URI or conninfo) or a set of arrays, but
returning info about connection parameters in PQconninfoOption? And
nothing that takes that as an input. Seems odd to me.

Show quoted text

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

pg_isready_con_str_v2.diffapplication/octet-stream; name=pg_isready_con_str_v2.diffDownload
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index 4ba257d..9b0c18b
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 14,42 ****
  
  #define	DEFAULT_CONNECT_TIMEOUT "3"
  
! static void
! help(const char *progname);
  
  int
  main(int argc, char **argv)
  {
! 	int c,optindex,opt_index = 2;
! 
  	const char *progname;
! 
! 	const char *pghost = NULL;
! 	const char *pgport = NULL;
! 	const char *pguser = NULL;
! 	const char *pgdbname = NULL;
! 	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
! 
! 	const char *keywords[7] = { NULL };
! 	const char *values[7] = { NULL };
! 
  	bool quiet = false;
- 
  	PGPing rv;
! 	PQconninfoOption *connect_options, *conn_opt_ptr;
  
  	/*
  	 * We accept user and database as options to avoid
--- 14,34 ----
  
  #define	DEFAULT_CONNECT_TIMEOUT "3"
  
! static void help(const char *progname);
! static char *get_conn_option(PQconninfoOption *conninfo, const char *keyword);
! static bool set_conn_option(PQconninfoOption *conninfo, const char *keyword, const char *value);
! static char *get_conn_str(PQconninfoOption *conninfo);
! static void copy_conn_options(PQconninfoOption *conninfo_dest, PQconninfoOption *conninfo_src);
  
  int
  main(int argc, char **argv)
  {
! 	int c;
  	const char *progname;
! 	char *conninfo_str, *pghost, *pgport;
  	bool quiet = false;
  	PGPing rv;
! 	PQconninfoOption *connect_options, *dbname_opts;
  
  	/*
  	 * We accept user and database as options to avoid
*************** main(int argc, char **argv)
*** 57,83 ****
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
  			case 'd':
! 				pgdbname = pg_strdup(optarg);
  				break;
  			case 'h':
! 				pghost = pg_strdup(optarg);
  				break;
  			case 'p':
! 				pgport = pg_strdup(optarg);
  				break;
  			case 'q':
  				quiet = true;
  				break;
  			case 't':
! 				connect_timeout = pg_strdup(optarg);
  				break;
  			case 'U':
! 				pguser = pg_strdup(optarg);
  				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
--- 49,88 ----
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	connect_options = PQconndefaults();
! 	set_conn_option(connect_options, "connect_timeout", DEFAULT_CONNECT_TIMEOUT);
! 	set_conn_option(connect_options, "fallback_application_name", progname);
! 	if (!get_conn_option(connect_options, "host"))
! 		set_conn_option(connect_options, "host", DEFAULT_PGSOCKET_DIR);
! 
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, NULL)) != -1)
  	{
  		switch (c)
  		{
  			case 'd':
! 				dbname_opts = PQconninfoParse(optarg, NULL);
! 				if (dbname_opts)
! 				{
! 					copy_conn_options(connect_options, dbname_opts);
! 					PQconninfoFree(dbname_opts);
! 				}
! 				else
! 					set_conn_option(connect_options, "dbname", optarg);
  				break;
  			case 'h':
! 				set_conn_option(connect_options, "host", optarg);
  				break;
  			case 'p':
! 				set_conn_option(connect_options, "port", optarg);
  				break;
  			case 'q':
  				quiet = true;
  				break;
  			case 't':
! 				set_conn_option(connect_options, "connect_timeout", optarg);
  				break;
  			case 'U':
! 				set_conn_option(connect_options, "user", optarg);
  				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
*************** main(int argc, char **argv)
*** 101,166 ****
  		exit(PQPING_NO_ATTEMPT);
  	}
  
! 	/*
! 	 * Set connection options
! 	 */
! 
! 	keywords[0] = "connect_timeout";
! 	values[0] = connect_timeout;
! 	keywords[1] = "fallback_application_name";
! 	values[1] = progname;
! 	if (pguser)
! 	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
! 	}
! 	if (pgdbname)
! 	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
! 	}
! 
! 	/*
! 	 * Get the default host and port so we can display them in our output
! 	 */
! 	connect_options = PQconndefaults();
! 	conn_opt_ptr = connect_options;
! 	while (conn_opt_ptr->keyword)
! 	{
! 		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
! 		{
! 			if (pghost)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pghost;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pghost = conn_opt_ptr->val;
! 			else
! 				pghost = DEFAULT_PGSOCKET_DIR;
! 		}
! 		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
! 		{
! 			if (pgport)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pgport;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pgport = conn_opt_ptr->val;
! 		}
! 		conn_opt_ptr++;
! 	}
! 
! 	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
  	{
  		printf("%s:%s - ", pghost, pgport);
  
  		switch (rv)
  		{
--- 106,122 ----
  		exit(PQPING_NO_ATTEMPT);
  	}
  
! 	conninfo_str = get_conn_str(connect_options);
! 	rv = PQping(conninfo_str);
! 	free(conninfo_str);	
  
  	if (!quiet)
  	{
+ 		pghost = get_conn_option(connect_options, "host");
+ 		pgport = get_conn_option(connect_options, "port");
  		printf("%s:%s - ", pghost, pgport);
+ 		free(pghost);
+ 		free(pgport);
  
  		switch (rv)
  		{
*************** help(const char *progname)
*** 206,208 ****
--- 162,224 ----
  	printf(_("  -U, --username=USERNAME  database username\n"));
  	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
+ 
+ static char *
+ get_conn_option(PQconninfoOption *conninfo, const char *keyword)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if ((strcmp(opts->keyword, keyword) == 0) && (opts->val))
+ 			return pg_strdup(opts->val);
+ 
+ 	return NULL;
+ }
+ 
+ static bool
+ set_conn_option(PQconninfoOption *conninfo, const char *keyword, const char *value)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if (strcmp(opts->keyword, keyword) == 0)
+ 		{
+ 			if (opts->val)
+ 				free(opts->val);
+ 			if (value)
+ 				opts->val = pg_strdup(value);
+ 			return true;
+ 		}
+ 
+ 	return false;
+ }
+ 
+ static char *
+ get_conn_str(PQconninfoOption *conninfo)
+ {
+ 	PQconninfoOption *opts;
+ 	size_t buf_size = 0, count = 0;
+ 	char *conn_string;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if ((opts->val) && (strlen(opts->val) > 0))
+ 			buf_size += strlen(opts->keyword) + strlen(opts->val) + 2;
+ 
+ 	conn_string = pg_malloc0(buf_size);
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if ((opts->val) && (strlen(opts->val) > 0))
+ 			count += snprintf(conn_string + count, buf_size - count, "%s%s=%s", (count > 0 ? " " : ""), opts->keyword, opts->val);
+ 
+ 	return conn_string;
+ }
+ 
+ static void
+ copy_conn_options(PQconninfoOption *conninfo_dest, PQconninfoOption *conninfo_src)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo_src; opts->keyword; opts++)
+ 		if (opts->val)
+ 			set_conn_option(conninfo_dest, opts->keyword, opts->val);
+ }
#43Phil Sorber
phil@omniti.com
In reply to: Phil Sorber (#42)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

Minor adjustment.

Show quoted text

There still seems to be a bit of a disconnect in libpq in my opinion.
Taking options as a string (URI or conninfo) or a set of arrays, but
returning info about connection parameters in PQconninfoOption? And
nothing that takes that as an input. Seems odd to me.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

pg_isready_con_str_v3.diffapplication/octet-stream; name=pg_isready_con_str_v3.diffDownload
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index 4ba257d..96be545
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 14,42 ****
  
  #define	DEFAULT_CONNECT_TIMEOUT "3"
  
! static void
! help(const char *progname);
  
  int
  main(int argc, char **argv)
  {
! 	int c,optindex,opt_index = 2;
! 
  	const char *progname;
! 
! 	const char *pghost = NULL;
! 	const char *pgport = NULL;
! 	const char *pguser = NULL;
! 	const char *pgdbname = NULL;
! 	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
! 
! 	const char *keywords[7] = { NULL };
! 	const char *values[7] = { NULL };
! 
  	bool quiet = false;
- 
  	PGPing rv;
! 	PQconninfoOption *connect_options, *conn_opt_ptr;
  
  	/*
  	 * We accept user and database as options to avoid
--- 14,34 ----
  
  #define	DEFAULT_CONNECT_TIMEOUT "3"
  
! static void help(const char *progname);
! static char *get_conn_option(PQconninfoOption *conninfo, const char *keyword);
! static bool set_conn_option(PQconninfoOption *conninfo, const char *keyword, const char *value);
! static char *get_conn_str(PQconninfoOption *conninfo);
! static void copy_conn_options(PQconninfoOption *conninfo_dest, PQconninfoOption *conninfo_src);
  
  int
  main(int argc, char **argv)
  {
! 	int c;
  	const char *progname;
! 	char *conninfo_str, *pghost, *pgport;
  	bool quiet = false;
  	PGPing rv;
! 	PQconninfoOption *connect_options, *dbname_opts;
  
  	/*
  	 * We accept user and database as options to avoid
*************** main(int argc, char **argv)
*** 57,83 ****
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
  			case 'd':
! 				pgdbname = pg_strdup(optarg);
  				break;
  			case 'h':
! 				pghost = pg_strdup(optarg);
  				break;
  			case 'p':
! 				pgport = pg_strdup(optarg);
  				break;
  			case 'q':
  				quiet = true;
  				break;
  			case 't':
! 				connect_timeout = pg_strdup(optarg);
  				break;
  			case 'U':
! 				pguser = pg_strdup(optarg);
  				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
--- 49,88 ----
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	connect_options = PQconndefaults();
! 	set_conn_option(connect_options, "connect_timeout", DEFAULT_CONNECT_TIMEOUT);
! 	set_conn_option(connect_options, "fallback_application_name", progname);
! 	if (!get_conn_option(connect_options, "host"))
! 		set_conn_option(connect_options, "host", DEFAULT_PGSOCKET_DIR);
! 
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, NULL)) != -1)
  	{
  		switch (c)
  		{
  			case 'd':
! 				dbname_opts = PQconninfoParse(optarg, NULL);
! 				if (dbname_opts)
! 				{
! 					copy_conn_options(connect_options, dbname_opts);
! 					PQconninfoFree(dbname_opts);
! 				}
! 				else
! 					set_conn_option(connect_options, "dbname", optarg);
  				break;
  			case 'h':
! 				set_conn_option(connect_options, "host", optarg);
  				break;
  			case 'p':
! 				set_conn_option(connect_options, "port", optarg);
  				break;
  			case 'q':
  				quiet = true;
  				break;
  			case 't':
! 				set_conn_option(connect_options, "connect_timeout", optarg);
  				break;
  			case 'U':
! 				set_conn_option(connect_options, "user", optarg);
  				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
*************** main(int argc, char **argv)
*** 101,165 ****
  		exit(PQPING_NO_ATTEMPT);
  	}
  
! 	/*
! 	 * Set connection options
! 	 */
! 
! 	keywords[0] = "connect_timeout";
! 	values[0] = connect_timeout;
! 	keywords[1] = "fallback_application_name";
! 	values[1] = progname;
! 	if (pguser)
! 	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
! 	}
! 	if (pgdbname)
! 	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
! 	}
! 
! 	/*
! 	 * Get the default host and port so we can display them in our output
! 	 */
! 	connect_options = PQconndefaults();
! 	conn_opt_ptr = connect_options;
! 	while (conn_opt_ptr->keyword)
! 	{
! 		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
! 		{
! 			if (pghost)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pghost;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pghost = conn_opt_ptr->val;
! 			else
! 				pghost = DEFAULT_PGSOCKET_DIR;
! 		}
! 		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
! 		{
! 			if (pgport)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pgport;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pgport = conn_opt_ptr->val;
! 		}
! 		conn_opt_ptr++;
! 	}
! 
! 	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
  	{
  		printf("%s:%s - ", pghost, pgport);
  
  		switch (rv)
--- 106,119 ----
  		exit(PQPING_NO_ATTEMPT);
  	}
  
! 	conninfo_str = get_conn_str(connect_options);
! 	rv = PQping(conninfo_str);
! 	free(conninfo_str);	
  
  	if (!quiet)
  	{
+ 		pghost = get_conn_option(connect_options, "host");
+ 		pgport = get_conn_option(connect_options, "port");
  		printf("%s:%s - ", pghost, pgport);
  
  		switch (rv)
*************** help(const char *progname)
*** 206,208 ****
--- 160,222 ----
  	printf(_("  -U, --username=USERNAME  database username\n"));
  	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  }
+ 
+ static char *
+ get_conn_option(PQconninfoOption *conninfo, const char *keyword)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if (strcmp(opts->keyword, keyword) == 0)
+ 			return opts->val;
+ 
+ 	return NULL;
+ }
+ 
+ static bool
+ set_conn_option(PQconninfoOption *conninfo, const char *keyword, const char *value)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if (strcmp(opts->keyword, keyword) == 0)
+ 		{
+ 			if (opts->val)
+ 				free(opts->val);
+ 			if (value)
+ 				opts->val = pg_strdup(value);
+ 			return true;
+ 		}
+ 
+ 	return false;
+ }
+ 
+ static char *
+ get_conn_str(PQconninfoOption *conninfo)
+ {
+ 	PQconninfoOption *opts;
+ 	size_t buf_size = 0, count = 0;
+ 	char *conn_string;
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if ((opts->val) && (strlen(opts->val) > 0))
+ 			buf_size += strlen(opts->keyword) + strlen(opts->val) + 2;
+ 
+ 	conn_string = pg_malloc0(buf_size);
+ 
+ 	for (opts = conninfo; opts->keyword; opts++)
+ 		if ((opts->val) && (strlen(opts->val) > 0))
+ 			count += snprintf(conn_string + count, buf_size - count, "%s%s=%s", (count > 0 ? " " : ""), opts->keyword, opts->val);
+ 
+ 	return conn_string;
+ }
+ 
+ static void
+ copy_conn_options(PQconninfoOption *conninfo_dest, PQconninfoOption *conninfo_src)
+ {
+ 	PQconninfoOption *opts;
+ 
+ 	for (opts = conninfo_src; opts->keyword; opts++)
+ 		if (opts->val)
+ 			set_conn_option(conninfo_dest, opts->keyword, opts->val);
+ }
#44Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#43)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Thu, Feb 7, 2013 at 12:05 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

The patch looks complicated to me. I was thinking that we can address
the problem
just by using PQconninfoParse() and PQconndefaults() like uri-regress.c does.
The patch should be very simple. Why do we need so complicated code?

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#45Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#44)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Feb 6, 2013 at 11:11 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 12:05 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

The patch looks complicated to me. I was thinking that we can address
the problem
just by using PQconninfoParse() and PQconndefaults() like uri-regress.c does.
The patch should be very simple. Why do we need so complicated code?

Did you like the previous version better?

/messages/by-id/CADAkt-hnB3OhCpkR+PCg1c_Bjrsb7J__BPV+-jrjS5opjR2oww@mail.gmail.com

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#46Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#45)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Thu, Feb 7, 2013 at 1:15 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Feb 6, 2013 at 11:11 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 12:05 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

The patch looks complicated to me. I was thinking that we can address
the problem
just by using PQconninfoParse() and PQconndefaults() like uri-regress.c does.
The patch should be very simple. Why do we need so complicated code?

Did you like the previous version better?

/messages/by-id/CADAkt-hnB3OhCpkR+PCg1c_Bjrsb7J__BPV+-jrjS5opjR2oww@mail.gmail.com

Yes because that version is simpler. But which version is better depends on
the reason why you implemented new version. If you have some idea about
the merit and demerit of each version, could you elaborate them?

+ set_connect_options(connect_options, &pgdbname, &pghost,
&pgport, &connect_timeout, &pguser);

This code prevents us from giving options other than the above, for example
application_name, in the conninfo. I think that pg_isready should accept all
the libpq options.

When more than one -d options are specified, psql always prefer the last one
and ignore the others. OTOH, pg_isready with this patch seems to merge them.
I'm not sure if there is specific rule about the priority order of -d
option. But
it seems better to follow the existing way, i.e., always prefer the
last -d option.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#47Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#46)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Wed, Feb 6, 2013 at 11:36 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 1:15 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Feb 6, 2013 at 11:11 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 12:05 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

The patch looks complicated to me. I was thinking that we can address
the problem
just by using PQconninfoParse() and PQconndefaults() like uri-regress.c does.
The patch should be very simple. Why do we need so complicated code?

Did you like the previous version better?

/messages/by-id/CADAkt-hnB3OhCpkR+PCg1c_Bjrsb7J__BPV+-jrjS5opjR2oww@mail.gmail.com

Yes because that version is simpler. But which version is better depends on
the reason why you implemented new version. If you have some idea about
the merit and demerit of each version, could you elaborate them?

I didn't like the way that I had to hard code the options in the first
one as you pointed out below. I also was looking through the code for
something else and saw that a lot of the apps were starting with
defaults then building from there, rather than trying to add the
defaults at the end. I think they were still doing it wrong because
they were using getenv() on their own rather than asking libpq for the
defaults though. So the new version gets the defaults at the beginning
and also makes it easy to add new params without changing function
definitions.

+ set_connect_options(connect_options, &pgdbname, &pghost,
&pgport, &connect_timeout, &pguser);

This code prevents us from giving options other than the above, for example
application_name, in the conninfo. I think that pg_isready should accept all
the libpq options.

I'm with you there. The new version fixes that as well.

When more than one -d options are specified, psql always prefer the last one
and ignore the others. OTOH, pg_isready with this patch seems to merge them.
I'm not sure if there is specific rule about the priority order of -d
option. But
it seems better to follow the existing way, i.e., always prefer the
last -d option.

The problem I am having here is resolving the differences between
different -d options and other command line options. For example:

-h foo -p 4321 -d "host=bar port=1234" -d "host=baz"

I would expect that to be 'baz:1234' but you are saying it should be 'baz:4321'?

I look at -d as just a way to pass in multiple options (when you
aren't strictly passing in dbname) and should be able to expand the
above example to:

-h foo -p 4321 -h bar -p 1234 -h baz

If we hold off on parsing the value of -d until the end so we are sure
we have the last one, then we might lose other parameters that were
after the -d option. For example:

-h foo -p 4321 -d "host=bar port=1234" -d "host=baz user=you" -U me

Should this be 'me@baz:1234' or 'you@baz:4321' or 'me@baz:4321'?

So we would have to track the last instance of a parameter as well as
the order those final versions came in. Sound to me like there is no
clear answer there, but maybe there is a project consensus that has
already been reached with regard to this? Or some general computing
wisdom that applies?

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#48Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#47)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Thu, Feb 7, 2013 at 2:14 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Feb 6, 2013 at 11:36 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 1:15 AM, Phil Sorber <phil@omniti.com> wrote:

On Wed, Feb 6, 2013 at 11:11 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

On Thu, Feb 7, 2013 at 12:05 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 12:44 PM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:08 AM, Phil Sorber <phil@omniti.com> wrote:

On Tue, Feb 5, 2013 at 9:06 AM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

Phil Sorber escribió:

On Tue, Feb 5, 2013 at 6:41 AM, Robert Haas <robertmhaas@gmail.com> wrote:

On Sat, Feb 2, 2013 at 9:55 PM, Phil Sorber <phil@omniti.com> wrote:

OK, here is the patch that handles the connection string in dbname.
I'll post the other patch under a different posting because I am sure
it will get plenty of debate on it's own.

I'm sorry, can you remind me what this does for us vs. the existing coding?

It's supposed to handle the connection string passed as dbname case to
be able to get the right output for host:port.

Surely the idea is that you can also give it a postgres:// URI, right?

Absolutely.

Here is it. I like this approach more than the previous one, but I'd
like some feedback.

The patch looks complicated to me. I was thinking that we can address
the problem
just by using PQconninfoParse() and PQconndefaults() like uri-regress.c does.
The patch should be very simple. Why do we need so complicated code?

Did you like the previous version better?

/messages/by-id/CADAkt-hnB3OhCpkR+PCg1c_Bjrsb7J__BPV+-jrjS5opjR2oww@mail.gmail.com

Yes because that version is simpler. But which version is better depends on
the reason why you implemented new version. If you have some idea about
the merit and demerit of each version, could you elaborate them?

I didn't like the way that I had to hard code the options in the first
one as you pointed out below. I also was looking through the code for
something else and saw that a lot of the apps were starting with
defaults then building from there, rather than trying to add the
defaults at the end. I think they were still doing it wrong because
they were using getenv() on their own rather than asking libpq for the
defaults though. So the new version gets the defaults at the beginning
and also makes it easy to add new params without changing function
definitions.

+ set_connect_options(connect_options, &pgdbname, &pghost,
&pgport, &connect_timeout, &pguser);

This code prevents us from giving options other than the above, for example
application_name, in the conninfo. I think that pg_isready should accept all
the libpq options.

I'm with you there. The new version fixes that as well.

When more than one -d options are specified, psql always prefer the last one
and ignore the others. OTOH, pg_isready with this patch seems to merge them.
I'm not sure if there is specific rule about the priority order of -d
option. But
it seems better to follow the existing way, i.e., always prefer the
last -d option.

The problem I am having here is resolving the differences between
different -d options and other command line options. For example:

-h foo -p 4321 -d "host=bar port=1234" -d "host=baz"

I would expect that to be 'baz:1234' but you are saying it should be 'baz:4321'?

I look at -d as just a way to pass in multiple options (when you
aren't strictly passing in dbname) and should be able to expand the
above example to:

-h foo -p 4321 -h bar -p 1234 -h baz

If we hold off on parsing the value of -d until the end so we are sure
we have the last one, then we might lose other parameters that were
after the -d option. For example:

-h foo -p 4321 -d "host=bar port=1234" -d "host=baz user=you" -U me

Should this be 'me@baz:1234' or 'you@baz:4321' or 'me@baz:4321'?

So we would have to track the last instance of a parameter as well as
the order those final versions came in. Sound to me like there is no
clear answer there, but maybe there is a project consensus that has
already been reached with regard to this?

No maybe. But I think that all the client commands should follow the
same rule. Otherwise a user would get confused when specifying
options.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#49Phil Sorber
phil@omniti.com
In reply to: Fujii Masao (#48)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Fri, Feb 8, 2013 at 12:46 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

No maybe. But I think that all the client commands should follow the
same rule. Otherwise a user would get confused when specifying
options.

I would consider the rest of the apps using it as a consensus. I will
make sure it aligns in behavior.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#50Phil Sorber
phil@omniti.com
In reply to: Phil Sorber (#49)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Fri, Feb 8, 2013 at 1:07 PM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Feb 8, 2013 at 12:46 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

No maybe. But I think that all the client commands should follow the
same rule. Otherwise a user would get confused when specifying
options.

I would consider the rest of the apps using it as a consensus. I will
make sure it aligns in behavior.

I've done as you suggested, and made sure they align with other
command line utils. What I have found is that dbname is passed
(almost) last in the param array so that it clobbers all previous
values. I have made this patch as minimal as possible basing it off of
master and not off of my previous attempt. For the record I still like
the overall design of my previous attempt better, but I have not
included a new version based on that here so as not to confuse the
issue, however I would gladly do so upon request.

Updated patch attached.

Show quoted text

Regards,

--
Fujii Masao

Attachments:

pg_isready_con_str_v4.diffapplication/octet-stream; name=pg_isready_con_str_v4.diffDownload
diff --git a/src/bin/scripts/pg_isready.c b/src/bin/scripts/pg_isready.c
new file mode 100644
index 4ba257d..59f3d24
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
*************** help(const char *progname);
*** 20,26 ****
  int
  main(int argc, char **argv)
  {
! 	int c,optindex,opt_index = 2;
  
  	const char *progname;
  
--- 20,26 ----
  int
  main(int argc, char **argv)
  {
! 	int c,opt_index = 0;
  
  	const char *progname;
  
*************** main(int argc, char **argv)
*** 36,42 ****
  	bool quiet = false;
  
  	PGPing rv;
! 	PQconninfoOption *connect_options, *conn_opt_ptr;
  
  	/*
  	 * We accept user and database as options to avoid
--- 36,42 ----
  	bool quiet = false;
  
  	PGPing rv;
! 	PQconninfoOption *connect_options, *conn_opt_ptr, *dbname_options = NULL, *db_opt_ptr = NULL;
  
  	/*
  	 * We accept user and database as options to avoid
*************** main(int argc, char **argv)
*** 57,63 ****
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 57,63 ----
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, NULL)) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 102,137 ****
  	}
  
  	/*
- 	 * Set connection options
- 	 */
- 
- 	keywords[0] = "connect_timeout";
- 	values[0] = connect_timeout;
- 	keywords[1] = "fallback_application_name";
- 	values[1] = progname;
- 	if (pguser)
- 	{
- 		keywords[opt_index] = "user";
- 		values[opt_index] = pguser;
- 		opt_index++;
- 	}
- 	if (pgdbname)
- 	{
- 		keywords[opt_index] = "dbname";
- 		values[opt_index] = pgdbname;
- 		opt_index++;
- 	}
- 
- 	/*
  	 * Get the default host and port so we can display them in our output
  	 */
  	connect_options = PQconndefaults();
  	conn_opt_ptr = connect_options;
  	while (conn_opt_ptr->keyword)
  	{
  		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
  		{
! 			if (pghost)
  			{
  				keywords[opt_index] = conn_opt_ptr->keyword;
  				values[opt_index] = pghost;
--- 102,125 ----
  	}
  
  	/*
  	 * Get the default host and port so we can display them in our output
  	 */
  	connect_options = PQconndefaults();
  	conn_opt_ptr = connect_options;
+ 	if (pgdbname)
+ 	{
+ 		dbname_options = PQconninfoParse(pgdbname, NULL);
+ 		db_opt_ptr = dbname_options;
+ 	}
  	while (conn_opt_ptr->keyword)
  	{
  		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
  		{
! 			if (db_opt_ptr && db_opt_ptr->val)
! 			{
! 				pghost = db_opt_ptr->val;
! 			}
! 			else if (pghost)
  			{
  				keywords[opt_index] = conn_opt_ptr->keyword;
  				values[opt_index] = pghost;
*************** main(int argc, char **argv)
*** 144,150 ****
  		}
  		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
  		{
! 			if (pgport)
  			{
  				keywords[opt_index] = conn_opt_ptr->keyword;
  				values[opt_index] = pgport;
--- 132,142 ----
  		}
  		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
  		{
! 			if (db_opt_ptr && db_opt_ptr->val)
! 			{
! 				pgport = db_opt_ptr->val;
! 			}
! 			else if (pgport)
  			{
  				keywords[opt_index] = conn_opt_ptr->keyword;
  				values[opt_index] = pgport;
*************** main(int argc, char **argv)
*** 154,160 ****
--- 146,171 ----
  				pgport = conn_opt_ptr->val;
  		}
  		conn_opt_ptr++;
+ 		if (db_opt_ptr)
+ 			db_opt_ptr++;
  	}
+ 	if (pguser)
+ 	{
+ 		keywords[opt_index] = "user";
+ 		values[opt_index] = pguser;
+ 		opt_index++;
+ 	}
+ 	if (pgdbname)
+ 	{
+ 		keywords[opt_index] = "dbname";
+ 		values[opt_index] = pgdbname;
+ 		opt_index++;
+ 	}
+ 	keywords[opt_index] = "connect_timeout";
+ 	values[opt_index] = connect_timeout;
+ 	opt_index++;
+ 	keywords[opt_index] = "fallback_application_name";
+ 	values[opt_index] = progname;
  
  	rv = PQpingParams(keywords, values, 1);
  
#51Fujii Masao
masao.fujii@gmail.com
In reply to: Phil Sorber (#50)
1 attachment(s)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

Sorry for the delay in responding to you.

On Mon, Feb 11, 2013 at 6:03 AM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Feb 8, 2013 at 1:07 PM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Feb 8, 2013 at 12:46 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

No maybe. But I think that all the client commands should follow the
same rule. Otherwise a user would get confused when specifying
options.

I would consider the rest of the apps using it as a consensus. I will
make sure it aligns in behavior.

I've done as you suggested, and made sure they align with other
command line utils. What I have found is that dbname is passed
(almost) last in the param array so that it clobbers all previous
values. I have made this patch as minimal as possible basing it off of
master and not off of my previous attempt. For the record I still like
the overall design of my previous attempt better, but I have not
included a new version based on that here so as not to confuse the
issue, however I would gladly do so upon request.

Updated patch attached.

Thanks! The patch basically looks good to me.

I updated the patch against current master and fixed some problems:

- Handle the hostaddr in the connection string properly.
- Remove the character 'V' from the third argument of getopt_long().
- Handle the error cases of PQconninfoParse() and PQconndefaults().
- etc...

Please see the attached patch.

Regards,

--
Fujii Masao

Attachments:

pg_isready_con_str_v5.patchapplication/octet-stream; name=pg_isready_con_str_v5.patchDownload
*** a/src/bin/scripts/pg_isready.c
--- b/src/bin/scripts/pg_isready.c
***************
*** 20,28 **** static void
  int
  main(int argc, char **argv)
  {
! 	int			c,
! 				optindex,
! 				opt_index = 2;
  
  	const char *progname;
  
--- 20,26 ----
  int
  main(int argc, char **argv)
  {
! 	int			c;
  
  	const char *progname;
  
***************
*** 32,45 **** main(int argc, char **argv)
  	const char *pgdbname = NULL;
  	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
  
! 	const char *keywords[7] = {NULL};
! 	const char *values[7] = {NULL};
  
  	bool		quiet = false;
  
! 	PGPing		rv;
! 	PQconninfoOption *connect_options,
! 			   *conn_opt_ptr;
  
  	/*
  	 * We accept user and database as options to avoid useless errors from
--- 30,51 ----
  	const char *pgdbname = NULL;
  	const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
  
! 	const char *pghost_str = NULL;
! 	const char *pgport_str = NULL;
! 
! #define PARAMS_ARRAY_SIZE	7
! 
! 	const char *keywords[PARAMS_ARRAY_SIZE];
! 	const char *values[PARAMS_ARRAY_SIZE];
  
  	bool		quiet = false;
  
! 	PGPing rv;
! 	PQconninfoOption *opts = NULL;
! 	PQconninfoOption *defs = NULL;
! 	PQconninfoOption *opt;
! 	PQconninfoOption *def;
! 	char	   *errmsg = NULL;
  
  	/*
  	 * We accept user and database as options to avoid useless errors from
***************
*** 60,66 **** main(int argc, char **argv)
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:V", long_options, &optindex)) != -1)
  	{
  		switch (c)
  		{
--- 66,72 ----
  	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
  	handle_help_version_opts(argc, argv, progname, help);
  
! 	while ((c = getopt_long(argc, argv, "d:h:p:qt:U:", long_options, NULL)) != -1)
  	{
  		switch (c)
  		{
***************
*** 106,171 **** main(int argc, char **argv)
  		exit(PQPING_NO_ATTEMPT);
  	}
  
  	/*
! 	 * Set connection options
  	 */
! 
! 	keywords[0] = "connect_timeout";
! 	values[0] = connect_timeout;
! 	keywords[1] = "fallback_application_name";
! 	values[1] = progname;
! 	if (pguser)
  	{
! 		keywords[opt_index] = "user";
! 		values[opt_index] = pguser;
! 		opt_index++;
  	}
! 	if (pgdbname)
  	{
! 		keywords[opt_index] = "dbname";
! 		values[opt_index] = pgdbname;
! 		opt_index++;
  	}
  
! 	/*
! 	 * Get the default host and port so we can display them in our output
! 	 */
! 	connect_options = PQconndefaults();
! 	conn_opt_ptr = connect_options;
! 	while (conn_opt_ptr->keyword)
  	{
! 		if (strncmp(conn_opt_ptr->keyword, "host", 5) == 0)
  		{
! 			if (pghost)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pghost;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pghost = conn_opt_ptr->val;
  			else
! 				pghost = DEFAULT_PGSOCKET_DIR;
  		}
! 		else if (strncmp(conn_opt_ptr->keyword, "port", 5) == 0)
  		{
! 			if (pgport)
! 			{
! 				keywords[opt_index] = conn_opt_ptr->keyword;
! 				values[opt_index] = pgport;
! 				opt_index++;
! 			}
! 			else if (conn_opt_ptr->val)
! 				pgport = conn_opt_ptr->val;
  		}
! 		conn_opt_ptr++;
  	}
  
  	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
  	{
! 		printf("%s:%s - ", pghost, pgport);
  
  		switch (rv)
  		{
--- 112,185 ----
  		exit(PQPING_NO_ATTEMPT);
  	}
  
+ 	keywords[0] = "host";
+ 	values[0] = pghost;
+ 	keywords[1] = "port";
+ 	values[1] = pgport;
+ 	keywords[2] = "user";
+ 	values[2] = pguser;
+ 	keywords[3] = "dbname";
+ 	values[3] = pgdbname;
+ 	keywords[4] = "connect_timeout";
+ 	values[4] = connect_timeout;
+ 	keywords[5] = "fallback_application_name";
+ 	values[5] = progname;
+ 	keywords[6] = NULL;
+ 	values[6] = NULL;
+ 
  	/*
! 	 * Get the default host and port so we can display them in our output
  	 */
! 	if (pgdbname)
  	{
! 		opts = PQconninfoParse(pgdbname, &errmsg);
! 		if (opts == NULL)
! 		{
! 			fprintf(stderr, _("%s: %s\n"), progname, errmsg);
! 			exit(PQPING_NO_ATTEMPT);
! 		}
  	}
! 
! 	defs = PQconndefaults();
! 	if (defs == NULL)
  	{
! 		fprintf(stderr, _("%s: cannot fetch default options\n"), progname);
! 		exit(PQPING_NO_ATTEMPT);
  	}
  
! 	for (opt = opts, def = defs; def->keyword; def++)
  	{
! 		if (strcmp(def->keyword, "hostaddr") == 0 ||
! 			strcmp(def->keyword, "host") == 0)
  		{
! 			if (opt && opt->val)
! 				pghost_str = opt->val;
! 			else if (pghost)
! 				pghost_str = pghost;
! 			else if (def->val)
! 				pghost_str = def->val;
  			else
! 				pghost_str = DEFAULT_PGSOCKET_DIR;
  		}
! 		else if (strcmp(def->keyword, "port") == 0)
  		{
! 			if (opt && opt->val)
! 				pgport_str = opt->val;
! 			else if (pgport)
! 				pgport_str = pgport;
! 			else if (def->val)
! 				pgport_str = def->val;
  		}
! 
! 		if (opt)
! 			opt++;
  	}
  
  	rv = PQpingParams(keywords, values, 1);
  
  	if (!quiet)
  	{
! 		printf("%s:%s - ", pghost_str, pgport_str);
  
  		switch (rv)
  		{
***************
*** 186,193 **** main(int argc, char **argv)
  		}
  	}
  
- 	PQconninfoFree(connect_options);
- 
  	exit(rv);
  }
  
--- 200,205 ----
#52Fujii Masao
masao.fujii@gmail.com
In reply to: Fujii Masao (#51)
Re: [PATCH] pg_isready (was: [WIP] pg_ping utility)

On Mon, Jun 3, 2013 at 2:14 AM, Fujii Masao <masao.fujii@gmail.com> wrote:

Sorry for the delay in responding to you.

On Mon, Feb 11, 2013 at 6:03 AM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Feb 8, 2013 at 1:07 PM, Phil Sorber <phil@omniti.com> wrote:

On Fri, Feb 8, 2013 at 12:46 PM, Fujii Masao <masao.fujii@gmail.com> wrote:

No maybe. But I think that all the client commands should follow the
same rule. Otherwise a user would get confused when specifying
options.

I would consider the rest of the apps using it as a consensus. I will
make sure it aligns in behavior.

I've done as you suggested, and made sure they align with other
command line utils. What I have found is that dbname is passed
(almost) last in the param array so that it clobbers all previous
values. I have made this patch as minimal as possible basing it off of
master and not off of my previous attempt. For the record I still like
the overall design of my previous attempt better, but I have not
included a new version based on that here so as not to confuse the
issue, however I would gladly do so upon request.

Updated patch attached.

Thanks! The patch basically looks good to me.

I updated the patch against current master and fixed some problems:

- Handle the hostaddr in the connection string properly.
- Remove the character 'V' from the third argument of getopt_long().
- Handle the error cases of PQconninfoParse() and PQconndefaults().
- etc...

Please see the attached patch.

Committed.

Regards,

--
Fujii Masao

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers