mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-17 19:30:00 +08:00
Add PQping and PQpingParams to libpq to allow detection of the server's
status, including a status where the server is running but refuses a postgres connection. Have pg_ctl use this new function. This fixes the case where pg_ctl reports that the server is not running (cannot connect) but in fact it is running.
This commit is contained in:
parent
212a1c7b0b
commit
afd7d9adca
@ -1511,6 +1511,74 @@ int PQbackendPID(const PGconn *conn);
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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">
|
<varlistentry id="libpq-pqconnectionneedspassword">
|
||||||
<term><function>PQconnectionNeedsPassword</function><indexterm><primary>PQconnectionNeedsPassword</></></term>
|
<term><function>PQconnectionNeedsPassword</function><indexterm><primary>PQconnectionNeedsPassword</></></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -136,7 +136,7 @@ static char **readfile(const char *path);
|
|||||||
static int start_postmaster(void);
|
static int start_postmaster(void);
|
||||||
static void read_post_opts(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 bool postmaster_is_alive(pid_t pid);
|
||||||
|
|
||||||
static char postopts_file[MAXPGPATH];
|
static char postopts_file[MAXPGPATH];
|
||||||
@ -400,11 +400,10 @@ start_postmaster(void)
|
|||||||
* Note that the checkpoint parameter enables a Windows service control
|
* Note that the checkpoint parameter enables a Windows service control
|
||||||
* manager checkpoint, it's got nothing to do with database checkpoints!!
|
* manager checkpoint, it's got nothing to do with database checkpoints!!
|
||||||
*/
|
*/
|
||||||
static bool
|
static PGPing
|
||||||
test_postmaster_connection(bool do_checkpoint)
|
test_postmaster_connection(bool do_checkpoint)
|
||||||
{
|
{
|
||||||
PGconn *conn;
|
PGPing ret = PQACCESS; /* assume success for zero wait */
|
||||||
bool success = false;
|
|
||||||
int i;
|
int i;
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
char *p;
|
char *p;
|
||||||
@ -508,18 +507,10 @@ test_postmaster_connection(bool do_checkpoint)
|
|||||||
|
|
||||||
for (i = 0; i < wait_seconds; i++)
|
for (i = 0; i < wait_seconds; i++)
|
||||||
{
|
{
|
||||||
if ((conn = PQconnectdb(connstr)) != NULL &&
|
if ((ret = PQping(connstr)) != PQNORESPONSE)
|
||||||
(PQstatus(conn) == CONNECTION_OK ||
|
return ret;
|
||||||
PQconnectionNeedsPassword(conn)))
|
|
||||||
{
|
|
||||||
PQfinish(conn);
|
|
||||||
success = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
if (do_checkpoint)
|
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)
|
if (do_wait)
|
||||||
{
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
print_msg(_("waiting for server to start..."));
|
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"
|
write_stderr(_("%s: could not start server\n"
|
||||||
"Examine the log output.\n"),
|
"Examine the log output.\n"),
|
||||||
@ -759,6 +753,9 @@ do_start(void)
|
|||||||
{
|
{
|
||||||
print_msg(_(" done\n"));
|
print_msg(_(" done\n"));
|
||||||
print_msg(_("server started\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
|
else
|
||||||
|
@ -157,3 +157,5 @@ PQescapeLiteral 154
|
|||||||
PQescapeIdentifier 155
|
PQescapeIdentifier 155
|
||||||
PQconnectdbParams 156
|
PQconnectdbParams 156
|
||||||
PQconnectStartParams 157
|
PQconnectStartParams 157
|
||||||
|
PQping 158
|
||||||
|
PQpingParams 159
|
||||||
|
@ -285,6 +285,7 @@ static bool connectOptions1(PGconn *conn, const char *conninfo);
|
|||||||
static bool connectOptions2(PGconn *conn);
|
static bool connectOptions2(PGconn *conn);
|
||||||
static int connectDBStart(PGconn *conn);
|
static int connectDBStart(PGconn *conn);
|
||||||
static int connectDBComplete(PGconn *conn);
|
static int connectDBComplete(PGconn *conn);
|
||||||
|
static PGPing internal_ping(PGconn *conn);
|
||||||
static PGconn *makeEmptyPGconn(void);
|
static PGconn *makeEmptyPGconn(void);
|
||||||
static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
|
static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
|
||||||
static void freePGconn(PGconn *conn);
|
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
|
* PQconnectdb
|
||||||
*
|
*
|
||||||
@ -408,6 +423,18 @@ PQconnectdb(const char *conninfo)
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGPing
|
||||||
|
PQping(const char *conninfo)
|
||||||
|
{
|
||||||
|
PGconn *conn = PQconnectStart(conninfo);
|
||||||
|
PGPing ret;
|
||||||
|
|
||||||
|
ret = internal_ping(conn);
|
||||||
|
PQfinish(conn);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PQconnectStartParams
|
* PQconnectStartParams
|
||||||
*
|
*
|
||||||
@ -2513,6 +2540,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
|
* makeEmptyPGconn
|
||||||
* - create a PGconn data structure with (as yet) no interesting data
|
* - create a PGconn data structure with (as yet) no interesting data
|
||||||
|
@ -107,6 +107,13 @@ typedef enum
|
|||||||
PQERRORS_VERBOSE /* all the facts, ma'am */
|
PQERRORS_VERBOSE /* all the facts, ma'am */
|
||||||
} PGVerbosity;
|
} PGVerbosity;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PQACCESS, /* connected to server */
|
||||||
|
PQREJECT, /* server rejected access */
|
||||||
|
PQNORESPONSE /* server did not respond */
|
||||||
|
} PGPing;
|
||||||
|
|
||||||
/* PGconn encapsulates a connection to the backend.
|
/* PGconn encapsulates a connection to the backend.
|
||||||
* The contents of this struct are not supposed to be known to applications.
|
* 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 PQsetnonblocking(PGconn *conn, int arg);
|
||||||
extern int PQisnonblocking(const PGconn *conn);
|
extern int PQisnonblocking(const PGconn *conn);
|
||||||
extern int PQisthreadsafe(void);
|
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) */
|
/* Force the write buffer to be written (or at least try) */
|
||||||
extern int PQflush(PGconn *conn);
|
extern int PQflush(PGconn *conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user