[PATCH] remove pg_archivecleanup and pg_standby
Forking this thread:
/messages/by-id/fd93f1c5-7818-a02c-01e5-1075ac0d4def@iki.fi
I think these are old-fashioned since 9.6 (?), so remove them for v14.
I found it confusing when re-familiarizing myself with modern streaming
replication that there are extensions which only help do things the "old way".
Attachments:
v1-0001-Retire-pg_standby.patchtext/x-diff; charset=us-asciiDownload
From db6e3369f84b38c56598f76d52122c6ba180ee85 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 26 Oct 2020 16:37:46 -0500
Subject: [PATCH v1 1/2] Retire pg_standby..
..since pg9.0, use builtin streaming replication protocol with warm/hot standby
---
contrib/Makefile | 1 -
contrib/pg_standby/.gitignore | 1 -
contrib/pg_standby/Makefile | 20 -
contrib/pg_standby/pg_standby.c | 907 ----------------------------
doc/src/sgml/contrib.sgml | 1 -
doc/src/sgml/filelist.sgml | 1 -
doc/src/sgml/high-availability.sgml | 14 +-
doc/src/sgml/pgstandby.sgml | 394 ------------
src/tools/msvc/Mkvcbuild.pm | 4 +-
9 files changed, 4 insertions(+), 1339 deletions(-)
delete mode 100644 contrib/pg_standby/.gitignore
delete mode 100644 contrib/pg_standby/Makefile
delete mode 100644 contrib/pg_standby/pg_standby.c
delete mode 100644 doc/src/sgml/pgstandby.sgml
diff --git a/contrib/Makefile b/contrib/Makefile
index 7a4866e338..cdc041c7db 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -33,7 +33,6 @@ SUBDIRS = \
pg_buffercache \
pg_freespacemap \
pg_prewarm \
- pg_standby \
pg_stat_statements \
pg_surgery \
pg_trgm \
diff --git a/contrib/pg_standby/.gitignore b/contrib/pg_standby/.gitignore
deleted file mode 100644
index a401b085a8..0000000000
--- a/contrib/pg_standby/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/pg_standby
diff --git a/contrib/pg_standby/Makefile b/contrib/pg_standby/Makefile
deleted file mode 100644
index 87732bedf1..0000000000
--- a/contrib/pg_standby/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# contrib/pg_standby/Makefile
-
-PGFILEDESC = "pg_standby - supports creation of a warm standby"
-PGAPPICON = win32
-
-PROGRAM = pg_standby
-OBJS = \
- $(WIN32RES) \
- pg_standby.o
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_standby
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
deleted file mode 100644
index c9f33e4254..0000000000
--- a/contrib/pg_standby/pg_standby.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * contrib/pg_standby/pg_standby.c
- *
- *
- * pg_standby.c
- *
- * Production-ready example of how to create a Warm Standby
- * database server using continuous archiving as a
- * replication mechanism
- *
- * We separate the parameters for archive and nextWALfile
- * so that we can check the archive exists, even if the
- * 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.
- *
- * Original author: Simon Riggs simon@2ndquadrant.com
- * Current maintainer: Simon Riggs
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "access/xlog_internal.h"
-#include "pg_getopt.h"
-
-const char *progname;
-
-int WalSegSz = -1;
-
-/* Options and defaults */
-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? */
-bool need_cleanup = false; /* do we need to remove files from
- * archive? */
-
-#ifndef WIN32
-static volatile sig_atomic_t signaled = false;
-#endif
-
-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 */
-char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
-char restoreCommand[MAXPGPATH]; /* run this to restore */
-char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
- * from archive */
-
-/*
- * 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
-
-static int Failover = NoFailover;
-
-#define RESTORE_COMMAND_COPY 0
-#define RESTORE_COMMAND_LINK 1
-int restoreCommandType;
-
-#define XLOG_DATA 0
-#define XLOG_HISTORY 1
-int nextWALFileType;
-
-#define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
- snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
-
-struct stat stat_buf;
-
-static bool SetWALFileNameForCleanup(void);
-static bool SetWALSegSize(void);
-
-
-/* =====================================================================
- *
- * 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
- * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
- * or personally to the current maintainer. Those changes may be
- * folded in to later versions of this program.
- */
-
-/*
- * Initialize allows customized commands into the warm standby program.
- *
- * As an example, and probably the common case, we use either
- * cp/ln commands on *nix, or copy/move command on Windows.
- */
-static void
-CustomizableInitialize(void)
-{
-#ifdef WIN32
- snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("mklink", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("copy", WALFilePath, xlogFilePath);
- break;
- }
-#else
- snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("ln -s -f", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("cp", WALFilePath, xlogFilePath);
- break;
- }
-#endif
-
- /*
- * 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
- * directory, we use stat to test if it's accessible
- */
- if (stat(archiveLocation, &stat_buf) != 0)
- {
- fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
- fflush(stderr);
- exit(2);
- }
-}
-
-/*
- * CustomizableNextWALFileReady()
- *
- * Is the requested file ready yet?
- */
-static bool
-CustomizableNextWALFileReady(void)
-{
- if (stat(WALFilePath, &stat_buf) == 0)
- {
- /*
- * 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");
- }
- }
- }
-
- /*
- * Return only if it's the right size already.
- */
- if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
- {
-#ifdef WIN32
-
- /*
- * Windows 'cp' sets the final file size before the copy is
- * 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.
- */
- pg_usleep(sleeptime * 1000000L);
-#endif
- nextWALFileType = XLOG_DATA;
- return true;
- }
-
- /*
- * If still too small, wait until it is the correct size
- */
- if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
- {
- if (debug)
- {
- fprintf(stderr, "file size greater than expected\n");
- fflush(stderr);
- }
- exit(3);
- }
- }
-
- return false;
-}
-
-static void
-CustomizableCleanupPriorWALFiles(void)
-{
- /*
- * Work out name of prior file from current filename
- */
- if (nextWALFileType == XLOG_DATA)
- {
- int rc;
- DIR *xldir;
- struct dirent *xlde;
-
- /*
- * Assume it's OK to keep failing. The failure situation may change
- * over time, so we'd rather keep going on the main processing than
- * fail because we couldn't clean up yet.
- */
- if ((xldir = opendir(archiveLocation)) != NULL)
- {
- while (errno = 0, (xlde = readdir(xldir)) != NULL)
- {
- /*
- * 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.
- *
- * 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.
- */
- if (IsXLogFileName(xlde->d_name) &&
- strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
- {
-#ifdef WIN32
- snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
-#else
- snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
-#endif
-
- if (debug)
- fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
-
- rc = unlink(WALFilePath);
- if (rc != 0)
- {
- fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- break;
- }
- }
- }
-
- if (errno)
- fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
- if (debug)
- fprintf(stderr, "\n");
- }
- else
- fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- if (closedir(xldir))
- fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- fflush(stderr);
- }
-}
-
-/* =====================================================================
- * End of Customizable section
- * =====================================================================
- */
-
-/*
- * SetWALFileNameForCleanup()
- *
- * Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need_cleanup
- */
-static bool
-SetWALFileNameForCleanup(void)
-{
- uint32 tli = 1,
- log = 0,
- seg = 0;
- uint32 log_diff = 0,
- seg_diff = 0;
- bool cleanup = false;
- int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
-
- if (restartWALFileName)
- {
- /*
- * 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.
- */
- if (strcmp(restartWALFileName, nextWALFileName) > 0)
- return false;
-
- strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
- return true;
- }
-
- if (keepfiles > 0)
- {
- sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
- if (tli > 0 && seg > 0)
- {
- log_diff = keepfiles / max_segments_per_logfile;
- seg_diff = keepfiles % max_segments_per_logfile;
- if (seg_diff > seg)
- {
- log_diff++;
- seg = max_segments_per_logfile - (seg_diff - seg);
- }
- else
- seg -= seg_diff;
-
- if (log >= log_diff)
- {
- log -= log_diff;
- cleanup = true;
- }
- else
- {
- log = 0;
- seg = 0;
- }
- }
- }
-
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
-
- return cleanup;
-}
-
-/*
- * 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;
- PGAlignedXLogBlock buf;
-
- Assert(WalSegSz == -1);
-
- if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
- {
- fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- return false;
- }
-
- errno = 0;
- if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
- {
- XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
-
- 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)
- fprintf(stderr, "could not read file \"%s\": %s\n",
- WALFilePath, strerror(errno));
- }
- else
- {
- if (debug)
- fprintf(stderr, "not enough data in file \"%s\"\n",
- WALFilePath);
- }
- }
-
- fflush(stderr);
-
- close(fd);
- return ret_val;
-}
-
-/*
- * CheckForExternalTrigger()
- *
- * Is there a trigger file? Sets global 'Failover' variable to indicate
- * what kind of a trigger file it was. A "fast" trigger file is turned
- * into a "smart" file as a side-effect.
- */
-static void
-CheckForExternalTrigger(void)
-{
- char buf[32];
- int fd;
- int len;
-
- /*
- * Look for a trigger file, if that option has been selected
- *
- * We use stat() here because triggerPath is always a file rather than
- * potentially being in an archive
- */
- if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
- return;
-
- /*
- * An empty trigger file performs smart failover. There's a little race
- * 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
- * invoked next time, we'll see the word "fast" and fail over immediately.
- */
- if (stat_buf.st_size == 0)
- {
- 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;
- }
-
- if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- close(fd);
- return;
- }
- buf[len] = '\0';
-
- if (strncmp(buf, "smart", 5) == 0)
- {
- Failover = SmartFailover;
- fprintf(stderr, "trigger file found: smart failover\n");
- fflush(stderr);
- close(fd);
- return;
- }
-
- if (strncmp(buf, "fast", 4) == 0)
- {
- Failover = FastFailover;
-
- fprintf(stderr, "trigger file found: fast failover\n");
- fflush(stderr);
-
- /*
- * Turn it into a "smart" trigger by truncating the file. Otherwise if
- * the server asks us again to restore a segment that was restored
- * already, we would return "not found" and upset the server.
- */
- if (ftruncate(fd, 0) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- }
- close(fd);
-
- return;
- }
- close(fd);
-
- fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
- fflush(stderr);
-}
-
-/*
- * RestoreWALFileForRecovery()
- *
- * Perform the action required to restore the file from archive
- */
-static bool
-RestoreWALFileForRecovery(void)
-{
- int rc = 0;
- int numretries = 0;
-
- if (debug)
- {
- fprintf(stderr, "running restore: ");
- fflush(stderr);
- }
-
- while (numretries <= maxretries)
- {
- rc = system(restoreCommand);
- if (rc == 0)
- {
- if (debug)
- {
- fprintf(stderr, "OK\n");
- fflush(stderr);
- }
- return true;
- }
- pg_usleep(numretries++ * sleeptime * 1000000L);
- }
-
- /*
- * Allow caller to add additional info
- */
- if (debug)
- fprintf(stderr, "not restored\n");
- return false;
-}
-
-static void
-usage(void)
-{
- 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");
- printf(" -c copy file from archive (default)\n");
- printf(" -d generate lots of debugging output (testing only)\n");
- printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
- " (0 keeps all)\n");
- printf(" -l does nothing; use of link is now deprecated\n");
- 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");
- printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
- printf(" -V, --version output version information, then exit\n");
- printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
- printf(" -?, --help show this help, then exit\n");
- printf("\n"
- "Main intended use as restore_command in postgresql.conf:\n"
- " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
- "e.g.\n"
- " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
- printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
- printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
-}
-
-#ifndef WIN32
-static void
-sighandler(int sig)
-{
- signaled = true;
-}
-
-/* We don't want SIGQUIT to core dump */
-static void
-sigquit_handler(int sig)
-{
- pqsignal(SIGINT, SIG_DFL);
- kill(getpid(), SIGINT);
-}
-#endif
-
-/*------------ MAIN ----------------------------------------*/
-int
-main(int argc, char **argv)
-{
- int c;
-
- 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);
- }
- }
-
-#ifndef WIN32
-
- /*
- * You can send SIGUSR1 to trigger failover.
- *
- * Postmaster uses SIGQUIT to request immediate shutdown. The default
- * action is to core dump, but we don't want that, so trap it and commit
- * suicide without core dump.
- *
- * 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.
- *
- * There's no way to trigger failover via signal on Windows.
- */
- (void) pqsignal(SIGUSR1, sighandler);
- (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
- (void) pqsignal(SIGQUIT, sigquit_handler);
-#endif
-
- 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);
- if (keepfiles < 0)
- {
- fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 'l': /* Use link */
-
- /*
- * Link feature disabled, possibly permanently. Linking causes
- * a problem after recovery ends that is not currently
- * resolved by PostgreSQL. 25 Jun 2009
- */
-#ifdef NOT_USED
- restoreCommandType = RESTORE_COMMAND_LINK;
-#endif
- break;
- case 'r': /* Retries */
- maxretries = atoi(optarg);
- if (maxretries < 0)
- {
- fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 's': /* Sleep time */
- sleeptime = atoi(optarg);
- if (sleeptime <= 0 || sleeptime > 60)
- {
- fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
- exit(2);
- }
- break;
- case 't': /* Trigger file */
- triggerPath = pg_strdup(optarg);
- break;
- case 'w': /* Max wait time */
- maxwaittime = atoi(optarg);
- if (maxwaittime < 0)
- {
- fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
- exit(2);
- }
- break;
- default:
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- break;
- }
- }
-
- /*
- * Parameter checking - after checking to see if trigger file present
- */
- if (argc == 1)
- {
- fprintf(stderr, "%s: not enough command-line arguments\n", progname);
- exit(2);
- }
-
- /*
- * We will go to the archiveLocation to get nextWALFileName.
- * nextWALFileName may not exist yet, which would not be an error, so we
- * separate the archiveLocation and nextWALFileName so we can check
- * separately whether archiveLocation exists, if not that is an error
- */
- if (optind < argc)
- {
- archiveLocation = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify archive location\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- nextWALFileName = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- xlogFilePath = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- restartWALFileName = argv[optind];
- optind++;
- }
-
- CustomizableInitialize();
-
- if (debug)
- {
- 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",
- sleeptime, (sleeptime > 1 ? "s" : " "));
- fprintf(stderr, "Max wait interval: %d %s\n",
- maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
- fprintf(stderr, "Command for restore: %s\n", restoreCommand);
- 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
- */
- if (IsTLHistoryFileName(nextWALFileName))
- {
- nextWALFileType = XLOG_HISTORY;
- if (RestoreWALFileForRecovery())
- exit(0);
- else
- {
- if (debug)
- {
- fprintf(stderr, "history file not found\n");
- fflush(stderr);
- }
- exit(1);
- }
- }
-
- /*
- * Main wait loop
- */
- for (;;)
- {
- /* Check for trigger file or signal first */
- CheckForExternalTrigger();
-#ifndef WIN32
- if (signaled)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "signaled to exit: fast failover\n");
- fflush(stderr);
- }
- }
-#endif
-
- /*
- * Check for fast failover immediately, before checking if the
- * requested WAL file is available
- */
- if (Failover == FastFailover)
- exit(1);
-
- if (CustomizableNextWALFileReady())
- {
- /*
- * Once we have restored this file successfully we can remove some
- * prior WAL files. If this restore fails we mustn't remove any
- * file because some of them will be requested again immediately
- * after the failed restore, or when we restart recovery.
- */
- if (RestoreWALFileForRecovery())
- {
- if (need_cleanup)
- CustomizableCleanupPriorWALFiles();
-
- exit(0);
- }
- else
- {
- /* Something went wrong in copying the file */
- exit(1);
- }
- }
-
- /* Check for smart failover if the next WAL file was not available */
- if (Failover == SmartFailover)
- exit(1);
-
- if (sleeptime <= 60)
- pg_usleep(sleeptime * 1000000L);
-
- waittime += sleeptime;
- if (waittime >= maxwaittime && maxwaittime > 0)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "Timed out after %d seconds: fast failover\n",
- waittime);
- fflush(stderr);
- }
- }
- if (debug)
- {
- fprintf(stderr, "WAL file not present yet.");
- if (triggerPath)
- fprintf(stderr, " Checking for trigger file...");
- fprintf(stderr, "\n");
- fflush(stderr);
- }
- }
-}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index 4e833d79ef..be4292ec33 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -199,6 +199,5 @@ pages.
part of the core <productname>PostgreSQL</productname> distribution.
</para>
- &pgstandby;
</sect1>
</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..db1d369743 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -138,7 +138,6 @@
<!ENTITY pgfreespacemap SYSTEM "pgfreespacemap.sgml">
<!ENTITY pgprewarm SYSTEM "pgprewarm.sgml">
<!ENTITY pgrowlocks SYSTEM "pgrowlocks.sgml">
-<!ENTITY pgstandby SYSTEM "pgstandby.sgml">
<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml">
<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml">
<!ENTITY pgsurgery SYSTEM "pgsurgery.sgml">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index 19d7bd2b28..6425d8b15d 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -702,8 +702,7 @@ protocol to make nodes agree on a serializable transactional order.
Do not use pg_standby or similar tools with the built-in standby mode
described here. <xref linkend="guc-restore-command"/> should return immediately
if the file does not exist; the server will retry the command again if
- necessary. See <xref linkend="log-shipping-alternative"/>
- for using tools like pg_standby.
+ necessary.
</para>
</note>
@@ -1494,8 +1493,7 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
<para>
An alternative to the built-in standby mode described in the previous
sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below. See the
- <xref linkend="pgstandby"/> module for a reference implementation of this.
+ This was the only option available in versions 8.4 and below.
</para>
<para>
@@ -1551,14 +1549,6 @@ if (!triggered)
</programlisting>
</para>
- <para>
- A working example of a waiting <varname>restore_command</varname> is provided
- in the <xref linkend="pgstandby"/> module. It
- should be used as a reference on how to correctly implement the logic
- described above. It can also be extended as needed to support specific
- configurations and environments.
- </para>
-
<para>
The method for triggering failover is an important part of planning
and design. One potential option is the <varname>restore_command</varname>
diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml
deleted file mode 100644
index 66a6255930..0000000000
--- a/doc/src/sgml/pgstandby.sgml
+++ /dev/null
@@ -1,394 +0,0 @@
-<!-- doc/src/sgml/pgstandby.sgml -->
-
-<refentry id="pgstandby">
- <indexterm zone="pgstandby">
- <primary>pg_standby</primary>
- </indexterm>
-
- <refmeta>
- <refentrytitle><application>pg_standby</application></refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo>Application</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>pg_standby</refname>
- <refpurpose>supports the creation of a <productname>PostgreSQL</productname> warm standby server</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>pg_standby</command>
- <arg rep="repeat"><replaceable>option</replaceable></arg>
- <arg choice="plain"><replaceable>archivelocation</replaceable></arg>
- <arg choice="plain"><replaceable>nextwalfile</replaceable></arg>
- <arg choice="plain"><replaceable>walfilepath</replaceable></arg>
- <arg choice="opt"><replaceable>restartwalfile</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <application>pg_standby</application> supports creation of a <quote>warm standby</quote>
- database server. It is designed to be a production-ready program, as well
- as a customizable template should you require specific modifications.
- </para>
-
- <para>
- <application>pg_standby</application> is designed to be a waiting
- <varname>restore_command</varname>, which is needed to turn a standard
- archive recovery into a warm standby operation. Other
- configuration is required as well, all of which is described in the main
- server manual (see <xref linkend="warm-standby"/>).
- </para>
-
- <para>
- To configure a standby
- server to use <application>pg_standby</application>, put this into its
- <filename>postgresql.conf</filename> configuration file:
-<programlisting>
-restore_command = 'pg_standby <replaceable>archiveDir</replaceable> %f %p %r'
-</programlisting>
- where <replaceable>archiveDir</replaceable> is the directory from which WAL segment
- files should be restored.
- </para>
- <para>
- If <replaceable>restartwalfile</replaceable> is specified, normally by using the
- <literal>%r</literal> macro, then all WAL files logically preceding this
- file will be removed from <replaceable>archivelocation</replaceable>. This minimizes
- the number of files that need to be retained, while preserving
- crash-restart capability. Use of this parameter is appropriate if the
- <replaceable>archivelocation</replaceable> is a transient staging area for this
- particular standby server, but <emphasis>not</emphasis> when the
- <replaceable>archivelocation</replaceable> is intended as a long-term WAL archive area.
- </para>
- <para>
- <application>pg_standby</application> assumes that
- <replaceable>archivelocation</replaceable> is a directory readable by the
- server-owning user. If <replaceable>restartwalfile</replaceable> (or <literal>-k</literal>)
- is specified,
- the <replaceable>archivelocation</replaceable> directory must be writable too.
- </para>
- <para>
- There are two ways to fail over to a <quote>warm standby</quote> database server
- when the primary server fails:
-
- <variablelist>
- <varlistentry>
- <term>Smart Failover</term>
- <listitem>
- <para>
- In smart failover, the server is brought up after applying all WAL
- files available in the archive. This results in zero data loss, even if
- the standby server has fallen behind, but if there is a lot of
- unapplied WAL it can be a long time before the standby server becomes
- ready. To trigger a smart failover, create a trigger file containing
- the word <literal>smart</literal>, or just create it and leave it empty.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Fast Failover</term>
- <listitem>
- <para>
- In fast failover, the server is brought up immediately. Any WAL files
- in the archive that have not yet been applied will be ignored, and
- all transactions in those files are lost. To trigger a fast failover,
- create a trigger file and write the word <literal>fast</literal> into it.
- <application>pg_standby</application> can also be configured to execute a fast
- failover automatically if no new WAL file appears within a defined
- interval.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>
- <application>pg_standby</application> accepts the following command-line arguments:
-
- <variablelist>
-
- <varlistentry>
- <term><option>-c</option></term>
- <listitem>
- <para>
- Use <literal>cp</literal> or <literal>copy</literal> command to restore WAL files
- from archive. This is the only supported behavior so this option is useless.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
- <listitem>
- <para>
- Print lots of debug logging output on <filename>stderr</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-k</option></term>
- <listitem>
- <para>
- Remove files from <replaceable>archivelocation</replaceable> so that
- no more than this many WAL files before the current one are kept in the
- archive. Zero (the default) means not to remove any files from
- <replaceable>archivelocation</replaceable>.
- This parameter will be silently ignored if
- <replaceable>restartwalfile</replaceable> is specified, since that
- specification method is more accurate in determining the correct
- archive cut-off point.
- Use of this parameter is <emphasis>deprecated</emphasis> as of
- <productname>PostgreSQL</productname> 8.3; it is safer and more efficient to
- specify a <replaceable>restartwalfile</replaceable> parameter. A too
- small setting could result in removal of files that are still needed
- for a restart of the standby server, while a too large setting wastes
- archive space.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-r</option> <replaceable>maxretries</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of times to retry the copy command if
- it fails (default 3). After each failure, we wait for
- <replaceable>sleeptime</replaceable> * <replaceable>num_retries</replaceable>
- so that the wait time increases progressively. So by default,
- we will wait 5 secs, 10 secs, then 15 secs before reporting
- the failure back to the standby server. This will be
- interpreted as end of recovery and the standby will come
- up fully as a result.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-s</option> <replaceable>sleeptime</replaceable></term>
- <listitem>
- <para>
- Set the number of seconds (up to 60, default 5) to sleep between
- tests to see if the WAL file to be restored is available in
- the archive yet. The default setting is not necessarily
- recommended; consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-t</option> <replaceable>triggerfile</replaceable></term>
- <listitem>
- <para>
- Specify a trigger file whose presence should cause failover.
- It is recommended that you use a structured file name to
- avoid confusion as to which server is being triggered
- when multiple servers exist on the same system; for example
- <filename>/tmp/pgsql.trigger.5432</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-V</option></term>
- <term><option>--version</option></term>
- <listitem>
- <para>
- Print the <application>pg_standby</application> version and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-w</option> <replaceable>maxwaittime</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of seconds to wait for the next WAL file,
- after which a fast failover will be performed.
- A setting of zero (the default) means wait forever.
- The default setting is not necessarily recommended;
- consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-?</option></term>
- <term><option>--help</option></term>
- <listitem>
- <para>
- Show help about <application>pg_standby</application> command line
- arguments, and exit.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <para>
- <application>pg_standby</application> is designed to work with
- <productname>PostgreSQL</productname> 8.2 and later.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.3 provides the <literal>%r</literal> macro,
- which is designed to let <application>pg_standby</application> know the
- last file it needs to keep. With <productname>PostgreSQL</productname> 8.2, the
- <literal>-k</literal> option must be used if archive cleanup is
- required. This option remains available in 8.3, but its use is deprecated.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.4 provides the
- <varname>recovery_end_command</varname> option. Without this option
- a leftover trigger file can be hazardous.
- </para>
-
- <para>
- <application>pg_standby</application> is written in C and has an
- easy-to-modify source code, with specifically designated sections to modify
- for your own needs
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <para>On Linux or Unix systems, you might use:
-
-<programlisting>
-archive_command = 'cp %p .../archive/%f'
-
-restore_command = 'pg_standby -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442'
-</programlisting>
- where the archive directory is physically located on the standby server,
- so that the <varname>archive_command</varname> is accessing it across NFS,
- but the files are local to the standby (enabling use of <literal>ln</literal>).
- This will:
- <itemizedlist>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 2 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>/tmp/pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>On Windows, you might use:
-
-<programlisting>
-archive_command = 'copy %p ...\\archive\\%f'
-
-restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'del C:\pgsql.trigger.5442'
-</programlisting>
- Note that backslashes need to be doubled in the
- <varname>archive_command</varname>, but <emphasis>not</emphasis> in the
- <varname>restore_command</varname> or <varname>recovery_end_command</varname>.
- This will:
- <itemizedlist>
- <listitem>
- <para>
- use the <literal>copy</literal> command to restore WAL files from archive
- </para>
- </listitem>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 5 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>C:\pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- The <literal>copy</literal> command on Windows sets the final file size
- before the file is completely copied, which would ordinarily confuse
- <application>pg_standby</application>. Therefore
- <application>pg_standby</application> waits <replaceable>sleeptime</replaceable>
- seconds once it sees the proper file size. GNUWin32's <literal>cp</literal>
- sets the file size only after the file copy is complete.
- </para>
-
- <para>
- Since the Windows example uses <literal>copy</literal> at both ends, either
- or both servers might be accessing the archive directory across the
- network.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Author</title>
-
- <para>
- Simon Riggs <email>simon@2ndquadrant.com</email>
- </para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgarchivecleanup"/></member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 90594bd41b..33ebea2965 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -34,8 +34,8 @@ my @unlink_on_exit;
# Set of variables for modules in contrib/ and src/test/modules/
my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
my @contrib_uselibpq = ('dblink', 'oid2name', 'postgres_fdw', 'vacuumlo');
-my @contrib_uselibpgport = ('oid2name', 'pg_standby', 'vacuumlo');
-my @contrib_uselibpgcommon = ('oid2name', 'pg_standby', 'vacuumlo');
+my @contrib_uselibpgport = ('oid2name', 'vacuumlo');
+my @contrib_uselibpgcommon = ('oid2name', 'vacuumlo');
my $contrib_extralibs = undef;
my $contrib_extraincludes = { 'dblink' => ['src/backend'] };
my $contrib_extrasource = {
--
2.17.0
v1-0002-Retire-pg_archivecleanup.patchtext/x-diff; charset=utf-8Download
From e2c86541d4f9f8d01c0f407ec4d8f5aec35e080f Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 26 Oct 2020 16:45:39 -0500
Subject: [PATCH v1 2/2] Retire pg_archivecleanup
---
doc/src/sgml/config.sgml | 4 -
doc/src/sgml/high-availability.sgml | 12 -
doc/src/sgml/ref/allfiles.sgml | 1 -
doc/src/sgml/ref/pgarchivecleanup.sgml | 215 ----------
doc/src/sgml/reference.sgml | 1 -
src/bin/Makefile | 1 -
src/bin/pg_archivecleanup/.gitignore | 3 -
src/bin/pg_archivecleanup/Makefile | 36 --
src/bin/pg_archivecleanup/nls.mk | 6 -
src/bin/pg_archivecleanup/pg_archivecleanup.c | 378 ------------------
src/bin/pg_archivecleanup/po/cs.po | 189 ---------
src/bin/pg_archivecleanup/po/de.po | 178 ---------
src/bin/pg_archivecleanup/po/es.po | 185 ---------
src/bin/pg_archivecleanup/po/fr.po | 201 ----------
src/bin/pg_archivecleanup/po/ja.po | 212 ----------
src/bin/pg_archivecleanup/po/ko.po | 179 ---------
src/bin/pg_archivecleanup/po/pl.po | 178 ---------
src/bin/pg_archivecleanup/po/ru.po | 192 ---------
src/bin/pg_archivecleanup/po/sv.po | 179 ---------
src/bin/pg_archivecleanup/po/tr.po | 185 ---------
src/bin/pg_archivecleanup/po/uk.po | 161 --------
src/bin/pg_archivecleanup/po/vi.po | 183 ---------
src/bin/pg_archivecleanup/po/zh_CN.po | 174 --------
.../t/010_pg_archivecleanup.pl | 98 -----
src/tools/msvc/Mkvcbuild.pm | 4 +-
25 files changed, 2 insertions(+), 3153 deletions(-)
delete mode 100644 doc/src/sgml/ref/pgarchivecleanup.sgml
delete mode 100644 src/bin/pg_archivecleanup/.gitignore
delete mode 100644 src/bin/pg_archivecleanup/Makefile
delete mode 100644 src/bin/pg_archivecleanup/nls.mk
delete mode 100644 src/bin/pg_archivecleanup/pg_archivecleanup.c
delete mode 100644 src/bin/pg_archivecleanup/po/cs.po
delete mode 100644 src/bin/pg_archivecleanup/po/de.po
delete mode 100644 src/bin/pg_archivecleanup/po/es.po
delete mode 100644 src/bin/pg_archivecleanup/po/fr.po
delete mode 100644 src/bin/pg_archivecleanup/po/ja.po
delete mode 100644 src/bin/pg_archivecleanup/po/ko.po
delete mode 100644 src/bin/pg_archivecleanup/po/pl.po
delete mode 100644 src/bin/pg_archivecleanup/po/ru.po
delete mode 100644 src/bin/pg_archivecleanup/po/sv.po
delete mode 100644 src/bin/pg_archivecleanup/po/tr.po
delete mode 100644 src/bin/pg_archivecleanup/po/uk.po
delete mode 100644 src/bin/pg_archivecleanup/po/vi.po
delete mode 100644 src/bin/pg_archivecleanup/po/zh_CN.po
delete mode 100644 src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1b6f3a6456..d89b977ff2 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -3567,10 +3567,6 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
may be safely removed.
This information can be used to truncate the archive to just the
minimum required to support restart from the current restore.
- The <xref linkend="pgarchivecleanup"/> module
- is often used in <varname>archive_cleanup_command</varname> for
- single-standby configurations, for example:
-<programlisting>archive_cleanup_command = 'pg_archivecleanup /mnt/server/archivedir %r'</programlisting>
Note however that if multiple standby servers are restoring from the
same archive directory, you will need to ensure that you do not delete
WAL files until they are no longer needed by any of the servers.
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index 6425d8b15d..b2ca63d370 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -726,23 +726,11 @@ protocol to make nodes agree on a serializable transactional order.
If you're using a WAL archive, its size can be minimized using the <xref
linkend="guc-archive-cleanup-command"/> parameter to remove files that are no
longer required by the standby server.
- The <application>pg_archivecleanup</application> utility is designed specifically to
- be used with <varname>archive_cleanup_command</varname> in typical single-standby
- configurations, see <xref linkend="pgarchivecleanup"/>.
Note however, that if you're using the archive for backup purposes, you
need to retain files needed to recover from at least the latest base
backup, even if they're no longer needed by the standby.
</para>
- <para>
- A simple example of configuration is:
-<programlisting>
-primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass options=''-c wal_sender_timeout=5000'''
-restore_command = 'cp /path/to/archive/%f %p'
-archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
-</programlisting>
- </para>
-
<para>
You can have any number of standby servers, but if you use streaming
replication, make sure you set <varname>max_wal_senders</varname> high enough in
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 0f0064150c..9729cc3f92 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -196,7 +196,6 @@ Complete list of usable sgml source files in this directory.
<!ENTITY dropuser SYSTEM "dropuser.sgml">
<!ENTITY ecpgRef SYSTEM "ecpg-ref.sgml">
<!ENTITY initdb SYSTEM "initdb.sgml">
-<!ENTITY pgarchivecleanup SYSTEM "pgarchivecleanup.sgml">
<!ENTITY pgBasebackup SYSTEM "pg_basebackup.sgml">
<!ENTITY pgbench SYSTEM "pgbench.sgml">
<!ENTITY pgChecksums SYSTEM "pg_checksums.sgml">
diff --git a/doc/src/sgml/ref/pgarchivecleanup.sgml b/doc/src/sgml/ref/pgarchivecleanup.sgml
deleted file mode 100644
index 56f02fc0e6..0000000000
--- a/doc/src/sgml/ref/pgarchivecleanup.sgml
+++ /dev/null
@@ -1,215 +0,0 @@
-<!--
-doc/src/sgml/ref/pgarchivecleanup.sgml
-PostgreSQL documentation
--->
-
-<refentry id="pgarchivecleanup">
- <indexterm zone="pgarchivecleanup">
- <primary>pg_archivecleanup</primary>
- </indexterm>
-
- <refmeta>
- <refentrytitle><application>pg_archivecleanup</application></refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo>Application</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>pg_archivecleanup</refname>
- <refpurpose>clean up <productname>PostgreSQL</productname> WAL archive files</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>pg_archivecleanup</command>
- <arg rep="repeat"><replaceable>option</replaceable></arg>
- <arg choice="plain"><replaceable>archivelocation</replaceable></arg>
- <arg choice="plain"><replaceable>oldestkeptwalfile</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <application>pg_archivecleanup</application> is designed to be used as an
- <literal>archive_cleanup_command</literal> to clean up WAL file archives when
- running as a standby server (see <xref linkend="warm-standby"/>).
- <application>pg_archivecleanup</application> can also be used as a standalone program to
- clean WAL file archives.
- </para>
-
- <para>
- To configure a standby
- server to use <application>pg_archivecleanup</application>, put this into its
- <filename>postgresql.conf</filename> configuration file:
-<programlisting>
-archive_cleanup_command = 'pg_archivecleanup <replaceable>archivelocation</replaceable> %r'
-</programlisting>
- where <replaceable>archivelocation</replaceable> is the directory from which WAL segment
- files should be removed.
- </para>
- <para>
- When used within <xref linkend="guc-archive-cleanup-command"/>, all WAL files
- logically preceding the value of the <literal>%r</literal> argument will be removed
- from <replaceable>archivelocation</replaceable>. This minimizes the number of files
- that need to be retained, while preserving crash-restart capability. Use of
- this parameter is appropriate if the <replaceable>archivelocation</replaceable> is a
- transient staging area for this particular standby server, but
- <emphasis>not</emphasis> when the <replaceable>archivelocation</replaceable> is intended as a
- long-term WAL archive area, or when multiple standby servers are recovering
- from the same archive location.
- </para>
- <para>
- When used as a standalone program all WAL files logically preceding the
- <replaceable>oldestkeptwalfile</replaceable> will be removed from <replaceable>archivelocation</replaceable>.
- In this mode, if you specify a <filename>.partial</filename> or <filename>.backup</filename>
- file name, then only the file prefix will be used as the
- <replaceable>oldestkeptwalfile</replaceable>. This treatment of <filename>.backup</filename>
- file name allows you to remove
- all WAL files archived prior to a specific base backup without error.
- For example, the following example will remove all files older than
- WAL file name <filename>000000010000003700000010</filename>:
-<programlisting>
-pg_archivecleanup -d archive 000000010000003700000010.00000020.backup
-
-pg_archivecleanup: keep WAL file "archive/000000010000003700000010" and later
-pg_archivecleanup: removing file "archive/00000001000000370000000F"
-pg_archivecleanup: removing file "archive/00000001000000370000000E"
-</programlisting>
- </para>
- <para>
- <application>pg_archivecleanup</application> assumes that
- <replaceable>archivelocation</replaceable> is a directory readable and writable by the
- server-owning user.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>
- <application>pg_archivecleanup</application> accepts the following command-line arguments:
-
- <variablelist>
-
- <varlistentry>
- <term><option>-d</option></term>
- <listitem>
- <para>
- Print lots of debug logging output on <filename>stderr</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-n</option></term>
- <listitem>
- <para>
- Print the names of the files that would have been removed on <filename>stdout</filename> (performs a dry run).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-V</option></term>
- <term><option>--version</option></term>
- <listitem>
- <para>
- Print the <application>pg_archivecleanup</application> version and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-x</option> <replaceable>extension</replaceable></term>
- <listitem>
- <para>
- Provide an extension
- that will be stripped from all file names before deciding if they
- should be deleted. This is typically useful for cleaning up archives
- that have been compressed during storage, and therefore have had an
- extension added by the compression program. For example: <literal>-x
- .gz</literal>.
- </para>
-
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-?</option></term>
- <term><option>--help</option></term>
- <listitem>
- <para>
- Show help about <application>pg_archivecleanup</application> command line
- arguments, and exit.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
- </refsect1>
-
- <refsect1>
- <title>Environment</title>
-
- <para>
- The environment variable <envar>PG_COLOR</envar> specifies whether to use
- color in diagnostic messages. Possible values are
- <literal>always</literal>, <literal>auto</literal> and
- <literal>never</literal>.
- </para>
- </refsect1>
-
-
- <refsect1>
- <title>Notes</title>
-
- <para>
- <application>pg_archivecleanup</application> is designed to work with
- <productname>PostgreSQL</productname> 8.0 and later when used as a standalone utility,
- or with <productname>PostgreSQL</productname> 9.0 and later when used as an
- archive cleanup command.
- </para>
-
- <para>
- <application>pg_archivecleanup</application> is written in C and has an
- easy-to-modify source code, with specifically designated sections to modify
- for your own needs
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <para>On Linux or Unix systems, you might use:
-<programlisting>
-archive_cleanup_command = 'pg_archivecleanup -d /mnt/standby/archive %r 2>>cleanup.log'
-</programlisting>
- where the archive directory is physically located on the standby server,
- so that the <varname>archive_command</varname> is accessing it across NFS,
- but the files are local to the standby.
- This will:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- produce debugging output in <filename>cleanup.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgstandby"/></member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index dd2bddab8c..5a8690efcb 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -276,7 +276,6 @@
</partintro>
&initdb;
- &pgarchivecleanup;
&pgChecksums;
&pgControldata;
&pgCtl;
diff --git a/src/bin/Makefile b/src/bin/Makefile
index 8b870357a1..19fb434e50 100644
--- a/src/bin/Makefile
+++ b/src/bin/Makefile
@@ -15,7 +15,6 @@ include $(top_builddir)/src/Makefile.global
SUBDIRS = \
initdb \
- pg_archivecleanup \
pg_basebackup \
pg_checksums \
pg_config \
diff --git a/src/bin/pg_archivecleanup/.gitignore b/src/bin/pg_archivecleanup/.gitignore
deleted file mode 100644
index bd05d00156..0000000000
--- a/src/bin/pg_archivecleanup/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/pg_archivecleanup
-
-/tmp_check/
diff --git a/src/bin/pg_archivecleanup/Makefile b/src/bin/pg_archivecleanup/Makefile
deleted file mode 100644
index 49935d6dce..0000000000
--- a/src/bin/pg_archivecleanup/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-# src/bin/pg_archivecleanup/Makefile
-
-PGFILEDESC = "pg_archivecleanup - cleans archive when used with streaming replication"
-PGAPPICON = win32
-
-subdir = src/bin/pg_archivecleanup
-top_builddir = ../../..
-include $(top_builddir)/src/Makefile.global
-
-OBJS = \
- $(WIN32RES) \
- pg_archivecleanup.o
-
-all: pg_archivecleanup
-
-pg_archivecleanup: $(OBJS) | submake-libpgport
- $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
-
-install: all installdirs
- $(INSTALL_PROGRAM) pg_archivecleanup$(X) '$(DESTDIR)$(bindir)/pg_archivecleanup$(X)'
-
-installdirs:
- $(MKDIR_P) '$(DESTDIR)$(bindir)'
-
-uninstall:
- rm -f '$(DESTDIR)$(bindir)/pg_archivecleanup$(X)'
-
-clean distclean maintainer-clean:
- rm -f pg_archivecleanup$(X) $(OBJS)
- rm -rf tmp_check
-
-check:
- $(prove_check)
-
-installcheck:
- $(prove_installcheck)
diff --git a/src/bin/pg_archivecleanup/nls.mk b/src/bin/pg_archivecleanup/nls.mk
deleted file mode 100644
index 20a09c8d78..0000000000
--- a/src/bin/pg_archivecleanup/nls.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-# src/bin/pg_archivecleanup/nls.mk
-CATALOG_NAME = pg_archivecleanup
-AVAIL_LANGUAGES = cs de es fr ja ko pl ru sv tr uk vi zh_CN
-GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) pg_archivecleanup.c
-GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS)
-GETTEXT_FLAGS = $(FRONTEND_COMMON_GETTEXT_FLAGS)
diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c
deleted file mode 100644
index 12338e3bb2..0000000000
--- a/src/bin/pg_archivecleanup/pg_archivecleanup.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * pg_archivecleanup.c
- *
- * To be used as archive_cleanup_command to clean an archive when using
- * standby mode.
- *
- * src/bin/pg_archivecleanup/pg_archivecleanup.c
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "access/xlog_internal.h"
-#include "common/logging.h"
-#include "pg_getopt.h"
-
-const char *progname;
-
-/* Options and defaults */
-bool dryrun = false; /* are we performing a dry-run operation? */
-char *additional_ext = NULL; /* Extension to remove from filenames */
-
-char *archiveLocation; /* where to find the archive? */
-char *restartWALFileName; /* the file from which we can restart restore */
-char exclusiveCleanupFileName[MAXFNAMELEN]; /* the oldest file we want
- * to remain in archive */
-
-
-/* =====================================================================
- *
- * 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
- * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
- * or personally to the current maintainer. Those changes may be
- * folded in to later versions of this program.
- */
-
-/*
- * Initialize allows customized commands into the archive cleanup program.
- *
- * You may wish to add code to check for tape libraries, etc..
- */
-static void
-Initialize(void)
-{
- /*
- * This code assumes that archiveLocation is a directory, so we use stat
- * to test if it's accessible.
- */
- struct stat stat_buf;
-
- if (stat(archiveLocation, &stat_buf) != 0 ||
- !S_ISDIR(stat_buf.st_mode))
- {
- pg_log_error("archive location \"%s\" does not exist",
- archiveLocation);
- exit(2);
- }
-}
-
-static void
-TrimExtension(char *filename, char *extension)
-{
- int flen;
- int elen;
-
- if (extension == NULL)
- return;
-
- elen = strlen(extension);
- flen = strlen(filename);
-
- if (flen > elen && strcmp(filename + flen - elen, extension) == 0)
- filename[flen - elen] = '\0';
-}
-
-static void
-CleanupPriorWALFiles(void)
-{
- int rc;
- DIR *xldir;
- struct dirent *xlde;
- char walfile[MAXPGPATH];
-
- if ((xldir = opendir(archiveLocation)) != NULL)
- {
- while (errno = 0, (xlde = readdir(xldir)) != NULL)
- {
- /*
- * Truncation is essentially harmless, because we skip names of
- * length other than XLOG_FNAME_LEN. (In principle, one could use
- * a 1000-character additional_ext and get trouble.)
- */
- strlcpy(walfile, xlde->d_name, MAXPGPATH);
- TrimExtension(walfile, additional_ext);
-
- /*
- * 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.
- *
- * 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.
- */
- if ((IsXLogFileName(walfile) || IsPartialXLogFileName(walfile)) &&
- strcmp(walfile + 8, exclusiveCleanupFileName + 8) < 0)
- {
- char WALFilePath[MAXPGPATH * 2]; /* the file path
- * including archive */
-
- /*
- * Use the original file name again now, including any
- * extension that might have been chopped off before testing
- * the sequence.
- */
- snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s",
- archiveLocation, xlde->d_name);
-
- if (dryrun)
- {
- /*
- * Prints the name of the file to be removed and skips the
- * actual removal. The regular printout is so that the
- * user can pipe the output into some other program.
- */
- printf("%s\n", WALFilePath);
- pg_log_debug("file \"%s\" would be removed", WALFilePath);
- continue;
- }
-
- pg_log_debug("removing file \"%s\"", WALFilePath);
-
- rc = unlink(WALFilePath);
- if (rc != 0)
- {
- pg_log_error("could not remove file \"%s\": %m",
- WALFilePath);
- break;
- }
- }
- }
-
- if (errno)
- pg_log_error("could not read archive location \"%s\": %m",
- archiveLocation);
- if (closedir(xldir))
- pg_log_error("could not close archive location \"%s\": %m",
- archiveLocation);
- }
- else
- pg_log_error("could not open archive location \"%s\": %m",
- archiveLocation);
-}
-
-/*
- * SetWALFileNameForCleanup()
- *
- * Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need cleanup
- */
-static void
-SetWALFileNameForCleanup(void)
-{
- bool fnameOK = false;
-
- TrimExtension(restartWALFileName, additional_ext);
-
- /*
- * If restartWALFileName is a WAL file name then just use it directly. If
- * restartWALFileName is a .partial or .backup filename, make sure we use
- * the prefix of the filename, otherwise we will remove wrong files since
- * 000000010000000000000010.partial and
- * 000000010000000000000010.00000020.backup are after
- * 000000010000000000000010.
- */
- if (IsXLogFileName(restartWALFileName))
- {
- strcpy(exclusiveCleanupFileName, restartWALFileName);
- fnameOK = true;
- }
- else if (IsPartialXLogFileName(restartWALFileName))
- {
- int args;
- uint32 tli = 1,
- log = 0,
- seg = 0;
-
- args = sscanf(restartWALFileName, "%08X%08X%08X.partial",
- &tli, &log, &seg);
- if (args == 3)
- {
- fnameOK = true;
-
- /*
- * Use just the prefix of the filename, ignore everything after
- * first period
- */
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
- }
- }
- else if (IsBackupHistoryFileName(restartWALFileName))
- {
- int args;
- uint32 tli = 1,
- log = 0,
- seg = 0,
- offset = 0;
-
- args = sscanf(restartWALFileName, "%08X%08X%08X.%08X.backup", &tli, &log, &seg, &offset);
- if (args == 4)
- {
- fnameOK = true;
-
- /*
- * Use just the prefix of the filename, ignore everything after
- * first period
- */
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
- }
- }
-
- if (!fnameOK)
- {
- pg_log_error("invalid file name argument");
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(2);
- }
-}
-
-/* =====================================================================
- * End of Customizable section
- * =====================================================================
- */
-
-static void
-usage(void)
-{
- printf(_("%s removes older WAL files from PostgreSQL archives.\n\n"), progname);
- printf(_("Usage:\n"));
- printf(_(" %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"), progname);
- printf(_("\nOptions:\n"));
- printf(_(" -d generate debug output (verbose mode)\n"));
- printf(_(" -n dry run, show the names of the files that would be removed\n"));
- printf(_(" -V, --version output version information, then exit\n"));
- printf(_(" -x EXT clean up files if they have this extension\n"));
- printf(_(" -?, --help show this help, then exit\n"));
- printf(_("\n"
- "For use as archive_cleanup_command in postgresql.conf:\n"
- " archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
- "e.g.\n"
- " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"));
- printf(_("\n"
- "Or for use as a standalone archive cleaner:\n"
- "e.g.\n"
- " pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"));
- printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
- printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
-}
-
-/*------------ MAIN ----------------------------------------*/
-int
-main(int argc, char **argv)
-{
- int c;
-
- pg_logging_init(argv[0]);
- set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_archivecleanup"));
- 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_archivecleanup (PostgreSQL) " PG_VERSION);
- exit(0);
- }
- }
-
- while ((c = getopt(argc, argv, "x:dn")) != -1)
- {
- switch (c)
- {
- case 'd': /* Debug mode */
- pg_logging_increase_verbosity();
- break;
- case 'n': /* Dry-Run mode */
- dryrun = true;
- break;
- case 'x':
- additional_ext = pg_strdup(optarg); /* Extension to remove
- * from xlogfile names */
- break;
- default:
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(2);
- break;
- }
- }
-
- /*
- * We will go to the archiveLocation to check restartWALFileName.
- * restartWALFileName may not exist anymore, which would not be an error,
- * so we separate the archiveLocation and restartWALFileName so we can
- * check separately whether archiveLocation exists, if not that is an
- * error
- */
- if (optind < argc)
- {
- archiveLocation = argv[optind];
- optind++;
- }
- else
- {
- pg_log_error("must specify archive location");
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- restartWALFileName = argv[optind];
- optind++;
- }
- else
- {
- pg_log_error("must specify oldest kept WAL file");
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- pg_log_error("too many command-line arguments");
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(2);
- }
-
- /*
- * Check archive exists and other initialization if required.
- */
- Initialize();
-
- /*
- * Check filename is a valid name, then process to find cut-off
- */
- SetWALFileNameForCleanup();
-
- pg_log_debug("keeping WAL file \"%s/%s\" and later",
- archiveLocation, exclusiveCleanupFileName);
-
- /*
- * Remove WAL files older than cut-off
- */
- CleanupPriorWALFiles();
-
- exit(0);
-}
diff --git a/src/bin/pg_archivecleanup/po/cs.po b/src/bin/pg_archivecleanup/po/cs.po
deleted file mode 100644
index c7f87a76a8..0000000000
--- a/src/bin/pg_archivecleanup/po/cs.po
+++ /dev/null
@@ -1,189 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2018 PostgreSQL Global Development Group
-# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 11\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-09-27 08:15+0000\n"
-"PO-Revision-Date: 2019-09-28 11:28+0200\n"
-"Last-Translator: \n"
-"Language-Team: \n"
-"Language: cs\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.2.3\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-#| msgid "fatal\n"
-msgid "fatal: "
-msgstr "fatal: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-#| msgid "SQL error: %s\n"
-msgid "error: "
-msgstr "error: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-#| msgid "warning"
-msgid "warning: "
-msgstr "warning: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "archivnà lokace \"%s\" neexistuje"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "nelze odstranit soubor \"%s\": %m"
-
-#: pg_archivecleanup.c:162
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "nelze naÄÃst archivnà lokaci \"%s\": %m"
-
-#: pg_archivecleanup.c:165
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "nelze uzavÅÃt archivnà lokaci \"%s\": %m"
-
-#: pg_archivecleanup.c:169
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "nelze otevÅÃt archivnà lokaci \"%s\": %m"
-
-#: pg_archivecleanup.c:242
-#, c-format
-msgid "invalid file name argument"
-msgstr "chybný argument jména souboru"
-
-#: pg_archivecleanup.c:243 pg_archivecleanup.c:316 pg_archivecleanup.c:337
-#: pg_archivecleanup.c:349 pg_archivecleanup.c:356
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Zkuste \"%s --help\" pro vÃce informacÃ.\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s odstranà staršà WAL soubory z PostgreSQL archivů.\n"
-"\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid "Usage:\n"
-msgstr "PoužitÃ:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"PÅepÃnaÄe:\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d vygeneruje debug výstup (vÃce informacÃ)\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n zkuÅ¡ebnà bÄh, ukazuje jména souborů které by byly odstranÄny\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version vypÃÅ¡e informaci o verzi, pak skonÄÃ\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT vyÄistà soubory pokud majà tuto pÅÃponu\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help ukáže tuto nápovÄdu, a skonÄÃ\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"Pro použità jako archive_cleanup_command v recovery.conf pokud standby_mode = on:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Nebo jako samostatný ÄistiÄ archivu:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:274
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"Chyby hlaste na adresu <pgsql-bugs@postgresql.org>.\n"
-
-#: pg_archivecleanup.c:336
-#, c-format
-msgid "must specify archive location"
-msgstr "nutno zadat archivnà lokaci"
-
-#: pg_archivecleanup.c:348
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "nutno zadat nejstarÄà uchovávaný WAL soubor"
-
-#: pg_archivecleanup.c:355
-#, c-format
-msgid "too many command-line arguments"
-msgstr "pÅÃliÅ¡ mnoho argumentů na pÅÃkazové Åádce"
-
-#~ msgid "%s: keeping WAL file \"%s\" and later\n"
-#~ msgstr "%s: uchovávám WAL soubor \"%s\" a novÄjÅ¡Ã\n"
-
-#~ msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-#~ msgstr "%s: ERROR: nelze odstranit soubor \"%s\": %s\n"
-
-#~ msgid "%s: removing file \"%s\"\n"
-#~ msgstr "%s: odstraÅuji soubor \"%s\"\n"
-
-#~ msgid "%s: file \"%s\" would be removed\n"
-#~ msgstr "%s: soubor \"%s\" by byl odstranÄn\n"
diff --git a/src/bin/pg_archivecleanup/po/de.po b/src/bin/pg_archivecleanup/po/de.po
deleted file mode 100644
index 7f1664b09d..0000000000
--- a/src/bin/pg_archivecleanup/po/de.po
+++ /dev/null
@@ -1,178 +0,0 @@
-# pg_archivecleanup message translation file for pg_archivecleanup
-# Copyright (C) 2019-2020 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# Peter Eisentraut <peter@eisentraut.org>, 2019 - 2020.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 13\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2020-04-09 10:17+0000\n"
-"PO-Revision-Date: 2020-04-09 15:15+0200\n"
-"Last-Translator: Peter Eisentraut <peter@eisentraut.org>\n"
-"Language-Team: German <pgsql-translators@postgresql.org>\n"
-"Language: de\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: ../../../src/common/logging.c:236
-#, c-format
-msgid "fatal: "
-msgstr "Fatal: "
-
-#: ../../../src/common/logging.c:243
-#, c-format
-msgid "error: "
-msgstr "Fehler: "
-
-#: ../../../src/common/logging.c:250
-#, c-format
-msgid "warning: "
-msgstr "Warnung: "
-
-#: pg_archivecleanup.c:66
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "Archivverzeichnis »%s« existiert nicht"
-
-#: pg_archivecleanup.c:152
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "konnte Datei »%s« nicht löschen: %m"
-
-#: pg_archivecleanup.c:160
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "konnte Archivverzeichnis »%s« nicht lesen: %m"
-
-#: pg_archivecleanup.c:163
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "konnte Archivverzeichnis »%s« nicht schlieÃen: %m"
-
-#: pg_archivecleanup.c:167
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "konnte Archivverzeichnis »%s« nicht öffnen: %m"
-
-#: pg_archivecleanup.c:240
-#, c-format
-msgid "invalid file name argument"
-msgstr "ungültiges Dateinamenargument"
-
-#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n"
-
-#: pg_archivecleanup.c:254
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s entfernt alte WAL-Dateien aus PostgreSQL-Archiven.\n"
-"\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid "Usage:\n"
-msgstr "Aufruf:\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPTION]... ARCHIVVERZEICHNIS ÃLTESTE-ZU-BEHALTENE-WALDATEI\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Optionen:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d Debug-Ausgaben erzeugen (Verbose-Modus)\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n Probelauf, Namen der Dateien anzeigen, die entfernt würden\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x ERW Dateien mit dieser Erweiterung aufräumen\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"Verwendung als archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVVERZ %%r'\n"
-"z.B.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiv %%r'\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Oder alleinstehende Verwendung zum Aufräumen eines Archivs:\n"
-"z.B.\n"
-" pg_archivecleanup /mnt/server/archiv 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:272
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <%s>.\n"
-msgstr ""
-"\n"
-"Berichten Sie Fehler an <%s>.\n"
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid "%s home page: <%s>\n"
-msgstr "%s Homepage: <%s>\n"
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "Archivverzeichnis muss angegeben werden"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "älteste zu behaltene WAL-Datei muss angegeben werden"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "zu viele Kommandozeilenargumente"
diff --git a/src/bin/pg_archivecleanup/po/es.po b/src/bin/pg_archivecleanup/po/es.po
deleted file mode 100644
index f0350a1385..0000000000
--- a/src/bin/pg_archivecleanup/po/es.po
+++ /dev/null
@@ -1,185 +0,0 @@
-# Spanish message translation file for pg_archivecleanup
-# Copyright (c) 2017-2019, PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-#
-# Carlos Chapi <carlos.chapi@2ndquadrant.com>, 2017.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 12\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2020-05-17 02:47+0000\n"
-"PO-Revision-Date: 2019-06-06 17:21-0400\n"
-"Last-Translator: Carlos Chapi <carlos.chapi@2ndquadrant.com>\n"
-"Language-Team: PgSQL-es-Ayuda <pgsql-es-ayuda@lists.postgresql.org>\n"
-"Language: es\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: BlackCAT 1.0\n"
-
-#: ../../../src/common/logging.c:236
-#, c-format
-msgid "fatal: "
-msgstr "fatal: "
-
-#: ../../../src/common/logging.c:243
-#, c-format
-msgid "error: "
-msgstr "error: "
-
-#: ../../../src/common/logging.c:250
-#, c-format
-msgid "warning: "
-msgstr "precaución: "
-
-#: pg_archivecleanup.c:66
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "ubicación de archivador «%s» no existe"
-
-#: pg_archivecleanup.c:152
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "no se pudo eliminar el archivo «%s»: %m"
-
-#: pg_archivecleanup.c:160
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "no se pudo leer la ubicación del archivador «%s»: %m"
-
-#: pg_archivecleanup.c:163
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "no se pudo cerrar la ubicación del archivador «%s»: %m"
-
-#: pg_archivecleanup.c:167
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "no se pudo abrir la ubicación del archivador «%s»: %m"
-
-#: pg_archivecleanup.c:240
-#, c-format
-msgid "invalid file name argument"
-msgstr "el nombre de archivo usado como argumento no es válido"
-
-#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Pruebe «%s --help» para mayor información.\n"
-
-#: pg_archivecleanup.c:254
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s elimina archivos de WAL antiguos del archivador de PostgreSQL.\n"
-"\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid "Usage:\n"
-msgstr "Empleo:\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPCIÃN].... UBICACIÃNARCHIVADOR WALMÃSANTIGUOAMANTENER\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Opciones:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d genera salida de depuración (modo verboso)\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n simulacro, muestra el nombre de los archivos que se eliminarÃan\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version muestra información de la versión, luego sale\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT hace limpieza de archivos que tengan esta extensión\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help muestra esta ayuda, luego sale\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"Para usar como archive_cleanup_command en postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPCIÃN]... UBICACIÃNARCHIVADOR %%r'\n"
-"por ej.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/servidor/directorioarchivador %%r'\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"O para usar como un limpiador de archivador de forma independiente:\n"
-"por ej.\n"
-" pg_archivecleanup /mnt/servidor/directorioarchivador 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:272
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <%s>.\n"
-msgstr ""
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid "%s home page: <%s>\n"
-msgstr ""
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "debe especificar la ubicación del archivador"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "debe especificar el fichero WAL más antiguo a mantener"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "demasiados argumentos de lÃnea de órdenes"
-
-#~ msgid ""
-#~ "\n"
-#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-#~ msgstr ""
-#~ "\n"
-#~ "Reporte errores a <pgsql-bugs@lists.postgresql.org>.\n"
diff --git a/src/bin/pg_archivecleanup/po/fr.po b/src/bin/pg_archivecleanup/po/fr.po
deleted file mode 100644
index 02749f8a63..0000000000
--- a/src/bin/pg_archivecleanup/po/fr.po
+++ /dev/null
@@ -1,201 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 12\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2020-04-16 06:16+0000\n"
-"PO-Revision-Date: 2020-04-16 13:39+0200\n"
-"Last-Translator: \n"
-"Language-Team: \n"
-"Language: fr\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.3\n"
-
-#: ../../../src/common/logging.c:236
-#, c-format
-msgid "fatal: "
-msgstr "fatal : "
-
-#: ../../../src/common/logging.c:243
-#, c-format
-msgid "error: "
-msgstr "erreur : "
-
-#: ../../../src/common/logging.c:250
-#, c-format
-msgid "warning: "
-msgstr "attention : "
-
-#: pg_archivecleanup.c:66
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "l'emplacement d'archivage « %s » n'existe pas"
-
-#: pg_archivecleanup.c:152
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "n'a pas pu supprimer le fichier « %s » : %m"
-
-#: pg_archivecleanup.c:160
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "n'a pas pu lire l'emplacement de l'archive « %s » : %m"
-
-#: pg_archivecleanup.c:163
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "n'a pas pu fermer l'emplacement de l'archive « %s » : %m"
-
-#: pg_archivecleanup.c:167
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "n'a pas pu ouvrir l'emplacement de l'archive « %s » : %m"
-
-#: pg_archivecleanup.c:240
-#, c-format
-msgid "invalid file name argument"
-msgstr "argument du nom de fichier invalide"
-
-#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Essayez « %s --help » pour plus d'informations.\n"
-
-#: pg_archivecleanup.c:254
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s supprime les anciens fichiers WAL des archives de PostgreSQL.\n"
-"\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid "Usage:\n"
-msgstr "Usage :\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPTION]... EMPLACEMENTARCHIVE PLUSANCIENFICHIERWALCONSERVÃ\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Options :\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d affiche des informations de débugage (mode verbeux)\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n test, affiche le nom des fichiers qui seraient supprimés\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version affiche la version et quitte\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT nettoie les fichiers s'ils ont cette extension\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help affiche cette aide et quitte\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"Pour utiliser comme archive_cleanup_command dans postgresql.conf :\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... EMPLACEMENTARCHIVE %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/serveur/reparchives %%r'\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Ou pour utiliser comme nettoyeur autonome d'archives :\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/serveur/reparchives 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:272
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <%s>.\n"
-msgstr ""
-"\n"
-"Rapporter les bogues à <%s>.\n"
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid "%s home page: <%s>\n"
-msgstr "page d'accueil de %s : <%s>\n"
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "doit spécifier l'emplacement de l'archive"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "doit spécifier le plus ancien journal de transactions conservé"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "trop d'arguments en ligne de commande"
-
-#~ msgid "%s: file \"%s\" would be removed\n"
-#~ msgstr "%s : le fichier « %s » serait supprimé\n"
-
-#~ msgid "%s: removing file \"%s\"\n"
-#~ msgstr "%s : suppression du fichier « %s »\n"
-
-#~ msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-#~ msgstr "%s : ERREUR : n'a pas pu supprimer le fichier « %s » : %s\n"
-
-#~ msgid "%s: keeping WAL file \"%s\" and later\n"
-#~ msgstr "%s : conservation du fichier WAL « %s » et des suivants\n"
-
-#~ msgid "%s: too many parameters\n"
-#~ msgstr "%s : trop de paramètres\n"
-
-#~ msgid ""
-#~ "\n"
-#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-#~ msgstr ""
-#~ "\n"
-#~ "Rapporter les bogues à <pgsql-bugs@lists.postgresql.org>.\n"
diff --git a/src/bin/pg_archivecleanup/po/ja.po b/src/bin/pg_archivecleanup/po/ja.po
deleted file mode 100644
index c1d079a6df..0000000000
--- a/src/bin/pg_archivecleanup/po/ja.po
+++ /dev/null
@@ -1,212 +0,0 @@
-# Japanese message translation file for pg_archivecleanup
-# Copyright (C) 2019 PostgreSQL Global Development Group
-# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL 12 beta 1)\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-06-06 10:43+0900\n"
-"PO-Revision-Date: 2019-06-06 17:02+0900\n"
-"Last-Translator: Kyotaro Horiguchi <horikyota.ntt@gmail.com>\n"
-"Language-Team: Japan PostgreSQL Users Group <jpug-doc@ml.postgresql.jp>\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.5.4\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-msgid "fatal: "
-msgstr "è´å½çã¨ã©ã¼: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-msgid "error: "
-msgstr "ã¨ã©ã¼: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-msgid "warning: "
-msgstr "è¦å: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-#| msgid "%s: archive location \"%s\" does not exist\n"
-msgid "archive location \"%s\" does not exist"
-msgstr "ã¢ã¼ã«ã¤ãã®å ´æ\"%s\"ãåå¨ãã¾ãã"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "ãã¡ã¤ã«\"%s\"ãåé¤ã§ãã¾ããã§ãã: %m"
-
-#: pg_archivecleanup.c:162
-#, c-format
-#| msgid "%s: could not read archive location \"%s\": %s\n"
-msgid "could not read archive location \"%s\": %m"
-msgstr "ã¢ã¼ã«ã¤ãã®å ´æ\"%s\"ãèªã¿è¾¼ãã¾ããã§ãã: %m"
-
-#: pg_archivecleanup.c:165
-#, c-format
-#| msgid "%s: could not close archive location \"%s\": %s\n"
-msgid "could not close archive location \"%s\": %m"
-msgstr "ã¢ã¼ã«ã¤ãã®å ´æ\"%s\"ãã¯ãã¼ãºã§ãã¾ããã§ãã: %m"
-
-#: pg_archivecleanup.c:169
-#, c-format
-#| msgid "%s: could not open archive location \"%s\": %s\n"
-msgid "could not open archive location \"%s\": %m"
-msgstr "ã¢ã¼ã«ã¤ãã®å ´æ\"%s\"ããªã¼ãã³ã§ãã¾ããã§ãã: %m"
-
-#: pg_archivecleanup.c:242
-#, c-format
-#| msgid "%s: invalid file name argument\n"
-msgid "invalid file name argument"
-msgstr "ãã¡ã¤ã«å弿°ãç¡å¹ã§ã"
-
-#: pg_archivecleanup.c:243 pg_archivecleanup.c:316 pg_archivecleanup.c:337
-#: pg_archivecleanup.c:349 pg_archivecleanup.c:356
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "\"%s --help\"ã§è©³ç´°ãåç
§ã§ãã¾ãã\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%sã¯PostgreSQLã®ã¢ã¼ã«ã¤ãããå¤ãWALãã¡ã¤ã«ãåé¤ãã¾ãã\n"
-"\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid "Usage:\n"
-msgstr "ä½¿ç¨æ³:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr ""
-"%s [ãªãã·ã§ã³] ... {ã¢ã¼ã«ã¤ãã®å ´æ} {ä¿åããæå¤ã® WAL ãã¡ã¤ã«å}\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"ãªãã·ã§ã³:\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d ãããã°æ
å ±ãåºåï¼åé·ã¢ã¼ãï¼\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid ""
-" -n dry run, show the names of the files that would be removed\n"
-msgstr " -n ãªãã¼ãµã«ãåé¤å¯¾è±¡ã®ãã¡ã¤ã«åã表示\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version ãã¼ã¸ã§ã³æ
å ±ãåºåãã¦çµäº\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT ãã®æ¡å¼µåãæã¤ãã¡ã¤ã«ãåé¤å¯¾è±¡ã¨ãã\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help ãã®ãã«ãã表示ãã¦çµäº\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-#| msgid ""
-#| "\n"
-#| "For use as archive_cleanup_command in recovery.conf when standby_mode = "
-#| "on:\n"
-#| " archive_cleanup_command = 'pg_archivecleanup [OPTION]... "
-#| "ARCHIVELOCATION %%r'\n"
-#| "e.g.\n"
-#| " archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir "
-#| "%%r'\n"
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION "
-"%%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"postgresql.confã§archive_cleanup_commandã¨ãã¦ä½¿ç¨ããå ´åã¯ä»¥ä¸ã®ããã«ãã¾"
-"ã:\n"
-" archive_cleanup_command = 'pg_archivecleanup [ãªãã·ã§ã³]... ã¢ã¼ã«ã¤ãã®å ´"
-"æ %%r'\n"
-"ä¾ã¨ãã¦ã¯:\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"ãããã¯ã¹ã¿ã³ãã¢ãã³ã®ã¢ã¼ã«ã¤ãã¯ãªã¼ãã¼ã¨ãã¦ä½¿ãå ´åã¯:\n"
-"使ç¨ä¾\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:274
-#, c-format
-#| msgid ""
-#| "\n"
-#| "Report bugs to <pgsql-bugs@postgresql.org>.\n"
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"ãã°ã¯ <pgsql-bugs@lists.postgresql.org> ã«å ±åãã¦ãã ããã\n"
-
-#: pg_archivecleanup.c:336
-#, c-format
-#| msgid "%s: must specify archive location\n"
-msgid "must specify archive location"
-msgstr "ã¢ã¼ã«ã¤ãã®å ´æãæå®ãã¦ãã ãã"
-
-#: pg_archivecleanup.c:348
-#, c-format
-#| msgid "%s: must specify oldest kept WAL file\n"
-msgid "must specify oldest kept WAL file"
-msgstr "ä¿åããæå¤ã®WALãã¡ã¤ã«ãæå®ãã¦ãã ãã"
-
-#: pg_archivecleanup.c:355
-#, c-format
-#| msgid "%s: too many command-line arguments\n"
-msgid "too many command-line arguments"
-msgstr "ã³ãã³ãã©ã¤ã³å¼æ°ãå¤ããã¾ã"
-
-#~ msgid "%s: keeping WAL file \"%s\" and later\n"
-#~ msgstr "%s: WAL file \"%s\" ã¨ãã以éã®åãä¿åãã¦ãã¾ã\n"
-
-#~ msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-#~ msgstr "%s: ã¨ã©ã¼: ãã¡ã¤ã« \"%s\" ãåé¤ã§ãã¾ããã§ãã: %s\n"
-
-#~ msgid "%s: removing file \"%s\"\n"
-#~ msgstr "%s: ãã¡ã¤ã« \"%s\" ãåé¤ãã¦ãã¾ã\n"
-
-#~ msgid "%s: file \"%s\" would be removed\n"
-#~ msgstr "%s: ãã¡ã¤ã« \"%s\" ã¯åé¤ããã¾ã\n"
diff --git a/src/bin/pg_archivecleanup/po/ko.po b/src/bin/pg_archivecleanup/po/ko.po
deleted file mode 100644
index 2a3a2fb620..0000000000
--- a/src/bin/pg_archivecleanup/po/ko.po
+++ /dev/null
@@ -1,179 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# Ioseph Kim <ioseph@uri.sarang.net>, 2017.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 12\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2020-02-09 20:16+0000\n"
-"PO-Revision-Date: 2019-10-31 11:13+0900\n"
-"Last-Translator: Ioseph Kim <ioseph@uri.sarang.net>\n"
-"Language-Team: Korean <pgsql-kr@postgresql.kr>\n"
-"Language: ko\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-msgid "fatal: "
-msgstr "ì¬ê°: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-msgid "error: "
-msgstr "ì¤ë¥: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-msgid "warning: "
-msgstr "ê²½ê³ : "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "\"%s\" ì´ë¦ì ìì¹´ì´ë¸ ìì¹ê° ìì"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "\"%s\" íì¼ì ìì í ì ìì: %m"
-
-#: pg_archivecleanup.c:162
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "\"%s\" ìì¹´ì´ë¸ ìì¹ë¥¼ ì½ì ì ìì: %m"
-
-#: pg_archivecleanup.c:165
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "\"%s\" ìì¹´ì´ë¸ ìì¹ë¥¼ ë«ì ì ìì: %m"
-
-#: pg_archivecleanup.c:169
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "\"%s\" ìì¹´ì´ë¸ ìì¹ë¥¼ ì´ ì ìì: %m"
-
-#: pg_archivecleanup.c:242
-#, c-format
-msgid "invalid file name argument"
-msgstr "ì못ë íì¼ ì´ë¦ 매ê°ë³ì"
-
-#: pg_archivecleanup.c:243 pg_archivecleanup.c:316 pg_archivecleanup.c:337
-#: pg_archivecleanup.c:349 pg_archivecleanup.c:356
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "ë³´ë¤ ìì¸í ì ë³´ë \"%s --help\" ëª
ë ¹ì 참조íì¸ì.\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s ëª
ë ¹ì PostgreSQL ìì¹´ì´ë¸ ë³´ê´ììì ì¤ëë\n"
-"WAL íì¼ì ì§ìëë¤.\n"
-"\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid "Usage:\n"
-msgstr "ì¬ì©ë²:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [ìµì
]... ìì¹´ì´ë¸ìì¹ ë³´ê´í ì ì¼ì¤ëëíì¼\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"ìµì
ë¤:\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d ë³´ë¤ ìì¸í ìì
ë´ì© ì¶ë ¥\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid ""
-" -n dry run, show the names of the files that would be removed\n"
-msgstr " -n ì§ì¸ ëìë§ íì¸íê³ ì§ì°ì§ë ìì\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version ë²ì ì 보를 ë³´ì¬ì£¼ê³ ë§ì¹¨\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT í´ë¹ íì¥ì íì¼ë¤ì ìì
ëìì¼ë¡ í¨\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help ëìë§ì ë³´ì¬ì£¼ê³ ë§ì¹¨\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION "
-"%%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"postgresql.conf íì¼ìì archive_cleanup_command ì¤ì ë°©ë²:\n"
-" archive_cleanup_command = 'pg_archivecleanup [ìµì
]... ìì¹´ì´ë¸ìì¹ %%r'\n"
-"ì¬ì©ì:\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"ëë ëª
ë ¹íìì ë
립ì ì¼ë¡ ì¬ì©íë ê²½ì°:\n"
-"ì¬ì©ì:\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:274
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"문ì ì ë³´ê³ <pgsql-bugs@lists.postgresql.org>.\n"
-
-#: pg_archivecleanup.c:336
-#, c-format
-msgid "must specify archive location"
-msgstr "ìì¹´ì´ë¸ ìì¹ë ì§ì í´ì¼ í¨"
-
-#: pg_archivecleanup.c:348
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "ë¨ê¸¸ ê°ì¥ ì¤ëë WAL íì¼ì ì§ì í´ì¼ í¨"
-
-#: pg_archivecleanup.c:355
-#, c-format
-msgid "too many command-line arguments"
-msgstr "ë무 ë§ì ëª
ë ¹í ì¸ì를 ì§ì íì"
diff --git a/src/bin/pg_archivecleanup/po/pl.po b/src/bin/pg_archivecleanup/po/pl.po
deleted file mode 100644
index 0b5e9d43da..0000000000
--- a/src/bin/pg_archivecleanup/po/pl.po
+++ /dev/null
@@ -1,178 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# grzegorz <begina.felicysym@wp.eu>, 2017.
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 10\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@postgresql.org\n"
-"POT-Creation-Date: 2017-03-14 17:45+0000\n"
-"PO-Revision-Date: 2017-03-14 19:43+0200\n"
-"Last-Translator: grzegorz <begina.felicysym@wp.eu>\n"
-"Language-Team: begina.felicysym@wp.eu\n"
-"Language: pl\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
-"|| n%100>=20) ? 1 : 2);\n"
-"X-Generator: Virtaal 0.7.1\n"
-
-#: pg_archivecleanup.c:73
-#, c-format
-msgid "%s: archive location \"%s\" does not exist\n"
-msgstr "%s: lokacja archiwum \"%s\" nie istnieje\n"
-
-#: pg_archivecleanup.c:149
-#, c-format
-msgid "%s: file \"%s\" would be removed\n"
-msgstr "%s: plik \"%s\" zostanie usuniÄty\n"
-
-#: pg_archivecleanup.c:155
-#, c-format
-msgid "%s: removing file \"%s\"\n"
-msgstr "%s: usuwanie pliku \"%s\"\n"
-
-#: pg_archivecleanup.c:161
-#, c-format
-msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-msgstr "%s: BÅÄD: nie daÅo siÄ usunÄ
Ä pliku \"%s\": %s\n"
-
-#: pg_archivecleanup.c:169
-#, c-format
-msgid "%s: could not read archive location \"%s\": %s\n"
-msgstr "%s: nie można czytaÄ z lokacji archiwum \"%s\": %s\n"
-
-#: pg_archivecleanup.c:172
-#, c-format
-msgid "%s: could not close archive location \"%s\": %s\n"
-msgstr "%s: nie można zamknÄ
Ä lokacji archiwum \"%s\": %s\n"
-
-#: pg_archivecleanup.c:176
-#, c-format
-msgid "%s: could not open archive location \"%s\": %s\n"
-msgstr "%s: nie można otworzyÄ lokacji archiwum \"%s\": %s\n"
-
-#: pg_archivecleanup.c:249
-#, c-format
-msgid "%s: invalid filename input\n"
-msgstr "%s: niepoprawna nazwa pliku wejÅcia\n"
-
-#: pg_archivecleanup.c:250 pg_archivecleanup.c:322 pg_archivecleanup.c:343
-#: pg_archivecleanup.c:355 pg_archivecleanup.c:362
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Użyj \"%s --help\" aby uzyskaÄ wiÄcej informacji.\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s usuwa starsze pliki WAL z archiwów PostgreSQL.\n"
-"\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid "Usage:\n"
-msgstr "SkÅadnia:\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPCJA]... LOKACJAARCHIWUM NAJSTARSZYZACHOWANYPLIKWAL\n"
-
-#: pg_archivecleanup.c:266
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Opcje:\n"
-
-#: pg_archivecleanup.c:267
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d generuje informacje diagnostyczne (trym rozgadany)\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n przebieg próbny, pokazuje nazwy plików do usuniÄcia\n"
-
-#: pg_archivecleanup.c:269
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version wypisuje informacje o wersji i koÅczy\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT czyÅci pliki jeÅli majÄ
takie rozszerzenie\n"
-
-#: pg_archivecleanup.c:271
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help pokazuje ten ekran pomocy i koÅczy\n"
-
-#: pg_archivecleanup.c:272
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in recovery.conf when standby_mode = on:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"Do użycia jako archive_cleanup_command w recovery.conf kiedy standby_mode = "
-"on:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPCJA]... LOKACJAARCHIWUM %%"
-"r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:277
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Lub by użyÄ podczas samodzielnego czyszczenia archiwów:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:281
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@postgresql.org>.\n"
-msgstr ""
-"\n"
-"BÅÄdy proszÄ przesyÅaÄ na adres <pgsql-bugs@postgresql.org>.\n"
-
-#: pg_archivecleanup.c:342
-#, c-format
-msgid "%s: must specify archive location\n"
-msgstr "%s: wymagane wskazanie lokacji archiwum\n"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "%s: must specify restartfilename\n"
-msgstr "%s: wymagane wskazanie nazwy pliku restartu\n"
-
-#: pg_archivecleanup.c:361
-#, c-format
-msgid "%s: too many parameters\n"
-msgstr "%s: za dużo parametrów\n"
-
-#: pg_archivecleanup.c:380
-#, c-format
-msgid "%s: keep WAL file \"%s\" and later\n"
-msgstr "%s: zachowaj plik WAL \"%s\" a nastÄpnie\n"
diff --git a/src/bin/pg_archivecleanup/po/ru.po b/src/bin/pg_archivecleanup/po/ru.po
deleted file mode 100644
index 579026ecba..0000000000
--- a/src/bin/pg_archivecleanup/po/ru.po
+++ /dev/null
@@ -1,192 +0,0 @@
-# Russian message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# Alexander Lakhin <a.lakhin@postgrespro.ru>, 2017, 2019.
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 10\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-09-09 12:21+0300\n"
-"PO-Revision-Date: 2019-08-28 14:04+0300\n"
-"Last-Translator: Alexander Lakhin <exclusion@gmail.com>\n"
-"Language-Team: Russian <pgsql-ru-general@postgresql.org>\n"
-"Language: ru\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-msgid "fatal: "
-msgstr "важно: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-msgid "error: "
-msgstr "оÑибка: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-msgid "warning: "
-msgstr "пÑедÑпÑеждение: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "ÑаÑположение аÑÑ
ива \"%s\" не ÑÑÑеÑÑвÑеÑ"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "не ÑдалоÑÑ ÑÑеÑеÑÑ Ñайл \"%s\": %m"
-
-#: pg_archivecleanup.c:162
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "не ÑдалоÑÑ Ð¿ÑоÑиÑаÑÑ ÑаÑположение аÑÑ
ива \"%s\": %m"
-
-#: pg_archivecleanup.c:165
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "не ÑдалоÑÑ Ð·Ð°ÐºÑÑÑÑ ÑаÑположение аÑÑ
ива \"%s\": %m"
-
-#: pg_archivecleanup.c:169
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "не ÑдалоÑÑ Ð¾ÑкÑÑÑÑ ÑаÑположение аÑÑ
ива \"%s\": %m"
-
-#: pg_archivecleanup.c:242
-#, c-format
-msgid "invalid file name argument"
-msgstr "невеÑнÑй аÑгÑÐ¼ÐµÐ½Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ Ñайла"
-
-#: pg_archivecleanup.c:243 pg_archivecleanup.c:316 pg_archivecleanup.c:337
-#: pg_archivecleanup.c:349 pg_archivecleanup.c:356
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "ÐÐ»Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑной инÑоÑмаÑии попÑобÑйÑе \"%s --help\".\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s ÑдалÑÐµÑ ÑÑаÑÑе ÑÐ°Ð¹Ð»Ñ WAL из аÑÑ
ивов PostgreSQL.\n"
-"\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid "Usage:\n"
-msgstr "ÐÑполÑзование:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr ""
-" %s [ÐÐÐ ÐÐÐТР]... Ð ÐСÐÐÐÐÐÐÐÐÐ_ÐРХÐÐРСТÐÐ ÐÐШÐÐ_СÐХРÐÐЯÐÐЫÐ_ФÐÐÐ_WAL\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"ÐаÑамеÑÑÑ:\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d генеÑиÑоваÑÑ Ð¿Ð¾Ð´ÑобнÑе ÑообÑÐµÐ½Ð¸Ñ (оÑладоÑнÑй Ñежим)\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid ""
-" -n dry run, show the names of the files that would be removed\n"
-msgstr ""
-" -n Ñ
олоÑÑой запÑÑк, ÑолÑко показаÑÑ Ð¸Ð¼ÐµÐ½Ð° Ñайлов, коÑоÑÑе "
-"бÑдÑÑ ÑдаленÑ\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version показаÑÑ Ð²ÐµÑÑÐ¸Ñ Ð¸ вÑйÑи\n"
-
-# well-spelled: РСШ
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x РСШ ÑбÑаÑÑ ÑÐ°Ð¹Ð»Ñ Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñм ÑаÑÑиÑением\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help показаÑÑ ÑÑÑ ÑпÑÐ°Ð²ÐºÑ Ð¸ вÑйÑи\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION "
-"%%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"ÐÐ»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² каÑеÑÑве archive_cleanup_command в postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [ÐÐÐ ÐÐÐТР]... "
-"Ð ÐСÐÐÐÐÐÐÐÐÐ_ÐРХÐÐÐ %%r'\n"
-"напÑимеÑ:\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Ðибо Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² каÑеÑÑве оÑделÑного ÑÑедÑÑва оÑиÑÑки аÑÑ
ива,\n"
-"напÑимеÑ:\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:274
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"Ðб оÑибкаÑ
ÑообÑайÑе по адÑеÑÑ <pgsql-bugs@lists.postgresql.org>.\n"
-
-#: pg_archivecleanup.c:336
-#, c-format
-msgid "must specify archive location"
-msgstr "необÑ
одимо задаÑÑ ÑаÑположение аÑÑ
ива"
-
-#: pg_archivecleanup.c:348
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "необÑ
одимо задаÑÑ Ð¸Ð¼Ñ ÑÑаÑейÑего ÑоÑ
ÑанÑемого Ñайла WAL"
-
-#: pg_archivecleanup.c:355
-#, c-format
-msgid "too many command-line arguments"
-msgstr "ÑлиÑком много аÑгÑменÑов командной ÑÑÑоки"
-
-#~ msgid "%s: file \"%s\" would be removed\n"
-#~ msgstr "%s: Ñайл \"%s\" не бÑÐ´ÐµÑ ÑдалÑн\n"
-
-#~ msgid "%s: removing file \"%s\"\n"
-#~ msgstr "%s: Ñдаление Ñайла \"%s\"\n"
-
-#~ msgid "%s: keeping WAL file \"%s\" and later\n"
-#~ msgstr "%s: бÑÐ´ÐµÑ ÑоÑ
ÑанÑн Ñайл WAL \"%s\" и поÑледÑÑÑие\n"
diff --git a/src/bin/pg_archivecleanup/po/sv.po b/src/bin/pg_archivecleanup/po/sv.po
deleted file mode 100644
index c0f3a77282..0000000000
--- a/src/bin/pg_archivecleanup/po/sv.po
+++ /dev/null
@@ -1,179 +0,0 @@
-# Swedish message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the PostgreSQL package.
-# Dennis Björklund <db@zigo.dhs.org>, 2017, 2018, 2019, 2020.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PostgreSQL 13\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2020-04-11 01:17+0000\n"
-"PO-Revision-Date: 2020-04-11 07:37+0200\n"
-"Last-Translator: FDennis Björklund <db@zigo.dhs.org>\n"
-"Language-Team: Swedish <pgsql-translators@postgresql.org>\n"
-"Language: sv\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-
-#: ../../../src/common/logging.c:236
-#, c-format
-msgid "fatal: "
-msgstr "fatalt: "
-
-#: ../../../src/common/logging.c:243
-#, c-format
-msgid "error: "
-msgstr "fel: "
-
-#: ../../../src/common/logging.c:250
-#, c-format
-msgid "warning: "
-msgstr "varning: "
-
-#: pg_archivecleanup.c:66
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "arkivplats \"%s\" finns inte"
-
-#: pg_archivecleanup.c:152
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "kunde inte ta bort fil \"%s\": %m"
-
-#: pg_archivecleanup.c:160
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "kunde inte läsa arkivplats \"%s\": %m"
-
-#: pg_archivecleanup.c:163
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "kunde inte stänga arkivplats \"%s\": %m"
-
-#: pg_archivecleanup.c:167
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "kunde inte öppna arkivplats \"%s\": %m"
-
-#: pg_archivecleanup.c:240
-#, c-format
-msgid "invalid file name argument"
-msgstr "ogiltigt filnamnsargument"
-
-#: pg_archivecleanup.c:241 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Försök med \"%s --help\" för mer information.\n"
-
-#: pg_archivecleanup.c:254
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s tar bort gamla WAL-filer från PostgreSQLs arkiv.\n"
-"\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid "Usage:\n"
-msgstr "Användning:\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [FLAGGA]... ARKIVPLATS ÃLDSTASPARADEWALFIL\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Flaggor:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d generera debugutskrift (utförligt läge)\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n gör inga ändringar visa namn på de filer som skulle ha tagits bort\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version visa versionsinformation, avsluta sedan\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x SUF städa upp filer om de har detta suffix\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help visa denna hjälp, avsluta sedan\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"För att använda som archive_cleanup_command i postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [FLAGGA]... ARKIVPLATS %%r'\n"
-"t.ex.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Eller för att använda som en separat arkivstädare:\n"
-"t.ex.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:272
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <%s>.\n"
-msgstr ""
-"\n"
-"Rapportera fel till <%s>.\n"
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid "%s home page: <%s>\n"
-msgstr "hemsida för %s: <%s>\n"
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "måste ange en arkivplats"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "måste ange äldsta sparade WAL-filen"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "för många kommandoradsargument"
diff --git a/src/bin/pg_archivecleanup/po/tr.po b/src/bin/pg_archivecleanup/po/tr.po
deleted file mode 100644
index c61889af82..0000000000
--- a/src/bin/pg_archivecleanup/po/tr.po
+++ /dev/null
@@ -1,185 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2017 PostgreSQL Global Development Group
-# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 10\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-04-26 13:48+0000\n"
-"PO-Revision-Date: 2019-05-28 10:30+0300\n"
-"Last-Translator: \n"
-"Language-Team: \n"
-"Language: tr\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.8.7.1\n"
-
-#: ../../../src/fe_utils/logging.c:182
-#, c-format
-msgid "fatal: "
-msgstr "ölümcül (fatal): "
-
-#: ../../../src/fe_utils/logging.c:189
-#, c-format
-msgid "error: "
-msgstr "hata: "
-
-#: ../../../src/fe_utils/logging.c:196
-#, c-format
-msgid "warning: "
-msgstr "uyarı: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "\"%s\" arÅiv lokasyonu mevcut deÄil"
-
-#: pg_archivecleanup.c:153
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "\"%s\" dosyası silinemedi: %m"
-
-#: pg_archivecleanup.c:161
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "\"%s\" arÅiv lokasyonu okunamadı: %m"
-
-#: pg_archivecleanup.c:164
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "\"%s\" arÅiv lokasyonu kapatılamadı: %m"
-
-#: pg_archivecleanup.c:168
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "\"%s\" arÅiv lokasyonu açılamadı: %m"
-
-#: pg_archivecleanup.c:241
-#, c-format
-msgid "invalid file name argument"
-msgstr "geçersiz dosya adı argümanı"
-
-#: pg_archivecleanup.c:242 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Daha fazla bilgi için \"%s --help\" yazın\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr "%s daha eski WAL dosyalarını PostgreSQL arÅivlerinden kaldırır.\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid "Usage:\n"
-msgstr "Kullanımı:\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [SECENEK]... ARSIVLOKASYONU TUTULANENESKIWALDOSYASI\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Seçenekler:\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d hata ayıklama çıktısı oluÅtur (ayrıntılı açıklamalı mod)\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n tatbikat modu, sadece kaldırılacak dosyaların adlarını göster\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version sürüm bilgisini göster, sonra çık\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT bu uzantıya sahip dosyaları temizle\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help bu yardımı göster, sonra çık\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"postgresql.conf'da archive_cleanup_command olarak kullanmak için:\n"
-" archive_cleanup_command = 'pg_archivecleanup [SECENEK]... ARSIVLOKASYONU %%r'\n"
-"örnek:\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-"\n"
-
-#: pg_archivecleanup.c:269
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Veya baÄımsız bir arÅiv temizleyici olarak kullanmak için: \n"
-"örnek:\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"Hataları <pgsql-bugs@lists.postgresql.org> adresine bildirebilirsiniz.\n"
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "arÅiv lokasyonu belirtilmeli"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "tutulan en eski WAL dosyası belirtilmeli"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "çok fazla komut-satırı argümanı"
-
-#~ msgid "%s: keeping WAL file \"%s\" and later\n"
-#~ msgstr "%s: \"%s\" ve sonrasındaki WAl dosyaları tutuluyor\n"
-
-#~ msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-#~ msgstr "%s: HATA: \"%s\" dosyası kaldırılamadı: %s\n"
-
-#~ msgid "%s: removing file \"%s\"\n"
-#~ msgstr "%s: \"%s\" dosyası kaldırılıyor\n"
-
-#~ msgid "%s: file \"%s\" would be removed\n"
-#~ msgstr "%s: \"%s\" dosyası kaldırılacak\n"
diff --git a/src/bin/pg_archivecleanup/po/uk.po b/src/bin/pg_archivecleanup/po/uk.po
deleted file mode 100644
index 61b792b791..0000000000
--- a/src/bin/pg_archivecleanup/po/uk.po
+++ /dev/null
@@ -1,161 +0,0 @@
-msgid ""
-msgstr ""
-"Project-Id-Version: postgresql\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-09-08 14:46+0000\n"
-"PO-Revision-Date: 2019-12-20 20:23\n"
-"Last-Translator: pasha_golub\n"
-"Language-Team: Ukrainian\n"
-"Language: uk_UA\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
-"X-Crowdin-Project: postgresql\n"
-"X-Crowdin-Language: uk\n"
-"X-Crowdin-File: /REL_12_STABLE/pg_archivecleanup.pot\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-msgid "fatal: "
-msgstr "збÑй: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-msgid "error: "
-msgstr "помилка: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-msgid "warning: "
-msgstr "попеÑедженнÑ: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "аÑÑ
Ñвного ÑозÑаÑÑÐ²Ð°Ð½Ð½Ñ \"%s\" не ÑÑнÑÑ"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "не можливо видалиÑи Ñайл \"%s\": %m"
-
-#: pg_archivecleanup.c:162
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "не вдалоÑÑ Ð¿ÑоÑиÑаÑи аÑÑ
Ñвне ÑозÑаÑÑÐ²Ð°Ð½Ð½Ñ \"%s\":%m"
-
-#: pg_archivecleanup.c:165
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "не вдалоÑÑ Ð·Ð°ÐºÑиÑи аÑÑ
Ñвне ÑозÑаÑÑÐ²Ð°Ð½Ð½Ñ \"%s\":%m"
-
-#: pg_archivecleanup.c:169
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "не вдалоÑÑ Ð²ÑдкÑиÑи аÑÑ
Ñвне ÑозÑаÑÑÐ²Ð°Ð½Ð½Ñ \"%s\":%m"
-
-#: pg_archivecleanup.c:242
-#, c-format
-msgid "invalid file name argument"
-msgstr "недÑйÑна назва Ñайла з аÑгÑменÑом"
-
-#: pg_archivecleanup.c:243 pg_archivecleanup.c:316 pg_archivecleanup.c:337
-#: pg_archivecleanup.c:349 pg_archivecleanup.c:356
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "СпÑобÑйÑе \"%s --help\" Ð´Ð»Ñ Ð´Ð¾Ð´Ð°ÑÐºÐ¾Ð²Ð¾Ñ ÑнÑоÑмаÑÑÑ.\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid "%s removes older WAL files from PostgreSQL archives.\n\n"
-msgstr "%s видалÑÑ ÑÑаÑÑ WAL-Ñайли з аÑÑ
ÑвÑв PostgreSQL.\n\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid "Usage:\n"
-msgstr "ÐикоÑиÑÑаннÑ:\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPTION]... Ð ÐÐТÐШУÐÐÐÐЯ_ÐРХÐÐÐ ÐÐÐÐÐÐÐÐШÐÐ_ÐÐÐÐ ÐÐÐÐÐÐ_WAL_ФÐÐÐ\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid "\n"
-"Options:\n"
-msgstr "\n"
-"ÐаÑамеÑÑи:\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d генеÑÑÑ Ð½Ð°Ð»Ð°Ð³Ð¾Ð´Ð¶ÑвалÑÐ½Ñ Ð¿Ð¾Ð²ÑÐ´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (деÑалÑний Ñежим)\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n ÑÑÑ
ий запÑÑк, показÑÑ ÑÑлÑки ÑÑ Ñайли, ÑÐºÑ Ð±ÑдÑÑÑ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ñ\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version показаÑи веÑÑÑÑ, поÑÑм вийÑи\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT пÑибÑаÑи Ñайли з Ñим ÑозÑиÑеннÑм\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help показаÑи ÑÑ Ð´Ð¾Ð²ÑдкÑ, поÑÑм вийÑи\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid "\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr "\n"
-"ÐÐ»Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑÐ°Ð½Ð½Ñ Ñк archive_cleanup_command Ñ postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"напÑ.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid "\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr "\n"
-"Ðбо Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑÐ°Ð½Ð½Ñ Ð² ÑкоÑÑÑ Ð¾ÐºÑемого заÑÐ¾Ð±Ñ Ð´Ð»Ñ ÑиÑÑки аÑÑ
ÑвÑв,\n"
-"напÑиклад:\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:274
-#, c-format
-msgid "\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr "\n"
-"ÐÑо помилки повÑдомлÑйÑе на <pgsql-bugs@lists.postgresql.org>.\n"
-
-#: pg_archivecleanup.c:336
-#, c-format
-msgid "must specify archive location"
-msgstr "необÑ
Ñдно вказаÑи ÑозÑаÑÑÐ²Ð°Ð½Ð½Ñ Ð°ÑÑ
Ñва"
-
-#: pg_archivecleanup.c:348
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "необÑ
Ñдно вказаÑи найдавнÑÑий збеÑежений WAL-Ñайл"
-
-#: pg_archivecleanup.c:355
-#, c-format
-msgid "too many command-line arguments"
-msgstr "занадÑо багаÑо аÑгÑменÑÑв командного ÑÑдка"
-
diff --git a/src/bin/pg_archivecleanup/po/vi.po b/src/bin/pg_archivecleanup/po/vi.po
deleted file mode 100644
index e35f8181a4..0000000000
--- a/src/bin/pg_archivecleanup/po/vi.po
+++ /dev/null
@@ -1,183 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2018 PostgreSQL Global Development Group
-# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
-# FIRST AUTHOR <kakalot49@gmail.com>, 2018.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 11\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@postgresql.org\n"
-"POT-Creation-Date: 2018-04-23 02:27+0900\n"
-"PO-Revision-Date: 2018-05-04 22:03+0900\n"
-"Language-Team: <pgvn_translators@postgresql.vn>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.6\n"
-"Last-Translator: Dang Minh Huong <kakalot49@gmail.com>\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-"Language: vi_VN\n"
-
-#: pg_archivecleanup.c:72
-#, c-format
-msgid "%s: archive location \"%s\" does not exist\n"
-msgstr "%s: vá» trà lưu trữ \"%s\" không tá»n tại\n"
-
-#: pg_archivecleanup.c:148
-#, c-format
-msgid "%s: file \"%s\" would be removed\n"
-msgstr "%s: tá»p \"%s\" sẽ bá» xóa\n"
-
-#: pg_archivecleanup.c:154
-#, c-format
-msgid "%s: removing file \"%s\"\n"
-msgstr "%s: Äang xóa tá»p \"%s\"\n"
-
-#: pg_archivecleanup.c:160
-#, c-format
-msgid "%s: ERROR: could not remove file \"%s\": %s\n"
-msgstr "%s: Lá»I: không thá» xóa tá»p \"%s\": %s\n"
-
-#: pg_archivecleanup.c:168
-#, c-format
-msgid "%s: could not read archive location \"%s\": %s\n"
-msgstr "%s: không thá» Äá»c vá» trà lưu trữ \"%s\": %s\n"
-
-#: pg_archivecleanup.c:171
-#, c-format
-msgid "%s: could not close archive location \"%s\": %s\n"
-msgstr "%s: không thá» Äóng vá» trà lưu trữ \"%s\": %s\n"
-
-#: pg_archivecleanup.c:175
-#, c-format
-msgid "%s: could not open archive location \"%s\": %s\n"
-msgstr "%s: không thỠmỠvỠtrà lưu trữ \"%s\": %s\n"
-
-#: pg_archivecleanup.c:248
-#, c-format
-msgid "%s: invalid file name argument\n"
-msgstr "%s: Äá»i sá» tên tá»p không hợp lá»\n"
-
-#: pg_archivecleanup.c:249 pg_archivecleanup.c:321 pg_archivecleanup.c:342
-#: pg_archivecleanup.c:354 pg_archivecleanup.c:361
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "Hãy thá» \"%s --help\" Äá» biết thêm thông tin.\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr "%s xóa các tá»p WAL cÅ© hÆ¡n khá»i lưu trữ PostgreSQL.\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid "Usage:\n"
-msgstr "Cách sỠdụng:\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [Tùy chá»n]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-
-#: pg_archivecleanup.c:265
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"Tùy chá»n:\n"
-
-#: pg_archivecleanup.c:266
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d xuất debug log (chế Äá» chi tiết)\n"
-
-#: pg_archivecleanup.c:267
-#, c-format
-msgid ""
-" -n dry run, show the names of the files that would be "
-"removed\n"
-msgstr " -n chạy khô, hiá»n thá» tên cá»§a các tá»p sẽ bá» xóa\n"
-
-#: pg_archivecleanup.c:268
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version xuất thông tin bản, sau Äó kết thúc\n"
-
-#: pg_archivecleanup.c:269
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT dá»n dẹp các táºp tin nếu chúng có phần má» rá»ng nà y\n"
-
-#: pg_archivecleanup.c:270
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help hiá»n thá» trợ giúp nà y, sau Äó thoát\n"
-
-#: pg_archivecleanup.c:271
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in recovery.conf when standby_mode = "
-"on:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION "
-"%%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir "
-"%%r'\n"
-msgstr ""
-"\n"
-"Äá» sá» dụng như archive_cleanup_command trong recovery.conf khi "
-"standby_mode = on:\n"
-" archive_cleanup_command = 'pg_archivecleanup [TÃY CHá»N] ... "
-"ARCHIVELOCATION %%r'\n"
-"và dụ.\n"
-" archive_cleanup_command = 'pg_archivecleanup/mnt/server/archiverdir "
-"%%r'\n"
-
-#: pg_archivecleanup.c:276
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"Hoặc Äá» sá» dụng như má»t trình dá»n dẹp lưu trữ Äá»c láºp:\n"
-"và dụ.\n"
-" pg_archivecleanup /mnt/server/archiverdir "
-"000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:280
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@postgresql.org>.\n"
-msgstr ""
-"\n"
-"Báo cáo bugs qua email <pgsql-bugs@postgresql.org>.\n"
-
-#: pg_archivecleanup.c:341
-#, c-format
-msgid "%s: must specify archive location\n"
-msgstr "%s: phải chá» Äá»nh vá» trà lưu trữ\n"
-
-#: pg_archivecleanup.c:353
-#, c-format
-msgid "%s: must specify oldest kept WAL file\n"
-msgstr "%s: phải chá» Äá»nh tá»p WAL ÄÆ°á»£c giữ lâu nhất\n"
-
-#: pg_archivecleanup.c:360
-#, c-format
-msgid "%s: too many command-line arguments\n"
-msgstr "%s: có quá nhiá»u Äá»i sá» dòng lá»nh\n"
-
-#: pg_archivecleanup.c:379
-#, c-format
-msgid "%s: keeping WAL file \"%s\" and later\n"
-msgstr "%s: giữ tá»p WAL \"%s\" và những tá»p tiếp theo\n"
diff --git a/src/bin/pg_archivecleanup/po/zh_CN.po b/src/bin/pg_archivecleanup/po/zh_CN.po
deleted file mode 100644
index 39c8569f34..0000000000
--- a/src/bin/pg_archivecleanup/po/zh_CN.po
+++ /dev/null
@@ -1,174 +0,0 @@
-# LANGUAGE message translation file for pg_archivecleanup
-# Copyright (C) 2019 PostgreSQL Global Development Group
-# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
-# FIRST AUTHOR <zhangjie2@cn.fujitsu.com>, 2019.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pg_archivecleanup (PostgreSQL) 12\n"
-"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
-"POT-Creation-Date: 2019-05-22 17:56+0800\n"
-"PO-Revision-Date: 2019-06-16 19:40+0800\n"
-"Last-Translator: Jie Zhang <zhangjie2@cn.fujitsu.com>\n"
-"Language-Team: Chinese (Simplified) <zhangjie2@cn.fujitsu.com>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_CN\n"
-
-#: ../../../src/common/logging.c:188
-#, c-format
-msgid "fatal: "
-msgstr "è´å½ç: "
-
-#: ../../../src/common/logging.c:195
-#, c-format
-msgid "error: "
-msgstr "é误: "
-
-#: ../../../src/common/logging.c:202
-#, c-format
-msgid "warning: "
-msgstr "è¦å: "
-
-#: pg_archivecleanup.c:68
-#, c-format
-msgid "archive location \"%s\" does not exist"
-msgstr "åæ¡£ä½ç½®\"%s\"ä¸åå¨"
-
-#: pg_archivecleanup.c:153
-#, c-format
-msgid "could not remove file \"%s\": %m"
-msgstr "æ æ³å 餿件 \"%s\": %m"
-
-#: pg_archivecleanup.c:161
-#, c-format
-msgid "could not read archive location \"%s\": %m"
-msgstr "æ æ³è¯»ååæ¡£ä½ç½®\"%s\": %m"
-
-#: pg_archivecleanup.c:164
-#, c-format
-msgid "could not close archive location \"%s\": %m"
-msgstr "æ æ³å
³éåæ¡£ä½ç½® \"%s\": %m"
-
-#: pg_archivecleanup.c:168
-#, c-format
-msgid "could not open archive location \"%s\": %m"
-msgstr "æ æ³æå¼åæ¡£ä½ç½®\"%s\": %m"
-
-#: pg_archivecleanup.c:241
-#, c-format
-msgid "invalid file name argument"
-msgstr "æä»¶ååæ°æ æ"
-
-#: pg_archivecleanup.c:242 pg_archivecleanup.c:315 pg_archivecleanup.c:336
-#: pg_archivecleanup.c:348 pg_archivecleanup.c:355
-#, c-format
-msgid "Try \"%s --help\" for more information.\n"
-msgstr "è¯·ç¨ \"%s --help\" è·åæ´å¤çä¿¡æ¯.\n"
-
-#: pg_archivecleanup.c:255
-#, c-format
-msgid ""
-"%s removes older WAL files from PostgreSQL archives.\n"
-"\n"
-msgstr ""
-"%s ä»PostgreSQLåæ¡£ä¸å 餿§çWALæä»¶.\n"
-"\n"
-
-#: pg_archivecleanup.c:256
-#, c-format
-msgid "Usage:\n"
-msgstr "ä½¿ç¨æ¹æ³:\n"
-
-#: pg_archivecleanup.c:257
-#, c-format
-msgid " %s [OPTION]... ARCHIVELOCATION OLDESTKEPTWALFILE\n"
-msgstr " %s [OPTION]... 彿¡£æä»¶ä½ç½® ææ©ä¿åçWALæä»¶\n"
-
-#: pg_archivecleanup.c:258
-#, c-format
-msgid ""
-"\n"
-"Options:\n"
-msgstr ""
-"\n"
-"é项:\n"
-
-#: pg_archivecleanup.c:259
-#, c-format
-msgid " -d generate debug output (verbose mode)\n"
-msgstr " -d çæè°è¯è¾åºï¼è¯¦ç»æ¨¡å¼ï¼\n"
-
-#: pg_archivecleanup.c:260
-#, c-format
-msgid " -n dry run, show the names of the files that would be removed\n"
-msgstr " -n dryè¿è¡ï¼æ¾ç¤ºè¦å é¤çæä»¶çåç§°\n"
-
-#: pg_archivecleanup.c:261
-#, c-format
-msgid " -V, --version output version information, then exit\n"
-msgstr " -V, --version è¾åºçæ¬ä¿¡æ¯ï¼ç¶åéåº\n"
-
-#: pg_archivecleanup.c:262
-#, c-format
-msgid " -x EXT clean up files if they have this extension\n"
-msgstr " -x EXT 妿æä»¶å
·ææ¤æ©å±åï¼åæ¸
餿件\n"
-
-#: pg_archivecleanup.c:263
-#, c-format
-msgid " -?, --help show this help, then exit\n"
-msgstr " -?, --help æ¾ç¤ºå¸®å©ä¿¡æ¯ï¼ç¶åéåº\n"
-
-#: pg_archivecleanup.c:264
-#, c-format
-msgid ""
-"\n"
-"For use as archive_cleanup_command in postgresql.conf:\n"
-" archive_cleanup_command = 'pg_archivecleanup [OPTION]... ARCHIVELOCATION %%r'\n"
-"e.g.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-msgstr ""
-"\n"
-"å¨postgresql.confä¸ï¼archive_cleanup_commandçç¨æ³ \n"
-" archive_cleanup_command = 'pg_archivecleanup [é项]... åæ¡£ä½ç½® %%r'\n"
-"ä¾.\n"
-" archive_cleanup_command = 'pg_archivecleanup /mnt/server/archiverdir %%r'\n"
-
-#: pg_archivecleanup.c:269
-#, c-format
-msgid ""
-"\n"
-"Or for use as a standalone archive cleaner:\n"
-"e.g.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-msgstr ""
-"\n"
-"æè
ï¼ç¨ä½ç¬ç«åæ¡£æ¸
çç¨åº:\n"
-"ä¾.\n"
-" pg_archivecleanup /mnt/server/archiverdir 000000010000000000000010.00000020.backup\n"
-
-#: pg_archivecleanup.c:273
-#, c-format
-msgid ""
-"\n"
-"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
-msgstr ""
-"\n"
-"æ¥åéè¯¯è³ <pgsql-bugs@lists.postgresql.org>.\n"
-
-#: pg_archivecleanup.c:335
-#, c-format
-msgid "must specify archive location"
-msgstr "å¿
é¡»æå®åæ¡£ä½ç½®"
-
-#: pg_archivecleanup.c:347
-#, c-format
-msgid "must specify oldest kept WAL file"
-msgstr "å¿
é¡»æå®ææ©ä¿åçWALæä»¶"
-
-#: pg_archivecleanup.c:354
-#, c-format
-msgid "too many command-line arguments"
-msgstr "å½ä»¤è¡åæ°å¤ªå¤"
-
diff --git a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl b/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
deleted file mode 100644
index 22782d3042..0000000000
--- a/src/bin/pg_archivecleanup/t/010_pg_archivecleanup.pl
+++ /dev/null
@@ -1,98 +0,0 @@
-use strict;
-use warnings;
-use TestLib;
-use Test::More tests => 42;
-
-program_help_ok('pg_archivecleanup');
-program_version_ok('pg_archivecleanup');
-program_options_handling_ok('pg_archivecleanup');
-
-my $tempdir = TestLib::tempdir;
-
-my @walfiles = (
- '00000001000000370000000C.gz', '00000001000000370000000D',
- '00000001000000370000000E', '00000001000000370000000F.partial',);
-
-sub create_files
-{
- foreach my $fn (@walfiles, 'unrelated_file')
- {
- open my $file, '>', "$tempdir/$fn";
- print $file 'CONTENT';
- close $file;
- }
- return;
-}
-
-create_files();
-
-command_fails_like(
- ['pg_archivecleanup'],
- qr/must specify archive location/,
- 'fails if archive location is not specified');
-
-command_fails_like(
- [ 'pg_archivecleanup', $tempdir ],
- qr/must specify oldest kept WAL file/,
- 'fails if oldest kept WAL file name is not specified');
-
-command_fails_like(
- [ 'pg_archivecleanup', 'notexist', 'foo' ],
- qr/archive location .* does not exist/,
- 'fails if archive location does not exist');
-
-command_fails_like(
- [ 'pg_archivecleanup', $tempdir, 'foo', 'bar' ],
- qr/too many command-line arguments/,
- 'fails with too many command-line arguments');
-
-command_fails_like(
- [ 'pg_archivecleanup', $tempdir, 'foo' ],
- qr/invalid file name argument/,
- 'fails with invalid restart file name');
-
-{
- # like command_like but checking stderr
- my $stderr;
- my $result = IPC::Run::run [ 'pg_archivecleanup', '-d', '-n', $tempdir,
- $walfiles[2] ], '2>', \$stderr;
- ok($result, "pg_archivecleanup dry run: exit code 0");
- like(
- $stderr,
- qr/$walfiles[1].*would be removed/,
- "pg_archivecleanup dry run: matches");
- foreach my $fn (@walfiles)
- {
- ok(-f "$tempdir/$fn", "$fn not removed");
- }
-}
-
-sub run_check
-{
- my ($suffix, $test_name) = @_;
-
- create_files();
-
- command_ok(
- [
- 'pg_archivecleanup', '-x', '.gz', $tempdir,
- $walfiles[2] . $suffix
- ],
- "$test_name: runs");
-
- ok(!-f "$tempdir/$walfiles[0]",
- "$test_name: first older WAL file was cleaned up");
- ok(!-f "$tempdir/$walfiles[1]",
- "$test_name: second older WAL file was cleaned up");
- ok(-f "$tempdir/$walfiles[2]",
- "$test_name: restartfile was not cleaned up");
- ok(-f "$tempdir/$walfiles[3]",
- "$test_name: newer WAL file was not cleaned up");
- ok(-f "$tempdir/unrelated_file",
- "$test_name: unrelated file was not cleaned up");
- return;
-}
-
-run_check('', 'pg_archivecleanup');
-run_check('.partial', 'pg_archivecleanup with .partial file');
-run_check('.00000020.backup', 'pg_archivecleanup with .backup file');
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 33ebea2965..a0a6512b11 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -56,11 +56,11 @@ my @contrib_excludes = (
my $frontend_defines = { 'initdb' => 'FRONTEND' };
my @frontend_uselibpq = ('pg_ctl', 'pg_upgrade', 'pgbench', 'psql', 'initdb');
my @frontend_uselibpgport = (
- 'pg_archivecleanup', 'pg_test_fsync',
+ 'pg_test_fsync',
'pg_test_timing', 'pg_upgrade',
'pg_waldump', 'pgbench');
my @frontend_uselibpgcommon = (
- 'pg_archivecleanup', 'pg_test_fsync',
+ 'pg_test_fsync',
'pg_test_timing', 'pg_upgrade',
'pg_waldump', 'pgbench');
my $frontend_extralibs = {
--
2.17.0
Hi,
Am Mittwoch, den 28.10.2020, 21:44 -0500 schrieb Justin Pryzby:
Forking this thread:
/messages/by-id/fd93f1c5-7818-a02c-01e5-1075ac0d4def@iki.fi
Glancing over this in the context of pg_standby/pg_archivecleanup, I am
not sure Heikki's "Ditto" is about "remove pg_archivecleanup just like
pg_standby" or rather "keep the note until we get around doing something
with it". Probably the former, but see below.
I think these are old-fashioned since 9.6 (?), so remove them for v14.
Why 9.6?
I found it confusing when re-familiarizing myself with modern streaming
replication that there are extensions which only help do things the "old way".
I guess not many will complain about pg_standby going away, but I am
under the impression that pg_archivecleanup is still used a lot in PITR
backup environments as a handy tool to expire WAL related to expired
base backups. I certainly saw hand-assembled shell code fail with "too
many files" and things when it tried to act on large amount of WAL.
So I think the part about it being used in archive_cleanup_command can
be probably be removed, but the part about it being useful as a stand-
alone tool, in particular this part:
|In this mode, if you specify a .partial or .backup file name, then only
|the file prefix will be used as the oldestkeptwalfile. This treatment
|of .backup file name allows you to remove all WAL files archived prior
|to a specific base backup without error.
At the very least, the commit message should give a rationale on why
pg_archivebackup is retired, and what it should be replaced with, in
case valid use-cases for it are still present.
Michael
--
Michael Banck
Projektleiter / Senior Berater
Tel.: +49 2166 9901-171
Fax: +49 2166 9901-100
Email: michael.banck@credativ.de
credativ GmbH, HRB Mönchengladbach 12080
USt-ID-Nummer: DE204566209
Trompeterallee 108, 41189 Mönchengladbach
Geschäftsführung: Dr. Michael Meskes, Jörg Folz, Sascha Heuer
Unser Umgang mit personenbezogenen Daten unterliegt
folgenden Bestimmungen: https://www.credativ.de/datenschutz
On Thu, Oct 29, 2020 at 08:40:31PM +0100, Michael Banck wrote:
Am Mittwoch, den 28.10.2020, 21:44 -0500 schrieb Justin Pryzby:
Forking this thread:
/messages/by-id/fd93f1c5-7818-a02c-01e5-1075ac0d4def@iki.fi
I think these are old-fashioned since 9.6 (?), so remove them for v14.
Why 9.6?
My work doesn't currently bring me in contact with replication, so I've had to
dig through release notes. I think streaming replication was new in 9.0, and
increasingly mature throughout 9.x. Maybe someone else will say a different
release was when streaming replication became the norm and wal shipping old.
I found it confusing when re-familiarizing myself with modern streaming
replication that there are extensions which only help do things the "old way".I guess not many will complain about pg_standby going away, but I am
under the impression that pg_archivecleanup is still used a lot in PITR
backup environments as a handy tool to expire WAL related to expired
base backups. I certainly saw hand-assembled shell code fail with "too
many files" and things when it tried to act on large amount of WAL.
I anticipate you're right, and I'll withdraw 0002.
--
Justin
On 02/11/2020 20:26, Justin Pryzby wrote:
On Thu, Oct 29, 2020 at 08:40:31PM +0100, Michael Banck wrote:
Am Mittwoch, den 28.10.2020, 21:44 -0500 schrieb Justin Pryzby:
Forking this thread:
/messages/by-id/fd93f1c5-7818-a02c-01e5-1075ac0d4def@iki.fiI think these are old-fashioned since 9.6 (?), so remove them for v14.
Why 9.6?
My work doesn't currently bring me in contact with replication, so I've had to
dig through release notes. I think streaming replication was new in 9.0, and
increasingly mature throughout 9.x. Maybe someone else will say a different
release was when streaming replication became the norm and wal shipping old.
Removing pg_standby has been proposed a couple of times in the past. See
/messages/by-id/20170913064824.rqflkadxwpboabgw@alap3.anarazel.de
for the latest attempt.
Masao-san, back in 2014 you mentioned "fast failover" as a feature that
was missing from the built-in standby mode
(/messages/by-id/CAHGQGwEE_8vvpQk0ex6Qa_aXt-OSJ7OdZjX4uM_FtqKfxq5SbQ@mail.gmail.com).
I think that's been implemented since, with the recovery_target
settings. Would you agree?
I'm pretty sure we can remove pg_standby by now. But if there's
something crucial missing from the built-in facilities, we need to talk
about implementing them.
- Heikki
On Thu, Oct 29, 2020 at 3:40 PM Michael Banck <michael.banck@credativ.de> wrote:
I guess not many will complain about pg_standby going away, but I am
under the impression that pg_archivecleanup is still used a lot in PITR
backup environments as a handy tool to expire WAL related to expired
base backups. I certainly saw hand-assembled shell code fail with "too
many files" and things when it tried to act on large amount of WAL.
Yeah, I see pg_archivecleanup used in customer environments all the
time. Like just this morning, for example.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
On Tue, Nov 03, 2020 at 05:28:46PM +0200, Heikki Linnakangas wrote:
Removing pg_standby has been proposed a couple of times in the past. See /messages/by-id/20170913064824.rqflkadxwpboabgw@alap3.anarazel.de
for the latest attempt.Masao-san, back in 2014 you mentioned "fast failover" as a feature that was
missing from the built-in standby mode (/messages/by-id/CAHGQGwEE_8vvpQk0ex6Qa_aXt-OSJ7OdZjX4uM_FtqKfxq5SbQ@mail.gmail.com).
I think that's been implemented since, with the recovery_target settings.
Would you agree?I'm pretty sure we can remove pg_standby by now. But if there's something
crucial missing from the built-in facilities, we need to talk about
implementing them.
Reading the thread you are mentioning, it seems to me that the
statu-quo is the same, but I find rather scary that this tool is used
in exactly zero tests.
Echoing with Robert, I think that pg_archivecleanup is still useful in
many cases, so that's not something we should remove.
--
Michael
On 2020-10-29 03:44, Justin Pryzby wrote:
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index 4e833d79ef..be4292ec33 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -199,6 +199,5 @@ pages. part of the core <productname>PostgreSQL</productname> distribution. </para>- &pgstandby;
</sect1>
</appendix>
With this removal, that section becomes empty. So you probably want to
clean up or reorganize this a bit.
See https://www.postgresql.org/docs/devel/contrib-prog.html for the context.
On Fri, Nov 20, 2020 at 05:26:54PM +0100, Peter Eisentraut wrote:
On 2020-10-29 03:44, Justin Pryzby wrote:
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index 4e833d79ef..be4292ec33 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -199,6 +199,5 @@ pages. part of the core <productname>PostgreSQL</productname> distribution. </para> - &pgstandby; </sect1> </appendix>With this removal, that section becomes empty. So you probably want to
clean up or reorganize this a bit.See https://www.postgresql.org/docs/devel/contrib-prog.html for the context.
Oops. I guess I'd write something like this. If we just remove it, then
there'd no place to add a new server application, and "client applications"
would be the only subsection.
--
Justin
Attachments:
v2-0001-Add-missing-word-are.patchtext/x-diff; charset=us-asciiDownload
From 2cc4d8adc0d8e2f7bd4c21989a85e6e97b1d2fd6 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Fri, 20 Nov 2020 14:31:15 -0600
Subject: [PATCH v2 1/2] Add missing word: 'are'
Should backpatch
---
doc/src/sgml/contrib.sgml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index 4e833d79ef..ae2759be55 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -180,7 +180,7 @@ pages.
applications in <literal>contrib</literal>. They can be run from anywhere,
independent of where the database server resides. See
also <xref linkend="reference-client"/> for information about client
- applications that part of the core <productname>PostgreSQL</productname>
+ applications that are part of the core <productname>PostgreSQL</productname>
distribution.
</para>
@@ -196,7 +196,7 @@ pages.
applications in <literal>contrib</literal>. They are typically run on the
host where the database server resides. See also <xref
linkend="reference-server"/> for information about server applications that
- part of the core <productname>PostgreSQL</productname> distribution.
+ are part of the core <productname>PostgreSQL</productname> distribution.
</para>
&pgstandby;
--
2.17.0
v2-0002-Retire-pg_standby.patchtext/x-diff; charset=us-asciiDownload
From 626fba9074d6bd0e0d6615c0be5932ed63603455 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 26 Oct 2020 16:37:46 -0500
Subject: [PATCH v2 2/2] Retire pg_standby..
..since pg9.0, use builtin streaming replication protocol with warm/hot standby
---
contrib/Makefile | 1 -
contrib/pg_standby/.gitignore | 1 -
contrib/pg_standby/Makefile | 20 -
contrib/pg_standby/pg_standby.c | 907 ----------------------------
doc/src/sgml/contrib.sgml | 7 +-
doc/src/sgml/filelist.sgml | 1 -
doc/src/sgml/high-availability.sgml | 14 +-
doc/src/sgml/pgstandby.sgml | 394 ------------
src/tools/msvc/Mkvcbuild.pm | 4 +-
9 files changed, 7 insertions(+), 1342 deletions(-)
delete mode 100644 contrib/pg_standby/.gitignore
delete mode 100644 contrib/pg_standby/Makefile
delete mode 100644 contrib/pg_standby/pg_standby.c
delete mode 100644 doc/src/sgml/pgstandby.sgml
diff --git a/contrib/Makefile b/contrib/Makefile
index 7a4866e338..cdc041c7db 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -33,7 +33,6 @@ SUBDIRS = \
pg_buffercache \
pg_freespacemap \
pg_prewarm \
- pg_standby \
pg_stat_statements \
pg_surgery \
pg_trgm \
diff --git a/contrib/pg_standby/.gitignore b/contrib/pg_standby/.gitignore
deleted file mode 100644
index a401b085a8..0000000000
--- a/contrib/pg_standby/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/pg_standby
diff --git a/contrib/pg_standby/Makefile b/contrib/pg_standby/Makefile
deleted file mode 100644
index 87732bedf1..0000000000
--- a/contrib/pg_standby/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# contrib/pg_standby/Makefile
-
-PGFILEDESC = "pg_standby - supports creation of a warm standby"
-PGAPPICON = win32
-
-PROGRAM = pg_standby
-OBJS = \
- $(WIN32RES) \
- pg_standby.o
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_standby
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
deleted file mode 100644
index c9f33e4254..0000000000
--- a/contrib/pg_standby/pg_standby.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * contrib/pg_standby/pg_standby.c
- *
- *
- * pg_standby.c
- *
- * Production-ready example of how to create a Warm Standby
- * database server using continuous archiving as a
- * replication mechanism
- *
- * We separate the parameters for archive and nextWALfile
- * so that we can check the archive exists, even if the
- * 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.
- *
- * Original author: Simon Riggs simon@2ndquadrant.com
- * Current maintainer: Simon Riggs
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "access/xlog_internal.h"
-#include "pg_getopt.h"
-
-const char *progname;
-
-int WalSegSz = -1;
-
-/* Options and defaults */
-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? */
-bool need_cleanup = false; /* do we need to remove files from
- * archive? */
-
-#ifndef WIN32
-static volatile sig_atomic_t signaled = false;
-#endif
-
-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 */
-char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
-char restoreCommand[MAXPGPATH]; /* run this to restore */
-char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
- * from archive */
-
-/*
- * 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
-
-static int Failover = NoFailover;
-
-#define RESTORE_COMMAND_COPY 0
-#define RESTORE_COMMAND_LINK 1
-int restoreCommandType;
-
-#define XLOG_DATA 0
-#define XLOG_HISTORY 1
-int nextWALFileType;
-
-#define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
- snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
-
-struct stat stat_buf;
-
-static bool SetWALFileNameForCleanup(void);
-static bool SetWALSegSize(void);
-
-
-/* =====================================================================
- *
- * 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
- * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
- * or personally to the current maintainer. Those changes may be
- * folded in to later versions of this program.
- */
-
-/*
- * Initialize allows customized commands into the warm standby program.
- *
- * As an example, and probably the common case, we use either
- * cp/ln commands on *nix, or copy/move command on Windows.
- */
-static void
-CustomizableInitialize(void)
-{
-#ifdef WIN32
- snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("mklink", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("copy", WALFilePath, xlogFilePath);
- break;
- }
-#else
- snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("ln -s -f", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("cp", WALFilePath, xlogFilePath);
- break;
- }
-#endif
-
- /*
- * 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
- * directory, we use stat to test if it's accessible
- */
- if (stat(archiveLocation, &stat_buf) != 0)
- {
- fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
- fflush(stderr);
- exit(2);
- }
-}
-
-/*
- * CustomizableNextWALFileReady()
- *
- * Is the requested file ready yet?
- */
-static bool
-CustomizableNextWALFileReady(void)
-{
- if (stat(WALFilePath, &stat_buf) == 0)
- {
- /*
- * 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");
- }
- }
- }
-
- /*
- * Return only if it's the right size already.
- */
- if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
- {
-#ifdef WIN32
-
- /*
- * Windows 'cp' sets the final file size before the copy is
- * 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.
- */
- pg_usleep(sleeptime * 1000000L);
-#endif
- nextWALFileType = XLOG_DATA;
- return true;
- }
-
- /*
- * If still too small, wait until it is the correct size
- */
- if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
- {
- if (debug)
- {
- fprintf(stderr, "file size greater than expected\n");
- fflush(stderr);
- }
- exit(3);
- }
- }
-
- return false;
-}
-
-static void
-CustomizableCleanupPriorWALFiles(void)
-{
- /*
- * Work out name of prior file from current filename
- */
- if (nextWALFileType == XLOG_DATA)
- {
- int rc;
- DIR *xldir;
- struct dirent *xlde;
-
- /*
- * Assume it's OK to keep failing. The failure situation may change
- * over time, so we'd rather keep going on the main processing than
- * fail because we couldn't clean up yet.
- */
- if ((xldir = opendir(archiveLocation)) != NULL)
- {
- while (errno = 0, (xlde = readdir(xldir)) != NULL)
- {
- /*
- * 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.
- *
- * 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.
- */
- if (IsXLogFileName(xlde->d_name) &&
- strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
- {
-#ifdef WIN32
- snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
-#else
- snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
-#endif
-
- if (debug)
- fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
-
- rc = unlink(WALFilePath);
- if (rc != 0)
- {
- fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- break;
- }
- }
- }
-
- if (errno)
- fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
- if (debug)
- fprintf(stderr, "\n");
- }
- else
- fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- if (closedir(xldir))
- fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- fflush(stderr);
- }
-}
-
-/* =====================================================================
- * End of Customizable section
- * =====================================================================
- */
-
-/*
- * SetWALFileNameForCleanup()
- *
- * Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need_cleanup
- */
-static bool
-SetWALFileNameForCleanup(void)
-{
- uint32 tli = 1,
- log = 0,
- seg = 0;
- uint32 log_diff = 0,
- seg_diff = 0;
- bool cleanup = false;
- int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
-
- if (restartWALFileName)
- {
- /*
- * 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.
- */
- if (strcmp(restartWALFileName, nextWALFileName) > 0)
- return false;
-
- strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
- return true;
- }
-
- if (keepfiles > 0)
- {
- sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
- if (tli > 0 && seg > 0)
- {
- log_diff = keepfiles / max_segments_per_logfile;
- seg_diff = keepfiles % max_segments_per_logfile;
- if (seg_diff > seg)
- {
- log_diff++;
- seg = max_segments_per_logfile - (seg_diff - seg);
- }
- else
- seg -= seg_diff;
-
- if (log >= log_diff)
- {
- log -= log_diff;
- cleanup = true;
- }
- else
- {
- log = 0;
- seg = 0;
- }
- }
- }
-
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
-
- return cleanup;
-}
-
-/*
- * 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;
- PGAlignedXLogBlock buf;
-
- Assert(WalSegSz == -1);
-
- if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
- {
- fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- return false;
- }
-
- errno = 0;
- if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
- {
- XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
-
- 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)
- fprintf(stderr, "could not read file \"%s\": %s\n",
- WALFilePath, strerror(errno));
- }
- else
- {
- if (debug)
- fprintf(stderr, "not enough data in file \"%s\"\n",
- WALFilePath);
- }
- }
-
- fflush(stderr);
-
- close(fd);
- return ret_val;
-}
-
-/*
- * CheckForExternalTrigger()
- *
- * Is there a trigger file? Sets global 'Failover' variable to indicate
- * what kind of a trigger file it was. A "fast" trigger file is turned
- * into a "smart" file as a side-effect.
- */
-static void
-CheckForExternalTrigger(void)
-{
- char buf[32];
- int fd;
- int len;
-
- /*
- * Look for a trigger file, if that option has been selected
- *
- * We use stat() here because triggerPath is always a file rather than
- * potentially being in an archive
- */
- if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
- return;
-
- /*
- * An empty trigger file performs smart failover. There's a little race
- * 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
- * invoked next time, we'll see the word "fast" and fail over immediately.
- */
- if (stat_buf.st_size == 0)
- {
- 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;
- }
-
- if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- close(fd);
- return;
- }
- buf[len] = '\0';
-
- if (strncmp(buf, "smart", 5) == 0)
- {
- Failover = SmartFailover;
- fprintf(stderr, "trigger file found: smart failover\n");
- fflush(stderr);
- close(fd);
- return;
- }
-
- if (strncmp(buf, "fast", 4) == 0)
- {
- Failover = FastFailover;
-
- fprintf(stderr, "trigger file found: fast failover\n");
- fflush(stderr);
-
- /*
- * Turn it into a "smart" trigger by truncating the file. Otherwise if
- * the server asks us again to restore a segment that was restored
- * already, we would return "not found" and upset the server.
- */
- if (ftruncate(fd, 0) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- }
- close(fd);
-
- return;
- }
- close(fd);
-
- fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
- fflush(stderr);
-}
-
-/*
- * RestoreWALFileForRecovery()
- *
- * Perform the action required to restore the file from archive
- */
-static bool
-RestoreWALFileForRecovery(void)
-{
- int rc = 0;
- int numretries = 0;
-
- if (debug)
- {
- fprintf(stderr, "running restore: ");
- fflush(stderr);
- }
-
- while (numretries <= maxretries)
- {
- rc = system(restoreCommand);
- if (rc == 0)
- {
- if (debug)
- {
- fprintf(stderr, "OK\n");
- fflush(stderr);
- }
- return true;
- }
- pg_usleep(numretries++ * sleeptime * 1000000L);
- }
-
- /*
- * Allow caller to add additional info
- */
- if (debug)
- fprintf(stderr, "not restored\n");
- return false;
-}
-
-static void
-usage(void)
-{
- 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");
- printf(" -c copy file from archive (default)\n");
- printf(" -d generate lots of debugging output (testing only)\n");
- printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
- " (0 keeps all)\n");
- printf(" -l does nothing; use of link is now deprecated\n");
- 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");
- printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
- printf(" -V, --version output version information, then exit\n");
- printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
- printf(" -?, --help show this help, then exit\n");
- printf("\n"
- "Main intended use as restore_command in postgresql.conf:\n"
- " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
- "e.g.\n"
- " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
- printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
- printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
-}
-
-#ifndef WIN32
-static void
-sighandler(int sig)
-{
- signaled = true;
-}
-
-/* We don't want SIGQUIT to core dump */
-static void
-sigquit_handler(int sig)
-{
- pqsignal(SIGINT, SIG_DFL);
- kill(getpid(), SIGINT);
-}
-#endif
-
-/*------------ MAIN ----------------------------------------*/
-int
-main(int argc, char **argv)
-{
- int c;
-
- 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);
- }
- }
-
-#ifndef WIN32
-
- /*
- * You can send SIGUSR1 to trigger failover.
- *
- * Postmaster uses SIGQUIT to request immediate shutdown. The default
- * action is to core dump, but we don't want that, so trap it and commit
- * suicide without core dump.
- *
- * 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.
- *
- * There's no way to trigger failover via signal on Windows.
- */
- (void) pqsignal(SIGUSR1, sighandler);
- (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
- (void) pqsignal(SIGQUIT, sigquit_handler);
-#endif
-
- 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);
- if (keepfiles < 0)
- {
- fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 'l': /* Use link */
-
- /*
- * Link feature disabled, possibly permanently. Linking causes
- * a problem after recovery ends that is not currently
- * resolved by PostgreSQL. 25 Jun 2009
- */
-#ifdef NOT_USED
- restoreCommandType = RESTORE_COMMAND_LINK;
-#endif
- break;
- case 'r': /* Retries */
- maxretries = atoi(optarg);
- if (maxretries < 0)
- {
- fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 's': /* Sleep time */
- sleeptime = atoi(optarg);
- if (sleeptime <= 0 || sleeptime > 60)
- {
- fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
- exit(2);
- }
- break;
- case 't': /* Trigger file */
- triggerPath = pg_strdup(optarg);
- break;
- case 'w': /* Max wait time */
- maxwaittime = atoi(optarg);
- if (maxwaittime < 0)
- {
- fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
- exit(2);
- }
- break;
- default:
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- break;
- }
- }
-
- /*
- * Parameter checking - after checking to see if trigger file present
- */
- if (argc == 1)
- {
- fprintf(stderr, "%s: not enough command-line arguments\n", progname);
- exit(2);
- }
-
- /*
- * We will go to the archiveLocation to get nextWALFileName.
- * nextWALFileName may not exist yet, which would not be an error, so we
- * separate the archiveLocation and nextWALFileName so we can check
- * separately whether archiveLocation exists, if not that is an error
- */
- if (optind < argc)
- {
- archiveLocation = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify archive location\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- nextWALFileName = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- xlogFilePath = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- restartWALFileName = argv[optind];
- optind++;
- }
-
- CustomizableInitialize();
-
- if (debug)
- {
- 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",
- sleeptime, (sleeptime > 1 ? "s" : " "));
- fprintf(stderr, "Max wait interval: %d %s\n",
- maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
- fprintf(stderr, "Command for restore: %s\n", restoreCommand);
- 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
- */
- if (IsTLHistoryFileName(nextWALFileName))
- {
- nextWALFileType = XLOG_HISTORY;
- if (RestoreWALFileForRecovery())
- exit(0);
- else
- {
- if (debug)
- {
- fprintf(stderr, "history file not found\n");
- fflush(stderr);
- }
- exit(1);
- }
- }
-
- /*
- * Main wait loop
- */
- for (;;)
- {
- /* Check for trigger file or signal first */
- CheckForExternalTrigger();
-#ifndef WIN32
- if (signaled)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "signaled to exit: fast failover\n");
- fflush(stderr);
- }
- }
-#endif
-
- /*
- * Check for fast failover immediately, before checking if the
- * requested WAL file is available
- */
- if (Failover == FastFailover)
- exit(1);
-
- if (CustomizableNextWALFileReady())
- {
- /*
- * Once we have restored this file successfully we can remove some
- * prior WAL files. If this restore fails we mustn't remove any
- * file because some of them will be requested again immediately
- * after the failed restore, or when we restart recovery.
- */
- if (RestoreWALFileForRecovery())
- {
- if (need_cleanup)
- CustomizableCleanupPriorWALFiles();
-
- exit(0);
- }
- else
- {
- /* Something went wrong in copying the file */
- exit(1);
- }
- }
-
- /* Check for smart failover if the next WAL file was not available */
- if (Failover == SmartFailover)
- exit(1);
-
- if (sleeptime <= 60)
- pg_usleep(sleeptime * 1000000L);
-
- waittime += sleeptime;
- if (waittime >= maxwaittime && maxwaittime > 0)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "Timed out after %d seconds: fast failover\n",
- waittime);
- fflush(stderr);
- }
- }
- if (debug)
- {
- fprintf(stderr, "WAL file not present yet.");
- if (triggerPath)
- fprintf(stderr, " Checking for trigger file...");
- fprintf(stderr, "\n");
- fflush(stderr);
- }
- }
-}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index ae2759be55..d3ca4b6932 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -192,13 +192,12 @@ pages.
<title>Server Applications</title>
<para>
- This section covers <productname>PostgreSQL</productname> server-related
- applications in <literal>contrib</literal>. They are typically run on the
- host where the database server resides. See also <xref
+ Some applications run on the <productname>PostgreSQL</productname> server
+ itself. Currently, no such applications are included in the
+ <literal>contrib</literal> directory. See also <xref
linkend="reference-server"/> for information about server applications that
are part of the core <productname>PostgreSQL</productname> distribution.
</para>
- &pgstandby;
</sect1>
</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..db1d369743 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -138,7 +138,6 @@
<!ENTITY pgfreespacemap SYSTEM "pgfreespacemap.sgml">
<!ENTITY pgprewarm SYSTEM "pgprewarm.sgml">
<!ENTITY pgrowlocks SYSTEM "pgrowlocks.sgml">
-<!ENTITY pgstandby SYSTEM "pgstandby.sgml">
<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml">
<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml">
<!ENTITY pgsurgery SYSTEM "pgsurgery.sgml">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index 1892def655..b2ca63d370 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -702,8 +702,7 @@ protocol to make nodes agree on a serializable transactional order.
Do not use pg_standby or similar tools with the built-in standby mode
described here. <xref linkend="guc-restore-command"/> should return immediately
if the file does not exist; the server will retry the command again if
- necessary. See <xref linkend="log-shipping-alternative"/>
- for using tools like pg_standby.
+ necessary.
</para>
</note>
@@ -1482,8 +1481,7 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
<para>
An alternative to the built-in standby mode described in the previous
sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below. See the
- <xref linkend="pgstandby"/> module for a reference implementation of this.
+ This was the only option available in versions 8.4 and below.
</para>
<para>
@@ -1539,14 +1537,6 @@ if (!triggered)
</programlisting>
</para>
- <para>
- A working example of a waiting <varname>restore_command</varname> is provided
- in the <xref linkend="pgstandby"/> module. It
- should be used as a reference on how to correctly implement the logic
- described above. It can also be extended as needed to support specific
- configurations and environments.
- </para>
-
<para>
The method for triggering failover is an important part of planning
and design. One potential option is the <varname>restore_command</varname>
diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml
deleted file mode 100644
index 66a6255930..0000000000
--- a/doc/src/sgml/pgstandby.sgml
+++ /dev/null
@@ -1,394 +0,0 @@
-<!-- doc/src/sgml/pgstandby.sgml -->
-
-<refentry id="pgstandby">
- <indexterm zone="pgstandby">
- <primary>pg_standby</primary>
- </indexterm>
-
- <refmeta>
- <refentrytitle><application>pg_standby</application></refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo>Application</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>pg_standby</refname>
- <refpurpose>supports the creation of a <productname>PostgreSQL</productname> warm standby server</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>pg_standby</command>
- <arg rep="repeat"><replaceable>option</replaceable></arg>
- <arg choice="plain"><replaceable>archivelocation</replaceable></arg>
- <arg choice="plain"><replaceable>nextwalfile</replaceable></arg>
- <arg choice="plain"><replaceable>walfilepath</replaceable></arg>
- <arg choice="opt"><replaceable>restartwalfile</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <application>pg_standby</application> supports creation of a <quote>warm standby</quote>
- database server. It is designed to be a production-ready program, as well
- as a customizable template should you require specific modifications.
- </para>
-
- <para>
- <application>pg_standby</application> is designed to be a waiting
- <varname>restore_command</varname>, which is needed to turn a standard
- archive recovery into a warm standby operation. Other
- configuration is required as well, all of which is described in the main
- server manual (see <xref linkend="warm-standby"/>).
- </para>
-
- <para>
- To configure a standby
- server to use <application>pg_standby</application>, put this into its
- <filename>postgresql.conf</filename> configuration file:
-<programlisting>
-restore_command = 'pg_standby <replaceable>archiveDir</replaceable> %f %p %r'
-</programlisting>
- where <replaceable>archiveDir</replaceable> is the directory from which WAL segment
- files should be restored.
- </para>
- <para>
- If <replaceable>restartwalfile</replaceable> is specified, normally by using the
- <literal>%r</literal> macro, then all WAL files logically preceding this
- file will be removed from <replaceable>archivelocation</replaceable>. This minimizes
- the number of files that need to be retained, while preserving
- crash-restart capability. Use of this parameter is appropriate if the
- <replaceable>archivelocation</replaceable> is a transient staging area for this
- particular standby server, but <emphasis>not</emphasis> when the
- <replaceable>archivelocation</replaceable> is intended as a long-term WAL archive area.
- </para>
- <para>
- <application>pg_standby</application> assumes that
- <replaceable>archivelocation</replaceable> is a directory readable by the
- server-owning user. If <replaceable>restartwalfile</replaceable> (or <literal>-k</literal>)
- is specified,
- the <replaceable>archivelocation</replaceable> directory must be writable too.
- </para>
- <para>
- There are two ways to fail over to a <quote>warm standby</quote> database server
- when the primary server fails:
-
- <variablelist>
- <varlistentry>
- <term>Smart Failover</term>
- <listitem>
- <para>
- In smart failover, the server is brought up after applying all WAL
- files available in the archive. This results in zero data loss, even if
- the standby server has fallen behind, but if there is a lot of
- unapplied WAL it can be a long time before the standby server becomes
- ready. To trigger a smart failover, create a trigger file containing
- the word <literal>smart</literal>, or just create it and leave it empty.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Fast Failover</term>
- <listitem>
- <para>
- In fast failover, the server is brought up immediately. Any WAL files
- in the archive that have not yet been applied will be ignored, and
- all transactions in those files are lost. To trigger a fast failover,
- create a trigger file and write the word <literal>fast</literal> into it.
- <application>pg_standby</application> can also be configured to execute a fast
- failover automatically if no new WAL file appears within a defined
- interval.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>
- <application>pg_standby</application> accepts the following command-line arguments:
-
- <variablelist>
-
- <varlistentry>
- <term><option>-c</option></term>
- <listitem>
- <para>
- Use <literal>cp</literal> or <literal>copy</literal> command to restore WAL files
- from archive. This is the only supported behavior so this option is useless.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
- <listitem>
- <para>
- Print lots of debug logging output on <filename>stderr</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-k</option></term>
- <listitem>
- <para>
- Remove files from <replaceable>archivelocation</replaceable> so that
- no more than this many WAL files before the current one are kept in the
- archive. Zero (the default) means not to remove any files from
- <replaceable>archivelocation</replaceable>.
- This parameter will be silently ignored if
- <replaceable>restartwalfile</replaceable> is specified, since that
- specification method is more accurate in determining the correct
- archive cut-off point.
- Use of this parameter is <emphasis>deprecated</emphasis> as of
- <productname>PostgreSQL</productname> 8.3; it is safer and more efficient to
- specify a <replaceable>restartwalfile</replaceable> parameter. A too
- small setting could result in removal of files that are still needed
- for a restart of the standby server, while a too large setting wastes
- archive space.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-r</option> <replaceable>maxretries</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of times to retry the copy command if
- it fails (default 3). After each failure, we wait for
- <replaceable>sleeptime</replaceable> * <replaceable>num_retries</replaceable>
- so that the wait time increases progressively. So by default,
- we will wait 5 secs, 10 secs, then 15 secs before reporting
- the failure back to the standby server. This will be
- interpreted as end of recovery and the standby will come
- up fully as a result.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-s</option> <replaceable>sleeptime</replaceable></term>
- <listitem>
- <para>
- Set the number of seconds (up to 60, default 5) to sleep between
- tests to see if the WAL file to be restored is available in
- the archive yet. The default setting is not necessarily
- recommended; consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-t</option> <replaceable>triggerfile</replaceable></term>
- <listitem>
- <para>
- Specify a trigger file whose presence should cause failover.
- It is recommended that you use a structured file name to
- avoid confusion as to which server is being triggered
- when multiple servers exist on the same system; for example
- <filename>/tmp/pgsql.trigger.5432</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-V</option></term>
- <term><option>--version</option></term>
- <listitem>
- <para>
- Print the <application>pg_standby</application> version and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-w</option> <replaceable>maxwaittime</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of seconds to wait for the next WAL file,
- after which a fast failover will be performed.
- A setting of zero (the default) means wait forever.
- The default setting is not necessarily recommended;
- consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-?</option></term>
- <term><option>--help</option></term>
- <listitem>
- <para>
- Show help about <application>pg_standby</application> command line
- arguments, and exit.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <para>
- <application>pg_standby</application> is designed to work with
- <productname>PostgreSQL</productname> 8.2 and later.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.3 provides the <literal>%r</literal> macro,
- which is designed to let <application>pg_standby</application> know the
- last file it needs to keep. With <productname>PostgreSQL</productname> 8.2, the
- <literal>-k</literal> option must be used if archive cleanup is
- required. This option remains available in 8.3, but its use is deprecated.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.4 provides the
- <varname>recovery_end_command</varname> option. Without this option
- a leftover trigger file can be hazardous.
- </para>
-
- <para>
- <application>pg_standby</application> is written in C and has an
- easy-to-modify source code, with specifically designated sections to modify
- for your own needs
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <para>On Linux or Unix systems, you might use:
-
-<programlisting>
-archive_command = 'cp %p .../archive/%f'
-
-restore_command = 'pg_standby -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442'
-</programlisting>
- where the archive directory is physically located on the standby server,
- so that the <varname>archive_command</varname> is accessing it across NFS,
- but the files are local to the standby (enabling use of <literal>ln</literal>).
- This will:
- <itemizedlist>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 2 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>/tmp/pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>On Windows, you might use:
-
-<programlisting>
-archive_command = 'copy %p ...\\archive\\%f'
-
-restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'del C:\pgsql.trigger.5442'
-</programlisting>
- Note that backslashes need to be doubled in the
- <varname>archive_command</varname>, but <emphasis>not</emphasis> in the
- <varname>restore_command</varname> or <varname>recovery_end_command</varname>.
- This will:
- <itemizedlist>
- <listitem>
- <para>
- use the <literal>copy</literal> command to restore WAL files from archive
- </para>
- </listitem>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 5 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>C:\pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- The <literal>copy</literal> command on Windows sets the final file size
- before the file is completely copied, which would ordinarily confuse
- <application>pg_standby</application>. Therefore
- <application>pg_standby</application> waits <replaceable>sleeptime</replaceable>
- seconds once it sees the proper file size. GNUWin32's <literal>cp</literal>
- sets the file size only after the file copy is complete.
- </para>
-
- <para>
- Since the Windows example uses <literal>copy</literal> at both ends, either
- or both servers might be accessing the archive directory across the
- network.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Author</title>
-
- <para>
- Simon Riggs <email>simon@2ndquadrant.com</email>
- </para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgarchivecleanup"/></member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index c86323a6df..a0a6512b11 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -34,8 +34,8 @@ my @unlink_on_exit;
# Set of variables for modules in contrib/ and src/test/modules/
my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
my @contrib_uselibpq = ('dblink', 'oid2name', 'postgres_fdw', 'vacuumlo');
-my @contrib_uselibpgport = ('oid2name', 'pg_standby', 'vacuumlo');
-my @contrib_uselibpgcommon = ('oid2name', 'pg_standby', 'vacuumlo');
+my @contrib_uselibpgport = ('oid2name', 'vacuumlo');
+my @contrib_uselibpgcommon = ('oid2name', 'vacuumlo');
my $contrib_extralibs = undef;
my $contrib_extraincludes = { 'dblink' => ['src/backend'] };
my $contrib_extrasource = {
--
2.17.0
On 2020-11-21 20:41, Justin Pryzby wrote:
On Fri, Nov 20, 2020 at 05:26:54PM +0100, Peter Eisentraut wrote:
On 2020-10-29 03:44, Justin Pryzby wrote:
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index 4e833d79ef..be4292ec33 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -199,6 +199,5 @@ pages. part of the core <productname>PostgreSQL</productname> distribution. </para> - &pgstandby; </sect1> </appendix>With this removal, that section becomes empty. So you probably want to
clean up or reorganize this a bit.See https://www.postgresql.org/docs/devel/contrib-prog.html for the context.
Oops. I guess I'd write something like this. If we just remove it, then
there'd no place to add a new server application, and "client applications"
would be the only subsection.
I have committed the typo fix. I don't have a well-formed opinion yet
about whether all the reservations about removing pg_standby have been
addressed.
On Wed, Nov 25, 2020 at 10:04 PM Peter Eisentraut
<peter.eisentraut@enterprisedb.com> wrote:
On 2020-11-21 20:41, Justin Pryzby wrote:
Oops. I guess I'd write something like this. If we just remove it, then
there'd no place to add a new server application, and "client applications"
would be the only subsection.I have committed the typo fix. I don't have a well-formed opinion yet
about whether all the reservations about removing pg_standby have been
addressed.
I would like to commit this, because "waiting restore commands" have
confusing interactions with my proposed prefetching-during-recovery
patch[1]/messages/by-id/CA+hUKGKFeYPL9K+SRixcsx1+6HsHhqK+POZyrnnZjw1jERpGcQ@mail.gmail.com. Here's a version that fixes an error when building the docs
(there was a stray remaining <xref linkend="pgstandby"/>), and adds a
commit message. Any objections?
Furthermore, I think we should also remove the section of the manual
that describes how to write your own "waiting restore command".
Thoughts?
[1]: /messages/by-id/CA+hUKGKFeYPL9K+SRixcsx1+6HsHhqK+POZyrnnZjw1jERpGcQ@mail.gmail.com
Attachments:
v3-0001-Retire-pg_standby.patchtext/x-patch; charset=US-ASCII; name=v3-0001-Retire-pg_standby.patchDownload
From 54b12290e304bf1d4c995836addb7a53e8e7b74b Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 26 Oct 2020 16:37:46 -0500
Subject: [PATCH v3] Retire pg_standby.
Streaming replication made pg_standby obsolete. It has been proposed
that we retire it many times. Now seems like a good time to do it,
because "waiting restore commands" are incompatible with a proposed WAL
prefetching feature.
Discussion: https://postgr.es/m/20201029024412.GP5380%40telsasoft.com
Author: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com>
---
contrib/Makefile | 1 -
contrib/pg_standby/.gitignore | 1 -
contrib/pg_standby/Makefile | 20 -
contrib/pg_standby/pg_standby.c | 907 -------------------------
doc/src/sgml/contrib.sgml | 7 +-
doc/src/sgml/filelist.sgml | 1 -
doc/src/sgml/high-availability.sgml | 14 +-
doc/src/sgml/pgstandby.sgml | 394 -----------
doc/src/sgml/ref/pgarchivecleanup.sgml | 7 -
src/tools/msvc/Mkvcbuild.pm | 4 +-
10 files changed, 7 insertions(+), 1349 deletions(-)
delete mode 100644 contrib/pg_standby/.gitignore
delete mode 100644 contrib/pg_standby/Makefile
delete mode 100644 contrib/pg_standby/pg_standby.c
delete mode 100644 doc/src/sgml/pgstandby.sgml
diff --git a/contrib/Makefile b/contrib/Makefile
index 7a4866e338..cdc041c7db 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -33,7 +33,6 @@ SUBDIRS = \
pg_buffercache \
pg_freespacemap \
pg_prewarm \
- pg_standby \
pg_stat_statements \
pg_surgery \
pg_trgm \
diff --git a/contrib/pg_standby/.gitignore b/contrib/pg_standby/.gitignore
deleted file mode 100644
index a401b085a8..0000000000
--- a/contrib/pg_standby/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/pg_standby
diff --git a/contrib/pg_standby/Makefile b/contrib/pg_standby/Makefile
deleted file mode 100644
index 87732bedf1..0000000000
--- a/contrib/pg_standby/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# contrib/pg_standby/Makefile
-
-PGFILEDESC = "pg_standby - supports creation of a warm standby"
-PGAPPICON = win32
-
-PROGRAM = pg_standby
-OBJS = \
- $(WIN32RES) \
- pg_standby.o
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_standby
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
deleted file mode 100644
index c9f33e4254..0000000000
--- a/contrib/pg_standby/pg_standby.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * contrib/pg_standby/pg_standby.c
- *
- *
- * pg_standby.c
- *
- * Production-ready example of how to create a Warm Standby
- * database server using continuous archiving as a
- * replication mechanism
- *
- * We separate the parameters for archive and nextWALfile
- * so that we can check the archive exists, even if the
- * 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.
- *
- * Original author: Simon Riggs simon@2ndquadrant.com
- * Current maintainer: Simon Riggs
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "access/xlog_internal.h"
-#include "pg_getopt.h"
-
-const char *progname;
-
-int WalSegSz = -1;
-
-/* Options and defaults */
-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? */
-bool need_cleanup = false; /* do we need to remove files from
- * archive? */
-
-#ifndef WIN32
-static volatile sig_atomic_t signaled = false;
-#endif
-
-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 */
-char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
-char restoreCommand[MAXPGPATH]; /* run this to restore */
-char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
- * from archive */
-
-/*
- * 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
-
-static int Failover = NoFailover;
-
-#define RESTORE_COMMAND_COPY 0
-#define RESTORE_COMMAND_LINK 1
-int restoreCommandType;
-
-#define XLOG_DATA 0
-#define XLOG_HISTORY 1
-int nextWALFileType;
-
-#define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
- snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
-
-struct stat stat_buf;
-
-static bool SetWALFileNameForCleanup(void);
-static bool SetWALSegSize(void);
-
-
-/* =====================================================================
- *
- * 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
- * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
- * or personally to the current maintainer. Those changes may be
- * folded in to later versions of this program.
- */
-
-/*
- * Initialize allows customized commands into the warm standby program.
- *
- * As an example, and probably the common case, we use either
- * cp/ln commands on *nix, or copy/move command on Windows.
- */
-static void
-CustomizableInitialize(void)
-{
-#ifdef WIN32
- snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("mklink", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("copy", WALFilePath, xlogFilePath);
- break;
- }
-#else
- snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("ln -s -f", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("cp", WALFilePath, xlogFilePath);
- break;
- }
-#endif
-
- /*
- * 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
- * directory, we use stat to test if it's accessible
- */
- if (stat(archiveLocation, &stat_buf) != 0)
- {
- fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
- fflush(stderr);
- exit(2);
- }
-}
-
-/*
- * CustomizableNextWALFileReady()
- *
- * Is the requested file ready yet?
- */
-static bool
-CustomizableNextWALFileReady(void)
-{
- if (stat(WALFilePath, &stat_buf) == 0)
- {
- /*
- * 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");
- }
- }
- }
-
- /*
- * Return only if it's the right size already.
- */
- if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
- {
-#ifdef WIN32
-
- /*
- * Windows 'cp' sets the final file size before the copy is
- * 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.
- */
- pg_usleep(sleeptime * 1000000L);
-#endif
- nextWALFileType = XLOG_DATA;
- return true;
- }
-
- /*
- * If still too small, wait until it is the correct size
- */
- if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
- {
- if (debug)
- {
- fprintf(stderr, "file size greater than expected\n");
- fflush(stderr);
- }
- exit(3);
- }
- }
-
- return false;
-}
-
-static void
-CustomizableCleanupPriorWALFiles(void)
-{
- /*
- * Work out name of prior file from current filename
- */
- if (nextWALFileType == XLOG_DATA)
- {
- int rc;
- DIR *xldir;
- struct dirent *xlde;
-
- /*
- * Assume it's OK to keep failing. The failure situation may change
- * over time, so we'd rather keep going on the main processing than
- * fail because we couldn't clean up yet.
- */
- if ((xldir = opendir(archiveLocation)) != NULL)
- {
- while (errno = 0, (xlde = readdir(xldir)) != NULL)
- {
- /*
- * 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.
- *
- * 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.
- */
- if (IsXLogFileName(xlde->d_name) &&
- strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
- {
-#ifdef WIN32
- snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
-#else
- snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
-#endif
-
- if (debug)
- fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
-
- rc = unlink(WALFilePath);
- if (rc != 0)
- {
- fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- break;
- }
- }
- }
-
- if (errno)
- fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
- if (debug)
- fprintf(stderr, "\n");
- }
- else
- fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- if (closedir(xldir))
- fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- fflush(stderr);
- }
-}
-
-/* =====================================================================
- * End of Customizable section
- * =====================================================================
- */
-
-/*
- * SetWALFileNameForCleanup()
- *
- * Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need_cleanup
- */
-static bool
-SetWALFileNameForCleanup(void)
-{
- uint32 tli = 1,
- log = 0,
- seg = 0;
- uint32 log_diff = 0,
- seg_diff = 0;
- bool cleanup = false;
- int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
-
- if (restartWALFileName)
- {
- /*
- * 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.
- */
- if (strcmp(restartWALFileName, nextWALFileName) > 0)
- return false;
-
- strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
- return true;
- }
-
- if (keepfiles > 0)
- {
- sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
- if (tli > 0 && seg > 0)
- {
- log_diff = keepfiles / max_segments_per_logfile;
- seg_diff = keepfiles % max_segments_per_logfile;
- if (seg_diff > seg)
- {
- log_diff++;
- seg = max_segments_per_logfile - (seg_diff - seg);
- }
- else
- seg -= seg_diff;
-
- if (log >= log_diff)
- {
- log -= log_diff;
- cleanup = true;
- }
- else
- {
- log = 0;
- seg = 0;
- }
- }
- }
-
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
-
- return cleanup;
-}
-
-/*
- * 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;
- PGAlignedXLogBlock buf;
-
- Assert(WalSegSz == -1);
-
- if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
- {
- fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- return false;
- }
-
- errno = 0;
- if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
- {
- XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
-
- 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)
- fprintf(stderr, "could not read file \"%s\": %s\n",
- WALFilePath, strerror(errno));
- }
- else
- {
- if (debug)
- fprintf(stderr, "not enough data in file \"%s\"\n",
- WALFilePath);
- }
- }
-
- fflush(stderr);
-
- close(fd);
- return ret_val;
-}
-
-/*
- * CheckForExternalTrigger()
- *
- * Is there a trigger file? Sets global 'Failover' variable to indicate
- * what kind of a trigger file it was. A "fast" trigger file is turned
- * into a "smart" file as a side-effect.
- */
-static void
-CheckForExternalTrigger(void)
-{
- char buf[32];
- int fd;
- int len;
-
- /*
- * Look for a trigger file, if that option has been selected
- *
- * We use stat() here because triggerPath is always a file rather than
- * potentially being in an archive
- */
- if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
- return;
-
- /*
- * An empty trigger file performs smart failover. There's a little race
- * 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
- * invoked next time, we'll see the word "fast" and fail over immediately.
- */
- if (stat_buf.st_size == 0)
- {
- 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;
- }
-
- if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- close(fd);
- return;
- }
- buf[len] = '\0';
-
- if (strncmp(buf, "smart", 5) == 0)
- {
- Failover = SmartFailover;
- fprintf(stderr, "trigger file found: smart failover\n");
- fflush(stderr);
- close(fd);
- return;
- }
-
- if (strncmp(buf, "fast", 4) == 0)
- {
- Failover = FastFailover;
-
- fprintf(stderr, "trigger file found: fast failover\n");
- fflush(stderr);
-
- /*
- * Turn it into a "smart" trigger by truncating the file. Otherwise if
- * the server asks us again to restore a segment that was restored
- * already, we would return "not found" and upset the server.
- */
- if (ftruncate(fd, 0) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- }
- close(fd);
-
- return;
- }
- close(fd);
-
- fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
- fflush(stderr);
-}
-
-/*
- * RestoreWALFileForRecovery()
- *
- * Perform the action required to restore the file from archive
- */
-static bool
-RestoreWALFileForRecovery(void)
-{
- int rc = 0;
- int numretries = 0;
-
- if (debug)
- {
- fprintf(stderr, "running restore: ");
- fflush(stderr);
- }
-
- while (numretries <= maxretries)
- {
- rc = system(restoreCommand);
- if (rc == 0)
- {
- if (debug)
- {
- fprintf(stderr, "OK\n");
- fflush(stderr);
- }
- return true;
- }
- pg_usleep(numretries++ * sleeptime * 1000000L);
- }
-
- /*
- * Allow caller to add additional info
- */
- if (debug)
- fprintf(stderr, "not restored\n");
- return false;
-}
-
-static void
-usage(void)
-{
- 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");
- printf(" -c copy file from archive (default)\n");
- printf(" -d generate lots of debugging output (testing only)\n");
- printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
- " (0 keeps all)\n");
- printf(" -l does nothing; use of link is now deprecated\n");
- 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");
- printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
- printf(" -V, --version output version information, then exit\n");
- printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
- printf(" -?, --help show this help, then exit\n");
- printf("\n"
- "Main intended use as restore_command in postgresql.conf:\n"
- " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
- "e.g.\n"
- " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
- printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
- printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
-}
-
-#ifndef WIN32
-static void
-sighandler(int sig)
-{
- signaled = true;
-}
-
-/* We don't want SIGQUIT to core dump */
-static void
-sigquit_handler(int sig)
-{
- pqsignal(SIGINT, SIG_DFL);
- kill(getpid(), SIGINT);
-}
-#endif
-
-/*------------ MAIN ----------------------------------------*/
-int
-main(int argc, char **argv)
-{
- int c;
-
- 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);
- }
- }
-
-#ifndef WIN32
-
- /*
- * You can send SIGUSR1 to trigger failover.
- *
- * Postmaster uses SIGQUIT to request immediate shutdown. The default
- * action is to core dump, but we don't want that, so trap it and commit
- * suicide without core dump.
- *
- * 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.
- *
- * There's no way to trigger failover via signal on Windows.
- */
- (void) pqsignal(SIGUSR1, sighandler);
- (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
- (void) pqsignal(SIGQUIT, sigquit_handler);
-#endif
-
- 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);
- if (keepfiles < 0)
- {
- fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 'l': /* Use link */
-
- /*
- * Link feature disabled, possibly permanently. Linking causes
- * a problem after recovery ends that is not currently
- * resolved by PostgreSQL. 25 Jun 2009
- */
-#ifdef NOT_USED
- restoreCommandType = RESTORE_COMMAND_LINK;
-#endif
- break;
- case 'r': /* Retries */
- maxretries = atoi(optarg);
- if (maxretries < 0)
- {
- fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 's': /* Sleep time */
- sleeptime = atoi(optarg);
- if (sleeptime <= 0 || sleeptime > 60)
- {
- fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
- exit(2);
- }
- break;
- case 't': /* Trigger file */
- triggerPath = pg_strdup(optarg);
- break;
- case 'w': /* Max wait time */
- maxwaittime = atoi(optarg);
- if (maxwaittime < 0)
- {
- fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
- exit(2);
- }
- break;
- default:
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- break;
- }
- }
-
- /*
- * Parameter checking - after checking to see if trigger file present
- */
- if (argc == 1)
- {
- fprintf(stderr, "%s: not enough command-line arguments\n", progname);
- exit(2);
- }
-
- /*
- * We will go to the archiveLocation to get nextWALFileName.
- * nextWALFileName may not exist yet, which would not be an error, so we
- * separate the archiveLocation and nextWALFileName so we can check
- * separately whether archiveLocation exists, if not that is an error
- */
- if (optind < argc)
- {
- archiveLocation = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify archive location\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- nextWALFileName = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- xlogFilePath = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- restartWALFileName = argv[optind];
- optind++;
- }
-
- CustomizableInitialize();
-
- if (debug)
- {
- 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",
- sleeptime, (sleeptime > 1 ? "s" : " "));
- fprintf(stderr, "Max wait interval: %d %s\n",
- maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
- fprintf(stderr, "Command for restore: %s\n", restoreCommand);
- 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
- */
- if (IsTLHistoryFileName(nextWALFileName))
- {
- nextWALFileType = XLOG_HISTORY;
- if (RestoreWALFileForRecovery())
- exit(0);
- else
- {
- if (debug)
- {
- fprintf(stderr, "history file not found\n");
- fflush(stderr);
- }
- exit(1);
- }
- }
-
- /*
- * Main wait loop
- */
- for (;;)
- {
- /* Check for trigger file or signal first */
- CheckForExternalTrigger();
-#ifndef WIN32
- if (signaled)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "signaled to exit: fast failover\n");
- fflush(stderr);
- }
- }
-#endif
-
- /*
- * Check for fast failover immediately, before checking if the
- * requested WAL file is available
- */
- if (Failover == FastFailover)
- exit(1);
-
- if (CustomizableNextWALFileReady())
- {
- /*
- * Once we have restored this file successfully we can remove some
- * prior WAL files. If this restore fails we mustn't remove any
- * file because some of them will be requested again immediately
- * after the failed restore, or when we restart recovery.
- */
- if (RestoreWALFileForRecovery())
- {
- if (need_cleanup)
- CustomizableCleanupPriorWALFiles();
-
- exit(0);
- }
- else
- {
- /* Something went wrong in copying the file */
- exit(1);
- }
- }
-
- /* Check for smart failover if the next WAL file was not available */
- if (Failover == SmartFailover)
- exit(1);
-
- if (sleeptime <= 60)
- pg_usleep(sleeptime * 1000000L);
-
- waittime += sleeptime;
- if (waittime >= maxwaittime && maxwaittime > 0)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "Timed out after %d seconds: fast failover\n",
- waittime);
- fflush(stderr);
- }
- }
- if (debug)
- {
- fprintf(stderr, "WAL file not present yet.");
- if (triggerPath)
- fprintf(stderr, " Checking for trigger file...");
- fprintf(stderr, "\n");
- fflush(stderr);
- }
- }
-}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index ae2759be55..d3ca4b6932 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -192,13 +192,12 @@ pages.
<title>Server Applications</title>
<para>
- This section covers <productname>PostgreSQL</productname> server-related
- applications in <literal>contrib</literal>. They are typically run on the
- host where the database server resides. See also <xref
+ Some applications run on the <productname>PostgreSQL</productname> server
+ itself. Currently, no such applications are included in the
+ <literal>contrib</literal> directory. See also <xref
linkend="reference-server"/> for information about server applications that
are part of the core <productname>PostgreSQL</productname> distribution.
</para>
- &pgstandby;
</sect1>
</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..db1d369743 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -138,7 +138,6 @@
<!ENTITY pgfreespacemap SYSTEM "pgfreespacemap.sgml">
<!ENTITY pgprewarm SYSTEM "pgprewarm.sgml">
<!ENTITY pgrowlocks SYSTEM "pgrowlocks.sgml">
-<!ENTITY pgstandby SYSTEM "pgstandby.sgml">
<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml">
<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml">
<!ENTITY pgsurgery SYSTEM "pgsurgery.sgml">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index dc263e4106..f4b02e74f9 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -702,8 +702,7 @@ protocol to make nodes agree on a serializable transactional order.
Do not use pg_standby or similar tools with the built-in standby mode
described here. <xref linkend="guc-restore-command"/> should return immediately
if the file does not exist; the server will retry the command again if
- necessary. See <xref linkend="log-shipping-alternative"/>
- for using tools like pg_standby.
+ necessary.
</para>
</note>
@@ -1494,8 +1493,7 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
<para>
An alternative to the built-in standby mode described in the previous
sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below. See the
- <xref linkend="pgstandby"/> module for a reference implementation of this.
+ This was the only option available in versions 8.4 and below.
</para>
<para>
@@ -1551,14 +1549,6 @@ if (!triggered)
</programlisting>
</para>
- <para>
- A working example of a waiting <varname>restore_command</varname> is provided
- in the <xref linkend="pgstandby"/> module. It
- should be used as a reference on how to correctly implement the logic
- described above. It can also be extended as needed to support specific
- configurations and environments.
- </para>
-
<para>
The method for triggering failover is an important part of planning
and design. One potential option is the <varname>restore_command</varname>
diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml
deleted file mode 100644
index 66a6255930..0000000000
--- a/doc/src/sgml/pgstandby.sgml
+++ /dev/null
@@ -1,394 +0,0 @@
-<!-- doc/src/sgml/pgstandby.sgml -->
-
-<refentry id="pgstandby">
- <indexterm zone="pgstandby">
- <primary>pg_standby</primary>
- </indexterm>
-
- <refmeta>
- <refentrytitle><application>pg_standby</application></refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo>Application</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>pg_standby</refname>
- <refpurpose>supports the creation of a <productname>PostgreSQL</productname> warm standby server</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>pg_standby</command>
- <arg rep="repeat"><replaceable>option</replaceable></arg>
- <arg choice="plain"><replaceable>archivelocation</replaceable></arg>
- <arg choice="plain"><replaceable>nextwalfile</replaceable></arg>
- <arg choice="plain"><replaceable>walfilepath</replaceable></arg>
- <arg choice="opt"><replaceable>restartwalfile</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <application>pg_standby</application> supports creation of a <quote>warm standby</quote>
- database server. It is designed to be a production-ready program, as well
- as a customizable template should you require specific modifications.
- </para>
-
- <para>
- <application>pg_standby</application> is designed to be a waiting
- <varname>restore_command</varname>, which is needed to turn a standard
- archive recovery into a warm standby operation. Other
- configuration is required as well, all of which is described in the main
- server manual (see <xref linkend="warm-standby"/>).
- </para>
-
- <para>
- To configure a standby
- server to use <application>pg_standby</application>, put this into its
- <filename>postgresql.conf</filename> configuration file:
-<programlisting>
-restore_command = 'pg_standby <replaceable>archiveDir</replaceable> %f %p %r'
-</programlisting>
- where <replaceable>archiveDir</replaceable> is the directory from which WAL segment
- files should be restored.
- </para>
- <para>
- If <replaceable>restartwalfile</replaceable> is specified, normally by using the
- <literal>%r</literal> macro, then all WAL files logically preceding this
- file will be removed from <replaceable>archivelocation</replaceable>. This minimizes
- the number of files that need to be retained, while preserving
- crash-restart capability. Use of this parameter is appropriate if the
- <replaceable>archivelocation</replaceable> is a transient staging area for this
- particular standby server, but <emphasis>not</emphasis> when the
- <replaceable>archivelocation</replaceable> is intended as a long-term WAL archive area.
- </para>
- <para>
- <application>pg_standby</application> assumes that
- <replaceable>archivelocation</replaceable> is a directory readable by the
- server-owning user. If <replaceable>restartwalfile</replaceable> (or <literal>-k</literal>)
- is specified,
- the <replaceable>archivelocation</replaceable> directory must be writable too.
- </para>
- <para>
- There are two ways to fail over to a <quote>warm standby</quote> database server
- when the primary server fails:
-
- <variablelist>
- <varlistentry>
- <term>Smart Failover</term>
- <listitem>
- <para>
- In smart failover, the server is brought up after applying all WAL
- files available in the archive. This results in zero data loss, even if
- the standby server has fallen behind, but if there is a lot of
- unapplied WAL it can be a long time before the standby server becomes
- ready. To trigger a smart failover, create a trigger file containing
- the word <literal>smart</literal>, or just create it and leave it empty.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Fast Failover</term>
- <listitem>
- <para>
- In fast failover, the server is brought up immediately. Any WAL files
- in the archive that have not yet been applied will be ignored, and
- all transactions in those files are lost. To trigger a fast failover,
- create a trigger file and write the word <literal>fast</literal> into it.
- <application>pg_standby</application> can also be configured to execute a fast
- failover automatically if no new WAL file appears within a defined
- interval.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>
- <application>pg_standby</application> accepts the following command-line arguments:
-
- <variablelist>
-
- <varlistentry>
- <term><option>-c</option></term>
- <listitem>
- <para>
- Use <literal>cp</literal> or <literal>copy</literal> command to restore WAL files
- from archive. This is the only supported behavior so this option is useless.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
- <listitem>
- <para>
- Print lots of debug logging output on <filename>stderr</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-k</option></term>
- <listitem>
- <para>
- Remove files from <replaceable>archivelocation</replaceable> so that
- no more than this many WAL files before the current one are kept in the
- archive. Zero (the default) means not to remove any files from
- <replaceable>archivelocation</replaceable>.
- This parameter will be silently ignored if
- <replaceable>restartwalfile</replaceable> is specified, since that
- specification method is more accurate in determining the correct
- archive cut-off point.
- Use of this parameter is <emphasis>deprecated</emphasis> as of
- <productname>PostgreSQL</productname> 8.3; it is safer and more efficient to
- specify a <replaceable>restartwalfile</replaceable> parameter. A too
- small setting could result in removal of files that are still needed
- for a restart of the standby server, while a too large setting wastes
- archive space.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-r</option> <replaceable>maxretries</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of times to retry the copy command if
- it fails (default 3). After each failure, we wait for
- <replaceable>sleeptime</replaceable> * <replaceable>num_retries</replaceable>
- so that the wait time increases progressively. So by default,
- we will wait 5 secs, 10 secs, then 15 secs before reporting
- the failure back to the standby server. This will be
- interpreted as end of recovery and the standby will come
- up fully as a result.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-s</option> <replaceable>sleeptime</replaceable></term>
- <listitem>
- <para>
- Set the number of seconds (up to 60, default 5) to sleep between
- tests to see if the WAL file to be restored is available in
- the archive yet. The default setting is not necessarily
- recommended; consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-t</option> <replaceable>triggerfile</replaceable></term>
- <listitem>
- <para>
- Specify a trigger file whose presence should cause failover.
- It is recommended that you use a structured file name to
- avoid confusion as to which server is being triggered
- when multiple servers exist on the same system; for example
- <filename>/tmp/pgsql.trigger.5432</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-V</option></term>
- <term><option>--version</option></term>
- <listitem>
- <para>
- Print the <application>pg_standby</application> version and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-w</option> <replaceable>maxwaittime</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of seconds to wait for the next WAL file,
- after which a fast failover will be performed.
- A setting of zero (the default) means wait forever.
- The default setting is not necessarily recommended;
- consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-?</option></term>
- <term><option>--help</option></term>
- <listitem>
- <para>
- Show help about <application>pg_standby</application> command line
- arguments, and exit.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <para>
- <application>pg_standby</application> is designed to work with
- <productname>PostgreSQL</productname> 8.2 and later.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.3 provides the <literal>%r</literal> macro,
- which is designed to let <application>pg_standby</application> know the
- last file it needs to keep. With <productname>PostgreSQL</productname> 8.2, the
- <literal>-k</literal> option must be used if archive cleanup is
- required. This option remains available in 8.3, but its use is deprecated.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.4 provides the
- <varname>recovery_end_command</varname> option. Without this option
- a leftover trigger file can be hazardous.
- </para>
-
- <para>
- <application>pg_standby</application> is written in C and has an
- easy-to-modify source code, with specifically designated sections to modify
- for your own needs
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <para>On Linux or Unix systems, you might use:
-
-<programlisting>
-archive_command = 'cp %p .../archive/%f'
-
-restore_command = 'pg_standby -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442'
-</programlisting>
- where the archive directory is physically located on the standby server,
- so that the <varname>archive_command</varname> is accessing it across NFS,
- but the files are local to the standby (enabling use of <literal>ln</literal>).
- This will:
- <itemizedlist>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 2 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>/tmp/pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>On Windows, you might use:
-
-<programlisting>
-archive_command = 'copy %p ...\\archive\\%f'
-
-restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'del C:\pgsql.trigger.5442'
-</programlisting>
- Note that backslashes need to be doubled in the
- <varname>archive_command</varname>, but <emphasis>not</emphasis> in the
- <varname>restore_command</varname> or <varname>recovery_end_command</varname>.
- This will:
- <itemizedlist>
- <listitem>
- <para>
- use the <literal>copy</literal> command to restore WAL files from archive
- </para>
- </listitem>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 5 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>C:\pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- The <literal>copy</literal> command on Windows sets the final file size
- before the file is completely copied, which would ordinarily confuse
- <application>pg_standby</application>. Therefore
- <application>pg_standby</application> waits <replaceable>sleeptime</replaceable>
- seconds once it sees the proper file size. GNUWin32's <literal>cp</literal>
- sets the file size only after the file copy is complete.
- </para>
-
- <para>
- Since the Windows example uses <literal>copy</literal> at both ends, either
- or both servers might be accessing the archive directory across the
- network.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Author</title>
-
- <para>
- Simon Riggs <email>simon@2ndquadrant.com</email>
- </para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgarchivecleanup"/></member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/doc/src/sgml/ref/pgarchivecleanup.sgml b/doc/src/sgml/ref/pgarchivecleanup.sgml
index 56f02fc0e6..e27db3c077 100644
--- a/doc/src/sgml/ref/pgarchivecleanup.sgml
+++ b/doc/src/sgml/ref/pgarchivecleanup.sgml
@@ -205,11 +205,4 @@ archive_cleanup_command = 'pg_archivecleanup -d /mnt/standby/archive %r 2>>clean
</itemizedlist>
</refsect1>
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgstandby"/></member>
- </simplelist>
- </refsect1>
</refentry>
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 7213e65e08..90328db04e 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -34,8 +34,8 @@ my @unlink_on_exit;
# Set of variables for modules in contrib/ and src/test/modules/
my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
my @contrib_uselibpq = ('dblink', 'oid2name', 'postgres_fdw', 'vacuumlo');
-my @contrib_uselibpgport = ('oid2name', 'pg_standby', 'vacuumlo');
-my @contrib_uselibpgcommon = ('oid2name', 'pg_standby', 'vacuumlo');
+my @contrib_uselibpgport = ('oid2name', 'vacuumlo');
+my @contrib_uselibpgcommon = ('oid2name', 'vacuumlo');
my $contrib_extralibs = undef;
my $contrib_extraincludes = { 'dblink' => ['src/backend'] };
my $contrib_extrasource = {
--
2.20.1
v3-0002-Remove-documentation-of-waiting-restore_command.patchtext/x-patch; charset=US-ASCII; name=v3-0002-Remove-documentation-of-waiting-restore_command.patchDownload
From f6541076dde7d8fb347ee618b33734d241bfa609 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Wed, 27 Jan 2021 16:04:55 +1300
Subject: [PATCH v3 2/2] Remove documentation of waiting restore_command.
Following the removal of pg_standby, also remove the documentation
section that describes how to write your own "waiting restore command".
Such restore commands do not interact well with a propose recovery
prefetching feature.
Discussion: https://postgr.es/m/20201029024412.GP5380%40telsasoft.com
---
doc/src/sgml/high-availability.sgml | 137 ----------------------------
1 file changed, 137 deletions(-)
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index f4b02e74f9..f9736bcbc1 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -1487,143 +1487,6 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
</para>
</sect1>
- <sect1 id="log-shipping-alternative">
- <title>Alternative Method for Log Shipping</title>
-
- <para>
- An alternative to the built-in standby mode described in the previous
- sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below.
- </para>
-
- <para>
- Note that in this mode, the server will apply WAL one file at a
- time, so if you use the standby server for queries (see Hot Standby),
- there is a delay between an action in the primary and when the
- action becomes visible in the standby, corresponding to the time it takes
- to fill up the WAL file. <varname>archive_timeout</varname> can be used to make that delay
- shorter. Also note that you can't combine streaming replication with
- this method.
- </para>
-
- <para>
- The operations that occur on both primary and standby servers are
- normal continuous archiving and recovery tasks. The only point of
- contact between the two database servers is the archive of WAL files
- that both share: primary writing to the archive, standby reading from
- the archive. Care must be taken to ensure that WAL archives from separate
- primary servers do not become mixed together or confused. The archive
- need not be large if it is only required for standby operation.
- </para>
-
- <para>
- The magic that makes the two loosely coupled servers work together is
- simply a <varname>restore_command</varname> used on the standby that,
- when asked for the next WAL file, waits for it to become available from
- the primary. Normal recovery
- processing would request a file from the WAL archive, reporting failure
- if the file was unavailable. For standby processing it is normal for
- the next WAL file to be unavailable, so the standby must wait for
- it to appear. For files ending in
- <literal>.history</literal> there is no need to wait, and a non-zero return
- code must be returned. A waiting <varname>restore_command</varname> can be
- written as a custom script that loops after polling for the existence of
- the next WAL file. There must also be some way to trigger failover, which
- should interrupt the <varname>restore_command</varname>, break the loop and
- return a file-not-found error to the standby server. This ends recovery
- and the standby will then come up as a normal server.
- </para>
-
- <para>
- Pseudocode for a suitable <varname>restore_command</varname> is:
-<programlisting>
-triggered = false;
-while (!NextWALFileReady() && !triggered)
-{
- sleep(100000L); /* wait for ~0.1 sec */
- if (CheckForExternalTrigger())
- triggered = true;
-}
-if (!triggered)
- CopyWALFileForRecovery();
-</programlisting>
- </para>
-
- <para>
- The method for triggering failover is an important part of planning
- and design. One potential option is the <varname>restore_command</varname>
- command. It is executed once for each WAL file, but the process
- running the <varname>restore_command</varname> is created and dies for
- each file, so there is no daemon or server process, and
- signals or a signal handler cannot be used. Therefore, the
- <varname>restore_command</varname> is not suitable to trigger failover.
- It is possible to use a simple timeout facility, especially if
- used in conjunction with a known <varname>archive_timeout</varname>
- setting on the primary. However, this is somewhat error prone
- since a network problem or busy primary server might be sufficient
- to initiate failover. A notification mechanism such as the explicit
- creation of a trigger file is ideal, if this can be arranged.
- </para>
-
- <sect2 id="warm-standby-config">
- <title>Implementation</title>
-
- <para>
- The short procedure for configuring a standby server using this alternative
- method is as follows. For
- full details of each step, refer to previous sections as noted.
- <orderedlist>
- <listitem>
- <para>
- Set up primary and standby systems as nearly identical as
- possible, including two identical copies of
- <productname>PostgreSQL</productname> at the same release level.
- </para>
- </listitem>
- <listitem>
- <para>
- Set up continuous archiving from the primary to a WAL archive
- directory on the standby server. Ensure that
- <xref linkend="guc-archive-mode"/>,
- <xref linkend="guc-archive-command"/> and
- <xref linkend="guc-archive-timeout"/>
- are set appropriately on the primary
- (see <xref linkend="backup-archiving-wal"/>).
- </para>
- </listitem>
- <listitem>
- <para>
- Make a base backup of the primary server (see <xref
- linkend="backup-base-backup"/>), and load this data onto the standby.
- </para>
- </listitem>
- <listitem>
- <para>
- Begin recovery on the standby server from the local WAL
- archive, using <varname>restore_command</varname> that waits
- as described previously (see <xref linkend="backup-pitr-recovery"/>).
- </para>
- </listitem>
- </orderedlist>
- </para>
-
- <para>
- Recovery treats the WAL archive as read-only, so once a WAL file has
- been copied to the standby system it can be copied to tape at the same
- time as it is being read by the standby database server.
- Thus, running a standby server for high availability can be performed at
- the same time as files are stored for longer term disaster recovery
- purposes.
- </para>
-
- <para>
- For testing purposes, it is possible to run both primary and standby
- servers on the same system. This does not provide any worthwhile
- improvement in server robustness, nor would it be described as HA.
- </para>
- </sect2>
- </sect1>
-
<sect1 id="hot-standby">
<title>Hot Standby</title>
--
2.20.1
On Wed, Jan 27, 2021 at 04:13:24PM +1300, Thomas Munro wrote:
I would like to commit this, because "waiting restore commands" have
confusing interactions with my proposed prefetching-during-recovery
patch[1]. Here's a version that fixes an error when building the docs
(there was a stray remaining <xref linkend="pgstandby"/>), and adds a
commit message. Any objections?
It looks like you are missing two references in your patch set:
$ git grep pg_standby
doc/src/sgml/high-availability.sgml: Do not use pg_standby or
similar tools with the built-in standby mode
src/backend/access/transam/xlog.c: * segment. Only recycle normal
files, pg_standby for example can create
The logic assumed in RemoveXlogFile() is actually a bit scary. I have
not checked in details but it could be possible to clean up more code
in this area?
Furthermore, I think we should also remove the section of the manual
that describes how to write your own "waiting restore command".
Thoughts?
Agreed. No objections to that.
--
Michael
On Wed, Jan 27, 2021 at 6:06 PM Michael Paquier <michael@paquier.xyz> wrote:
On Wed, Jan 27, 2021 at 04:13:24PM +1300, Thomas Munro wrote:
I would like to commit this, because "waiting restore commands" have
confusing interactions with my proposed prefetching-during-recovery
patch[1]. Here's a version that fixes an error when building the docs
(there was a stray remaining <xref linkend="pgstandby"/>), and adds a
commit message. Any objections?It looks like you are missing two references in your patch set:
$ git grep pg_standby
doc/src/sgml/high-availability.sgml: Do not use pg_standby or
similar tools with the built-in standby mode
src/backend/access/transam/xlog.c: * segment. Only recycle normal
files, pg_standby for example can create
Thanks, fixed.
The logic assumed in RemoveXlogFile() is actually a bit scary. I have
not checked in details but it could be possible to clean up more code
in this area?
I think the check that it's a regular file is a good idea anyway, but
I removed the offending comment.
Furthermore, I think we should also remove the section of the manual
that describes how to write your own "waiting restore command".
Thoughts?Agreed. No objections to that.
Thanks!
Attachments:
v4-0001-Retire-pg_standby.patchtext/x-patch; charset=US-ASCII; name=v4-0001-Retire-pg_standby.patchDownload
From 77015331a71e67a4dee5352afc9f5faa05524755 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 26 Oct 2020 16:37:46 -0500
Subject: [PATCH v4 1/2] Retire pg_standby.
Streaming replication made pg_standby obsolete. It has been proposed
that we retire it many times. Now seems like a good time to do it,
because "waiting restore commands" are incompatible with a proposed
recovery prefetching feature.
Discussion: https://postgr.es/m/20201029024412.GP5380%40telsasoft.com
Author: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
---
contrib/Makefile | 1 -
contrib/pg_standby/.gitignore | 1 -
contrib/pg_standby/Makefile | 20 -
contrib/pg_standby/pg_standby.c | 907 -------------------------
doc/src/sgml/contrib.sgml | 7 +-
doc/src/sgml/filelist.sgml | 1 -
doc/src/sgml/high-availability.sgml | 17 +-
doc/src/sgml/pgstandby.sgml | 394 -----------
doc/src/sgml/ref/pgarchivecleanup.sgml | 7 -
src/backend/access/transam/xlog.c | 2 +-
src/tools/msvc/Mkvcbuild.pm | 4 +-
11 files changed, 9 insertions(+), 1352 deletions(-)
delete mode 100644 contrib/pg_standby/.gitignore
delete mode 100644 contrib/pg_standby/Makefile
delete mode 100644 contrib/pg_standby/pg_standby.c
delete mode 100644 doc/src/sgml/pgstandby.sgml
diff --git a/contrib/Makefile b/contrib/Makefile
index 7a4866e338..cdc041c7db 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -33,7 +33,6 @@ SUBDIRS = \
pg_buffercache \
pg_freespacemap \
pg_prewarm \
- pg_standby \
pg_stat_statements \
pg_surgery \
pg_trgm \
diff --git a/contrib/pg_standby/.gitignore b/contrib/pg_standby/.gitignore
deleted file mode 100644
index a401b085a8..0000000000
--- a/contrib/pg_standby/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/pg_standby
diff --git a/contrib/pg_standby/Makefile b/contrib/pg_standby/Makefile
deleted file mode 100644
index 87732bedf1..0000000000
--- a/contrib/pg_standby/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# contrib/pg_standby/Makefile
-
-PGFILEDESC = "pg_standby - supports creation of a warm standby"
-PGAPPICON = win32
-
-PROGRAM = pg_standby
-OBJS = \
- $(WIN32RES) \
- pg_standby.o
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_standby
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
deleted file mode 100644
index c9f33e4254..0000000000
--- a/contrib/pg_standby/pg_standby.c
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * contrib/pg_standby/pg_standby.c
- *
- *
- * pg_standby.c
- *
- * Production-ready example of how to create a Warm Standby
- * database server using continuous archiving as a
- * replication mechanism
- *
- * We separate the parameters for archive and nextWALfile
- * so that we can check the archive exists, even if the
- * 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.
- *
- * Original author: Simon Riggs simon@2ndquadrant.com
- * Current maintainer: Simon Riggs
- */
-#include "postgres_fe.h"
-
-#include <ctype.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#include "access/xlog_internal.h"
-#include "pg_getopt.h"
-
-const char *progname;
-
-int WalSegSz = -1;
-
-/* Options and defaults */
-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? */
-bool need_cleanup = false; /* do we need to remove files from
- * archive? */
-
-#ifndef WIN32
-static volatile sig_atomic_t signaled = false;
-#endif
-
-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 */
-char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */
-char restoreCommand[MAXPGPATH]; /* run this to restore */
-char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to get
- * from archive */
-
-/*
- * 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
-
-static int Failover = NoFailover;
-
-#define RESTORE_COMMAND_COPY 0
-#define RESTORE_COMMAND_LINK 1
-int restoreCommandType;
-
-#define XLOG_DATA 0
-#define XLOG_HISTORY 1
-int nextWALFileType;
-
-#define SET_RESTORE_COMMAND(cmd, arg1, arg2) \
- snprintf(restoreCommand, MAXPGPATH, cmd " \"%s\" \"%s\"", arg1, arg2)
-
-struct stat stat_buf;
-
-static bool SetWALFileNameForCleanup(void);
-static bool SetWALSegSize(void);
-
-
-/* =====================================================================
- *
- * 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
- * encouraged to submit any changes to pgsql-hackers@lists.postgresql.org
- * or personally to the current maintainer. Those changes may be
- * folded in to later versions of this program.
- */
-
-/*
- * Initialize allows customized commands into the warm standby program.
- *
- * As an example, and probably the common case, we use either
- * cp/ln commands on *nix, or copy/move command on Windows.
- */
-static void
-CustomizableInitialize(void)
-{
-#ifdef WIN32
- snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("mklink", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("copy", WALFilePath, xlogFilePath);
- break;
- }
-#else
- snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, nextWALFileName);
- switch (restoreCommandType)
- {
- case RESTORE_COMMAND_LINK:
- SET_RESTORE_COMMAND("ln -s -f", WALFilePath, xlogFilePath);
- break;
- case RESTORE_COMMAND_COPY:
- default:
- SET_RESTORE_COMMAND("cp", WALFilePath, xlogFilePath);
- break;
- }
-#endif
-
- /*
- * 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
- * directory, we use stat to test if it's accessible
- */
- if (stat(archiveLocation, &stat_buf) != 0)
- {
- fprintf(stderr, "%s: archive location \"%s\" does not exist\n", progname, archiveLocation);
- fflush(stderr);
- exit(2);
- }
-}
-
-/*
- * CustomizableNextWALFileReady()
- *
- * Is the requested file ready yet?
- */
-static bool
-CustomizableNextWALFileReady(void)
-{
- if (stat(WALFilePath, &stat_buf) == 0)
- {
- /*
- * 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");
- }
- }
- }
-
- /*
- * Return only if it's the right size already.
- */
- if (WalSegSz > 0 && stat_buf.st_size == WalSegSz)
- {
-#ifdef WIN32
-
- /*
- * Windows 'cp' sets the final file size before the copy is
- * 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.
- */
- pg_usleep(sleeptime * 1000000L);
-#endif
- nextWALFileType = XLOG_DATA;
- return true;
- }
-
- /*
- * If still too small, wait until it is the correct size
- */
- if (WalSegSz > 0 && stat_buf.st_size > WalSegSz)
- {
- if (debug)
- {
- fprintf(stderr, "file size greater than expected\n");
- fflush(stderr);
- }
- exit(3);
- }
- }
-
- return false;
-}
-
-static void
-CustomizableCleanupPriorWALFiles(void)
-{
- /*
- * Work out name of prior file from current filename
- */
- if (nextWALFileType == XLOG_DATA)
- {
- int rc;
- DIR *xldir;
- struct dirent *xlde;
-
- /*
- * Assume it's OK to keep failing. The failure situation may change
- * over time, so we'd rather keep going on the main processing than
- * fail because we couldn't clean up yet.
- */
- if ((xldir = opendir(archiveLocation)) != NULL)
- {
- while (errno = 0, (xlde = readdir(xldir)) != NULL)
- {
- /*
- * 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.
- *
- * 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.
- */
- if (IsXLogFileName(xlde->d_name) &&
- strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
- {
-#ifdef WIN32
- snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name);
-#else
- snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name);
-#endif
-
- if (debug)
- fprintf(stderr, "\nremoving file \"%s\"", WALFilePath);
-
- rc = unlink(WALFilePath);
- if (rc != 0)
- {
- fprintf(stderr, "\n%s: ERROR: could not remove file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- break;
- }
- }
- }
-
- if (errno)
- fprintf(stderr, "%s: could not read archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
- if (debug)
- fprintf(stderr, "\n");
- }
- else
- fprintf(stderr, "%s: could not open archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- if (closedir(xldir))
- fprintf(stderr, "%s: could not close archive location \"%s\": %s\n",
- progname, archiveLocation, strerror(errno));
-
- fflush(stderr);
- }
-}
-
-/* =====================================================================
- * End of Customizable section
- * =====================================================================
- */
-
-/*
- * SetWALFileNameForCleanup()
- *
- * Set the earliest WAL filename that we want to keep on the archive
- * and decide whether we need_cleanup
- */
-static bool
-SetWALFileNameForCleanup(void)
-{
- uint32 tli = 1,
- log = 0,
- seg = 0;
- uint32 log_diff = 0,
- seg_diff = 0;
- bool cleanup = false;
- int max_segments_per_logfile = (0xFFFFFFFF / WalSegSz);
-
- if (restartWALFileName)
- {
- /*
- * 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.
- */
- if (strcmp(restartWALFileName, nextWALFileName) > 0)
- return false;
-
- strlcpy(exclusiveCleanupFileName, restartWALFileName, sizeof(exclusiveCleanupFileName));
- return true;
- }
-
- if (keepfiles > 0)
- {
- sscanf(nextWALFileName, "%08X%08X%08X", &tli, &log, &seg);
- if (tli > 0 && seg > 0)
- {
- log_diff = keepfiles / max_segments_per_logfile;
- seg_diff = keepfiles % max_segments_per_logfile;
- if (seg_diff > seg)
- {
- log_diff++;
- seg = max_segments_per_logfile - (seg_diff - seg);
- }
- else
- seg -= seg_diff;
-
- if (log >= log_diff)
- {
- log -= log_diff;
- cleanup = true;
- }
- else
- {
- log = 0;
- seg = 0;
- }
- }
- }
-
- XLogFileNameById(exclusiveCleanupFileName, tli, log, seg);
-
- return cleanup;
-}
-
-/*
- * 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;
- PGAlignedXLogBlock buf;
-
- Assert(WalSegSz == -1);
-
- if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
- {
- fprintf(stderr, "%s: could not open WAL file \"%s\": %s\n",
- progname, WALFilePath, strerror(errno));
- return false;
- }
-
- errno = 0;
- if (read(fd, buf.data, XLOG_BLCKSZ) == XLOG_BLCKSZ)
- {
- XLogLongPageHeader longhdr = (XLogLongPageHeader) buf.data;
-
- 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)
- fprintf(stderr, "could not read file \"%s\": %s\n",
- WALFilePath, strerror(errno));
- }
- else
- {
- if (debug)
- fprintf(stderr, "not enough data in file \"%s\"\n",
- WALFilePath);
- }
- }
-
- fflush(stderr);
-
- close(fd);
- return ret_val;
-}
-
-/*
- * CheckForExternalTrigger()
- *
- * Is there a trigger file? Sets global 'Failover' variable to indicate
- * what kind of a trigger file it was. A "fast" trigger file is turned
- * into a "smart" file as a side-effect.
- */
-static void
-CheckForExternalTrigger(void)
-{
- char buf[32];
- int fd;
- int len;
-
- /*
- * Look for a trigger file, if that option has been selected
- *
- * We use stat() here because triggerPath is always a file rather than
- * potentially being in an archive
- */
- if (!triggerPath || stat(triggerPath, &stat_buf) != 0)
- return;
-
- /*
- * An empty trigger file performs smart failover. There's a little race
- * 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
- * invoked next time, we'll see the word "fast" and fail over immediately.
- */
- if (stat_buf.st_size == 0)
- {
- 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;
- }
-
- if ((len = read(fd, buf, sizeof(buf) - 1)) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- close(fd);
- return;
- }
- buf[len] = '\0';
-
- if (strncmp(buf, "smart", 5) == 0)
- {
- Failover = SmartFailover;
- fprintf(stderr, "trigger file found: smart failover\n");
- fflush(stderr);
- close(fd);
- return;
- }
-
- if (strncmp(buf, "fast", 4) == 0)
- {
- Failover = FastFailover;
-
- fprintf(stderr, "trigger file found: fast failover\n");
- fflush(stderr);
-
- /*
- * Turn it into a "smart" trigger by truncating the file. Otherwise if
- * the server asks us again to restore a segment that was restored
- * already, we would return "not found" and upset the server.
- */
- if (ftruncate(fd, 0) < 0)
- {
- fprintf(stderr, "WARNING: could not read \"%s\": %s\n",
- triggerPath, strerror(errno));
- fflush(stderr);
- }
- close(fd);
-
- return;
- }
- close(fd);
-
- fprintf(stderr, "WARNING: invalid content in \"%s\"\n", triggerPath);
- fflush(stderr);
-}
-
-/*
- * RestoreWALFileForRecovery()
- *
- * Perform the action required to restore the file from archive
- */
-static bool
-RestoreWALFileForRecovery(void)
-{
- int rc = 0;
- int numretries = 0;
-
- if (debug)
- {
- fprintf(stderr, "running restore: ");
- fflush(stderr);
- }
-
- while (numretries <= maxretries)
- {
- rc = system(restoreCommand);
- if (rc == 0)
- {
- if (debug)
- {
- fprintf(stderr, "OK\n");
- fflush(stderr);
- }
- return true;
- }
- pg_usleep(numretries++ * sleeptime * 1000000L);
- }
-
- /*
- * Allow caller to add additional info
- */
- if (debug)
- fprintf(stderr, "not restored\n");
- return false;
-}
-
-static void
-usage(void)
-{
- 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");
- printf(" -c copy file from archive (default)\n");
- printf(" -d generate lots of debugging output (testing only)\n");
- printf(" -k NUMFILESTOKEEP if RESTARTWALFILE is not used, remove files prior to limit\n"
- " (0 keeps all)\n");
- printf(" -l does nothing; use of link is now deprecated\n");
- 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");
- printf(" -t TRIGGERFILE trigger file to initiate failover (no default)\n");
- printf(" -V, --version output version information, then exit\n");
- printf(" -w MAXWAITTIME max seconds to wait for a file (0=no limit) (default=0)\n");
- printf(" -?, --help show this help, then exit\n");
- printf("\n"
- "Main intended use as restore_command in postgresql.conf:\n"
- " restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
- "e.g.\n"
- " restore_command = 'pg_standby /mnt/server/archiverdir %%f %%p %%r'\n");
- printf("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
- printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
-}
-
-#ifndef WIN32
-static void
-sighandler(int sig)
-{
- signaled = true;
-}
-
-/* We don't want SIGQUIT to core dump */
-static void
-sigquit_handler(int sig)
-{
- pqsignal(SIGINT, SIG_DFL);
- kill(getpid(), SIGINT);
-}
-#endif
-
-/*------------ MAIN ----------------------------------------*/
-int
-main(int argc, char **argv)
-{
- int c;
-
- 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);
- }
- }
-
-#ifndef WIN32
-
- /*
- * You can send SIGUSR1 to trigger failover.
- *
- * Postmaster uses SIGQUIT to request immediate shutdown. The default
- * action is to core dump, but we don't want that, so trap it and commit
- * suicide without core dump.
- *
- * 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.
- *
- * There's no way to trigger failover via signal on Windows.
- */
- (void) pqsignal(SIGUSR1, sighandler);
- (void) pqsignal(SIGINT, sighandler); /* deprecated, use SIGUSR1 */
- (void) pqsignal(SIGQUIT, sigquit_handler);
-#endif
-
- 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);
- if (keepfiles < 0)
- {
- fprintf(stderr, "%s: -k keepfiles must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 'l': /* Use link */
-
- /*
- * Link feature disabled, possibly permanently. Linking causes
- * a problem after recovery ends that is not currently
- * resolved by PostgreSQL. 25 Jun 2009
- */
-#ifdef NOT_USED
- restoreCommandType = RESTORE_COMMAND_LINK;
-#endif
- break;
- case 'r': /* Retries */
- maxretries = atoi(optarg);
- if (maxretries < 0)
- {
- fprintf(stderr, "%s: -r maxretries must be >= 0\n", progname);
- exit(2);
- }
- break;
- case 's': /* Sleep time */
- sleeptime = atoi(optarg);
- if (sleeptime <= 0 || sleeptime > 60)
- {
- fprintf(stderr, "%s: -s sleeptime incorrectly set\n", progname);
- exit(2);
- }
- break;
- case 't': /* Trigger file */
- triggerPath = pg_strdup(optarg);
- break;
- case 'w': /* Max wait time */
- maxwaittime = atoi(optarg);
- if (maxwaittime < 0)
- {
- fprintf(stderr, "%s: -w maxwaittime incorrectly set\n", progname);
- exit(2);
- }
- break;
- default:
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- break;
- }
- }
-
- /*
- * Parameter checking - after checking to see if trigger file present
- */
- if (argc == 1)
- {
- fprintf(stderr, "%s: not enough command-line arguments\n", progname);
- exit(2);
- }
-
- /*
- * We will go to the archiveLocation to get nextWALFileName.
- * nextWALFileName may not exist yet, which would not be an error, so we
- * separate the archiveLocation and nextWALFileName so we can check
- * separately whether archiveLocation exists, if not that is an error
- */
- if (optind < argc)
- {
- archiveLocation = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify archive location\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- nextWALFileName = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify WAL file name as second non-option argument (use \"%%f\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- xlogFilePath = argv[optind];
- optind++;
- }
- else
- {
- fprintf(stderr, "%s: must specify xlog destination as third non-option argument (use \"%%p\")\n", progname);
- fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
- exit(2);
- }
-
- if (optind < argc)
- {
- restartWALFileName = argv[optind];
- optind++;
- }
-
- CustomizableInitialize();
-
- if (debug)
- {
- 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",
- sleeptime, (sleeptime > 1 ? "s" : " "));
- fprintf(stderr, "Max wait interval: %d %s\n",
- maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
- fprintf(stderr, "Command for restore: %s\n", restoreCommand);
- 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
- */
- if (IsTLHistoryFileName(nextWALFileName))
- {
- nextWALFileType = XLOG_HISTORY;
- if (RestoreWALFileForRecovery())
- exit(0);
- else
- {
- if (debug)
- {
- fprintf(stderr, "history file not found\n");
- fflush(stderr);
- }
- exit(1);
- }
- }
-
- /*
- * Main wait loop
- */
- for (;;)
- {
- /* Check for trigger file or signal first */
- CheckForExternalTrigger();
-#ifndef WIN32
- if (signaled)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "signaled to exit: fast failover\n");
- fflush(stderr);
- }
- }
-#endif
-
- /*
- * Check for fast failover immediately, before checking if the
- * requested WAL file is available
- */
- if (Failover == FastFailover)
- exit(1);
-
- if (CustomizableNextWALFileReady())
- {
- /*
- * Once we have restored this file successfully we can remove some
- * prior WAL files. If this restore fails we mustn't remove any
- * file because some of them will be requested again immediately
- * after the failed restore, or when we restart recovery.
- */
- if (RestoreWALFileForRecovery())
- {
- if (need_cleanup)
- CustomizableCleanupPriorWALFiles();
-
- exit(0);
- }
- else
- {
- /* Something went wrong in copying the file */
- exit(1);
- }
- }
-
- /* Check for smart failover if the next WAL file was not available */
- if (Failover == SmartFailover)
- exit(1);
-
- if (sleeptime <= 60)
- pg_usleep(sleeptime * 1000000L);
-
- waittime += sleeptime;
- if (waittime >= maxwaittime && maxwaittime > 0)
- {
- Failover = FastFailover;
- if (debug)
- {
- fprintf(stderr, "Timed out after %d seconds: fast failover\n",
- waittime);
- fflush(stderr);
- }
- }
- if (debug)
- {
- fprintf(stderr, "WAL file not present yet.");
- if (triggerPath)
- fprintf(stderr, " Checking for trigger file...");
- fprintf(stderr, "\n");
- fflush(stderr);
- }
- }
-}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index ae2759be55..d3ca4b6932 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -192,13 +192,12 @@ pages.
<title>Server Applications</title>
<para>
- This section covers <productname>PostgreSQL</productname> server-related
- applications in <literal>contrib</literal>. They are typically run on the
- host where the database server resides. See also <xref
+ Some applications run on the <productname>PostgreSQL</productname> server
+ itself. Currently, no such applications are included in the
+ <literal>contrib</literal> directory. See also <xref
linkend="reference-server"/> for information about server applications that
are part of the core <productname>PostgreSQL</productname> distribution.
</para>
- &pgstandby;
</sect1>
</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..db1d369743 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -138,7 +138,6 @@
<!ENTITY pgfreespacemap SYSTEM "pgfreespacemap.sgml">
<!ENTITY pgprewarm SYSTEM "pgprewarm.sgml">
<!ENTITY pgrowlocks SYSTEM "pgrowlocks.sgml">
-<!ENTITY pgstandby SYSTEM "pgstandby.sgml">
<!ENTITY pgstatstatements SYSTEM "pgstatstatements.sgml">
<!ENTITY pgstattuple SYSTEM "pgstattuple.sgml">
<!ENTITY pgsurgery SYSTEM "pgsurgery.sgml">
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index dc263e4106..9364dc74f7 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -699,11 +699,9 @@ protocol to make nodes agree on a serializable transactional order.
<note>
<para>
- Do not use pg_standby or similar tools with the built-in standby mode
- described here. <xref linkend="guc-restore-command"/> should return immediately
+ <xref linkend="guc-restore-command"/> should return immediately
if the file does not exist; the server will retry the command again if
- necessary. See <xref linkend="log-shipping-alternative"/>
- for using tools like pg_standby.
+ necessary.
</para>
</note>
@@ -1494,8 +1492,7 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
<para>
An alternative to the built-in standby mode described in the previous
sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below. See the
- <xref linkend="pgstandby"/> module for a reference implementation of this.
+ This was the only option available in versions 8.4 and below.
</para>
<para>
@@ -1551,14 +1548,6 @@ if (!triggered)
</programlisting>
</para>
- <para>
- A working example of a waiting <varname>restore_command</varname> is provided
- in the <xref linkend="pgstandby"/> module. It
- should be used as a reference on how to correctly implement the logic
- described above. It can also be extended as needed to support specific
- configurations and environments.
- </para>
-
<para>
The method for triggering failover is an important part of planning
and design. One potential option is the <varname>restore_command</varname>
diff --git a/doc/src/sgml/pgstandby.sgml b/doc/src/sgml/pgstandby.sgml
deleted file mode 100644
index 66a6255930..0000000000
--- a/doc/src/sgml/pgstandby.sgml
+++ /dev/null
@@ -1,394 +0,0 @@
-<!-- doc/src/sgml/pgstandby.sgml -->
-
-<refentry id="pgstandby">
- <indexterm zone="pgstandby">
- <primary>pg_standby</primary>
- </indexterm>
-
- <refmeta>
- <refentrytitle><application>pg_standby</application></refentrytitle>
- <manvolnum>1</manvolnum>
- <refmiscinfo>Application</refmiscinfo>
- </refmeta>
-
- <refnamediv>
- <refname>pg_standby</refname>
- <refpurpose>supports the creation of a <productname>PostgreSQL</productname> warm standby server</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <cmdsynopsis>
- <command>pg_standby</command>
- <arg rep="repeat"><replaceable>option</replaceable></arg>
- <arg choice="plain"><replaceable>archivelocation</replaceable></arg>
- <arg choice="plain"><replaceable>nextwalfile</replaceable></arg>
- <arg choice="plain"><replaceable>walfilepath</replaceable></arg>
- <arg choice="opt"><replaceable>restartwalfile</replaceable></arg>
- </cmdsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- <application>pg_standby</application> supports creation of a <quote>warm standby</quote>
- database server. It is designed to be a production-ready program, as well
- as a customizable template should you require specific modifications.
- </para>
-
- <para>
- <application>pg_standby</application> is designed to be a waiting
- <varname>restore_command</varname>, which is needed to turn a standard
- archive recovery into a warm standby operation. Other
- configuration is required as well, all of which is described in the main
- server manual (see <xref linkend="warm-standby"/>).
- </para>
-
- <para>
- To configure a standby
- server to use <application>pg_standby</application>, put this into its
- <filename>postgresql.conf</filename> configuration file:
-<programlisting>
-restore_command = 'pg_standby <replaceable>archiveDir</replaceable> %f %p %r'
-</programlisting>
- where <replaceable>archiveDir</replaceable> is the directory from which WAL segment
- files should be restored.
- </para>
- <para>
- If <replaceable>restartwalfile</replaceable> is specified, normally by using the
- <literal>%r</literal> macro, then all WAL files logically preceding this
- file will be removed from <replaceable>archivelocation</replaceable>. This minimizes
- the number of files that need to be retained, while preserving
- crash-restart capability. Use of this parameter is appropriate if the
- <replaceable>archivelocation</replaceable> is a transient staging area for this
- particular standby server, but <emphasis>not</emphasis> when the
- <replaceable>archivelocation</replaceable> is intended as a long-term WAL archive area.
- </para>
- <para>
- <application>pg_standby</application> assumes that
- <replaceable>archivelocation</replaceable> is a directory readable by the
- server-owning user. If <replaceable>restartwalfile</replaceable> (or <literal>-k</literal>)
- is specified,
- the <replaceable>archivelocation</replaceable> directory must be writable too.
- </para>
- <para>
- There are two ways to fail over to a <quote>warm standby</quote> database server
- when the primary server fails:
-
- <variablelist>
- <varlistentry>
- <term>Smart Failover</term>
- <listitem>
- <para>
- In smart failover, the server is brought up after applying all WAL
- files available in the archive. This results in zero data loss, even if
- the standby server has fallen behind, but if there is a lot of
- unapplied WAL it can be a long time before the standby server becomes
- ready. To trigger a smart failover, create a trigger file containing
- the word <literal>smart</literal>, or just create it and leave it empty.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Fast Failover</term>
- <listitem>
- <para>
- In fast failover, the server is brought up immediately. Any WAL files
- in the archive that have not yet been applied will be ignored, and
- all transactions in those files are lost. To trigger a fast failover,
- create a trigger file and write the word <literal>fast</literal> into it.
- <application>pg_standby</application> can also be configured to execute a fast
- failover automatically if no new WAL file appears within a defined
- interval.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Options</title>
-
- <para>
- <application>pg_standby</application> accepts the following command-line arguments:
-
- <variablelist>
-
- <varlistentry>
- <term><option>-c</option></term>
- <listitem>
- <para>
- Use <literal>cp</literal> or <literal>copy</literal> command to restore WAL files
- from archive. This is the only supported behavior so this option is useless.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-d</option></term>
- <listitem>
- <para>
- Print lots of debug logging output on <filename>stderr</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-k</option></term>
- <listitem>
- <para>
- Remove files from <replaceable>archivelocation</replaceable> so that
- no more than this many WAL files before the current one are kept in the
- archive. Zero (the default) means not to remove any files from
- <replaceable>archivelocation</replaceable>.
- This parameter will be silently ignored if
- <replaceable>restartwalfile</replaceable> is specified, since that
- specification method is more accurate in determining the correct
- archive cut-off point.
- Use of this parameter is <emphasis>deprecated</emphasis> as of
- <productname>PostgreSQL</productname> 8.3; it is safer and more efficient to
- specify a <replaceable>restartwalfile</replaceable> parameter. A too
- small setting could result in removal of files that are still needed
- for a restart of the standby server, while a too large setting wastes
- archive space.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-r</option> <replaceable>maxretries</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of times to retry the copy command if
- it fails (default 3). After each failure, we wait for
- <replaceable>sleeptime</replaceable> * <replaceable>num_retries</replaceable>
- so that the wait time increases progressively. So by default,
- we will wait 5 secs, 10 secs, then 15 secs before reporting
- the failure back to the standby server. This will be
- interpreted as end of recovery and the standby will come
- up fully as a result.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-s</option> <replaceable>sleeptime</replaceable></term>
- <listitem>
- <para>
- Set the number of seconds (up to 60, default 5) to sleep between
- tests to see if the WAL file to be restored is available in
- the archive yet. The default setting is not necessarily
- recommended; consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-t</option> <replaceable>triggerfile</replaceable></term>
- <listitem>
- <para>
- Specify a trigger file whose presence should cause failover.
- It is recommended that you use a structured file name to
- avoid confusion as to which server is being triggered
- when multiple servers exist on the same system; for example
- <filename>/tmp/pgsql.trigger.5432</filename>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-V</option></term>
- <term><option>--version</option></term>
- <listitem>
- <para>
- Print the <application>pg_standby</application> version and exit.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-w</option> <replaceable>maxwaittime</replaceable></term>
- <listitem>
- <para>
- Set the maximum number of seconds to wait for the next WAL file,
- after which a fast failover will be performed.
- A setting of zero (the default) means wait forever.
- The default setting is not necessarily recommended;
- consult <xref linkend="warm-standby"/> for discussion.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><option>-?</option></term>
- <term><option>--help</option></term>
- <listitem>
- <para>
- Show help about <application>pg_standby</application> command line
- arguments, and exit.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <para>
- <application>pg_standby</application> is designed to work with
- <productname>PostgreSQL</productname> 8.2 and later.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.3 provides the <literal>%r</literal> macro,
- which is designed to let <application>pg_standby</application> know the
- last file it needs to keep. With <productname>PostgreSQL</productname> 8.2, the
- <literal>-k</literal> option must be used if archive cleanup is
- required. This option remains available in 8.3, but its use is deprecated.
- </para>
- <para>
- <productname>PostgreSQL</productname> 8.4 provides the
- <varname>recovery_end_command</varname> option. Without this option
- a leftover trigger file can be hazardous.
- </para>
-
- <para>
- <application>pg_standby</application> is written in C and has an
- easy-to-modify source code, with specifically designated sections to modify
- for your own needs
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <para>On Linux or Unix systems, you might use:
-
-<programlisting>
-archive_command = 'cp %p .../archive/%f'
-
-restore_command = 'pg_standby -d -s 2 -t /tmp/pgsql.trigger.5442 .../archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'rm -f /tmp/pgsql.trigger.5442'
-</programlisting>
- where the archive directory is physically located on the standby server,
- so that the <varname>archive_command</varname> is accessing it across NFS,
- but the files are local to the standby (enabling use of <literal>ln</literal>).
- This will:
- <itemizedlist>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 2 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>/tmp/pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>On Windows, you might use:
-
-<programlisting>
-archive_command = 'copy %p ...\\archive\\%f'
-
-restore_command = 'pg_standby -d -s 5 -t C:\pgsql.trigger.5442 ...\archive %f %p %r 2>>standby.log'
-
-recovery_end_command = 'del C:\pgsql.trigger.5442'
-</programlisting>
- Note that backslashes need to be doubled in the
- <varname>archive_command</varname>, but <emphasis>not</emphasis> in the
- <varname>restore_command</varname> or <varname>recovery_end_command</varname>.
- This will:
- <itemizedlist>
- <listitem>
- <para>
- use the <literal>copy</literal> command to restore WAL files from archive
- </para>
- </listitem>
- <listitem>
- <para>
- produce debugging output in <filename>standby.log</filename>
- </para>
- </listitem>
- <listitem>
- <para>
- sleep for 5 seconds between checks for next WAL file availability
- </para>
- </listitem>
- <listitem>
- <para>
- stop waiting only when a trigger file called
- <filename>C:\pgsql.trigger.5442</filename> appears,
- and perform failover according to its content
- </para>
- </listitem>
- <listitem>
- <para>
- remove the trigger file when recovery ends
- </para>
- </listitem>
- <listitem>
- <para>
- remove no-longer-needed files from the archive directory
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- The <literal>copy</literal> command on Windows sets the final file size
- before the file is completely copied, which would ordinarily confuse
- <application>pg_standby</application>. Therefore
- <application>pg_standby</application> waits <replaceable>sleeptime</replaceable>
- seconds once it sees the proper file size. GNUWin32's <literal>cp</literal>
- sets the file size only after the file copy is complete.
- </para>
-
- <para>
- Since the Windows example uses <literal>copy</literal> at both ends, either
- or both servers might be accessing the archive directory across the
- network.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Author</title>
-
- <para>
- Simon Riggs <email>simon@2ndquadrant.com</email>
- </para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgarchivecleanup"/></member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/doc/src/sgml/ref/pgarchivecleanup.sgml b/doc/src/sgml/ref/pgarchivecleanup.sgml
index 56f02fc0e6..e27db3c077 100644
--- a/doc/src/sgml/ref/pgarchivecleanup.sgml
+++ b/doc/src/sgml/ref/pgarchivecleanup.sgml
@@ -205,11 +205,4 @@ archive_cleanup_command = 'pg_archivecleanup -d /mnt/standby/archive %r 2>>clean
</itemizedlist>
</refsect1>
- <refsect1>
- <title>See Also</title>
-
- <simplelist type="inline">
- <member><xref linkend="pgstandby"/></member>
- </simplelist>
- </refsect1>
</refentry>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index cc007b8963..3cc7b9f6d0 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4199,7 +4199,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
/*
* Before deleting the file, see if it can be recycled as a future log
- * segment. Only recycle normal files, pg_standby for example can create
+ * segment. Only recycle normal files, because we don't want to recycle
* symbolic links pointing to a separate archive directory.
*/
if (wal_recycle &&
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 7213e65e08..90328db04e 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -34,8 +34,8 @@ my @unlink_on_exit;
# Set of variables for modules in contrib/ and src/test/modules/
my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
my @contrib_uselibpq = ('dblink', 'oid2name', 'postgres_fdw', 'vacuumlo');
-my @contrib_uselibpgport = ('oid2name', 'pg_standby', 'vacuumlo');
-my @contrib_uselibpgcommon = ('oid2name', 'pg_standby', 'vacuumlo');
+my @contrib_uselibpgport = ('oid2name', 'vacuumlo');
+my @contrib_uselibpgcommon = ('oid2name', 'vacuumlo');
my $contrib_extralibs = undef;
my $contrib_extraincludes = { 'dblink' => ['src/backend'] };
my $contrib_extrasource = {
--
2.20.1
v4-0002-Remove-documentation-of-waiting-restore_command.patchtext/x-patch; charset=US-ASCII; name=v4-0002-Remove-documentation-of-waiting-restore_command.patchDownload
From c2b957cb0f7e62c2a9be75fc18eed6afb119d12a Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Wed, 27 Jan 2021 16:04:55 +1300
Subject: [PATCH v4 2/2] Remove documentation of waiting restore_command.
Following the removal of pg_standby, also remove the documentation
section that describes how to write your own "waiting restore_command".
Such restore commands do not interact well with a proposed recovery
prefetching feature.
Discussion: https://postgr.es/m/20201029024412.GP5380%40telsasoft.com
Reviewed-by: Michael Paquier <michael@paquier.xyz>
---
doc/src/sgml/high-availability.sgml | 137 ----------------------------
1 file changed, 137 deletions(-)
diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml
index 9364dc74f7..f49f5c0108 100644
--- a/doc/src/sgml/high-availability.sgml
+++ b/doc/src/sgml/high-availability.sgml
@@ -1486,143 +1486,6 @@ synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
</para>
</sect1>
- <sect1 id="log-shipping-alternative">
- <title>Alternative Method for Log Shipping</title>
-
- <para>
- An alternative to the built-in standby mode described in the previous
- sections is to use a <varname>restore_command</varname> that polls the archive location.
- This was the only option available in versions 8.4 and below.
- </para>
-
- <para>
- Note that in this mode, the server will apply WAL one file at a
- time, so if you use the standby server for queries (see Hot Standby),
- there is a delay between an action in the primary and when the
- action becomes visible in the standby, corresponding to the time it takes
- to fill up the WAL file. <varname>archive_timeout</varname> can be used to make that delay
- shorter. Also note that you can't combine streaming replication with
- this method.
- </para>
-
- <para>
- The operations that occur on both primary and standby servers are
- normal continuous archiving and recovery tasks. The only point of
- contact between the two database servers is the archive of WAL files
- that both share: primary writing to the archive, standby reading from
- the archive. Care must be taken to ensure that WAL archives from separate
- primary servers do not become mixed together or confused. The archive
- need not be large if it is only required for standby operation.
- </para>
-
- <para>
- The magic that makes the two loosely coupled servers work together is
- simply a <varname>restore_command</varname> used on the standby that,
- when asked for the next WAL file, waits for it to become available from
- the primary. Normal recovery
- processing would request a file from the WAL archive, reporting failure
- if the file was unavailable. For standby processing it is normal for
- the next WAL file to be unavailable, so the standby must wait for
- it to appear. For files ending in
- <literal>.history</literal> there is no need to wait, and a non-zero return
- code must be returned. A waiting <varname>restore_command</varname> can be
- written as a custom script that loops after polling for the existence of
- the next WAL file. There must also be some way to trigger failover, which
- should interrupt the <varname>restore_command</varname>, break the loop and
- return a file-not-found error to the standby server. This ends recovery
- and the standby will then come up as a normal server.
- </para>
-
- <para>
- Pseudocode for a suitable <varname>restore_command</varname> is:
-<programlisting>
-triggered = false;
-while (!NextWALFileReady() && !triggered)
-{
- sleep(100000L); /* wait for ~0.1 sec */
- if (CheckForExternalTrigger())
- triggered = true;
-}
-if (!triggered)
- CopyWALFileForRecovery();
-</programlisting>
- </para>
-
- <para>
- The method for triggering failover is an important part of planning
- and design. One potential option is the <varname>restore_command</varname>
- command. It is executed once for each WAL file, but the process
- running the <varname>restore_command</varname> is created and dies for
- each file, so there is no daemon or server process, and
- signals or a signal handler cannot be used. Therefore, the
- <varname>restore_command</varname> is not suitable to trigger failover.
- It is possible to use a simple timeout facility, especially if
- used in conjunction with a known <varname>archive_timeout</varname>
- setting on the primary. However, this is somewhat error prone
- since a network problem or busy primary server might be sufficient
- to initiate failover. A notification mechanism such as the explicit
- creation of a trigger file is ideal, if this can be arranged.
- </para>
-
- <sect2 id="warm-standby-config">
- <title>Implementation</title>
-
- <para>
- The short procedure for configuring a standby server using this alternative
- method is as follows. For
- full details of each step, refer to previous sections as noted.
- <orderedlist>
- <listitem>
- <para>
- Set up primary and standby systems as nearly identical as
- possible, including two identical copies of
- <productname>PostgreSQL</productname> at the same release level.
- </para>
- </listitem>
- <listitem>
- <para>
- Set up continuous archiving from the primary to a WAL archive
- directory on the standby server. Ensure that
- <xref linkend="guc-archive-mode"/>,
- <xref linkend="guc-archive-command"/> and
- <xref linkend="guc-archive-timeout"/>
- are set appropriately on the primary
- (see <xref linkend="backup-archiving-wal"/>).
- </para>
- </listitem>
- <listitem>
- <para>
- Make a base backup of the primary server (see <xref
- linkend="backup-base-backup"/>), and load this data onto the standby.
- </para>
- </listitem>
- <listitem>
- <para>
- Begin recovery on the standby server from the local WAL
- archive, using <varname>restore_command</varname> that waits
- as described previously (see <xref linkend="backup-pitr-recovery"/>).
- </para>
- </listitem>
- </orderedlist>
- </para>
-
- <para>
- Recovery treats the WAL archive as read-only, so once a WAL file has
- been copied to the standby system it can be copied to tape at the same
- time as it is being read by the standby database server.
- Thus, running a standby server for high availability can be performed at
- the same time as files are stored for longer term disaster recovery
- purposes.
- </para>
-
- <para>
- For testing purposes, it is possible to run both primary and standby
- servers on the same system. This does not provide any worthwhile
- improvement in server robustness, nor would it be described as HA.
- </para>
- </sect2>
- </sect1>
-
<sect1 id="hot-standby">
<title>Hot Standby</title>
--
2.20.1
On 2021/01/27 14:32, Thomas Munro wrote:
On Wed, Jan 27, 2021 at 6:06 PM Michael Paquier <michael@paquier.xyz> wrote:
On Wed, Jan 27, 2021 at 04:13:24PM +1300, Thomas Munro wrote:
I would like to commit this, because "waiting restore commands" have
confusing interactions with my proposed prefetching-during-recovery
patch[1]. Here's a version that fixes an error when building the docs
(there was a stray remaining <xref linkend="pgstandby"/>), and adds a
commit message. Any objections?
I agree with this direction (i.e, remove pg_standby). BTW last month when I gave the talk about possible retire of pg_standby at PostgreSQL Unconference Tokyo, no one in audience complained about that retire.
But one question is; shouldn't we follow "usual" way to retire the feature instead of dropping that immediately? That is, mark pg_standby as obsolete, announce that pg_standby will be dropped after several releases, and then drop pg_standby. This seems safe because there might be some users. While it's been marked as obsolete, maybe WAL prefetch feature doesn't work with pg_standby, but we can live with that because it's obsolete.
Regards,
--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION
On Wed, Jan 27, 2021 at 05:08:56PM +0900, Fujii Masao wrote:
But one question is; shouldn't we follow "usual" way to retire the
feature instead of dropping that immediately? That is, mark
pg_standby as obsolete, announce that pg_standby will be dropped
after several releases, and then drop pg_standby. This seems safe
because there might be some users. While it's been marked as
obsolete, maybe WAL prefetch feature doesn't work with pg_standby,
but we can live with that because it's obsolete.
Thanks. FWIW, at this stage, my take is just to move on and remove
it. If we mark that as obsolete, it will stay around forever while
annoying future development.
--
Michael
On Thu, Jan 28, 2021 at 8:36 PM Michael Paquier <michael@paquier.xyz> wrote:
On Wed, Jan 27, 2021 at 05:08:56PM +0900, Fujii Masao wrote:
But one question is; shouldn't we follow "usual" way to retire the
feature instead of dropping that immediately? That is, mark
pg_standby as obsolete, announce that pg_standby will be dropped
after several releases, and then drop pg_standby. This seems safe
because there might be some users. While it's been marked as
obsolete, maybe WAL prefetch feature doesn't work with pg_standby,
but we can live with that because it's obsolete.Thanks. FWIW, at this stage, my take is just to move on and remove
it. If we mark that as obsolete, it will stay around forever while
annoying future development.
I agree. Also, this thing is entirely separate from the server, so a
hypothetical user who really wants to upgrade to 14 but keep using
pg_standby a bit longer could always use the version that shipped with
13.
On Fri, Jan 29, 2021 at 11:13 AM Thomas Munro <thomas.munro@gmail.com> wrote:
On Thu, Jan 28, 2021 at 8:36 PM Michael Paquier <michael@paquier.xyz> wrote:
On Wed, Jan 27, 2021 at 05:08:56PM +0900, Fujii Masao wrote:
But one question is; shouldn't we follow "usual" way to retire the
feature instead of dropping that immediately? That is, mark
pg_standby as obsolete, announce that pg_standby will be dropped
after several releases, and then drop pg_standby. This seems safe
because there might be some users. While it's been marked as
obsolete, maybe WAL prefetch feature doesn't work with pg_standby,
but we can live with that because it's obsolete.Thanks. FWIW, at this stage, my take is just to move on and remove
it. If we mark that as obsolete, it will stay around forever while
annoying future development.I agree. Also, this thing is entirely separate from the server, so a
hypothetical user who really wants to upgrade to 14 but keep using
pg_standby a bit longer could always use the version that shipped with
13.
And, pushed.