On Fri, 2010-02-12 at 12:54 +0000, Simon Riggs wrote:

> So I suggest that you have a new action that gets called after every
> checkpoint to clear down the archive. It will remove all files from the
> archive prior to %r. We can implement that as a sequence of unlink()s
> from within the server, or we can just call a script to do it. I prefer
> the latter approach. However we do it, we need something initiated by
> the server to maintain the archive and stop it from overflowing. 

Attached patch implements pg_standby for use as an
archive_cleanup_command, reusing existing code with new -a option.

e.g.

archive_cleanup_command = 'pg_standby -a -d /mnt/server/archiverdir %r'

Happy to add the archive_cleanup_command into main server as well, if
you like. Won't take long.

-- 
 Simon Riggs           www.2ndQuadrant.com
Index: contrib/pg_standby/pg_standby.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/contrib/pg_standby/pg_standby.c,v
retrieving revision 1.27
diff -c -r1.27 pg_standby.c
*** contrib/pg_standby/pg_standby.c	4 Nov 2009 12:51:30 -0000	1.27
--- contrib/pg_standby/pg_standby.c	12 Feb 2010 14:26:42 -0000
***************
*** 53,58 ****
--- 53,59 ----
  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		cleanup_only = false;		/* -a option new for 9.0 */
  bool		need_cleanup = false;		/* do we need to remove files from
  										 * archive? */
  
***************
*** 243,249 ****
  	/*
  	 * Work out name of prior file from current filename
  	 */
! 	if (nextWALFileType == XLOG_DATA)
  	{
  		int			rc;
  		DIR		   *xldir;
--- 244,250 ----
  	/*
  	 * Work out name of prior file from current filename
  	 */
! 	if (cleanup_only || nextWALFileType == XLOG_DATA)
  	{
  		int			rc;
  		DIR		   *xldir;
***************
*** 334,340 ****
  		 * these files from archive. This shouldn't happen, but better safe
  		 * than sorry.
  		 */
! 		if (strcmp(restartWALFileName, nextWALFileName) > 0)
  			return false;
  
  		strcpy(exclusiveCleanupFileName, restartWALFileName);
--- 335,341 ----
  		 * these files from archive. This shouldn't happen, but better safe
  		 * than sorry.
  		 */
! 		if (!cleanup_only && strcmp(restartWALFileName, nextWALFileName) > 0)
  			return false;
  
  		strcpy(exclusiveCleanupFileName, restartWALFileName);
***************
*** 512,518 ****
  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("\n"
--- 513,519 ----
  static void
  usage(void)
  {
! 	printf("%s allows PostgreSQL standby servers to be configured.\n\n", progname);
  	printf("Usage:\n");
  	printf("  %s [OPTION]... ARCHIVELOCATION NEXTWALFILE XLOGFILEPATH [RESTARTWALFILE]\n", progname);
  	printf("\n"
***************
*** 520,526 ****
--- 521,534 ----
  		   "  restore_command = 'pg_standby [OPTION]... ARCHIVELOCATION %%f %%p %%r'\n"
  		   "e.g.\n"
  		   "  restore_command = 'pg_standby -l /mnt/server/archiverdir %%f %%p %%r'\n");
+ 	printf("  %s -a ARCHIVELOCATION RESTARTWALFILE\n", progname);
+ 	printf("\n"
+ 		"with main intended use as an archive_cleanup_command in the recovery.conf:\n"
+ 		   "  archive_cleanup_command = 'pg_standby -a ARCHIVELOCATION %%r'\n"
+ 		   "e.g.\n"
+ 		   "  archive_cleanup_command = 'pg_standby -a -d /mnt/server/archiverdir %%r'\n");
  	printf("\nOptions:\n");
+ 	printf("  -a                 cleans archive only\n");
  	printf("  -c                 copies file from archive (default)\n");
  	printf("  -d                 generate lots of debugging output (testing only)\n");
  	printf("  -k NUMFILESTOKEEP  if RESTARTWALFILE not used, removes files prior to limit\n"
***************
*** 595,604 ****
  	(void) signal(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;
--- 603,615 ----
  	(void) signal(SIGQUIT, sigquit_handler);
  #endif
  
! 	while ((c = getopt(argc, argv, "acdk:lr:s:t:w:")) != -1)
  	{
  		switch (c)
  		{
+ 			case 'a':			/* Cleanup only */
+ 				cleanup_only = true;
+ 				break;
  			case 'c':			/* Use copy */
  				restoreCommandType = RESTORE_COMMAND_COPY;
  				break;
***************
*** 684,734 ****
  		exit(2);
  	}
  
! 	if (optind < argc)
! 	{
! 		nextWALFileName = argv[optind];
! 		optind++;
! 	}
! 	else
  	{
! 		fprintf(stderr, "%s: use %%f to specify nextWALFileName\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: use %%p to specify xlogFilePath\n", progname);
  		fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
  		exit(2);
  	}
  
- 	if (optind < argc)
- 	{
- 		restartWALFileName = argv[optind];
- 		optind++;
- 	}
- 
  	CustomizableInitialize();
  
  	need_cleanup = SetWALFileNameForCleanup();
  
  	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);
  		fprintf(stderr, "Keep archive history	: ");
  		if (need_cleanup)
  			fprintf(stderr, "%s and later\n", exclusiveCleanupFileName);
--- 695,758 ----
  		exit(2);
  	}
  
! 	if (!cleanup_only)
  	{
! 		if (optind < argc)
! 		{
! 			nextWALFileName = argv[optind];
! 			optind++;
! 		}
! 		else
! 		{
! 			fprintf(stderr, "%s: use %%f to specify nextWALFileName\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: use %%p to specify xlogFilePath\n", progname);
! 			fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
! 			exit(2);
! 		}
  	}
  
  	if (optind < argc)
  	{
! 		restartWALFileName = argv[optind];
  		optind++;
  	}
! 
! 	if (cleanup_only && !restartWALFileName)	
  	{
! 		fprintf(stderr, "%s: must specify restart WAL filename\n", progname);
  		fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
  		exit(2);
  	}
  
  	CustomizableInitialize();
  
  	need_cleanup = SetWALFileNameForCleanup();
  
  	if (debug)
  	{
! 		if (!cleanup_only)		
! 		{
! 			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);
! 		}
  		fprintf(stderr, "Keep archive history	: ");
  		if (need_cleanup)
  			fprintf(stderr, "%s and later\n", exclusiveCleanupFileName);
***************
*** 738,743 ****
--- 762,777 ----
  	}
  
  	/*
+ 	 * Cleanup archive immediately if that's all we need to do.
+ 	 */
+ 	if (cleanup_only)		
+ 	{
+ 		if (need_cleanup)
+ 			CustomizableCleanupPriorWALFiles();
+ 		exit(0);
+ 	}
+ 
+ 	/*
  	 * 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
  	 */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to