diff options
-rw-r--r-- | doc/src/sgml/libpq.sgml | 68 | ||||
-rw-r--r-- | src/bin/pg_ctl/pg_ctl.c | 29 | ||||
-rw-r--r-- | src/interfaces/libpq/exports.txt | 2 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 53 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-fe.h | 10 |
5 files changed, 146 insertions, 16 deletions
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index c95fc4fd64d..d2a48113157 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1511,6 +1511,74 @@ int PQbackendPID(const PGconn *conn); </listitem> </varlistentry> + <varlistentry id="libpq-pqpingparams"> + <term><function>PQpingParams</function><indexterm><primary>PQpingParams</></></term> + <listitem> + <para> + <function>PQpingParams</function> indicates the status of the + server. The currently recognized parameter key words are the + same as <function>PQconnectParams</>. + +<synopsis> +PGPing PQpingParams(const char **keywords, const char **values, int expand_dbname); +</synopsis> + + It returns one of the following values: + + <variablelist> + <varlistentry id="libpq-pqpingparams-pqaccess"> + <term><literal>PQACCESS</literal></term> + <listitem> + <para> + The server is running and allows access. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqpingparams-pqreject"> + <term><literal>PQREJECT</literal></term> + <listitem> + <para> + The server is running but rejected a connection request. + </para> + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqpingparams-pqnoresponse"> + <term><literal>PQNORESPONSE</literal></term> + <listitem> + <para> + The server did not respond. + </para> + </listitem> + </varlistentry> + </variablelist> + + </para> + + </listitem> + </varlistentry> + + <varlistentry id="libpq-pqping"> + <term><function>PQping</function><indexterm><primary>PQping</></></term> + <listitem> + <para> + Returns the status of the server. + +<synopsis> +PGPing PQping(const char *conninfo); +</synopsis> + </para> + + <para> + This function uses the same <literal>conninfo</literal> parameter + key words as <function>PQconnectdb</>. It returns the same + values as <function>PQpingParams</> above. + </para> + + </listitem> + </varlistentry> + <varlistentry id="libpq-pqconnectionneedspassword"> <term><function>PQconnectionNeedsPassword</function><indexterm><primary>PQconnectionNeedsPassword</></></term> <listitem> diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 14d36b5fac1..211e023c24d 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -136,7 +136,7 @@ static char **readfile(const char *path); static int start_postmaster(void); static void read_post_opts(void); -static bool test_postmaster_connection(bool); +static PGPing test_postmaster_connection(bool); static bool postmaster_is_alive(pid_t pid); static char postopts_file[MAXPGPATH]; @@ -400,11 +400,10 @@ start_postmaster(void) * Note that the checkpoint parameter enables a Windows service control * manager checkpoint, it's got nothing to do with database checkpoints!! */ -static bool +static PGPing test_postmaster_connection(bool do_checkpoint) { - PGconn *conn; - bool success = false; + PGPing ret = PQACCESS; /* assume success for zero wait */ int i; char portstr[32]; char *p; @@ -508,18 +507,10 @@ test_postmaster_connection(bool do_checkpoint) for (i = 0; i < wait_seconds; i++) { - if ((conn = PQconnectdb(connstr)) != NULL && - (PQstatus(conn) == CONNECTION_OK || - PQconnectionNeedsPassword(conn))) - { - PQfinish(conn); - success = true; - break; - } + if ((ret = PQping(connstr)) != PQNORESPONSE) + return ret; else { - PQfinish(conn); - #if defined(WIN32) if (do_checkpoint) { @@ -543,7 +534,8 @@ test_postmaster_connection(bool do_checkpoint) } } - return success; + /* value of last call to PQping */ + return ret; } @@ -746,9 +738,11 @@ do_start(void) if (do_wait) { + int status; + print_msg(_("waiting for server to start...")); - if (test_postmaster_connection(false) == false) + if ((status = test_postmaster_connection(false)) == PQNORESPONSE) { write_stderr(_("%s: could not start server\n" "Examine the log output.\n"), @@ -759,6 +753,9 @@ do_start(void) { print_msg(_(" done\n")); print_msg(_("server started\n")); + if (status == PQREJECT) + write_stderr(_("warning: could not connect, perhaps due to invalid authentication or\n" + "misconfiguration.\n")); } } else diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index ecbd54c8815..a6c73af52e8 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -157,3 +157,5 @@ PQescapeLiteral 154 PQescapeIdentifier 155 PQconnectdbParams 156 PQconnectStartParams 157 +PQping 158 +PQpingParams 159 diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 8011604e5cd..6593f21d55e 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -285,6 +285,7 @@ static bool connectOptions1(PGconn *conn, const char *conninfo); static bool connectOptions2(PGconn *conn); static int connectDBStart(PGconn *conn); static int connectDBComplete(PGconn *conn); +static PGPing internal_ping(PGconn *conn); static PGconn *makeEmptyPGconn(void); static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions); static void freePGconn(PGconn *conn); @@ -375,6 +376,20 @@ PQconnectdbParams(const char **keywords, } +PGPing +PQpingParams(const char **keywords, + const char **values, + int expand_dbname) +{ + PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname); + PGPing ret; + + ret = internal_ping(conn); + PQfinish(conn); + + return ret; +} + /* * PQconnectdb * @@ -408,6 +423,18 @@ PQconnectdb(const char *conninfo) return conn; } +PGPing +PQping(const char *conninfo) +{ + PGconn *conn = PQconnectStart(conninfo); + PGPing ret; + + ret = internal_ping(conn); + PQfinish(conn); + + return ret; +} + /* * PQconnectStartParams * @@ -2514,6 +2541,32 @@ error_return: /* + * internal_ping + * Determine if a server is running and if we can connect to it. + */ +PGPing +internal_ping(PGconn *conn) +{ + if (conn && conn->status != CONNECTION_BAD) + { + (void) connectDBComplete(conn); + + /* + * If the connection needs a password, we can consider the + * server as accepting connections. + */ + if (conn && (conn->status != CONNECTION_BAD || + PQconnectionNeedsPassword(conn))) + return PQACCESS; + else + return PQREJECT; + } + else + return PQNORESPONSE; +} + + +/* * makeEmptyPGconn * - create a PGconn data structure with (as yet) no interesting data */ diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index 659d82d74d8..d1a6dd413a5 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -107,6 +107,13 @@ typedef enum PQERRORS_VERBOSE /* all the facts, ma'am */ } PGVerbosity; +typedef enum +{ + PQACCESS, /* connected to server */ + PQREJECT, /* server rejected access */ + PQNORESPONSE /* server did not respond */ +} PGPing; + /* PGconn encapsulates a connection to the backend. * The contents of this struct are not supposed to be known to applications. */ @@ -403,6 +410,9 @@ extern int PQendcopy(PGconn *conn); extern int PQsetnonblocking(PGconn *conn, int arg); extern int PQisnonblocking(const PGconn *conn); extern int PQisthreadsafe(void); +extern PGPing PQping(const char *conninfo); +extern PGPing PQpingParams(const char **keywords, + const char **values, int expand_dbname); /* Force the write buffer to be written (or at least try) */ extern int PQflush(PGconn *conn); |