new-pg_ctl-wait-implementation.patch
text/x-diff
Filename: new-pg_ctl-wait-implementation.patch
Type: text/x-diff
Part: 0
Message:
Re: Reducing pg_ctl's reaction time
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/postmaster/postmaster.c | 0 | 0 |
| src/backend/utils/init/miscinit.c | 0 | 0 |
| src/bin/pg_ctl/Makefile | 0 | 0 |
| src/bin/pg_ctl/pg_ctl.c | 0 | 0 |
| src/include/miscadmin.h | 0 | 0 |
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 2874f63..38f534f 100644
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
*************** PostmasterMain(int argc, char *argv[])
*** 1341,1346 ****
--- 1341,1354 ----
#endif
/*
+ * Report postmaster status in the postmaster.pid file, to allow pg_ctl to
+ * see what's happening. Note that all strings written to the status line
+ * must be the same length, per comments for AddToDataDirLockFile(). We
+ * currently make them all 8 bytes, padding with spaces.
+ */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "starting");
+
+ /*
* We're ready to rock and roll...
*/
StartupPID = StartupDataBase();
*************** pmdie(SIGNAL_ARGS)
*** 2608,2613 ****
--- 2616,2624 ----
Shutdown = SmartShutdown;
ereport(LOG,
(errmsg("received smart shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "stopping");
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
*************** pmdie(SIGNAL_ARGS)
*** 2663,2668 ****
--- 2674,2682 ----
Shutdown = FastShutdown;
ereport(LOG,
(errmsg("received fast shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "stopping");
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
*************** pmdie(SIGNAL_ARGS)
*** 2727,2732 ****
--- 2741,2749 ----
Shutdown = ImmediateShutdown;
ereport(LOG,
(errmsg("received immediate shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "stopping");
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
*************** reaper(SIGNAL_ARGS)
*** 2872,2877 ****
--- 2889,2896 ----
ereport(LOG,
(errmsg("database system is ready to accept connections")));
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "ready ");
#ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
*************** sigusr1_handler(SIGNAL_ARGS)
*** 5005,5014 ****
if (XLogArchivingAlways())
PgArchPID = pgarch_start();
! #ifdef USE_SYSTEMD
if (!EnableHotStandby)
sd_notify(0, "READY=1");
#endif
pmState = PM_RECOVERY;
}
--- 5024,5041 ----
if (XLogArchivingAlways())
PgArchPID = pgarch_start();
! /*
! * If we aren't planning to enter hot standby mode later, treat
! * RECOVERY_STARTED as meaning we're out of startup, and report status
! * accordingly.
! */
if (!EnableHotStandby)
+ {
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "standby ");
+ #ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
+ }
pmState = PM_RECOVERY;
}
*************** sigusr1_handler(SIGNAL_ARGS)
*** 5024,5029 ****
--- 5051,5058 ----
ereport(LOG,
(errmsg("database system is ready to accept read only connections")));
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, "ready ");
#ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 49a6afa..216bcc7 100644
*** a/src/backend/utils/init/miscinit.c
--- b/src/backend/utils/init/miscinit.c
*************** TouchSocketLockFiles(void)
*** 1149,1156 ****
*
* Note: because we don't truncate the file, if we were to rewrite a line
* with less data than it had before, there would be garbage after the last
! * line. We don't ever actually do that, so not worth adding another kernel
! * call to cover the possibility.
*/
void
AddToDataDirLockFile(int target_line, const char *str)
--- 1149,1157 ----
*
* Note: because we don't truncate the file, if we were to rewrite a line
* with less data than it had before, there would be garbage after the last
! * line. While we could fix that by adding a truncate call, that would make
! * the file update non-atomic, which we'd rather avoid. Therefore, callers
! * should endeavor never to shorten a line once it's been written.
*/
void
AddToDataDirLockFile(int target_line, const char *str)
*************** AddToDataDirLockFile(int target_line, co
*** 1193,1211 ****
srcptr = srcbuffer;
for (lineno = 1; lineno < target_line; lineno++)
{
! if ((srcptr = strchr(srcptr, '\n')) == NULL)
! {
! elog(LOG, "incomplete data in \"%s\": found only %d newlines while trying to add line %d",
! DIRECTORY_LOCK_FILE, lineno - 1, target_line);
! close(fd);
! return;
! }
! srcptr++;
}
memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
destptr = destbuffer + (srcptr - srcbuffer);
/*
* Write or rewrite the target line.
*/
snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
--- 1194,1219 ----
srcptr = srcbuffer;
for (lineno = 1; lineno < target_line; lineno++)
{
! char *eol = strchr(srcptr, '\n');
!
! if (eol == NULL)
! break; /* not enough lines in file yet */
! srcptr = eol + 1;
}
memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
destptr = destbuffer + (srcptr - srcbuffer);
/*
+ * Fill in any missing lines before the target line, in case lines are
+ * added to the file out of order.
+ */
+ for (; lineno < target_line; lineno++)
+ {
+ if (destptr < destbuffer + sizeof(destbuffer))
+ *destptr++ = '\n';
+ }
+
+ /*
* Write or rewrite the target line.
*/
snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
diff --git a/src/bin/pg_ctl/Makefile b/src/bin/pg_ctl/Makefile
index f5ec088..46f30bd 100644
*** a/src/bin/pg_ctl/Makefile
--- b/src/bin/pg_ctl/Makefile
*************** subdir = src/bin/pg_ctl
*** 16,29 ****
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
- override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
-
OBJS= pg_ctl.o $(WIN32RES)
all: pg_ctl
! pg_ctl: $(OBJS) | submake-libpq submake-libpgport
! $(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
install: all installdirs
$(INSTALL_PROGRAM) pg_ctl$(X) '$(DESTDIR)$(bindir)/pg_ctl$(X)'
--- 16,27 ----
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
OBJS= pg_ctl.o $(WIN32RES)
all: pg_ctl
! pg_ctl: $(OBJS) | submake-libpgport
! $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
install: all installdirs
$(INSTALL_PROGRAM) pg_ctl$(X) '$(DESTDIR)$(bindir)/pg_ctl$(X)'
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index ad2a16f..81b276c 100644
*** a/src/bin/pg_ctl/pg_ctl.c
--- b/src/bin/pg_ctl/pg_ctl.c
***************
*** 34,42 ****
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
#include "getopt_long.h"
- #include "libpq-fe.h"
#include "miscadmin.h"
- #include "pqexpbuffer.h"
/* PID can be negative for standalone backend */
typedef long pgpid_t;
--- 34,40 ----
*************** typedef enum
*** 49,54 ****
--- 47,58 ----
IMMEDIATE_MODE
} ShutdownMode;
+ typedef enum
+ {
+ POSTMASTER_READY,
+ POSTMASTER_STILL_STARTING,
+ POSTMASTER_FAILED
+ } WaitPMResult;
typedef enum
{
*************** static int CreateRestrictedProcess(char
*** 147,158 ****
#endif
static pgpid_t get_pgpid(bool is_status_request);
! static char **readfile(const char *path);
static void free_readfile(char **optlines);
static pgpid_t start_postmaster(void);
static void read_post_opts(void);
! static PGPing test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint);
static bool postmaster_is_alive(pid_t pid);
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
--- 151,162 ----
#endif
static pgpid_t get_pgpid(bool is_status_request);
! static char **readfile(const char *path, int *numlines);
static void free_readfile(char **optlines);
static pgpid_t start_postmaster(void);
static void read_post_opts(void);
! static WaitPMResult wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint);
static bool postmaster_is_alive(pid_t pid);
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
*************** get_pgpid(bool is_status_request)
*** 304,312 ****
/*
* get the lines from a text file - return NULL if file can't be opened
*/
static char **
! readfile(const char *path)
{
int fd;
int nlines;
--- 308,319 ----
/*
* get the lines from a text file - return NULL if file can't be opened
+ *
+ * *numlines is set to the number of line pointers returned; there is
+ * also an additional NULL pointer after the last real line.
*/
static char **
! readfile(const char *path, int *numlines)
{
int fd;
int nlines;
*************** readfile(const char *path)
*** 318,323 ****
--- 325,332 ----
int len;
struct stat statbuf;
+ *numlines = 0; /* in case of failure or empty file */
+
/*
* Slurp the file into memory.
*
*************** readfile(const char *path)
*** 367,372 ****
--- 376,382 ----
/* set up the result buffer */
result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
+ *numlines = nlines;
/* now split the buffer into lines */
linebegin = buffer;
*************** start_postmaster(void)
*** 509,515 ****
/*
! * Find the pgport and try a connection
*
* On Unix, pm_pid is the PID of the just-launched postmaster. On Windows,
* it may be the PID of an ancestor shell process, so we can't check the
--- 519,525 ----
/*
! * Wait for the postmaster to become ready.
*
* On Unix, pm_pid is the PID of the just-launched postmaster. On Windows,
* it may be the PID of an ancestor shell process, so we can't check the
*************** start_postmaster(void)
*** 522,689 ****
* Note that the checkpoint parameter enables a Windows service control
* manager checkpoint, it's got nothing to do with database checkpoints!!
*/
! static PGPing
! test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint)
{
- PGPing ret = PQPING_NO_RESPONSE;
- char connstr[MAXPGPATH * 2 + 256];
int i;
- /* if requested wait time is zero, return "still starting up" code */
- if (wait_seconds <= 0)
- return PQPING_REJECT;
-
- connstr[0] = '\0';
-
for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++)
{
! /* Do we need a connection string? */
! if (connstr[0] == '\0')
! {
! /*----------
! * The number of lines in postmaster.pid tells us several things:
! *
! * # of lines
! * 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
! * 5 9.1+ server, ports not opened
! * 6 9.1+ server, shared memory not created
! * 7 9.1+ server, shared memory created
! *
! * This code does not support pre-9.1 servers. On Unix machines
! * we could consider extracting the port number from the shmem
! * key, but that (a) is not robust, and (b) doesn't help with
! * finding out the socket directory. And it wouldn't work anyway
! * on Windows.
! *
! * If we see less than 6 lines in postmaster.pid, just keep
! * waiting.
! *----------
! */
! char **optlines;
! /* Try to read the postmaster.pid file */
! if ((optlines = readfile(pid_file)) != NULL &&
! optlines[0] != NULL &&
! optlines[1] != NULL &&
! optlines[2] != NULL)
! {
! if (optlines[3] == NULL)
! {
! /* File is exactly three lines, must be pre-9.1 */
! write_stderr(_("\n%s: -w option is not supported when starting a pre-9.1 server\n"),
! progname);
! return PQPING_NO_ATTEMPT;
! }
! else if (optlines[4] != NULL &&
! optlines[5] != NULL)
! {
! /* File is complete enough for us, parse it */
! pgpid_t pmpid;
! time_t pmstart;
! /*
! * Make sanity checks. If it's for the wrong PID, or the
! * recorded start time is before pg_ctl started, then
! * either we are looking at the wrong data directory, or
! * this is a pre-existing pidfile that hasn't (yet?) been
! * overwritten by our child postmaster. Allow 2 seconds
! * slop for possible cross-process clock skew.
! */
! pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
! pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
! if (pmstart >= start_time - 2 &&
#ifndef WIN32
! pmpid == pm_pid
#else
! /* Windows can only reject standalone-backend PIDs */
! pmpid > 0
#endif
! )
! {
! /*
! * OK, seems to be a valid pidfile from our child.
! */
! int portnum;
! char *sockdir;
! char *hostaddr;
! char host_str[MAXPGPATH];
!
! /*
! * Extract port number and host string to use. Prefer
! * using Unix socket if available.
! */
! portnum = atoi(optlines[LOCK_FILE_LINE_PORT - 1]);
! sockdir = optlines[LOCK_FILE_LINE_SOCKET_DIR - 1];
! hostaddr = optlines[LOCK_FILE_LINE_LISTEN_ADDR - 1];
!
! /*
! * While unix_socket_directories can accept relative
! * directories, libpq's host parameter must have a
! * leading slash to indicate a socket directory. So,
! * ignore sockdir if it's relative, and try to use TCP
! * instead.
! */
! if (sockdir[0] == '/')
! strlcpy(host_str, sockdir, sizeof(host_str));
! else
! strlcpy(host_str, hostaddr, sizeof(host_str));
!
! /* remove trailing newline */
! if (strchr(host_str, '\n') != NULL)
! *strchr(host_str, '\n') = '\0';
!
! /* Fail if couldn't get either sockdir or host addr */
! if (host_str[0] == '\0')
! {
! write_stderr(_("\n%s: -w option cannot use a relative socket directory specification\n"),
! progname);
! return PQPING_NO_ATTEMPT;
! }
!
! /*
! * Map listen-only addresses to counterparts usable
! * for establishing a connection. connect() to "::"
! * or "0.0.0.0" is not portable to OpenBSD 5.0 or to
! * Windows Server 2008, and connect() to "::" is
! * additionally not portable to NetBSD 6.0. (Cygwin
! * does handle both addresses, though.)
! */
! if (strcmp(host_str, "*") == 0)
! strcpy(host_str, "localhost");
! else if (strcmp(host_str, "0.0.0.0") == 0)
! strcpy(host_str, "127.0.0.1");
! else if (strcmp(host_str, "::") == 0)
! strcpy(host_str, "::1");
! /*
! * We need to set connect_timeout otherwise on Windows
! * the Service Control Manager (SCM) will probably
! * timeout first.
! */
! snprintf(connstr, sizeof(connstr),
! "dbname=postgres port=%d host='%s' connect_timeout=5",
! portnum, host_str);
! }
}
}
-
- /*
- * Free the results of readfile.
- *
- * This is safe to call even if optlines is NULL.
- */
- free_readfile(optlines);
}
! /* If we have a connection string, ping the server */
! if (connstr[0] != '\0')
! {
! ret = PQping(connstr);
! if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT)
! break;
! }
/*
* Check whether the child postmaster process is still alive. This
--- 532,599 ----
* Note that the checkpoint parameter enables a Windows service control
* manager checkpoint, it's got nothing to do with database checkpoints!!
*/
! static WaitPMResult
! wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint)
{
int i;
for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++)
{
! char **optlines;
! int numlines;
! /*
! * Try to read the postmaster.pid file. If it's not valid, or if the
! * status line isn't there yet, just keep waiting.
! */
! if ((optlines = readfile(pid_file, &numlines)) != NULL &&
! numlines >= LOCK_FILE_LINE_PM_STATUS)
! {
! /* File is complete enough for us, parse it */
! pgpid_t pmpid;
! time_t pmstart;
! /*
! * Make sanity checks. If it's for the wrong PID, or the recorded
! * start time is before pg_ctl started, then either we are looking
! * at the wrong data directory, or this is a pre-existing pidfile
! * that hasn't (yet?) been overwritten by our child postmaster.
! * Allow 2 seconds slop for possible cross-process clock skew.
! */
! pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
! pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
! if (pmstart >= start_time - 2 &&
#ifndef WIN32
! pmpid == pm_pid
#else
! /* Windows can only reject standalone-backend PIDs */
! pmpid > 0
#endif
! )
! {
! /*
! * OK, seems to be a valid pidfile from our child. Check the
! * status line (this assumes a v10 or later server).
! */
! char *pmstatus = optlines[LOCK_FILE_LINE_PM_STATUS - 1];
! /* status line may be blank-padded */
! if (strncmp(pmstatus, "ready", 5) == 0 ||
! strncmp(pmstatus, "standby", 7) == 0)
! {
! /* postmaster is done starting up */
! free_readfile(optlines);
! return POSTMASTER_READY;
}
}
}
! /*
! * Free the results of readfile.
! *
! * This is safe to call even if optlines is NULL.
! */
! free_readfile(optlines);
/*
* Check whether the child postmaster process is still alive. This
*************** test_postmaster_connection(pgpid_t pm_pi
*** 697,710 ****
int exitstatus;
if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
! return PQPING_NO_RESPONSE;
}
#else
if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
! return PQPING_NO_RESPONSE;
#endif
! /* No response, or startup still in process; wait */
if (i % WAITS_PER_SEC == 0)
{
#ifdef WIN32
--- 607,620 ----
int exitstatus;
if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
! return POSTMASTER_FAILED;
}
#else
if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
! return POSTMASTER_FAILED;
#endif
! /* Startup still in process; wait, printing a dot once per second */
if (i % WAITS_PER_SEC == 0)
{
#ifdef WIN32
*************** test_postmaster_connection(pgpid_t pm_pi
*** 729,736 ****
pg_usleep(USEC_PER_SEC / WAITS_PER_SEC);
}
! /* return result of last call to PQping */
! return ret;
}
--- 639,646 ----
pg_usleep(USEC_PER_SEC / WAITS_PER_SEC);
}
! /* out of patience; report that postmaster is still starting up */
! return POSTMASTER_STILL_STARTING;
}
*************** read_post_opts(void)
*** 764,777 ****
if (ctl_command == RESTART_COMMAND)
{
char **optlines;
! optlines = readfile(postopts_file);
if (optlines == NULL)
{
write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
exit(1);
}
! else if (optlines[0] == NULL || optlines[1] != NULL)
{
write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
progname, postopts_file);
--- 674,688 ----
if (ctl_command == RESTART_COMMAND)
{
char **optlines;
+ int numlines;
! optlines = readfile(postopts_file, &numlines);
if (optlines == NULL)
{
write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
exit(1);
}
! else if (numlines != 1)
{
write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
progname, postopts_file);
*************** do_start(void)
*** 917,944 ****
{
print_msg(_("waiting for server to start..."));
! switch (test_postmaster_connection(pm_pid, false))
{
! case PQPING_OK:
print_msg(_(" done\n"));
print_msg(_("server started\n"));
break;
! case PQPING_REJECT:
print_msg(_(" stopped waiting\n"));
print_msg(_("server is still starting up\n"));
break;
! case PQPING_NO_RESPONSE:
print_msg(_(" stopped waiting\n"));
write_stderr(_("%s: could not start server\n"
"Examine the log output.\n"),
progname);
exit(1);
break;
- case PQPING_NO_ATTEMPT:
- print_msg(_(" failed\n"));
- write_stderr(_("%s: could not wait for server because of misconfiguration\n"),
- progname);
- exit(1);
}
}
else
--- 828,850 ----
{
print_msg(_("waiting for server to start..."));
! switch (wait_for_postmaster(pm_pid, false))
{
! case POSTMASTER_READY:
print_msg(_(" done\n"));
print_msg(_("server started\n"));
break;
! case POSTMASTER_STILL_STARTING:
print_msg(_(" stopped waiting\n"));
print_msg(_("server is still starting up\n"));
break;
! case POSTMASTER_FAILED:
print_msg(_(" stopped waiting\n"));
write_stderr(_("%s: could not start server\n"
"Examine the log output.\n"),
progname);
exit(1);
break;
}
}
else
*************** do_status(void)
*** 1319,1329 ****
{
char **optlines;
char **curr_line;
printf(_("%s: server is running (PID: %ld)\n"),
progname, pid);
! optlines = readfile(postopts_file);
if (optlines != NULL)
{
for (curr_line = optlines; *curr_line != NULL; curr_line++)
--- 1225,1236 ----
{
char **optlines;
char **curr_line;
+ int numlines;
printf(_("%s: server is running (PID: %ld)\n"),
progname, pid);
! optlines = readfile(postopts_file, &numlines);
if (optlines != NULL)
{
for (curr_line = optlines; *curr_line != NULL; curr_line++)
*************** pgwin32_ServiceMain(DWORD argc, LPTSTR *
*** 1634,1640 ****
if (do_wait)
{
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
! if (test_postmaster_connection(postmasterPID, true) != PQPING_OK)
{
write_eventlog(EVENTLOG_ERROR_TYPE, _("Timed out waiting for server startup\n"));
pgwin32_SetServiceStatus(SERVICE_STOPPED);
--- 1541,1547 ----
if (do_wait)
{
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
! if (wait_for_postmaster(postmasterPID, true) != POSTMASTER_READY)
{
write_eventlog(EVENTLOG_ERROR_TYPE, _("Timed out waiting for server startup\n"));
pgwin32_SetServiceStatus(SERVICE_STOPPED);
*************** pgwin32_ServiceMain(DWORD argc, LPTSTR *
*** 1655,1661 ****
{
/*
* status.dwCheckPoint can be incremented by
! * test_postmaster_connection(), so it might not start from 0.
*/
int maxShutdownCheckPoint = status.dwCheckPoint + 12;
--- 1562,1568 ----
{
/*
* status.dwCheckPoint can be incremented by
! * wait_for_postmaster(), so it might not start from 0.
*/
int maxShutdownCheckPoint = status.dwCheckPoint + 12;
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 21a7728..0a07a02 100644
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
*************** extern char *shared_preload_libraries_st
*** 432,438 ****
extern char *local_preload_libraries_string;
/*
! * As of 9.1, the contents of the data-directory lock file are:
*
* line #
* 1 postmaster PID (or negative of a standalone backend's PID)
--- 432,438 ----
extern char *local_preload_libraries_string;
/*
! * As of Postgres 10, the contents of the data-directory lock file are:
*
* line #
* 1 postmaster PID (or negative of a standalone backend's PID)
*************** extern char *local_preload_libraries_str
*** 441,452 ****
* 4 port number
* 5 first Unix socket directory path (empty if none)
* 6 first listen_address (IP address or "*"; empty if no TCP port)
! * 7 shared memory key (not present on Windows)
*
* Lines 6 and up are added via AddToDataDirLockFile() after initial file
! * creation.
*
! * The socket lock file, if used, has the same contents as lines 1-5.
*/
#define LOCK_FILE_LINE_PID 1
#define LOCK_FILE_LINE_DATA_DIR 2
--- 441,455 ----
* 4 port number
* 5 first Unix socket directory path (empty if none)
* 6 first listen_address (IP address or "*"; empty if no TCP port)
! * 7 shared memory key (empty on Windows)
! * 8 postmaster status ("starting", "stopping", "ready ", "standby ")
*
* Lines 6 and up are added via AddToDataDirLockFile() after initial file
! * creation; also, line 5 is initially empty and is changed after the first
! * Unix socket is opened.
*
! * Socket lock file(s), if used, have the same contents as lines 1-5, with
! * line 5 being their own directory.
*/
#define LOCK_FILE_LINE_PID 1
#define LOCK_FILE_LINE_DATA_DIR 2
*************** extern char *local_preload_libraries_str
*** 455,460 ****
--- 458,464 ----
#define LOCK_FILE_LINE_SOCKET_DIR 5
#define LOCK_FILE_LINE_LISTEN_ADDR 6
#define LOCK_FILE_LINE_SHMEM_KEY 7
+ #define LOCK_FILE_LINE_PM_STATUS 8
extern void CreateDataDirLockFile(bool amPostmaster);
extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster,