[PATCH] remove pg_archivecleanup and pg_standby

Started by Justin Pryzbyabout 5 years ago16 messages
#1Justin Pryzby
pryzby@telsasoft.com
2 attachment(s)

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

#2Michael Banck
michael.banck@credativ.de
In reply to: Justin Pryzby (#1)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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

#3Justin Pryzby
pryzby@telsasoft.com
In reply to: Michael Banck (#2)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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

#4Heikki Linnakangas
hlinnaka@iki.fi
In reply to: Justin Pryzby (#3)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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.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.

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

#5Robert Haas
robertmhaas@gmail.com
In reply to: Michael Banck (#2)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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

#6Michael Paquier
michael@paquier.xyz
In reply to: Heikki Linnakangas (#4)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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

#7Peter Eisentraut
peter.eisentraut@enterprisedb.com
In reply to: Justin Pryzby (#1)
Re: [PATCH] remove pg_archivecleanup and pg_standby

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.

#8Justin Pryzby
pryzby@telsasoft.com
In reply to: Peter Eisentraut (#7)
2 attachment(s)
Re: [PATCH] remove pg_standby

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

#9Peter Eisentraut
peter.eisentraut@enterprisedb.com
In reply to: Justin Pryzby (#8)
Re: [PATCH] remove pg_standby

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.

#10Thomas Munro
thomas.munro@gmail.com
In reply to: Peter Eisentraut (#9)
2 attachment(s)
Re: [PATCH] remove pg_standby

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() &amp;&amp; !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

#11Michael Paquier
michael@paquier.xyz
In reply to: Thomas Munro (#10)
Re: [PATCH] remove pg_standby

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

#12Thomas Munro
thomas.munro@gmail.com
In reply to: Michael Paquier (#11)
2 attachment(s)
Re: [PATCH] remove pg_standby

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() &amp;&amp; !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

#13Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Thomas Munro (#12)
Re: [PATCH] remove pg_standby

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

#14Michael Paquier
michael@paquier.xyz
In reply to: Fujii Masao (#13)
Re: [PATCH] remove pg_standby

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

#15Thomas Munro
thomas.munro@gmail.com
In reply to: Michael Paquier (#14)
Re: [PATCH] remove pg_standby

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.

#16Thomas Munro
thomas.munro@gmail.com
In reply to: Thomas Munro (#15)
Re: [PATCH] remove pg_standby

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.