Include the first valid listen address in pg_ctl to improve server start
"wait" detection and add postmaster start time to help determine if the postmaster is actually using the specified data directory.
This commit is contained in:
parent
39c8dd6620
commit
30aeda4394
@ -117,8 +117,9 @@ last started with</entry>
|
||||
<row>
|
||||
<entry><filename>postmaster.pid</></entry>
|
||||
<entry>A lock file recording the current postmaster process id (PID),
|
||||
cluster data directory, port number, Unix domain socket directory,
|
||||
and shared memory segment ID</entry>
|
||||
postmaster start time, cluster data directory, port number, user-specified
|
||||
Unix domain socket directory, first valid listen_address host, and
|
||||
shared memory segment ID</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
|
@ -104,7 +104,7 @@ on_exit_reset(void)
|
||||
}
|
||||
|
||||
void
|
||||
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
||||
AddToLockFile(int target_line, const char *str)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -198,9 +198,17 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
|
||||
/* Register on-exit routine to detach new segment before deleting */
|
||||
on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
|
||||
|
||||
/* Record key and ID in lockfile for data directory. */
|
||||
RecordSharedMemoryInLockFile((unsigned long) memKey,
|
||||
(unsigned long) shmid);
|
||||
/*
|
||||
* Append record key and ID in lockfile for data directory. Format
|
||||
* to try to keep it the same length.
|
||||
*/
|
||||
{
|
||||
char line[32];
|
||||
|
||||
sprintf(line, "%9lu %9lu\n", (unsigned long) memKey,
|
||||
(unsigned long) shmid);
|
||||
AddToLockFile(LOCK_FILE_LINES, line);
|
||||
}
|
||||
|
||||
return memAddress;
|
||||
}
|
||||
|
@ -483,7 +483,8 @@ PostmasterMain(int argc, char *argv[])
|
||||
int status;
|
||||
char *userDoption = NULL;
|
||||
int i;
|
||||
|
||||
bool connection_line_output = false;
|
||||
|
||||
MyProcPid = PostmasterPid = getpid();
|
||||
|
||||
MyStartTime = time(NULL);
|
||||
@ -860,10 +861,22 @@ PostmasterMain(int argc, char *argv[])
|
||||
UnixSocketDir,
|
||||
ListenSocket, MAXLISTEN);
|
||||
else
|
||||
{
|
||||
status = StreamServerPort(AF_UNSPEC, curhost,
|
||||
(unsigned short) PostPortNumber,
|
||||
UnixSocketDir,
|
||||
ListenSocket, MAXLISTEN);
|
||||
/* must supply a valid listen_address for PQping() */
|
||||
if (!connection_line_output)
|
||||
{
|
||||
char line[MAXPGPATH + 2];
|
||||
|
||||
sprintf(line, "%s\n", curhost);
|
||||
AddToLockFile(LOCK_FILE_LINES - 1, line);
|
||||
connection_line_output = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == STATUS_OK)
|
||||
success++;
|
||||
else
|
||||
@ -880,6 +893,10 @@ PostmasterMain(int argc, char *argv[])
|
||||
pfree(rawstring);
|
||||
}
|
||||
|
||||
/* Supply an empty listen_address line for PQping() */
|
||||
if (!connection_line_output)
|
||||
AddToLockFile(LOCK_FILE_LINES - 1, "\n");
|
||||
|
||||
#ifdef USE_BONJOUR
|
||||
/* Register for Bonjour only if we opened TCP socket(s) */
|
||||
if (enable_bonjour && ListenSocket[0] != PGINVALID_SOCKET)
|
||||
|
@ -46,7 +46,20 @@
|
||||
|
||||
|
||||
#define DIRECTORY_LOCK_FILE "postmaster.pid"
|
||||
|
||||
/*
|
||||
* The lock file contents are:
|
||||
*
|
||||
* line #
|
||||
* 1 pid
|
||||
* 2 postmaster start time
|
||||
* 3 data directory
|
||||
* 4 port #
|
||||
* 5 user-specified socket directory
|
||||
* (the lines below are added later)
|
||||
* 6 first valid listen_address
|
||||
* 7 shared memory key
|
||||
*/
|
||||
|
||||
ProcessingMode Mode = InitProcessing;
|
||||
|
||||
/* Note: we rely on this to initialize as zeroes */
|
||||
@ -678,7 +691,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
||||
bool isDDLock, const char *refName)
|
||||
{
|
||||
int fd;
|
||||
char buffer[MAXPGPATH * 2 + 256];
|
||||
char buffer[MAXPGPATH * 3 + 256];
|
||||
int ntries;
|
||||
int len;
|
||||
int encoded_pid;
|
||||
@ -845,11 +858,10 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
||||
if (isDDLock)
|
||||
{
|
||||
char *ptr = buffer;
|
||||
unsigned long id1,
|
||||
id2;
|
||||
unsigned long id1, id2;
|
||||
int lineno;
|
||||
|
||||
for (lineno = 1; lineno <= 4; lineno++)
|
||||
for (lineno = 1; lineno <= LOCK_FILE_LINES - 1; lineno++)
|
||||
{
|
||||
if ((ptr = strchr(ptr, '\n')) == NULL)
|
||||
{
|
||||
@ -893,9 +905,10 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
||||
/*
|
||||
* Successfully created the file, now fill it.
|
||||
*/
|
||||
snprintf(buffer, sizeof(buffer), "%d\n%s\n%d\n%s\n",
|
||||
snprintf(buffer, sizeof(buffer), "%d\n%ld\n%s\n%d\n%s\n",
|
||||
amPostmaster ? (int) my_pid : -((int) my_pid),
|
||||
DataDir, PostPortNumber, UnixSocketDir);
|
||||
(long) MyStartTime, DataDir, PostPortNumber,
|
||||
UnixSocketDir);
|
||||
errno = 0;
|
||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
|
||||
{
|
||||
@ -1004,24 +1017,19 @@ TouchSocketLockFile(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Append information about a shared memory segment to the data directory
|
||||
* lock file.
|
||||
*
|
||||
* This may be called multiple times in the life of a postmaster, if we
|
||||
* delete and recreate shmem due to backend crash. Therefore, be prepared
|
||||
* to overwrite existing information. (As of 7.1, a postmaster only creates
|
||||
* one shm seg at a time; but for the purposes here, if we did have more than
|
||||
* one then any one of them would do anyway.)
|
||||
* Add lines to the data directory lock file. This erases all following
|
||||
* lines, but that is OK because lines are added in order.
|
||||
*/
|
||||
void
|
||||
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
||||
AddToLockFile(int target_line, const char *str)
|
||||
{
|
||||
int fd;
|
||||
int len;
|
||||
int lineno;
|
||||
char *ptr;
|
||||
char buffer[MAXPGPATH * 2 + 256];
|
||||
char buffer[MAXPGPATH * 3 + 256];
|
||||
|
||||
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
|
||||
if (fd < 0)
|
||||
@ -1048,7 +1056,7 @@ RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
||||
* Skip over first four lines (PID, pgdata, portnum, socketdir).
|
||||
*/
|
||||
ptr = buffer;
|
||||
for (lineno = 1; lineno <= 4; lineno++)
|
||||
for (lineno = 1; lineno < target_line; lineno++)
|
||||
{
|
||||
if ((ptr = strchr(ptr, '\n')) == NULL)
|
||||
{
|
||||
@ -1059,11 +1067,7 @@ RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append key information. Format to try to keep it the same length
|
||||
* always (trailing junk won't hurt, but might confuse humans).
|
||||
*/
|
||||
sprintf(ptr, "%9lu %9lu\n", id1, id2);
|
||||
strlcat(buffer, str, sizeof(buffer));
|
||||
|
||||
/*
|
||||
* And rewrite the data. Since we write in a single kernel call, this
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <locale.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@ -138,6 +139,7 @@ static void read_post_opts(void);
|
||||
|
||||
static PGPing test_postmaster_connection(bool);
|
||||
static bool postmaster_is_alive(pid_t pid);
|
||||
static time_t start_time;
|
||||
|
||||
static char postopts_file[MAXPGPATH];
|
||||
static char pid_file[MAXPGPATH];
|
||||
@ -404,13 +406,13 @@ static PGPing
|
||||
test_postmaster_connection(bool do_checkpoint)
|
||||
{
|
||||
int portnum = 0;
|
||||
char socket_dir[MAXPGPATH];
|
||||
char host_str[MAXPGPATH];
|
||||
char connstr[MAXPGPATH + 256];
|
||||
PGPing ret = PQPING_OK; /* assume success for wait == zero */
|
||||
char **optlines;
|
||||
int i;
|
||||
|
||||
socket_dir[0] = '\0';
|
||||
host_str[0] = '\0';
|
||||
connstr[0] = '\0';
|
||||
|
||||
for (i = 0; i < wait_seconds; i++)
|
||||
@ -425,13 +427,14 @@ test_postmaster_connection(bool do_checkpoint)
|
||||
* 0 lock file created but status not written
|
||||
* 2 pre-9.1 server, shared memory not created
|
||||
* 3 pre-9.1 server, shared memory created
|
||||
* 4 9.1+ server, shared memory not created
|
||||
* 5 9.1+ server, shared memory created
|
||||
* 5 9.1+ server, listen host not created
|
||||
* 6 9.1+ server, shared memory not created
|
||||
* 7 9.1+ server, shared memory created
|
||||
*
|
||||
* For pre-9.1 Unix servers, we grab the port number from the
|
||||
* shmem key (first value on line 3). Pre-9.1 Win32 has no
|
||||
* written shmem key, so we fail. 9.1+ writes both the port
|
||||
* number and socket address in the file for us to use.
|
||||
* written shmem key, so we fail. 9.1+ writes connection
|
||||
* information in the file for us to use.
|
||||
* (PG_VERSION could also have told us the major version.)
|
||||
*/
|
||||
|
||||
@ -439,7 +442,10 @@ test_postmaster_connection(bool do_checkpoint)
|
||||
if ((optlines = readfile(pid_file)) != NULL &&
|
||||
optlines[0] != NULL &&
|
||||
optlines[1] != NULL &&
|
||||
optlines[2] != NULL)
|
||||
optlines[2] != NULL &&
|
||||
/* pre-9.1 server or listen_address line is present? */
|
||||
(optlines[3] == NULL ||
|
||||
optlines[5] != NULL))
|
||||
{
|
||||
/* A 3-line file? */
|
||||
if (optlines[3] == NULL)
|
||||
@ -459,31 +465,53 @@ test_postmaster_connection(bool do_checkpoint)
|
||||
return PQPING_NO_ATTEMPT;
|
||||
}
|
||||
}
|
||||
else /* 9.1+ server */
|
||||
else
|
||||
{
|
||||
portnum = atoi(optlines[2]);
|
||||
|
||||
/* Get socket directory, if specified. */
|
||||
if (optlines[3][0] != '\n')
|
||||
/*
|
||||
* Easy check to see if we are looking at the right
|
||||
* data directory: Is the postmaster older than this
|
||||
* execution of pg_ctl? Subtract 2 seconds to account
|
||||
* for possible clock skew between pg_ctl and the
|
||||
* postmaster.
|
||||
*/
|
||||
if (atol(optlines[1]) < start_time - 2)
|
||||
{
|
||||
/*
|
||||
* While unix_socket_directory can accept relative
|
||||
* directories, libpq's host must have a leading slash
|
||||
* to indicate a socket directory.
|
||||
*/
|
||||
if (optlines[3][0] != '/')
|
||||
{
|
||||
write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
|
||||
progname);
|
||||
return PQPING_NO_ATTEMPT;
|
||||
}
|
||||
strlcpy(socket_dir, optlines[3], MAXPGPATH);
|
||||
/* remove newline */
|
||||
if (strchr(socket_dir, '\n') != NULL)
|
||||
*strchr(socket_dir, '\n') = '\0';
|
||||
write_stderr(_("%s: this data directory is running an older postmaster\n"),
|
||||
progname);
|
||||
return PQPING_NO_ATTEMPT;
|
||||
}
|
||||
}
|
||||
|
||||
portnum = atoi(optlines[3]);
|
||||
|
||||
/*
|
||||
* Determine the proper host string to use.
|
||||
*/
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
/*
|
||||
* Use socket directory, if specified. We assume if we
|
||||
* have unix sockets, the server does too because we
|
||||
* just started the postmaster.
|
||||
*/
|
||||
/*
|
||||
* While unix_socket_directory can accept relative
|
||||
* directories, libpq's host must have a leading slash
|
||||
* to indicate a socket directory.
|
||||
*/
|
||||
if (optlines[4][0] != '\n' && optlines[4][0] != '/')
|
||||
{
|
||||
write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
|
||||
progname);
|
||||
return PQPING_NO_ATTEMPT;
|
||||
}
|
||||
strlcpy(host_str, optlines[4], sizeof(host_str));
|
||||
#else
|
||||
strlcpy(host_str, optlines[5], sizeof(host_str));
|
||||
#endif
|
||||
/* remove newline */
|
||||
if (strchr(host_str, '\n') != NULL)
|
||||
*strchr(host_str, '\n') = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to set connect_timeout otherwise on Windows the
|
||||
* Service Control Manager (SCM) will probably timeout first.
|
||||
@ -491,9 +519,9 @@ test_postmaster_connection(bool do_checkpoint)
|
||||
snprintf(connstr, sizeof(connstr),
|
||||
"dbname=postgres port=%d connect_timeout=5", portnum);
|
||||
|
||||
if (socket_dir[0] != '\0')
|
||||
if (host_str[0] != '\0')
|
||||
snprintf(connstr + strlen(connstr), sizeof(connstr) - strlen(connstr),
|
||||
" host='%s'", socket_dir);
|
||||
" host='%s'", host_str);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1756,6 +1784,7 @@ main(int argc, char **argv)
|
||||
|
||||
progname = get_progname(argv[0]);
|
||||
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
|
||||
start_time = time(NULL);
|
||||
|
||||
/*
|
||||
* save argv[0] so do_start() can look for the postmaster if necessary. we
|
||||
|
@ -348,11 +348,11 @@ extern PGDLLIMPORT bool process_shared_preload_libraries_in_progress;
|
||||
extern char *shared_preload_libraries_string;
|
||||
extern char *local_preload_libraries_string;
|
||||
|
||||
#define LOCK_FILE_LINES 7
|
||||
extern void CreateDataDirLockFile(bool amPostmaster);
|
||||
extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster);
|
||||
extern void TouchSocketLockFile(void);
|
||||
extern void RecordSharedMemoryInLockFile(unsigned long id1,
|
||||
unsigned long id2);
|
||||
extern void AddToLockFile(int target_line, const char *str);
|
||||
extern void ValidatePgVersion(const char *path);
|
||||
extern void process_shared_preload_libraries(void);
|
||||
extern void process_local_preload_libraries(void);
|
||||
|
Loading…
Reference in New Issue
Block a user