2007-02-08 23:16:19 +08:00
|
|
|
/*
|
2010-09-21 04:08:53 +08:00
|
|
|
* contrib/pg_standby/pg_standby.c
|
2008-05-17 09:28:26 +08:00
|
|
|
*
|
|
|
|
*
|
2007-02-08 23:16:19 +08:00
|
|
|
* pg_standby.c
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
2007-02-08 23:16:19 +08:00
|
|
|
* Production-ready example of how to create a Warm Standby
|
2007-11-16 05:14:46 +08:00
|
|
|
* database server using continuous archiving as a
|
2007-02-08 23:16:19 +08:00
|
|
|
* replication mechanism
|
|
|
|
*
|
|
|
|
* We separate the parameters for archive and nextWALfile
|
2007-11-16 05:14:46 +08:00
|
|
|
* so that we can check the archive exists, even if the
|
2007-02-08 23:16:19 +08:00
|
|
|
* WAL file doesn't (yet).
|
|
|
|
*
|
|
|
|
* This program will be executed once in full for each file
|
|
|
|
* requested by the warm standby server.
|
|
|
|
*
|
|
|
|
* It is designed to cater to a variety of needs, as well
|
|
|
|
* providing a customizable section.
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
|
|
|
* Original author: Simon Riggs simon@2ndquadrant.com
|
|
|
|
* Current maintainer: Simon Riggs
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/stat.h>
|
2009-05-15 04:31:09 +08:00
|
|
|
#include <fcntl.h>
|
2007-02-08 23:16:19 +08:00
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
2015-07-02 09:35:38 +08:00
|
|
|
#include "access/xlog_internal.h"
|
2019-10-23 11:56:22 +08:00
|
|
|
#include "pg_getopt.h"
|
2015-07-02 09:35:38 +08:00
|
|
|
|
2009-02-27 17:30:21 +08:00
|
|
|
const char *progname;
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
int WalSegSz = -1;
|
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
/* Options and defaults */
|
2007-11-16 05:14:46 +08:00
|
|
|
int sleeptime = 5; /* amount of time to sleep between file checks */
|
|
|
|
int waittime = -1; /* how long we have been waiting, -1 no wait
|
|
|
|
* yet */
|
|
|
|
int maxwaittime = 0; /* how long are we prepared to wait for? */
|
|
|
|
int keepfiles = 0; /* number of WAL files to keep, 0 keep all */
|
|
|
|
int maxretries = 3; /* number of retries on restore command */
|
|
|
|
bool debug = false; /* are we debugging? */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-22 03:18:54 +08:00
|
|
|
bool need_cleanup = false; /* do we need to remove files from
|
|
|
|
* archive? */
|
2007-09-27 06:36:30 +08:00
|
|
|
|
2009-11-04 20:51:30 +08:00
|
|
|
#ifndef WIN32
|
2007-09-27 06:36:30 +08:00
|
|
|
static volatile sig_atomic_t signaled = false;
|
2009-11-04 20:51:30 +08:00
|
|
|
#endif
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2007-11-16 05:14:46 +08:00
|
|
|
char *archiveLocation; /* where to find the archive? */
|
|
|
|
char *triggerPath; /* where to find the trigger file? */
|
|
|
|
char *xlogFilePath; /* where we are going to restore to */
|
|
|
|
char *nextWALFileName; /* the file we need to get from archive */
|
|
|
|
char *restartWALFileName; /* the file from which we can restart restore */
|
2017-05-18 04:31:56 +08:00
|
|
|
char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
|
2007-11-16 05:14:46 +08:00
|
|
|
char restoreCommand[MAXPGPATH]; /* run this to restore */
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-22 03:18:54 +08:00
|
|
|
char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
|
|
|
|
* from archive */
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
/*
|
|
|
|
* Two types of failover are supported (smart and fast failover).
|
|
|
|
*
|
|
|
|
* The content of the trigger file determines the type of failover. If the
|
|
|
|
* trigger file contains the word "smart" (or the file is empty), smart
|
|
|
|
* failover is chosen: pg_standby acts as cp or ln command itself, on
|
|
|
|
* successful completion all the available WAL records will be applied
|
|
|
|
* resulting in zero data loss. But, it might take a long time to finish
|
|
|
|
* recovery if there's a lot of unapplied WAL.
|
|
|
|
*
|
|
|
|
* On the other hand, if the trigger file contains the word "fast", the
|
|
|
|
* recovery is finished immediately even if unapplied WAL files remain. Any
|
|
|
|
* transactions in the unapplied WAL files are lost.
|
|
|
|
*
|
|
|
|
* An empty trigger file performs smart failover. SIGUSR or SIGINT triggers
|
|
|
|
* fast failover. A timeout causes fast failover (smart failover would have
|
|
|
|
* the same effect, since if the timeout is reached there is no unapplied WAL).
|
|
|
|
*/
|
|
|
|
#define NoFailover 0
|
|
|
|
#define SmartFailover 1
|
|
|
|
#define FastFailover 2
|
|
|
|
|
2009-06-11 22:49:15 +08:00
|
|
|
static int Failover = NoFailover;
|
2009-05-15 04:31:09 +08:00
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
#define RESTORE_COMMAND_COPY 0
|
|
|
|
#define RESTORE_COMMAND_LINK 1
|
2007-11-16 05:14:46 +08:00
|
|
|
int restoreCommandType;
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
#define XLOG_DATA 0
|
|
|
|
#define XLOG_HISTORY 1
|
2007-11-16 05:14:46 +08:00
|
|
|
int nextWALFileType;
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
#define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
|
2007-07-16 16:40:52 +08:00
|
|
|
snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
struct stat stat_buf;
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
static bool SetWALFileNameForCleanup(void);
|
|
|
|
static bool SetWALSegSize(void);
|
|
|
|
|
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
/* =====================================================================
|
|
|
|
*
|
|
|
|
* Customizable section
|
|
|
|
*
|
|
|
|
* =====================================================================
|
|
|
|
*
|
|
|
|
* Currently, this section assumes that the Archive is a locally
|
|
|
|
* accessible directory. If you want to make other assumptions,
|
|
|
|
* such as using a vendor-specific archive and access API, these
|
|
|
|
* routines are the ones you'll need to change. You're
|
2019-01-20 02:06:35 +08:00
|
|
|
* encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
|
2007-11-16 05:14:46 +08:00
|
|
|
* or personally to the current maintainer. Those changes may be
|
2007-02-08 23:16:19 +08:00
|
|
|
* folded in to later versions of this program.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2007-11-16 05:14:46 +08:00
|
|
|
* Initialize allows customized commands into the warm standby program.
|
2007-02-08 23:16:19 +08:00
|
|
|
*
|
2007-11-16 05:14:46 +08:00
|
|
|
* As an example, and probably the common case, we use either
|
|
|
|
* cp/ln commands on *nix, or copy/move command on Windows.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
CustomizableInitialize(void)
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, nextWALFileName);
|
|
|
|
switch (restoreCommandType)
|
|
|
|
{
|
|
|
|
case RESTORE_COMMAND_LINK:
|
2007-11-16 05:14:46 +08:00
|
|
|
SET_RESTORE_COMMAND("mklink", WALFilePath, xlogFilePath);
|
2008-12-16 05:11:54 +08:00
|
|
|
break;
|
2007-02-08 23:16:19 +08:00
|
|
|
case RESTORE_COMMAND_COPY:
|
|
|
|
default:
|
2007-11-16 05:14:46 +08:00
|
|
|
SET_RESTORE_COMMAND("copy", WALFilePath, xlogFilePath);
|
2007-02-08 23:16:19 +08:00
|
|
|
break;
|
2007-11-16 05:14:46 +08:00
|
|
|
}
|
2007-02-08 23:16:19 +08:00
|
|
|
#else
|
|
|
|
snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, nextWALFileName);
|
|
|
|
switch (restoreCommandType)
|
|
|
|
{
|
|
|
|
case RESTORE_COMMAND_LINK:
|
2007-11-16 05:14:46 +08:00
|
|
|
SET_RESTORE_COMMAND("ln -s -f", WALFilePath, xlogFilePath);
|
2007-02-08 23:16:19 +08:00
|
|
|
break;
|
|
|
|
case RESTORE_COMMAND_COPY:
|
|
|
|
default:
|
2007-11-16 05:14:46 +08:00
|
|
|
SET_RESTORE_COMMAND("cp", WALFilePath, xlogFilePath);
|
2007-02-08 23:16:19 +08:00
|
|
|
break;
|
2007-11-16 05:14:46 +08:00
|
|
|
}
|
2007-02-08 23:16:19 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
2007-11-16 05:14:46 +08:00
|
|
|
* This code assumes that archiveLocation is a directory You may wish to
|
|
|
|
* add code to check for tape libraries, etc.. So, since it is a
|
2010-05-15 17:31:57 +08:00
|
|
|
* directory, we use stat to test if it's accessible
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
|
|
|
if (stat(archiveLocation, &stat_buf) != 0)
|
|
|
|
{
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
2007-11-16 05:14:46 +08:00
|
|
|
exit(2);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CustomizableNextWALFileReady()
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
2007-02-08 23:16:19 +08:00
|
|
|
* Is the requested file ready yet?
|
|
|
|
*/
|
2007-11-16 05:14:46 +08:00
|
|
|
static bool
|
2015-08-15 23:25:00 +08:00
|
|
|
CustomizableNextWALFileReady(void)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
if (stat(WALFilePath, &stat_buf) == 0)
|
|
|
|
{
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
/*
|
|
|
|
* If we've not seen any WAL segments, we don't know the WAL segment
|
|
|
|
* size, which we need. If it looks like a WAL segment, determine size
|
|
|
|
* of segments for the cluster.
|
|
|
|
*/
|
|
|
|
if (WalSegSz == -1 && IsXLogFileName(nextWALFileName))
|
|
|
|
{
|
|
|
|
if (SetWALSegSize())
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Successfully determined WAL segment size. Can compute
|
|
|
|
* cleanup cutoff now.
|
|
|
|
*/
|
|
|
|
need_cleanup = SetWALFileNameForCleanup();
|
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
_("WAL segment size: %d \n"), WalSegSz);
|
|
|
|
fprintf(stderr, "Keep archive history: ");
|
|
|
|
|
|
|
|
if (need_cleanup)
|
|
|
|
fprintf(stderr, "%s and later\n",
|
|
|
|
exclusiveCleanupFileName);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "no cleanup required\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
/*
|
2018-07-01 21:10:08 +08:00
|
|
|
* Return only if it's the right size already.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
2018-07-01 21:10:08 +08:00
|
|
|
if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
|
2007-11-16 05:14:46 +08:00
|
|
|
{
|
2007-02-08 23:16:19 +08:00
|
|
|
#ifdef WIN32
|
2007-11-16 05:14:46 +08:00
|
|
|
|
|
|
|
/*
|
2008-12-16 06:13:02 +08:00
|
|
|
* Windows 'cp' sets the final file size before the copy is
|
2009-06-11 22:49:15 +08:00
|
|
|
* complete, and not yet ready to be opened by pg_standby. So we
|
|
|
|
* wait for sleeptime secs before attempting to restore. If that
|
|
|
|
* is not enough, we will rely on the retry/holdoff mechanism.
|
|
|
|
* GNUWin32's cp does not have this problem.
|
2007-11-16 05:14:46 +08:00
|
|
|
*/
|
|
|
|
pg_usleep(sleeptime * 1000000L);
|
2007-02-08 23:16:19 +08:00
|
|
|
#endif
|
2007-11-16 05:14:46 +08:00
|
|
|
nextWALFileType = XLOG_DATA;
|
|
|
|
return true;
|
|
|
|
}
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If still too small, wait until it is the correct size
|
|
|
|
*/
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2007-11-16 05:14:46 +08:00
|
|
|
fprintf(stderr, "file size greater than expected\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
2007-11-16 05:14:46 +08:00
|
|
|
exit(3);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
CustomizableCleanupPriorWALFiles(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Work out name of prior file from current filename
|
|
|
|
*/
|
2007-09-27 06:36:30 +08:00
|
|
|
if (nextWALFileType == XLOG_DATA)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2007-11-16 05:14:46 +08:00
|
|
|
int rc;
|
|
|
|
DIR *xldir;
|
|
|
|
struct dirent *xlde;
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
/*
|
2010-05-15 17:31:57 +08:00
|
|
|
* Assume it's OK to keep failing. The failure situation may change
|
2007-11-16 05:14:46 +08:00
|
|
|
* over time, so we'd rather keep going on the main processing than
|
2011-02-02 08:07:42 +08:00
|
|
|
* fail because we couldn't clean up yet.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
|
|
|
if ((xldir = opendir(archiveLocation)) != NULL)
|
|
|
|
{
|
2014-03-22 01:45:11 +08:00
|
|
|
while (errno = 0, (xlde = readdir(xldir)) != NULL)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
/*
|
2007-11-16 05:14:46 +08:00
|
|
|
* We ignore the timeline part of the XLOG segment identifiers
|
|
|
|
* in deciding whether a segment is still needed. This
|
|
|
|
* ensures that we won't prematurely remove a segment from a
|
|
|
|
* parent timeline. We could probably be a little more
|
|
|
|
* proactive about removing segments of non-parent timelines,
|
|
|
|
* but that would be a whole lot more complicated.
|
2007-02-08 23:16:19 +08:00
|
|
|
*
|
2007-11-16 05:14:46 +08:00
|
|
|
* We use the alphanumeric sorting property of the filenames
|
|
|
|
* to decide which ones are earlier than the
|
|
|
|
* exclusiveCleanupFileName file. Note that this means files
|
|
|
|
* are not removed in the order they were originally written,
|
|
|
|
* in case this worries you.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
2015-07-02 09:35:38 +08:00
|
|
|
if (IsXLogFileName(xlde->d_name) &&
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-22 03:35:54 +08:00
|
|
|
strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
#ifdef WIN32
|
2017-04-12 02:13:31 +08:00
|
|
|
snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
|
2007-02-08 23:16:19 +08:00
|
|
|
#else
|
2017-04-12 02:13:31 +08:00
|
|
|
snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
|
2007-02-08 23:16:19 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (debug)
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
|
2007-03-04 02:50:45 +08:00
|
|
|
|
|
|
|
rc = unlink(WALFilePath);
|
2007-09-27 06:36:30 +08:00
|
|
|
if (rc != 0)
|
|
|
|
{
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
|
2009-02-27 17:30:21 +08:00
|
|
|
progname, WALFilePath, strerror(errno));
|
2007-09-27 06:36:30 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
2014-03-22 01:45:11 +08:00
|
|
|
|
|
|
|
if (errno)
|
|
|
|
fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
|
|
|
|
progname, archiveLocation, strerror(errno));
|
2007-09-27 06:36:30 +08:00
|
|
|
if (debug)
|
|
|
|
fprintf(stderr, "\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
else
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
|
|
|
|
progname, archiveLocation, strerror(errno));
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2014-03-22 01:45:11 +08:00
|
|
|
if (closedir(xldir))
|
|
|
|
fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
|
|
|
|
progname, archiveLocation, strerror(errno));
|
|
|
|
|
2007-09-27 06:36:30 +08:00
|
|
|
fflush(stderr);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* =====================================================================
|
|
|
|
* End of Customizable section
|
|
|
|
* =====================================================================
|
|
|
|
*/
|
|
|
|
|
2007-09-27 06:36:30 +08:00
|
|
|
/*
|
|
|
|
* SetWALFileNameForCleanup()
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
2007-09-27 06:36:30 +08:00
|
|
|
* Set the earliest WAL filename that we want to keep on the archive
|
2007-11-16 05:14:46 +08:00
|
|
|
* and decide whether we need_cleanup
|
2007-09-27 06:36:30 +08:00
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
SetWALFileNameForCleanup(void)
|
|
|
|
{
|
2007-11-16 05:14:46 +08:00
|
|
|
uint32 tli = 1,
|
|
|
|
log = 0,
|
|
|
|
seg = 0;
|
|
|
|
uint32 log_diff = 0,
|
|
|
|
seg_diff = 0;
|
|
|
|
bool cleanup = false;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
|
2007-09-27 06:36:30 +08:00
|
|
|
|
|
|
|
if (restartWALFileName)
|
|
|
|
{
|
2008-05-09 22:27:47 +08:00
|
|
|
/*
|
2009-06-11 22:49:15 +08:00
|
|
|
* Don't do cleanup if the restartWALFileName provided is later than
|
|
|
|
* the xlog file requested. This is an error and we must not remove
|
|
|
|
* these files from archive. This shouldn't happen, but better safe
|
|
|
|
* than sorry.
|
2008-05-09 22:27:47 +08:00
|
|
|
*/
|
|
|
|
if (strcmp(restartWALFileName, nextWALFileName) > 0)
|
|
|
|
return false;
|
|
|
|
|
2014-02-18 00:20:21 +08:00
|
|
|
strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
|
2007-09-27 06:36:30 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keepfiles > 0)
|
|
|
|
{
|
|
|
|
sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
|
2013-11-08 06:35:43 +08:00
|
|
|
if (tli > 0 && seg > 0)
|
2007-09-27 06:36:30 +08:00
|
|
|
{
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
log_diff = keepfiles / max_segments_per_logfile;
|
|
|
|
seg_diff = keepfiles % max_segments_per_logfile;
|
2007-11-16 05:14:46 +08:00
|
|
|
if (seg_diff > seg)
|
2007-09-27 06:36:30 +08:00
|
|
|
{
|
|
|
|
log_diff++;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
seg = max_segments_per_logfile - (seg_diff - seg);
|
2007-09-27 06:36:30 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
seg -= seg_diff;
|
|
|
|
|
|
|
|
if (log >= log_diff)
|
|
|
|
{
|
|
|
|
log -= log_diff;
|
|
|
|
cleanup = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log = 0;
|
|
|
|
seg = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-02 09:35:38 +08:00
|
|
|
XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
|
2007-09-27 06:36:30 +08:00
|
|
|
|
|
|
|
return cleanup;
|
|
|
|
}
|
|
|
|
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
/*
|
|
|
|
* Try to set the wal segment size from the WAL file specified by WALFilePath.
|
|
|
|
*
|
|
|
|
* Return true if size could be determined, false otherwise.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
SetWALSegSize(void)
|
|
|
|
{
|
|
|
|
bool ret_val = false;
|
|
|
|
int fd;
|
2018-09-02 03:27:12 +08:00
|
|
|
PGAlignedXLogBlock buf;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
|
|
|
|
Assert(WalSegSz == -1);
|
|
|
|
|
|
|
|
if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
|
|
|
|
{
|
2017-09-25 00:05:06 +08:00
|
|
|
fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
|
|
|
|
progname, WALFilePath, strerror(errno));
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
2017-09-25 00:05:06 +08:00
|
|
|
|
|
|
|
errno = 0;
|
2018-09-02 03:27:12 +08:00
|
|
|
if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
{
|
2018-09-02 03:27:12 +08:00
|
|
|
XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
|
|
|
|
WalSegSz = longhdr->xlp_seg_size;
|
|
|
|
|
|
|
|
if (IsValidWalSegSize(WalSegSz))
|
|
|
|
{
|
|
|
|
/* successfully retrieved WAL segment size */
|
|
|
|
ret_val = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: WAL segment size must be a power of two between 1MB and 1GB, but the WAL file header specifies %d bytes\n",
|
|
|
|
progname, WalSegSz);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Don't complain loudly, this is to be expected for segments being
|
|
|
|
* created.
|
|
|
|
*/
|
|
|
|
if (errno != 0)
|
|
|
|
{
|
|
|
|
if (debug)
|
2017-09-25 00:05:06 +08:00
|
|
|
fprintf(stderr, "could not read file \"%s\": %s\n",
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
WALFilePath, strerror(errno));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (debug)
|
2017-09-25 00:05:06 +08:00
|
|
|
fprintf(stderr, "not enough data in file \"%s\"\n",
|
|
|
|
WALFilePath);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fflush(stderr);
|
2017-09-25 00:05:06 +08:00
|
|
|
|
|
|
|
close(fd);
|
Make WAL segment size configurable at initdb time.
For performance reasons a larger segment size than the default 16MB
can be useful. A larger segment size has two main benefits: Firstly,
in setups using archiving, it makes it easier to write scripts that
can keep up with higher amounts of WAL, secondly, the WAL has to be
written and synced to disk less frequently.
But at the same time large segment size are disadvantageous for
smaller databases. So far the segment size had to be configured at
compile time, often making it unrealistic to choose one fitting to a
particularly load. Therefore change it to a initdb time setting.
This includes a breaking changes to the xlogreader.h API, which now
requires the current segment size to be configured. For that and
similar reasons a number of binaries had to be taught how to recognize
the current segment size.
Author: Beena Emerson, editorialized by Andres Freund
Reviewed-By: Andres Freund, David Steele, Kuntal Ghosh, Michael
Paquier, Peter Eisentraut, Robert Hass, Tushar Ahuja
Discussion: https://postgr.es/m/CAOG9ApEAcQ--1ieKbhFzXSQPw_YLmepaa4hNdnY5+ZULpt81Mw@mail.gmail.com
2017-09-20 13:03:48 +08:00
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
/*
|
|
|
|
* CheckForExternalTrigger()
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
2009-05-15 04:31:09 +08:00
|
|
|
* Is there a trigger file? Sets global 'Failover' variable to indicate
|
2009-06-11 22:49:15 +08:00
|
|
|
* what kind of a trigger file it was. A "fast" trigger file is turned
|
|
|
|
* into a "smart" file as a side-effect.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
2009-05-15 04:31:09 +08:00
|
|
|
static void
|
2007-02-08 23:16:19 +08:00
|
|
|
CheckForExternalTrigger(void)
|
|
|
|
{
|
2009-06-11 22:49:15 +08:00
|
|
|
char buf[32];
|
|
|
|
int fd;
|
|
|
|
int len;
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
/*
|
2007-11-16 05:14:46 +08:00
|
|
|
* Look for a trigger file, if that option has been selected
|
2007-02-08 23:16:19 +08:00
|
|
|
*
|
2007-11-16 05:14:46 +08:00
|
|
|
* We use stat() here because triggerPath is always a file rather than
|
|
|
|
* potentially being in an archive
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
2009-05-15 04:31:09 +08:00
|
|
|
if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* An empty trigger file performs smart failover. There's a little race
|
2009-06-11 22:49:15 +08:00
|
|
|
* condition here: if the writer of the trigger file has just created the
|
|
|
|
* file, but not yet written anything to it, we'll treat that as smart
|
|
|
|
* shutdown even if the other process was just about to write "fast" to
|
|
|
|
* it. But that's fine: we'll restore one more WAL file, and when we're
|
2009-05-15 04:31:09 +08:00
|
|
|
* invoked next time, we'll see the word "fast" and fail over immediately.
|
|
|
|
*/
|
|
|
|
if (stat_buf.st_size == 0)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
Failover = SmartFailover;
|
|
|
|
fprintf(stderr, "trigger file found: smart failover\n");
|
|
|
|
fflush(stderr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fd = open(triggerPath, O_RDWR, 0)) < 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "WARNING: could not open \"%s\": %s\n",
|
|
|
|
triggerPath, strerror(errno));
|
|
|
|
fflush(stderr);
|
|
|
|
return;
|
|
|
|
}
|
2009-06-11 22:49:15 +08:00
|
|
|
|
2015-01-15 22:26:03 +08:00
|
|
|
if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
|
2009-05-15 04:31:09 +08:00
|
|
|
{
|
|
|
|
fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
|
|
|
|
triggerPath, strerror(errno));
|
|
|
|
fflush(stderr);
|
|
|
|
close(fd);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
buf[len] = '\0';
|
2009-06-11 22:49:15 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
if (strncmp(buf, "smart", 5) == 0)
|
|
|
|
{
|
|
|
|
Failover = SmartFailover;
|
|
|
|
fprintf(stderr, "trigger file found: smart failover\n");
|
|
|
|
fflush(stderr);
|
|
|
|
close(fd);
|
|
|
|
return;
|
|
|
|
}
|
2009-06-11 22:49:15 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
if (strncmp(buf, "fast", 4) == 0)
|
|
|
|
{
|
|
|
|
Failover = FastFailover;
|
|
|
|
|
|
|
|
fprintf(stderr, "trigger file found: fast failover\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
/*
|
2009-06-11 22:49:15 +08:00
|
|
|
* Turn it into a "smart" trigger by truncating the file. Otherwise if
|
|
|
|
* the server asks us again to restore a segment that was restored
|
2009-06-18 18:08:08 +08:00
|
|
|
* already, we would return "not found" and upset the server.
|
2007-02-08 23:16:19 +08:00
|
|
|
*/
|
2009-05-15 04:31:09 +08:00
|
|
|
if (ftruncate(fd, 0) < 0)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
|
|
|
|
triggerPath, strerror(errno));
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
2009-05-15 04:31:09 +08:00
|
|
|
close(fd);
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
close(fd);
|
2009-06-11 22:49:15 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
|
|
|
|
fflush(stderr);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RestoreWALFileForRecovery()
|
2007-11-16 05:14:46 +08:00
|
|
|
*
|
2007-02-08 23:16:19 +08:00
|
|
|
* Perform the action required to restore the file from archive
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
RestoreWALFileForRecovery(void)
|
|
|
|
{
|
2007-11-16 05:14:46 +08:00
|
|
|
int rc = 0;
|
|
|
|
int numretries = 0;
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
if (debug)
|
|
|
|
{
|
2012-05-24 00:58:17 +08:00
|
|
|
fprintf(stderr, "running restore: ");
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
|
2009-03-27 06:29:13 +08:00
|
|
|
while (numretries <= maxretries)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
rc = system(restoreCommand);
|
|
|
|
if (rc == 0)
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
2012-05-24 00:58:17 +08:00
|
|
|
fprintf(stderr, "OK\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2007-11-16 05:14:46 +08:00
|
|
|
pg_usleep(numretries++ * sleeptime * 1000000L);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allow caller to add additional info
|
|
|
|
*/
|
|
|
|
if (debug)
|
2009-05-15 04:31:09 +08:00
|
|
|
fprintf(stderr, "not restored\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-09-27 06:36:30 +08:00
|
|
|
usage(void)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
printf("%s allows PostgreSQL warm standby servers to be configured.\n\n", progname);
|
|
|
|
printf("Usage:\n");
|
|
|
|
printf(" %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
|
|
|
|
printf("\nOptions:\n");
|
2012-05-20 06:14:25 +08:00
|
|
|
printf(" -c copy file from archive (default)\n");
|
2009-02-27 17:30:21 +08:00
|
|
|
printf(" -d generate lots of debugging output (testing only)\n");
|
2012-05-20 06:14:25 +08:00
|
|
|
printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
|
2009-02-27 17:30:21 +08:00
|
|
|
" (0 keeps all)\n");
|
2009-06-25 20:03:11 +08:00
|
|
|
printf(" -l does nothing; use of link is now deprecated\n");
|
2009-02-27 17:30:21 +08:00
|
|
|
printf(" -r MAXRETRIES max number of times to retry, with progressive wait\n"
|
|
|
|
" (default=3)\n");
|
|
|
|
printf(" -s SLEEPTIME seconds to wait between file checks (min=1, max=60,\n"
|
|
|
|
" default=5)\n");
|
2012-05-20 06:14:25 +08:00
|
|
|
printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
|
2012-06-18 07:44:00 +08:00
|
|
|
printf(" -V, --version output version information, then exit\n");
|
2009-02-27 17:30:21 +08:00
|
|
|
printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
|
2012-06-18 07:44:00 +08:00
|
|
|
printf(" -?, --help show this help, then exit\n");
|
2011-05-06 04:11:51 +08:00
|
|
|
printf("\n"
|
2018-11-25 23:31:16 +08:00
|
|
|
"Main intended use as restore_command in postgresql.conf:\n"
|
2011-05-06 04:11:51 +08:00
|
|
|
" restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
|
|
|
|
"e.g.\n"
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-22 03:35:54 +08:00
|
|
|
" restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
|
2020-02-28 15:54:49 +08:00
|
|
|
printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
|
2020-02-28 15:54:49 +08:00
|
|
|
printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
|
2009-11-04 20:51:30 +08:00
|
|
|
#ifndef WIN32
|
2007-02-08 23:16:19 +08:00
|
|
|
static void
|
|
|
|
sighandler(int sig)
|
|
|
|
{
|
|
|
|
signaled = true;
|
|
|
|
}
|
|
|
|
|
2009-03-19 03:27:28 +08:00
|
|
|
/* We don't want SIGQUIT to core dump */
|
|
|
|
static void
|
|
|
|
sigquit_handler(int sig)
|
|
|
|
{
|
2013-03-18 04:09:47 +08:00
|
|
|
pqsignal(SIGINT, SIG_DFL);
|
2009-03-19 03:27:28 +08:00
|
|
|
kill(getpid(), SIGINT);
|
|
|
|
}
|
2009-03-19 04:30:35 +08:00
|
|
|
#endif
|
2009-03-19 03:27:28 +08:00
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
/*------------ MAIN ----------------------------------------*/
|
2007-11-16 05:14:46 +08:00
|
|
|
int
|
2007-02-08 23:16:19 +08:00
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
2009-02-27 17:30:21 +08:00
|
|
|
progname = get_progname(argv[0]);
|
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
{
|
|
|
|
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
|
|
|
|
{
|
|
|
|
usage();
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
|
|
|
|
{
|
|
|
|
puts("pg_standby (PostgreSQL) " PG_VERSION);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-04 20:51:30 +08:00
|
|
|
#ifndef WIN32
|
2010-02-26 10:01:40 +08:00
|
|
|
|
2009-03-19 03:27:28 +08:00
|
|
|
/*
|
|
|
|
* You can send SIGUSR1 to trigger failover.
|
|
|
|
*
|
|
|
|
* Postmaster uses SIGQUIT to request immediate shutdown. The default
|
2009-06-11 22:49:15 +08:00
|
|
|
* action is to core dump, but we don't want that, so trap it and commit
|
|
|
|
* suicide without core dump.
|
2009-03-19 03:27:28 +08:00
|
|
|
*
|
2009-06-11 22:49:15 +08:00
|
|
|
* We used to use SIGINT and SIGQUIT to trigger failover, but that turned
|
|
|
|
* out to be a bad idea because postmaster uses SIGQUIT to request
|
|
|
|
* immediate shutdown. We still trap SIGINT, but that may change in a
|
|
|
|
* future release.
|
2009-11-04 20:51:30 +08:00
|
|
|
*
|
|
|
|
* There's no way to trigger failover via signal on Windows.
|
2009-03-19 03:27:28 +08:00
|
|
|
*/
|
2013-03-18 04:09:47 +08:00
|
|
|
(void) pqsignal(SIGUSR1, sighandler);
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-22 03:18:54 +08:00
|
|
|
(void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
|
2013-03-18 04:09:47 +08:00
|
|
|
(void) pqsignal(SIGQUIT, sigquit_handler);
|
2009-03-19 04:30:35 +08:00
|
|
|
#endif
|
2007-02-08 23:16:19 +08:00
|
|
|
|
|
|
|
while ((c = getopt(argc, argv, "cdk:lr:s:t:w:")) != -1)
|
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case 'c': /* Use copy */
|
|
|
|
restoreCommandType = RESTORE_COMMAND_COPY;
|
|
|
|
break;
|
|
|
|
case 'd': /* Debug mode */
|
|
|
|
debug = true;
|
|
|
|
break;
|
|
|
|
case 'k': /* keepfiles */
|
|
|
|
keepfiles = atoi(optarg);
|
2007-09-27 06:36:30 +08:00
|
|
|
if (keepfiles < 0)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l': /* Use link */
|
2010-02-26 10:01:40 +08:00
|
|
|
|
2009-06-25 20:03:11 +08:00
|
|
|
/*
|
2010-02-26 10:01:40 +08:00
|
|
|
* Link feature disabled, possibly permanently. Linking causes
|
|
|
|
* a problem after recovery ends that is not currently
|
2009-06-25 20:03:11 +08:00
|
|
|
* resolved by PostgreSQL. 25 Jun 2009
|
2009-06-26 03:33:25 +08:00
|
|
|
*/
|
|
|
|
#ifdef NOT_USED
|
|
|
|
restoreCommandType = RESTORE_COMMAND_LINK;
|
|
|
|
#endif
|
2007-02-08 23:16:19 +08:00
|
|
|
break;
|
|
|
|
case 'r': /* Retries */
|
|
|
|
maxretries = atoi(optarg);
|
|
|
|
if (maxretries < 0)
|
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's': /* Sleep time */
|
|
|
|
sleeptime = atoi(optarg);
|
|
|
|
if (sleeptime <= 0 || sleeptime > 60)
|
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 't': /* Trigger file */
|
2016-08-31 06:22:43 +08:00
|
|
|
triggerPath = pg_strdup(optarg);
|
2007-11-16 05:14:46 +08:00
|
|
|
break;
|
2007-02-08 23:16:19 +08:00
|
|
|
case 'w': /* Max wait time */
|
|
|
|
maxwaittime = atoi(optarg);
|
|
|
|
if (maxwaittime < 0)
|
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-16 05:14:46 +08:00
|
|
|
/*
|
2007-02-08 23:16:19 +08:00
|
|
|
* Parameter checking - after checking to see if trigger file present
|
|
|
|
*/
|
|
|
|
if (argc == 1)
|
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: not enough command-line arguments\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We will go to the archiveLocation to get nextWALFileName.
|
2007-11-16 05:14:46 +08:00
|
|
|
* nextWALFileName may not exist yet, which would not be an error, so we
|
|
|
|
* separate the archiveLocation and nextWALFileName so we can check
|
2007-02-08 23:16:19 +08:00
|
|
|
* separately whether archiveLocation exists, if not that is an error
|
|
|
|
*/
|
|
|
|
if (optind < argc)
|
|
|
|
{
|
|
|
|
archiveLocation = argv[optind];
|
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "%s: must specify archive location\n", progname);
|
|
|
|
fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optind < argc)
|
|
|
|
{
|
|
|
|
nextWALFileName = argv[optind];
|
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optind < argc)
|
|
|
|
{
|
|
|
|
xlogFilePath = argv[optind];
|
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-15 02:03:08 +08:00
|
|
|
fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
|
2009-02-27 17:30:21 +08:00
|
|
|
fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
|
2007-02-08 23:16:19 +08:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
2007-09-27 06:36:30 +08:00
|
|
|
if (optind < argc)
|
|
|
|
{
|
|
|
|
restartWALFileName = argv[optind];
|
|
|
|
optind++;
|
|
|
|
}
|
|
|
|
|
2007-02-08 23:16:19 +08:00
|
|
|
CustomizableInitialize();
|
|
|
|
|
|
|
|
if (debug)
|
|
|
|
{
|
2011-05-28 06:01:42 +08:00
|
|
|
fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : "<not set>");
|
|
|
|
fprintf(stderr, "Waiting for WAL file: %s\n", nextWALFileName);
|
|
|
|
fprintf(stderr, "WAL file path: %s\n", WALFilePath);
|
|
|
|
fprintf(stderr, "Restoring to: %s\n", xlogFilePath);
|
|
|
|
fprintf(stderr, "Sleep interval: %d second%s\n",
|
2007-11-16 05:14:46 +08:00
|
|
|
sleeptime, (sleeptime > 1 ? "s" : " "));
|
2011-05-28 06:01:42 +08:00
|
|
|
fprintf(stderr, "Max wait interval: %d %s\n",
|
2007-11-16 05:14:46 +08:00
|
|
|
maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
|
2011-05-28 06:01:42 +08:00
|
|
|
fprintf(stderr, "Command for restore: %s\n", restoreCommand);
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for initial history file: always the first file to be requested
|
|
|
|
* It's OK if the file isn't there - all other files need to wait
|
|
|
|
*/
|
2015-07-02 09:35:38 +08:00
|
|
|
if (IsTLHistoryFileName(nextWALFileName))
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
|
|
|
nextWALFileType = XLOG_HISTORY;
|
|
|
|
if (RestoreWALFileForRecovery())
|
|
|
|
exit(0);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "history file not found\n");
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-16 05:14:46 +08:00
|
|
|
/*
|
2007-02-08 23:16:19 +08:00
|
|
|
* Main wait loop
|
|
|
|
*/
|
2009-05-15 04:31:09 +08:00
|
|
|
for (;;)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
/* Check for trigger file or signal first */
|
|
|
|
CheckForExternalTrigger();
|
2009-11-04 20:51:30 +08:00
|
|
|
#ifndef WIN32
|
2007-02-08 23:16:19 +08:00
|
|
|
if (signaled)
|
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
Failover = FastFailover;
|
2007-02-08 23:16:19 +08:00
|
|
|
if (debug)
|
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
fprintf(stderr, "signaled to exit: fast failover\n");
|
2007-02-08 23:16:19 +08:00
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
}
|
2009-11-04 20:51:30 +08:00
|
|
|
#endif
|
2009-05-15 04:31:09 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for fast failover immediately, before checking if the
|
|
|
|
* requested WAL file is available
|
|
|
|
*/
|
|
|
|
if (Failover == FastFailover)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
if (CustomizableNextWALFileReady())
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
/*
|
|
|
|
* Once we have restored this file successfully we can remove some
|
2017-02-06 17:33:58 +08:00
|
|
|
* prior WAL files. If this restore fails we mustn't remove any
|
2009-06-11 22:49:15 +08:00
|
|
|
* file because some of them will be requested again immediately
|
|
|
|
* after the failed restore, or when we restart recovery.
|
2009-05-15 04:31:09 +08:00
|
|
|
*/
|
|
|
|
if (RestoreWALFileForRecovery())
|
|
|
|
{
|
|
|
|
if (need_cleanup)
|
|
|
|
CustomizableCleanupPriorWALFiles();
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
else
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
/* Something went wrong in copying the file */
|
|
|
|
exit(1);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
2009-05-15 04:31:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for smart failover if the next WAL file was not available */
|
|
|
|
if (Failover == SmartFailover)
|
|
|
|
exit(1);
|
2007-02-08 23:16:19 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
if (sleeptime <= 60)
|
|
|
|
pg_usleep(sleeptime * 1000000L);
|
2007-11-16 05:14:46 +08:00
|
|
|
|
2009-05-15 04:31:09 +08:00
|
|
|
waittime += sleeptime;
|
|
|
|
if (waittime >= maxwaittime && maxwaittime > 0)
|
|
|
|
{
|
|
|
|
Failover = FastFailover;
|
|
|
|
if (debug)
|
2007-02-08 23:16:19 +08:00
|
|
|
{
|
2009-05-15 04:31:09 +08:00
|
|
|
fprintf(stderr, "Timed out after %d seconds: fast failover\n",
|
|
|
|
waittime);
|
|
|
|
fflush(stderr);
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|
2009-05-15 04:31:09 +08:00
|
|
|
if (debug)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "WAL file not present yet.");
|
|
|
|
if (triggerPath)
|
|
|
|
fprintf(stderr, " Checking for trigger file...");
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
2007-02-08 23:16:19 +08:00
|
|
|
}
|
|
|
|
}
|