On Fri, Mar 9, 2012 at 12:46 AM, Jaime Casanova <ja...@2ndquadrant.com> wrote:
> On Thu, Mar 8, 2012 at 8:25 AM, Robert Haas <robertmh...@gmail.com> wrote:
>> On Sun, Feb 12, 2012 at 9:19 PM, Greg Smith <g...@2ndquadrant.com> wrote:
>>> The smaller step of automatically stripping the specified suffix from the
>>> input file name, when it matches the one we've told the program to expect,
>>> seems like a usability improvement unlikely to lead to bad things though.
>>>  I've certainly made the mistake you've shown when using the patched version
>>> of the program myself, just didn't think about catching and correcting it
>>> myself before.  We can rev this to add that feature and resubmit easily
>>> enough, will turn that around soon.
>>
>> This change seems plenty small enough to slip in even at this late
>> date, but I guess we're lacking a new version of the patch.
>>
>
> Sorry, here's the patch rebased and with the suggestion from Alex.
> Which reminds me, I never thank him for the review (shame on me) :D
>

with the patch this time

-- 
Jaime Casanova         www.2ndQuadrant.com
Professional PostgreSQL: Soporte 24x7 y capacitación
diff --git a/contrib/pg_archivecleanup/pg_archivecleanup.c b/contrib/pg_archivecleanup/pg_archivecleanup.c
new file mode 100644
index adfc83d..8f6ca2c
*** a/contrib/pg_archivecleanup/pg_archivecleanup.c
--- b/contrib/pg_archivecleanup/pg_archivecleanup.c
*************** const char *progname;
*** 37,42 ****
--- 37,43 ----
  /* Options and defaults */
  bool		debug = false;		/* are we debugging? */
  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 */
*************** static void
*** 94,106 ****
--- 95,136 ----
  CleanupPriorWALFiles(void)
  {
  	int			rc;
+ 	int			chop_at;
  	DIR		   *xldir;
  	struct dirent *xlde;
+ 	char		walfile[MAXPGPATH];
  
  	if ((xldir = opendir(archiveLocation)) != NULL)
  	{
  		while ((xlde = readdir(xldir)) != NULL)
  		{
+ 			strncpy(walfile, xlde->d_name, MAXPGPATH);
+ 			/* 
+ 			 * Remove any specified additional extension from the filename
+ 			 * before testing it against the conditions below.
+ 			 */
+ 			if (additional_ext)
+ 			{
+ 				chop_at = strlen(walfile) - strlen(additional_ext);
+ 				/*
+ 				 * Only chop if this is long enough to be a file name and the
+ 				 * extension matches.
+ 				 */
+ 				if ((chop_at >= (XLOG_DATA_FNAME_LEN - 1)) && 
+ 					(strcmp(walfile + chop_at,additional_ext)==0))
+ 				{
+ 					walfile[chop_at] = '\0';
+ 					/* 
+ 					 * This is too chatty even for regular debug output, but
+ 					 * leaving it in for program testing.
+ 					 */
+ 					if (false)
+ 						fprintf(stderr, 
+ 							"removed extension='%s' from file=%s result=%s\n",
+ 							additional_ext,xlde->d_name,walfile);				
+ 				}
+ 			}
+ 
  			/*
  			 * We ignore the timeline part of the XLOG segment identifiers in
  			 * deciding whether a segment is still needed.	This ensures that
*************** CleanupPriorWALFiles(void)
*** 114,123 ****
  			 * file. Note that this means files are not removed in the order
  			 * they were originally written, in case this worries you.
  			 */
! 			if (strlen(xlde->d_name) == XLOG_DATA_FNAME_LEN &&
! 			strspn(xlde->d_name, "0123456789ABCDEF") == XLOG_DATA_FNAME_LEN &&
! 				strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0)
  			{
  				snprintf(WALFilePath, MAXPGPATH, "%s/%s",
  						 archiveLocation, xlde->d_name);
  
--- 144,157 ----
  			 * file. Note that this means files are not removed in the order
  			 * they were originally written, in case this worries you.
  			 */
! 			if (strlen(walfile) == XLOG_DATA_FNAME_LEN &&
! 			strspn(walfile, "0123456789ABCDEF") == XLOG_DATA_FNAME_LEN &&
! 				strcmp(walfile + 8, exclusiveCleanupFileName + 8) < 0)
  			{
+ 				/* 
+ 				 * Use the original file name again now, including any extension
+ 				 * that might have been chopped off before testing the sequence.
+ 				 */
  				snprintf(WALFilePath, MAXPGPATH, "%s/%s",
  						 archiveLocation, xlde->d_name);
  
*************** SetWALFileNameForCleanup(void)
*** 167,172 ****
--- 201,228 ----
  {
  	bool		fnameOK = false;
  
+ 	/* if restartWALFileName was specified with an extension remove it first */
+ 	if (additional_ext)
+ 	{
+ 		int		max_len = 0; /* Initialize just to keep quiet the compiler */
+ 		int		chop_at = strlen(restartWALFileName) - strlen(additional_ext);
+ 
+ 		if (strlen(restartWALFileName) == (XLOG_DATA_FNAME_LEN + strlen(additional_ext))) 
+ 			max_len = XLOG_DATA_FNAME_LEN;	
+ 		else if (strlen(restartWALFileName) == (XLOG_BACKUP_FNAME_LEN + strlen(additional_ext) + 1))
+ 			max_len = XLOG_BACKUP_FNAME_LEN;	
+ 
+ 		/*
+ 		 * Only chop if this is long enough to be a file name and the
+ 		 * extension matches.
+ 		 */
+ 		if ((chop_at >= (max_len - 1)) && 
+ 			(strcmp(restartWALFileName + chop_at, additional_ext)==0))
+ 		{
+ 			restartWALFileName[chop_at] = '\0';
+ 		}
+ 	}
+ 
  	/*
  	 * If restartWALFileName is a WAL file name then just use it directly. If
  	 * restartWALFileName is a .backup filename, make sure we use the prefix
*************** usage(void)
*** 223,228 ****
--- 279,285 ----
  	printf("\nOptions:\n");
  	printf("  -d                 generates debug output (verbose mode)\n");
  	printf("  -n                 shows the names of the files that would have been removed (dry-run)\n");
+  	printf("  -x EXT             cleanup files if they have this same extension\n");
  	printf("  --help             show this help, then exit\n");
  	printf("  --version          output version information, then exit\n");
  	printf("\n"
*************** main(int argc, char **argv)
*** 259,265 ****
  		}
  	}
  
! 	while ((c = getopt(argc, argv, "dn")) != -1)
  	{
  		switch (c)
  		{
--- 316,322 ----
  		}
  	}
  
! 	while ((c = getopt(argc, argv, "x:dn")) != -1)
  	{
  		switch (c)
  		{
*************** main(int argc, char **argv)
*** 269,274 ****
--- 326,334 ----
  			case 'n':			/* Dry-Run mode */
  				dryrun = true;
  				break;
+ 			case 'x':
+ 				additional_ext = optarg; /* Extension to remove from xlogfile names */
+ 				break;
  			default:
  				fprintf(stderr, "Try \"%s --help\" for more information.\n", progname);
  				exit(2);
diff --git a/doc/src/sgml/pgarchivecleanup.sgml b/doc/src/sgml/pgarchivecleanup.sgml
new file mode 100644
index 8148c53..40bac85
*** a/doc/src/sgml/pgarchivecleanup.sgml
--- b/doc/src/sgml/pgarchivecleanup.sgml
*************** pg_archivecleanup:  removing file "archi
*** 107,112 ****
--- 107,127 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry>
+       <term><option>-x</option> <replaceable>extension</></term>
+       <listitem>
+        <para>
+         When using the program as a standalone utility, 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.  Note that the
+         <filename>.backup</> file name passed to the program should not
+         include the extension.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
      </variablelist>
     </para>
  
-- 
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