Allow pg_archivecleanup to strip optional file extensions.
authorRobert Haas <rhaas@postgresql.org>
Thu, 5 Apr 2012 18:18:42 +0000 (14:18 -0400)
committerRobert Haas <rhaas@postgresql.org>
Thu, 5 Apr 2012 18:18:42 +0000 (14:18 -0400)
Greg Smith and Jaime Casanova, reviewed by Alex Shulgin and myself.
e

contrib/pg_archivecleanup/pg_archivecleanup.c
doc/src/sgml/pgarchivecleanup.sgml

index adfc83dea70eca52beebcd73e53f061161a1b300..1b3cecf3c44c13c7e020dec2358102df83bcc4f1 100644 (file)
@@ -37,6 +37,7 @@ const char *progname;
 /* 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 */
@@ -90,17 +91,37 @@ Initialize(void)
    }
 }
 
+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 ((xlde = readdir(xldir)) != NULL)
        {
+           strncpy(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
@@ -114,10 +135,14 @@ CleanupPriorWALFiles(void)
             * 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)
+           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);
 
@@ -167,6 +192,8 @@ 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 .backup filename, make sure we use the prefix
@@ -223,6 +250,7 @@ usage(void)
    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"
@@ -259,7 +287,7 @@ main(int argc, char **argv)
        }
    }
 
-   while ((c = getopt(argc, argv, "dn")) != -1)
+   while ((c = getopt(argc, argv, "x:dn")) != -1)
    {
        switch (c)
        {
@@ -269,6 +297,9 @@ main(int argc, char **argv)
            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);
index 8148c53d3a0a591f8912fa0a2180a4df4bc0333d..40bac8547003043b7c68f47c4e238487e55f7e42 100644 (file)
@@ -107,6 +107,21 @@ pg_archivecleanup:  removing file "archive/00000001000000370000000E"
       </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>